Game of Set program, need help with for loop nesting and more

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Frinavale
    Recognized Expert Expert
    • Oct 2006
    • 9749

    #16
    We need to stop for a second.
    You have to understand scope before we can fix this problem.

    Actually, firstly you should know that you should not have variables with the same name as a function/method.

    Right now you have a method named "populateDeckOf Cards()".
    You also have declared an ArrayList named "populateDeckOf Cards" in your constructor method....and for some reason you're trying to access it in your populateDeckOfC ards() method but.......

    This is a very confusing thing to do and is probably the source of your problems.

    With that aside we have to go over the concept of scope and classes.

    As I stated before, a class is like a blue print for creating Objects. An Object is something that exists in memory.

    Objects/Classes have members. Members can be simple variables (like Integers, and Strings and such), but they can also be methods that will modify Object's state or do things.

    In your case you have a Card class.
    A card has a few different members:
    • public String number;
    • public String color;
    • public String pattern;
    • public String shape;


    You have declared them as part of the class. This means that these variables will exist as long as the Card Object exists in memory. Once you're finished with the Card Object, they are destroyed and are no longer accessible. The scope of these methods are at the class level.

    The card class also has a bunch of methods:
    • public Card(String number, String color, String pattern, String shape) <-- the constructor
    • public String getNumber()
    • public String getColor()
    • public String pattern()<--you should to rename this to getPattern because you already have a String variable named pattern.
    • public String shape()<-- you should to rename this to getShape because you already have a String variable named shape.


    These methods in the Card class have access to class members (the variables above)....and if you had declared the Strings as "private" the these strings would Only be accessible to the methods that are members of the Card class. (But you declared them public...which is weird...especia lly since you've provided get methods to retrieve them....)


    Let's add another method to the Card class...let's create a method named PrintCard. Since this PrintCard method is part of the Card class it has access to all of the member variables of the Card class and so it is able to print the card details to the screen:

    Code:
    public void PrintCard(){
      StringBuilder theOutput=new StringBuilder();
      theOutput.append(number);
      theOutput.append(color);
      theOutput.append(pattern);
      theOutput.append(shape);
      System.out.println(theOutput.toString() );
    }
    The variable "theOutput" in the PrintCard method has a method level scope. This means that theOutput cannot be accessed out side of the PrintCard method. It is only available within the PrintCard method. It also means that theOuput is destroyed as soon as the method is finished executing.

    Hope you're with me so far.

    Say we have a loop and we declare a variable inside the loop. That variable only exists until the loop is finished executing. It cannot be access outside of the loop.

    As you can see, variables have life-spans. It is important to take care in where you declare them because this will have a big impact on how things work.

    Now let's look at the GameOfSet class.
    It has one class member variable:
    • ArrayList<Card> cards;


    This means that this variable is accessible to all of the methods in the GameOfSet class.

    The important thing is that this variable has to exist before you can use it....or else you're going to get Null Reference errors (like I explained before).

    That is the whole purpose to the Constructor method. The constructor method is used to instantiate all of the class member variables. It is called when you use the "new" keyword to instantiate an Object of the class.

    For example, when you create a new instance of the GameOfSet like:

    GameOfSet theGame = new GameOfSet();

    The constructor method is called. It is the constructor's responsibility to make sure that all of the class member variables are instantiated.

    Therefore, your constructor needs to at least have the following:
    Code:
    public GameOfSet() {
             cards = new ArrayList<Card>();  
    }
    Now your "cards" ArrayList variable is instantiated and can be used by all of the methods in the GameOfSet class.

    Your GameOfSet has one method:
    • public void populateDeckOfC ards()


    This method doesn't return anything...
    What is the purpose of having this method then?

    It is supposed to populate the class member variable "cards" with Card Objects.

    You should call this method after you have instantiated the "cards" ArrayList in the constructor. That way the "cards" variable will not only be instantiated, but it will also have data in it!

    So your constructor should look like:
    Code:
    public GameOfSet() {
             cards = new ArrayList<Card>();  
              populateDeckOfCards();
    }
    Now to address your problem on line 50.

    You have:
    populateDeckOfC ards().add(theC ard);

    First of all populateDeckOfC ards is the name of the method. In Java you execute a method by calling it's name and providing it with parameters (eg: populateDeckOfC ards() will call the populateDeckOfC ards method). Then you have .add(theCard) but how is that supposed to work (especially since the method doesn't return anything)? .... In otherwords this really doesn't make any sense and that is why the compiler is telling you that there is a problem.

    Secondly, you cannot access any variables that were declared in the constructor method in the populateDeckOfC ards() method. So even if you changed the name of the variable that was declared in the constructor method, it is not accessible in the populateDeckOfC ards() because this is how scope works.

    But the "cards" variable is accessible in the populateDeckOfC ards() method.
    Because it is has been declared at the class level...therefo re has scope for every method in the class.


    Later I'll tell you about "public" and "private" scope.
    For now I'll let you figure out how to populate the cards variable :)

    -Frinny

    Comment

    • falconsx23
      New Member
      • Nov 2008
      • 55

      #17
      Ok Thanks for the response I can probably figure it, Ill get back to you if i am still stuck

      Comment

      • JosAH
        Recognized Expert MVP
        • Mar 2007
        • 11453

        #18
        Originally posted by Frinavale
        Actually, firstly you should know that you should not have variables with the same name as a function/method.

        Right now you have a method named "populateDeckOf Cards()".
        You also have declared an ArrayList named "populateDeckOf Cards" in your constructor method....and for some reason you're trying to access it in your populateDeckOfC ards() method but.......
        Although it can be confusing there's technically nothing wrong with it; member and method names live in separate symbol tables and the compiler can unambiguously recoginise where to look: if a name is followed by an open parenthesis it must be a method, otherwise it's a member. Have a look:

        Code:
        public class Method  {
        
        	static final int method= 0;
        	static final int METHOD= 1;
        	
        	static int method(int method) {
        		return (method == Method.method)?
        			Method.METHOD:
        			method(method-Method.METHOD)*method;
        	}
        	public static void main(String[] args) {
        
        		System.out.println(method(5));
        	}
        }
        kind regards,

        Jos

        Comment

        • Frinavale
          Recognized Expert Expert
          • Oct 2006
          • 9749

          #19
          This is true for Java but please remember that I haven't used Java for quite a few years....and in VB.NET this sort of thing could be pretty bad. Especially if you declared a public class member array with the same name as a public method. In VB.NET arrays use () instead of [] and so there would be ambiguity (I don't even think it's possible to do this actually...I think the compiler would complain...mind you I would start complaining way before the compiler!)

          I would try to keep things as clear as possible, and even though it is possible to name a variable with the same name as a method (or even have mulitple variables with the same name in different cases) it is going to be confusing to anyone looking at the code and I would strongly be apposed to suggesting the idea.

          The problem in this case is that the OP was clearly confused by the name of the variable in the constructor, the method name, how to use/call methods and how to use variables.

          Besides that it just feels wrong to have a public string "pattern" and a public method "pattern()".... .they both do return the pattern string...what's the point really? The pattern string should be private in my mind and interaction should take place through the get/set methods associated with this member. This will allow for possible future design changes to the private pattern string member without effecting the public API.

          I don't think that the OP understands the concept of public and private scope modifiers yet....so I was going to just leave that alone :)

          Besides that your Method class with the class members: int method and int METHOD, that has an int method() method that takes an int method as a parameter and then makes a recursive call to itself is pretty gross.

          Yuck...
          It's like some kid just showed me a deformed bug with multiple body parts that looked like heads.
          Thanks for that Jos....bleh....

          It would make a lot more sense if you had named things appropriately:
          Code:
          public class FactorialCalculator{
              static final int ZERO = 0;
              static final int ONE = 1;
              static int factorial(int number){
                  return (number == ZERO) ?  
                    ONE :  
                    factorial(number - ONE) * number;
              }
          
              public static void main(String[] args) {
                    System.out.println(factorial(5));
              }
          }
          -Frinny

          Comment

          • JosAH
            Recognized Expert MVP
            • Mar 2007
            • 11453

            #20
            Originally posted by Frinavale
            Thanks for that Jos....bleh....
            True, all true but your previous post insinuated (to me at least) that this practice would be incorrect which it isn't. If someone writes code like I did in my previous example he deserves to be defenestrated head first. Sun's naming convention partially solves the problem because methods shoud be (or start with) a verb while members are supposed to be nouns.

            kind regards,

            Jos

            Comment

            • falconsx23
              New Member
              • Nov 2008
              • 55

              #21
              Ok its been about three weeks since we talked about this program. I made a couple of adjustments like creating the deck of cards inside the constructor and creating a method that creates 12 random cards. Each card that is created randomly will be different meaning each card will have a different number, color, pattern and shape.

              Now I am trying to create the actual play of the game. I am going to have the game played by using the console (kinda confused on what that actually is) instead of GUI such as JFrame or an applet. The way I understand the console is that it would be the printed out (as output) on to the terminal window.

              The way I started doing this is by using System.out.prin tln. So right now the part that I am stuck on is actually displaying or printing the 12 random cards onto the screen. The way I tried it is shown in comments at the bottom of the program. I know what I am trying to do doesnt make sense, but I am still working on it.

              Code:
              import java.util.Scanner;
              import java.util.*;
              import javax.swing.*;
              import java.awt.*;
              
              /**
               * Write a description of class GameOfSet here.
               * @author (Michael Brown) 
               * @version (a version number or a date)
               */
              public class GameOfSet
              {
                  
                  ArrayList<Card> deckOfCards;   //An array list of card objects
                   
                  
                  /**
                   * Constructor for objects of class GameOfSet
                   * @param String to determine Shape and String to determine color
                   * @param number can be 1-3
                   * @param color can be red, green, purple
                   * @param pattern can be solid, stripped, open
                   * @param shape can be diamond, squiggle, oval
                   * 
                   */
                  public GameOfSet()
                  {
                      deckOfCards = new ArrayList<Card>(81);          //"Card" is what the arraylist is made up of
                    
                    ArrayList<String> number = new ArrayList<String>(3);                     //ArrayList of numbers
                    number.add("1");
                    number.add("2");
                    number.add("3");
                    
                    ArrayList<String>  color = new ArrayList<String>(3);                     //ArrayList of colors
                    color.add("red");
                    color.add("green");
                    color.add("purple ");
                    
                    ArrayList<String> pattern = new ArrayList<String>(3);                 //ArrayList of patterns
                    pattern.add("solid");
                    pattern.add("striped");
                    pattern.add("open");
                    
                    ArrayList<String> shape = new ArrayList<String>(3);                   //ArrayList of Shapes
                     shape.add("diamond");
                     shape.add("squiggle");
                     shape.add("oval");
                    
                    Card theCard = null;
                       for(int i = 0; i < number.size(); i++)
                       {
                                        
                           for(int j = 0; j < color.size(); j++)
                           {
                                   
                                for(int k = 0; k < pattern.size(); k++)
                                {
                                   
                                      for(int m = 0; m < shape.size(); m++)
                                      {
                                           theCard = new Card(number.get(i),color.get(j),pattern.get(k),shape.get(m));
                                           deckOfCards.add(theCard);    // adds the new card that is being created to the deck of cards array list
                                    }
                                      
                              }
                          }                     
                      
                        }   
                  }
              
                   /**
                    * To allow 12 cards from the deckOfCards ArrayList  to be choosen at random 
                    * Then laid out in a grid of 3 rows with 4 cards each
                    */
                   public ArrayList<Card> createRandomNumberOfCards()
                   {
                       Random generator = new Random();                       //Creating the random class
                       ArrayList <Integer> list = new ArrayList <Integer>();
                       int randomIndex = 0;                //A random interger (range 1 to 12) so random class creates 12 random cards
                       int x = 12;
                       ArrayList <Card> randomCards = new ArrayList <Card>();         //Another ArrayList, when a card is pulled from the deckOfCard ArrayList, it is stored into the randomCards arrayList
                       while(x>0) 
                       {
                           randomIndex = generator.nextInt(81);               //randomIndex is a random number ranging from 0 to 81 cards 
                           
                           while(list.contains(new Integer(randomIndex)))  //this is a nested list that make sure that there is more then one of the same random card being returned. 
                           {
                              randomIndex = generator.nextInt(81);               //If there is one of the same card being returned then it will simply make a new random card 
                          }
                          list.add(randomIndex);                                         // value at randomIndex is being added to the list of integers
                          x--;
                         
                                    
                       }
                            for(int y= 0; y < 12; y++)
                           {
                                                                                                                         //gets a number from the "list" ArrayList. Then deckOfCards
                               randomCards.add(deckOfCards.get(list.get(y)));  //uses that number to get the value from the deckOfcards ArraysList and places it into the random card class
                               
                           }
                       
                           return  randomCards;                                                       //This is the random card being returned 
                    }
                   
                   
                    /**
                     * To create a grid that contains 12 cards
                     * 3 rows and 4 columns
                     */
                    
                    public static void main (String[] args)
                    {
                      System.out.println("Welcome to the Game Of Set");
                      System.out.println("12 random cards out of 81 are choosen randomly");
                      //System.out.println(Card(String number(),color(), pattern(), shape()));  //Prints out the 12 random cards 
                      //System.out.println( ArrayList <Card> randomCards ) ;
                     // System.out.println(Card randomCards());
                      }
                      
                   
              }

              Comment

              • Frinavale
                Recognized Expert Expert
                • Oct 2006
                • 9749

                #22
                In post 16 I gave an example of a method that prints a card to a screen.

                You will have to add a public method to the Card class ("printCard" or "displayCar d" or something) that will output the card details to the screen.

                Then you will have to add a public method to the GameOfSet class ("printDeck" or "displayDeck".. .) that will loop through all of the cards in the deck of cards and call the method that outputs the card details.

                Or you could just write a toString method for the Card class that returns a String representation of the card....then loop through the deck of cards and output the card details to the screen by calling the toString method for each card in the deck.

                The important thing here is that in order to achieve what you want to achieve you need to loop through all of the cards in the deck of cards and call a method (or methods) that will result in the card details being printed to the screen.

                -Frinny

                Comment

                • JosAH
                  Recognized Expert MVP
                  • Mar 2007
                  • 11453

                  #23
                  Originally posted by Frinavale
                  You will have to add a public method to the Card class ("printCard" or "displayCar d" or something) that will output the card details to the screen.
                  Don't do that; implement a public toString() method that returns a String representation of the object; PrintStreams and Writers call that method when they have to print a non-primitive value; it's much more flexible like that.

                  kind regards,

                  Jos

                  Comment

                  • falconsx23
                    New Member
                    • Nov 2008
                    • 55

                    #24
                    Before I explain what I am stuck on, I will try to explain what I do. I agree with you Jos that going with the ToString method. Just in case you didn't know I have another class named Card, which is for creating a Card. I think it will make sense if I place the toString method inside the card class. I will use the toString method to create 12 random cards.

                    Then, inside my GameOfSet class I will create a main method to call the toString method, which creates 12 random cards and prints out the 12 random cards using System.out.prin tln.

                    Now the problem that I am having is that I am not too familiar with using the toString so I am going to need your help on how to create the 12 random cards inside the toString method of my Card class.



                    Code:
                    public class Card
                    {
                        public String number;        
                        public String color;   
                        public String pattern;
                        public String shape;
                        
                         /**
                          * a deck of cards 
                          * @param number of objects on cards
                          * @param color of shape and pattern
                          * @param what type of pattern
                          * @param what type of shape
                          */
                        public Card(String number, String color, String pattern, String shape)
                        {
                            this.number = number;
                            this.color = color;
                            this. pattern = pattern;
                            this.shape = shape;   
                        }
                        
                        /**
                         * number of objects
                         * only 1-3
                         */
                        public String getNumber()
                        {
                            
                            return number;
                        }
                        
                        /**
                         * returns color
                         */
                         
                        public String getColor()
                       {
                            return color;
                        }
                        
                        /**
                         * returns pattern
                         */
                        public String pattern()
                        {
                            
                            return pattern;
                        }
                        
                        /**
                         * returns shape
                         */
                        public String shape()
                        {  
                            return shape;
                        }
                        
                        public String toString ()
                          {
                              randomCards (String number, color, pattern, shape);
                            return  "Here are the 12 random cards "  + new ArrayList<Card> randomCards(12);   //12 random cards are being shown to the user
                               
                              
                            }
                        
                    }

                    Comment

                    • Frinavale
                      Recognized Expert Expert
                      • Oct 2006
                      • 9749

                      #25
                      I think it would be best to create 12 random Cards Objects in the GameOfSet class...

                      Loop through the 12 random cards and call their toString() methods. The toString() method should return a string that contains the Card object's details. You can print this string to the screen by passing it to the the System.out.prin tln() method.

                      The reason i think it would be best to create the 12 random Card Objects in the GameOfSet class is because a Card Object represents a single Card....it does not represent 12 cards, just one card; therefore, it doesn't make sense to have the Card's toString() method print 12 cards (how can it really? it only has access to that single card's details)

                      Comment

                      • falconsx23
                        New Member
                        • Nov 2008
                        • 55

                        #26
                        Yes, but in my public ArrayList<Card> createRandomNum berOfCards()method I have 12 random cards being created. Which means my randomCards arrayList holds 12 random cards from the deck of cards arrayList.

                        So what I am trying to say is I am not sure how to print those 12 random cards from the randomCards ArrayList using the toString method.

                        Here is what I doing now
                        Code:
                           public String toString ()
                              {
                                  for(int i = 0, i < randomCards.size, i++)
                                 {
                                    System.out.println(randomCards())
                               
                                   return randomCards();
                                  
                                
                                }
                        This is in the game of Set class

                        Comment

                        • Frinavale
                          Recognized Expert Expert
                          • Oct 2006
                          • 9749

                          #27
                          Originally posted by falconsx23
                          Yes, but in my public ArrayList<Card> createRandomNum berOfCards()method I have 12 random cards being created. Which means my randomCards arrayList holds 12 random cards from the deck of cards arrayList.

                          So what I am trying to say is I am not sure how to print those 12 random cards from the randomCards ArrayList using the toString method.
                          Ok, declare a variable to hold the ArrayList (the 12 random cards), then loop through each Card in the ArrayList and call it's toString method to retrieve the string containing the card details.

                          For example:

                          Code:
                          ArrayList<Card> randomCards = createRandomNumberOfCards();
                          for(int i= 0; i < randomCards.size(); i++){
                             String cardDetails = randomCards[i].toString();
                             System.System.out.println(cardDetails);
                          }

                          Please be aware that the Card class's toString() method has to return a String containing the card's details.

                          For example:
                          Code:
                          public String toString(){
                            StringBuilder theOutput=new StringBuilder();
                            theOutput.append(" number:");
                            theOutput.append(number);
                            theOutput.append(" colour:");
                            theOutput.append(color);
                            theOutput.append(" pattern:");
                            theOutput.append(pattern);
                            theOutput.append(" shape:");
                            theOutput.append(shape);
                            theOutput.append(" ");
                            return theOutput.toString();
                          }

                          Comment

                          • falconsx23
                            New Member
                            • Nov 2008
                            • 55

                            #28
                            Ok what you are saying is making a little more sense. But before I am able to fully understand what you are saying,


                            Code:
                                ArrayList<Card> randomCards = createRandomNumberOfCards();
                                for(int i= 0; i < randomCards.size(); i++){
                                   String cardDetails = randomCards[i].toString();
                                   System.System.out.println(cardDetails);
                                }
                            where should this be placed. To me it looks like it should be placed inside the toString method, but I am not sure. When I tried to, I received many errors, unless I was doing it wrong. And do you still feel that my toString method should be placed in the gameOfSetClass or Card class?

                            Comment

                            • Frinavale
                              Recognized Expert Expert
                              • Oct 2006
                              • 9749

                              #29
                              It cannot go in the Card's toString() method.

                              Because the Card's toString method returns a string representation of that instance of the Card class (that Card Object).

                              It needs to go in the function that is using the ArrayList of 12 card objects.
                              The function where that is happening is in the GameOfSet class....

                              -Frinny

                              Comment

                              • falconsx23
                                New Member
                                • Nov 2008
                                • 55

                                #30
                                Thanks I got that part done. Now Im trying to have the program ask the user to enter an actually set. For 3 cards to form a set they must be all different or all alike within each category. For example.

                                Code:
                                0  number:3 color:green pattern:open shape:squiggle 
                                1  number:1 color:red pattern:open shape:diamond 
                                2  number:1 color:purple  pattern:solid shape:squiggle 
                                3  number:1 color:green pattern:striped shape:diamond 
                                4  number:1 color:red pattern:solid shape:diamond
                                5  number:1 color:purple  pattern:solid shape:diamond 
                                6  number:1 color:green pattern:open shape:squiggle 
                                7  number:2 color:green pattern:open shape:diamond 
                                8  number:3 color:purple  pattern:solid shape:squiggle 
                                9  number:1 color:purple  pattern:striped shape:squiggle 
                                10  number:1 color:red pattern:striped shape:diamond 
                                11  number:3 color:red pattern:striped shape:diamond

                                Cards 1, 4, and 10 is an example of a set since they are all alike in every category except pattern.

                                The problem that I am having for now is how to code this. The only way I can think of is using if statements. Any suggestions? Im working on it now.

                                Here is some of the code that I fixed up from last time.

                                Code:
                                 public void playGame()
                                      {
                                         ArrayList<Card> randomCards = createRandomNumberOfCards();
                                          for(int i= 0; i < randomCards.size(); i++)   //checking for every  card in the randomCard ArrayList
                                          {
                                              
                                          
                                              String cardDetails = randomCards.get(i).toString();    //using the toString of the Card method (which converts the details of the cards into a String 
                                              System.out.println(i + " " + cardDetails);   //prints out the cards (details of the cards) into the terminal window


                                }


                                I wrote the toString() method the same way you had it.

                                The code below is what I am working on in the GameOfSet class.

                                Code:
                                 Card one = randomCards.get(1);
                                          Card two = randomCards.get(2);
                                          Card three = randomCards.get(3);
                                          Card four = randomCards.get(4);
                                          Card five = randomCards.get(5);
                                          Card six = randomCards.get(6);
                                          Card seven = randomCards.get(7);
                                          Card eight = randomCards.get(8);
                                          Card nine = randomCards.get(9);
                                          Card ten = randomCards.get(10);
                                          Card eleven = randomCards.get(11);
                                        
                                          System.out.println("Pick your 1st card for a set  " +  one);
                                          Scanner in = new Scanner(System.in);
                                          String setH = in.nextLine(); 
                                          
                                          System.out.println("Pick your 2nd card for a set");
                                          System.out.println("Pick your 3rd card for a set");
                                I made it where each card has a variable. Now Im trying to think of a way where I can have it where the user enters one of those card variables, then another and another and then the program will compare each of those cards to each other to determine if they are a set.

                                Comment

                                Working...