Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

[Java] Exclude duplicates from Random generator?

Options
  • 04-11-2013 11:22am
    #1
    Registered Users Posts: 1,238 ✭✭✭


    I am writing a High-Low card game in Java, and my I need to get the card generator working. I'm using

    Random rand =
    new Random();
    rand.nextInt((52) + 1));

    However, I need to stop the generator from using the same number twice, as there is only one of each card in the deck.

    We have not covered arrays yet, so I cannot use them.

    Thanks



Comments

  • Closed Accounts Posts: 753 ✭✭✭Jonny Blaze


    Without using an array that's going to be really annoying.

    You would basically need 52 variables enumerating each possible card's status like a bool that you would have to check against each time you draw a card.

    Every time you draw a card then you could flip the value of the corresponding variable to false to indicate it's already been drawn.

    However that would pose a problem when it came to face cards.

    Is this for coursework or practice?


  • Registered Users Posts: 1,238 ✭✭✭Prodgey


    Without using an array that's going to be really annoying.

    You would basically need 52 variables enumerating each possible card's status like a bool that you would have to check against each time you draw a card.

    Every time you draw a card then you could flip the value of the corresponding variable to false to indicate it's already been drawn.

    However that would pose a problem when it came to face cards.

    Is this for coursework or practice?


    Thanks for your response.
    Coursework, so I can't imagine that he wants us to create 52 variables.


  • Registered Users Posts: 26,558 ✭✭✭✭Creamy Goodness


    "We have not covered arrays yet, so I cannot use them."

    not aimed at you but this ****ing pisses me off about college lecturers, why can't you skip ahead and learn by yourself to use a *basic* programming structure.

    without arrays this task becomes a code smell (repeating code), with arrays it's less than 5 lines of extra code.


  • Registered Users Posts: 1,238 ✭✭✭Prodgey


    "We have not covered arrays yet, so I cannot use them."

    not aimed at you but this ****ing pisses me off about college lecturers, why can't you skip ahead and learn by yourself to use a *basic* programming structure.

    without arrays this task becomes a code smell (repeating code), with arrays it's less than 5 lines of extra code.

    I suppose it's so we don't get into a bad habit of using them improperly.


  • Closed Accounts Posts: 753 ✭✭✭Jonny Blaze


    Yeah I know what you mean.

    I think the aim is to improve your problem solving skills by forcing you to look at any/ all alternatives to a problem before jumping to any particular conclusion.

    But arrays man... so basic! ;)

    So let me think...

    Each suit has 2 through 10 plus 4 face cards (jack, queen, king and ace).

    You could maybe try using just 13 variables representing each card and each having a count of 4 which is decremented in a loop as you draw randoms within the same range.

    You wouldn't necessarily be duplicating cards even if you drew three 10's in a row for example because they could be coming from each suit.

    Something like that might work.


  • Advertisement
  • Closed Accounts Posts: 753 ✭✭✭Jonny Blaze


    So like:
    int two = 4;
    int 3 = 4;
    
    ..
    ..
    
    int queen = 4;
    int king = 4;
    
    //Then do you random generator..
    
    Random rand =
    new Random();
    curCard = rand.nextInt((52) + 1));
    
    //then a switch based on curCard's value
    
    case(2)
    {
         if(two > 0)
         {
             two--;
             break;
         }
    
         return;
    }
    
    ...
    ...
    
    case (11)
    {
       if(queen > 0)
       {
           queen--;
           break;
       }
       return;
    }
    
    //etc..
    
    

    Long winded though..


  • Registered Users Posts: 8,671 ✭✭✭GarIT


    Use a loop to declare a variable for each card.
    Random generator to pick which card you want.
    Set that cards value to 0.
    Only accept the card drawn if it's value is not 0.


  • Registered Users Posts: 1,466 ✭✭✭Smoggy


    Use a string to hold all the values picked so far.

    Example :

    23,12,31,1,7

    Then when generating a new card make sure it's not present in the string list, using the likes of indexof.


  • Registered Users Posts: 1,311 ✭✭✭Procasinator


    Have you covered any collections? Sets, for instance?

    You could use a bit mask in this situation. Something like:
    public class DummyCardClass
    {
    	private long cardMask = 0;
    
    	private long allCardsMask = 0xFFFFFFFFFFFFF;
    
    	public bool allCardsTaken()
    	{
    		return cardMask & allCardsMask == allCardsMask;
    	}
    
    	public bool isCardTaken(int card)
    	{
    		long cardQuery = 1;
    		cardQuery = cardQuery << card;
    		return cardQuery & cardMask != 0;
    	}
    
    	public void takeCard(int card)
    	{
    		long cardQuery  = 1;
    		cardQuery = cardQuery << card;
    		cardMask = cardMask | cardQuery;
    	}
    }
    

    I haven't tested the code, but the general idea should work.


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,090 Mod ✭✭✭✭Tar.Aldarion


    Have you done enums? The lecturer could mean for you to use and enum, for cards and then for suits etc.
    http://howtoprogramwithjava.com/enums/


  • Advertisement
  • Registered Users Posts: 710 ✭✭✭mad turnip


    ArrayList<Integer> cards = new ArrayList<Integer>(53);
    		for(int i = 1; i < 52; i++){
    			cards.add(i);
    		}
    		Collections.shuffle(cards);
    

    that is likely the simplest approach to doing it.


  • Closed Accounts Posts: 753 ✭✭✭Jonny Blaze


    mad turnip wrote: »
    ArrayList<Integer> cards = new ArrayList<Integer>(53);
            for(int i = 1; i < 52; i++){
                cards.add(i);
            }
            Collections.shuffle(cards);
    
    that is likely the simplest approach to doing it.

    It's possible however that since they haven't even covered arrays yet that they aren't supposed to be using more complex data structures/types such as arraylists though.


  • Registered Users Posts: 2,021 ✭✭✭ChRoMe


    "We have not covered arrays yet, so I cannot use them."

    not aimed at you but this ****ing pisses me off about college lecturers, why can't you skip ahead and learn by yourself to use a *basic* programming structure.

    without arrays this task becomes a code smell (repeating code), with arrays it's less than 5 lines of extra code.

    Its an educational assignment, there are bigger things at play here.

    In a well structured course its a perfectly reasonable approach. Nothing is stopping the student doing independent learning, just applying that knowledge to assignments, an important distinction.


  • Registered Users Posts: 710 ✭✭✭mad turnip


    It's possible however that since they haven't even covered arrays yet that they aren't supposed to be using more complex data structures/types such as arraylists though.

    I wouldn't usually post this but: #yolo!


  • Closed Accounts Posts: 753 ✭✭✭Jonny Blaze


    So how bout it OP?

    You manage it in the end?


  • Registered Users Posts: 1,238 ✭✭✭Prodgey


    Unfortunately no. Most people in my class seem to be going with the assumption that the deck is just shuffled and cards can be reused, so I'll go with that.

    Thanks for all the responses.


  • Registered Users Posts: 6,131 ✭✭✭Talisman


    Why don't you post the wording used to describe the problem? What data structures have you covered in your course so far?


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,090 Mod ✭✭✭✭Tar.Aldarion


    Prodgey wrote: »
    Unfortunately no. Most people seem to be going with the assumption that the deck is just shuffled and cards can be reused.

    Thanks for all the responses.

    There were some that matched your criteria or required you to do at least some of it yourself.

    Some of them straight out tell you how to do it easily like GarIT etc.


  • Registered Users Posts: 1,238 ✭✭✭Prodgey


    There were some that matched your criteria or required you to do at least some of it yourself.

    Some of them straight out tell you how to do it easily like GarIT etc.

    Declaring variables for 52 cards would make the program inefficient.


  • Registered Users Posts: 1,238 ✭✭✭Prodgey


    Edited my post for clarity


  • Advertisement
  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,090 Mod ✭✭✭✭Tar.Aldarion


    Prodgey wrote: »
    Declaring variables for 52 cards would make the program inefficient.

    then you declare variables for 13 cards and 4 suits.


  • Registered Users Posts: 1,311 ✭✭✭Procasinator


    Any reason why you ruled out the mask? Wouldn't be inefficient, and isn't really that much code (compared to using 52 variables, especially). Even if you haven't been introduced to bit-wise operators in class, they are quite standard.

    You could even use the built-in BitSet if you like. If you do use BitSet, just be aware that it uses arrays of longs internally, to support masks greater than the 64-bit long. If that disqualifies it's usage, than using something like the the code I posted earlier should get you there.


  • Closed Accounts Posts: 753 ✭✭✭Jonny Blaze


    Any reason why you ruled out the mask? Wouldn't be inefficient, and isn't really that much code (compared to using 52 variables, especially). Even if you haven't been introduced to bit-wise operators in class, they are quite standard.

    You could even use the built-in BitSet if you like. If you do use BitSet, just be aware that it uses arrays of longs internally, to support masks greater than the 64-bit long. If that disqualifies it's usage, than using something like the the code I posted earlier should get you there.

    Ha ha!

    If someone had told me about bitmasks when I was in first year programming I would have crapped myself! ;)


  • Registered Users Posts: 1,311 ✭✭✭Procasinator


    So far, your suggestions have been:
    • 52 booleans values, and the various if statements you'll need.
    • Storing the cards taken in a string, and do a lookup on the string.
    • Using a bit mask.

    Could you maybe use a linked list? You've probably already been introduced to all the concepts needed to make a linked list, and even if you can't use LinkedList directly, it's trivial to write you own.


  • Registered Users Posts: 6,131 ✭✭✭Talisman


    I think you have over thought the problem. In high-low only two cards are drawn at a time, so you're only concern should be that second card drawn isn't the same card as the first.

    A card's value is determined by two values face (A,2,3,4,5,6,7,8,9,10,J,Q,K) and suit (Clubs,Diamonds,Hearts,Spades) so you need a Card class that stores two values.
    public class Card {
      private int face;
      private int suit;
    }
    

    Picking a card is a simple random number generator. The class will need a function to generate the values for face and suit.
    public void pickCard () {
      // face is 1 .. 13
      face = (int) (Math.random() * 13) + 1;
      // suit is 0 .. 3
      suit = (int) (Math.random() * 4);
    }
    

    The class also needs a function to determine if two cards are equal:
    public boolean isEqual (Card c) {
      // a == b if (a.face == b.face) && (a.suit == b.suit)
      return (face == c.face && suit == c.suit);
    }
    

    If you want to display the value of a card as a string you need two switch statements:
    public String toString() {
      // Convert the Card values to a String
      // e.g. face = 1, suit = 0 -> "Ace of Clubs"
      String cardName = null;
      // Face
      switch (face) {
        case 1:  cardName = "Ace";
                 break;
        case 2:  cardName = "Two";
                 break;
        case 3:  cardName = "Three";
                 break;
        case 4:  cardName = "Four";
                 break;
        case 5:  cardName = "Five";
                 break;
        case 6:  cardName = "Six";
                 break;
        case 7:  cardName = "Seven";
                 break;
        case 8:  cardName = "Eight";
                 break;
        case 9:  cardName = "Nine";
                 break;
        case 10: cardName = "Ten";
                 break;
        case 11: cardName = "Jack";
                 break;
        case 12: cardName = "Queen";
                 break;
        case 13: cardName = "King";
                 break;
      }
      // Suit
      switch (suit) {
        case 0: cardName += " of Clubs";
                break;
    	case 1: cardName += " of Diamonds";
                break;
        case 2: cardName += " of Hearts";
                break;
        case 3: cardName += " of Spades";
                break;
      }
      // return the String value
      return cardName;
    }
    

    Should be easy enough to stitch it together.


Advertisement