I am a complete beginner with Java and am having trouble understanding how to pass objects around between classes and methods. I have made some progress, however my app now fails when I try to create playing cards inside a for loop. It works fine if I remove the loop. Here is the first part of the class that contains the error:
public class Testing
{
public static void main(String[] args)
{
int Deal = 1;
for(int Hand = 0; Hand < Deal; ++Hand)
{
//instantiate and derive values for Player
Card card1 = new Card();
card1.setSuit(); //assign card 1's suit
card1.setValue(); //asign card 1's value
//instantiate and derive values for Computer
Card card2 = new Card();
card2.setSuit(); //assign card 2's suit
card2.setValue(); //assign card 2's suit
//compare the two cards and make sure they are different
cardCompare(card1,card2);
}
//output the two cards to the screen
output(card1,card2);
}
This is the error I get:
Testing.java:26: error: cannot find symbol
output(card1,card2);
^
symbol: variable card1
location: class Testing
Testing.java:26: error: cannot find symbol
output(card1,card2);
^
symbol: variable card2
location: class Testing
2 errors
Since the code works if I remove the for loop, I'm assuming that somehow the names card1 and card2 are not visible outside the loop? If I wanted to create ten or twenty cards, I'd want to do that in a loop, so I must be missing something about instantiating new objects and using them elsewhere in the program.
Thanks for your help.
**Update: thanks for the initial feedback. I see now that if I move my instantiate statements outside the for loop, I could theoretically assign new values for those objects over and over again using a loop, which is all I need to complete this particular task.
I'm still curious though, is it not possible to instantiate new objects inside a loop, but still use them outside the loop? It seems like this must be possible somehow.
public class Testing
{
public static void main(String[] args)
{
int Deal = 1;
//instantiate and derive values for Player
Card card1 = new Card();
//instantiate and derive values for Computer
Card card2 = new Card();
for(int Hand = 0; Hand < Deal; ++Hand)
{
card1.setSuit(); //assign card 1's suit
card1.setValue(); //asign card 1's value
card2.setSuit(); //assign card 2's suit
card2.setValue(); //assign card 2's value
//compare the two cards and make sure they are different
cardCompare(card1,card2);
}
//output the two cards to the screen
output(card1,card2);
}
The card1 and card variables are declared inside the for loop and is thus only visible inside of the loop. To use it outside of the loop, you must declare it before the loop. Please read up on Java scoping rules.
Both card1 and card2 are in scope of the for loop, not the rest of main(). Move your initialization to before the for.
Well, as it stands, its going to keep trying to overwrite card1 and card2 since you'll both declare and initialize them "deal" times. Additionally, and more importantly, they'll be out of scope. Instead, declare it beforehand and only initialize them inside the loop.
What you probably want here is:
public class Testing
{
public static void main(String[] args)
{
int Deal = 1;
ArrayList<Card> playerCards = new ArrayList<Card>();
ArrayList<Card> computerCards = new ArrayList<Card>();
//instantiate and derive values for Player
Card card1;
//instantiate and derive values for Computer
Card card2;
for(int Hand = 0; Hand < Deal; ++Hand)
{
card1 = new Card();
card1.setSuit(); //assign card 1's suit
card1.setValue(); //asign card 1's value
card2 = new Card();
card2.setSuit(); //assign card 2's suit
card2.setValue(); //assign card 2's value
//compare the two cards and make sure they are different
cardCompare(card1,card2);
playerCards.Add(card1);
computerCards.Add(card2);
}
//output the two cards to the screen
output(card1,card2);
}
Haven't tested it, but it should work.
You also need to rethink your use of your Output method, too. Since you're going to have ~20 cards per person, when do you think you need to show them to the user? Currently, you have it outside of the for loop, so it's only going to display the LAST value assigned to each one. If you want to show them each card they're getting, put the output call inside the for loop, and maybe use Thread.Sleep() to pause the program for a half second or so so that they can see each card they get. That, or write an overload of output that accepts an ArrayList of cards, and prints all of them at the same time. Once again, if you need help with that, ask me.
By the way, im not sure what cardcompare() is really doing behind the scenes, but you probably want to make it return a bool representing whether or not they were different. something like:
bool areCardsDistinct = cardcompare(card1,card2);
That way, you can use the result to decide whether or not to get random new cards again
Related
I am creating a simplistic poker game in Java that will create a deck of cards, let you draw a hand and display what kind of suit you have. Here is what I have so far and have run into a problem.
I have 3 different Array Lists, one for the card values, one for the card suits, and one to hold the actual card objects once the card suit and value is applied. I created a loop that is supposed to add a suit to each value (13 values) and add them into the newCards ArrayList (it is of type CARD, a different class I have that allows the objects to have both an integer and a string). After I try to print out newCards to see if it works properly. I get quite a few exception errors.
I'm not sure how to efficiently create a loop like this so any help is appreciated.
import java.util.*;
public class pokerMain {
public static void main (String [] args){
ArrayList<String> suits = new ArrayList<String>();//array list for the card suits
ArrayList<Integer> val = new ArrayList<Integer>();//array list for card values
ArrayList<CARDS> newCards = new ArrayList<CARDS>();//array list for cards with assigned val/suits
suits.add("Clubs");//These are the suits, added to the suits ArrayList
suits.add("Hearts");
suits.add("Diamonds");
suits.add("Spades");
System.out.println("suits contains: " + suits );//Testing for suit
for(int i = 1; i <= 13; i ++){//loop that adds all 13 values to to the val ArrayList
val.add(i);
}
System.out.println("val contains " + val);//Testing for val
This is the loop
for(int i = 0; i <= val.size(); i ++){//This loop will be used to add a suit to every card value
newCards.add(new CARDS(suits.get(0), val.get(i)));//assigns hearts
newCards.add(new CARDS(suits.get(1), val.get(i)));//assigns hearts
newCards.add(new CARDS(suits.get(2), val.get(i)));//assigns diamonds
newCards.add(new CARDS(suits.get(3), val.get(i)));//assigns spades
}
-------------------------------------------------------------------------
System.out.println(newCards.toString());//prints newCards arrayList
//newCards.add(card);// puts card object into array list newCards
To prevent code duplication you could try two loops and use for each
for(String s : suits) {
for(Integer i : val) {
newCards.add(new CARDS(s, i));
}
}
Firstly, as John Mercier said, for:each is the way to go here.
Secondly, and this isn't causing your problem, but CARDS is not exactly a conventional class name. Something like Card or Cards (or wrap the Card in a Deck class...).
Thirdly, and most importantly, the main() doesn't seem to be your problem, as far as I can tell. Check your CARDS class.
I'm new to Java and I am having trouble wrapping my mind around one of the concepts.
The assignment I am currently working on is the card game War. The current instructions is for me to remove a random card from a a deck of cards.
I have created an array, but it is an array of class Card. The class creates the card by basically adding an int and a String together. I then created the array from that class. In my mind, I neither have an int or a String in my array, is that correct?
Now I need to remove one of the random cards from the deck and give it to a player. This is where I am getting lost. I would think I can just use Random to remove a random card, but I always seem to get an error.
I'm not asking for you to do the assignment for me, but if you would please point me in the right direction and possibly correct me if I am confused.
Current Class I am working on:
import java.util.Random;
import java.util.*;
public class War3
{
Random ran = new Random();
public FullDeck randomCard()
{
ArrayList <FullDeck> randCard = new ArrayList <FullDeck> (52);
int index = ran.nextInt(randCard.size());
FullDeck x = randCard.remove(index);
return x;
}
public void display()
{
System.out.println("Your card is" + randomCard());
}
}
Entire project for clarification Java - War Game - Gist
Many thanks in advance.
ArrayList <FullDeck> randCard = new ArrayList <FullDeck> (52);
This creates an ArrayList. You do not need to specify the number 52, since ArrayLists grow dynamically, as opposed to Arrays. The call is similar to
ArrayList <FullDeck> randCard = new ArrayList <FullDeck> ();, the difference being that the constructor you used sets the initial capacity of the ArrayList to 52. That in no way restricts the size of the ArrayList though.
Anyway, you are creating a new, empty ArrayList. Then you want the size, but since you didn't put anything into the list, it is still empty, to the size is zero. You then try to call ran.nextInt(0)... nextInt(int n) expects a number greater than zero. From the javadoc:
public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
Two issues that I see:
You're creating an ArrayList that can hold a reference to 52 instances of the FullDeck class, but you're not adding anything to it. You need to do something like randCard.add(new FullDeck()) 52 times/in a loop**. Then likely you'll want to "shuffle" the deck, see this question for how to do that.
You're naming is a little weird...the FullDeck class in actuality seems like it should be renamed to just Card, and the randCard variable should be renamed to something like fullDeck...after you've added 52 Cards.
**EDIT: actually, the generation of a deck of cards will be more complicated to make sure you don't have any duplicate cards.
includes a pile of cards in a player’s hand and two actions: TAKE and DISCARD. TAKE puts a card on the top of a player’s pile of cards when that player receives a card from a dealer. DISCARD removes a card from the top of a player’s pile of cards when a player plays it against another player in the game. Each player receives 16 cards from the dealer at the
beginning of a game........
I tried my code like this which gives me nothing
public class play {
int noOfCards = 16;
static void TAKE(Stack st, int a) {
st.push(new Integer(a));
}
static void DISCARD(Stack st) {
Integer a = (Integer) st.pop();
}
public static void main(String args[]) {
for(int i=0; i<=16; i++) {
Stack st = new Stack();
st.take();
st.discard();
}
}
}
I am new to this concepts ....give me a path to solve this question
I'm sorry but I didn't fully understand the whole process you're trying to do. But I still gave it a shot.
public class Play
{
private static int noOfCards = 16;
private static Stack<Integer> player1 = new Stack<Integer>();
private static Stack<Integer> player2 = new Stack<Integer>();
static void takeCard(Stack<Integer> st,int cardValue){
st.push(cardValue);
}
static int discardCard(Stack<Integer> st){
return st.pop();
}
static int getRandomValue(int min, int max){
Random r = new Random();
return r.nextInt((max - min) + 1) + min;
}
//Filled card pile with random values from 1-13
public static void main(String[] args)
{
for(int i = 0 ; i < noOfCards; i++){
takeCard(player1,getRandomValue(1,13));
takeCard(player2,getRandomValue(1,13));
}
//player 1 takes a card!
//Size of player1's pile before and after taking card
System.out.println("Before:" + player1.size());
takeCard(player1, getRandomValue(1, 13));
System.out.println("After" + player1.size());
//player 2 discards a card and outputs the card's value
System.out.println("Player 2 discards: " + discardCard(player2));
}
}
Not sure what you want it to do. Are you just trying to implement TAKE and DISCARD? Despite not knowing exactly what you're trying to do, there are lots of issues with your code.
One immediate issue is the fact that your Stack initialization is inside your for loop meaning that every time you execute that loop, you create a brand new Stack, which will be empty. So, essentially, your main method does this:
Create a new Stack (it's empty)
Add a card to the stack
Remove a card from the stack
Repeat steps 1-3 16 times
Another issue is that Java is case sensitive so calling st.take() doesn't match up with TAKE().
Yet another issue is that st.take() is like saying "Call the 'take()' method on my instance of Stack". Stack doesn't define a method called take() - it has methods like push() and pop() (look here: http://docs.oracle.com/javase/7/docs/api/java/util/Stack.html). Your take and discard methods are on the class Play, so you'd want to invoke them like this:
Play.TAKE(st, 3);
Play.DISCARD(st);
Another issue: when you try to invoke keep or discard, you don't send any parameters, but you've defined these methods to take parameters. See above.
Is discard supposed to return the value of the card being discarded? You retrieve that value and store it into the local variable "a" and then you don't do anything with it. If you're not going to return it, you don't need to create "a". If you are going to return it, your return type shouldn't be void.
I created two methods for my Bingo Game in Java. One method creates a new board which populates the Bingo Board with integers according to the Bingo rule (1-75). My second method generates random numbers with a range of 1 - 75.
public static int drawNum(){
Random rand = new Random();
int num = rand.nextInt(75)+1;
return num;
}
public static void bingoCard(){
int [][]card=new int [5][5];
ArrayList<Integer> alreadyUsed = new ArrayList<Integer>();
boolean valid = false;
int tmp = 0;
for(int i = 0; i <= 4; i++){
for(int row = 0; row < card.length; row++){
while(!valid){
tmp = (int)(Math.random() * 15) + 1 + 15 * i;
if(!alreadyUsed.contains(tmp)){
valid = true;
alreadyUsed.add(tmp);
}
}
card[row][i] = tmp;
valid = false;
}
}
card[2][2] = 0;
//create array to make title.
String title []={"B","I","N","G","O"};
for(int i=0;i<title.length;i++){
System.out.print(title[i]+ "\t");
}
System.out.println();
for(int row=0;row<card.length;row++){
for(int col=0;col<card[row].length;col++){
System.out.print(card[row][col]+ "\t");
}
System.out.println();
}
}
What I need help with is, how do I check whether or not the drawNum() method corresponds to any values stored inside my bingoCard() array? If so, print out a new array with the integers filled in. If the condition is met for a bingo, then you win.
I hope I don't make it sound like I want you to do it for me, but I am confused as to how to start coding that part. Thank you.
This my recommendation - Learn Object Oriented Programming immediately
I see you are using objects provided in the JDK, so why not learn to make your own?
Make two classes with the following methods (-) and members (+) (PS. This is not a formal way to document code)
BingoCard
+list of numbers on card
-reset() : gets new numbers for this card
-test(BingoDrawer) : Tests to see if this card won on this drawing
-toString() : returns a String representation of this card
BingoDrawer
+list of numbers drawn
-reset() : draws new numbers
-hasNumber(int number) : tests if this number was drawn
-toString() : returns a String representation of this drawing
One more suggestions
Instead of keeping track of what you used, keep track of what you have not used, it will make things much easier because you can just choose stuff from that list randomly. Unlike your current action which is choosing (a logical number) from thin air and hoping (which causes issues) it is not a collision
If you follow my recommendation you can write code like this
public static void main(String[] args) {
BingoCard bc = new BingoCard();
BingoDrawer bd = new BingoDrawer();
while(thePlayerWantsToPlay()) { //function to be defined by you
bc.reset();
bd.reset();
System.out.println(bc);
System.out.println(bd);
System.out.println(bc.test(bd));
}
}
You can take it a step further and make a BingoGame class and do what I did in main there and just create an instance of BingoGame and call some start method on the object.
For checking if you have the number in your board, read through the board in a similar manner as you do for the already_used numbers, except with the number the user just entered.
The conditions for the user to win should be checked after the board has another number guessed.
There are a few ways to do this, a simple one would be to iterate over every possible pattern that could win, checking to see if there are tokens there.
All of this would be in a loop, that goes a little like this:
Set up board via user entering numbers.
Start loop
set either a timer to wait for, or wait for a keypress (so the game doesn't just play really fast)
Get random number
Possibly add to board
Check if winner
if winner, break the loop and do something else.
Print the new board out.
(end of loop)
If they got here, that could mean they won!
Wait to exit
You can just write it out as pseudo-code and fill in the methods after that. It usually helps to work on these things in a top-down fashion. So, for bingo you might have:
board = generateBoard();
while (!bingoFound(board)) {
number = drawNumber();
board = stampNumbers(board, number);
}
If that makes sense, you can go a step deeper and define each method. For example, bingoFound might look like:
public boolean bingoFound(int[][] board) {
boolean wasFound = bingoRowFound(board)
|| bingoColFound(board)
|| bingoDiagonalFound(board);
return wasFound;
}
Again, I've defined everything in (mostly) pseudo-code. If this looks ok, you can move a step deeper. Let's define the bingoRowFound method.
public boolean bingoRowFound(int[][] board) {
for (int row = 0; row < NUM_ROWS; row++) {
boolean rowIsABingo = true;
for (int col = 0; col < NUM_COLS; col++) {
// We have to check that everything up until this point has
// been marked off. I am using -1 to indicate that a spot has
// been marked.
rowIsABingo = rowIsABingo && board[row][col] == -1;
}
if (rowIsABingo) { return rowIsABingo; }
}
return false; // If we didn't find a bingo, return false.
}
Some of the methods (like drawNumber) will be really easy to implement. Others, like looking for a diagonal bingo might be a bit more difficult.
Feb 12 2014 Update:
Retracted code, since this was a college course assignment, and I want to prevent people just copying the code. I almost got in trouble for being accused of sharing code (which is a nono in assignments) when another student lifted my code from my Github repo and sent it in as their own.
There were two classes, one main class and a class to hold my methods and constructors.
BINGOFINAL.java was my main class.
Bingo_Card.java held my constructor and methods.
If you want to run this, make sure you create a new project called BINGOFINAL, and put Bingo_Card.java into that same */src/ extension.
I have an 2d array that represent a tic tac toe board.
And empty box is just "" ;
My current game board is saved in ar1 which is 2d string array.
I want to make an array of game boards which is array of 2d array = 3d array.
So I guess it would be like that:
String[][][]ar3 = new String[80][9][9]; // array of game boards
for(int k=0;k<ar3.length;k++)// filling the array with the current game board
{
ar3[k] = ar1;
}
Yea I want 80 boards and the game would be 9x9.
Till now everything is fine .. but now I would like to look on the game board(ar1) and make every possible move on the ar3.
So for every possible move I got a board on ar3.
For that I would create an array that would contain the empty indexes on the board which is every possible move on ar2:
int[][]ar2 = new int[81][2]; // contains blank boxes indexes
int line = 0;
for(int k=0;k<SIZE;k++) //finds blank boxes indexes and adding to the array
for(int j=0;j<SIZE;j++,line++)
{
if(ar1[k][j].equals(""))
{
ar2[line][0] = k;
ar2[line][1] = j;
}
else
{
ar2[line][0] = -1;
ar2[line][1] = -1;
}
}
As you can see in case that the box has something else then "" which is X or O then I put -1
This code is doing what I want but here comes the problem now I will try to generate all the possible moves which stored in ar2 in ar3:
String[][][]ar3 = new String[80][9][9]; // array of game boards
for(int k=0;k<ar3.length;k++)// filling the array with the current game board
{
ar3[k] = ar1;
}
for(int k=0;k<ar3.length;k++)// making a move
{
int i1 = ar2[k][0];
int i2 = ar2[k][1];
if(!(i1 == -1 || i2 == -1))
if(num%2==0)
ar3[k][i1][i2] = "X";
else
ar3[k][i1][i2] = "O";
}
I have no idea why instead of making a single move for each board , for each index in ar3 it's making all of the moves for all of the boards .. for example (I will demonstrate on a 3x3 board)
^ means empty
The board before looks like this:
^ ^ ^
^ X ^
^ ^ ^
but after the "move" i'm trying to make (let's say 0,0)
all of the boards looks like this:
O ^ ^
^ X ^
^ ^ ^
Instead just of the first 1... and then I'm doing the same thing with diffrent indexes for the second board (ar3[1]) but it affects all of the boards.. (ar3[0-k]) so eventually I got 80 boards which are the same.
Any one got an idea?
Why it changes all of the boards?instead just the one on the K index?
Thanks!
I'm not sure I understand the code fully, so this is a wild guess, but:
In the first excerpt you're giving all slots in ar3 a reference to the same object, ar1. This means that if you change ar1's contents, you'll see that change across all ar3 items because all those items are references to the same object. You could check to see whether this is your problem.
Now, as a comment, I'd advise you to start doing two things that help me personally in these cases: The first is to give your identifiers as meaningful names as possible, so much that comments aren't really needed to understand what's what. The second is to take advantage of the fact that you're writing in a language like Java and try to write your code in a more object oriented fashion. For instance, if, instead of a 3D array, you have a normal array of (say) GameBoard objects, each of which contains its 2D information, it could have a very positive effect in making any "suspicious" code patterns (that don't correspond to your actual intention, that is) more apparent.