How can you populate a deck of cards with out knowing how many?

  • (2 Pages)
  • +
  • 1
  • 2

15 Replies - 1369 Views - Last Post: 13 July 2013 - 02:45 PM Rate Topic: -----

#1 Dylsauce   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 98
  • Joined: 30-June 13

How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 09:06 AM

So I'm making a card deck as many do, but mine is an uno deck so instead of hearts, spades, etc, it has 4 colors: RGBY and instead of ace-king it has all the numbers from 1-x, where x is just any highestRank you decide at the start of the game, could be 2, could be a million. Now my problem is populating a deck of random cards. I need to have 2 of every combination of rank and color, so there will be 2 R1s and 2 R2s etc...
I supposed I could use some nested for loops like this:
for (int i = 0;i < highestRank; i++)
			
		for(int p = 0; p < 4; p++)


The problem with that is 1, it wont be random and 2, it only creates one of every card. And where to store the cards? I can use a List, Stack, Or Queue. The game will basically work like this: I'll have 2 collections, one face up cards, on of face down cards players will add cards to the face up pile and take cards from the face down pile, when face down is empty we just flip face up upside down (i.e we take the oldest card from it) which makes it seem best to use a queue. My only problem is I can't figure out how to populate it randomly? Any ideas? Here is a constructor for a card

	
// Constructor which initializes the colour an rank passed in as parameters
	public UnoCard(char color, int rank) {
		this.color = color;
		this.rank = rank;
	}


And here is a queue ADT, but I only have a circularArrayQueue implementation of it which is kind of confusing as well :(

/**
 * QueueADT defines the interface to a queue collection.
 *
 * @author Dr. Lewis
 * @author Dr. Chase
 * @version 1.0, 8/12/08
 */

public interface QueueADT<T>
{

   /**  
    * Adds one element to the rear of this queue. 
    * 
    * @param element  the element to be added to the rear of this queue  
    */
   public void enqueue (T element);

   /**  
    * Removes and returns the element at the front of this queue.
    * 
    * @return  the element at the front of this queue
    */
   public T dequeue();

   /**  
    * Returns without removing the element at the front of this queue.
    *
    * @return  the first element in this queue
    */
   public T first();
   
   /**  
    * Returns true if this queue contains no elements.
    * 
    * @return  true if this queue is empty
    */
   public boolean isEmpty();

   /**  
    * Returns the number of elements in this queue. 
    * 
    * @return  the integer representation of the size of this queue
    */
   public int size();

   /**  
    * Returns a string representation of this queue. 
    *
    * @return  the string representation of this queue
    */
   public String toString();
}



Is This A Good Question/Topic? 0
  • +

Replies To: How can you populate a deck of cards with out knowing how many?

#2 ConciselyVerbose   User is offline

  • D.I.C Regular

Reputation: 91
  • View blog
  • Posts: 315
  • Joined: 05-July 13

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 09:22 AM

With a normal deck of cards on of the easiest ways is to decide cardRank/maxRank is the suit and cardRank%maxRank as the rank. You could do the same here, and just loop until 4*highest rank.

As for randomizing it, it is easier to create the list (in whatever form you decide on), populate it, then shuffle it.
Was This Post Helpful? 1
  • +
  • -

#3 Dylsauce   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 98
  • Joined: 30-June 13

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 09:25 AM

Quote

cardRank/maxRank is the suit and cardRank%maxRank as the rank.
I don't quite understand what you mean by that
Was This Post Helpful? 0
  • +
  • -

#4 ConciselyVerbose   User is offline

  • D.I.C Regular

Reputation: 91
  • View blog
  • Posts: 315
  • Joined: 05-July 13

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 09:44 AM

OK, so with a typical deck of 52 cards, you have 4 suits of 13 cards each. Say you assign rank 0 to be hearts, 1 to be diamonds, 2 to be spades, and 3 to be clubs. Then when you get 28, 28/13 is 2, meaning your card is spades. The remainder (28%13) will be 2. Since ace is 0, this would mean the card is actually a 3 of spades.

Doing this with, say 8, would result in a 9 of hearts, for the same reason.

If you are making a separate object you could just as easily do nested loops.

This post has been edited by ConciselyVerbose: 13 July 2013 - 09:46 AM

Was This Post Helpful? 1
  • +
  • -

#5 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1576
  • View blog
  • Posts: 3,548
  • Joined: 05-April 11

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 09:44 AM

The easy way?
Shuffle the array :)
		final int highestRank = 10;
		ArrayList<Object> cards = new ArrayList<>(highestRank);
		
		for (int i=0; i<highestRank; i++) {
			cards.add(i);
		}
		
		Collections.shuffle(cards);
		
		//Print out the scrambled cards
		System.out.println(cards);
		
		Queue<Object> deck = new LinkedList<>(cards);


Need two of the same card? Then just add it twice to the array. That will make no difference at all when shuffling
Was This Post Helpful? 1
  • +
  • -

#6 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1576
  • View blog
  • Posts: 3,548
  • Joined: 05-April 11

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 09:55 AM

Writing your own shuffling algorithm isn't too hard either
Just simply swap around in the array until it is scrambled enough
Using the Random class makes it very easy to pick a random index to swap with
	public static void scramble(Object[] array) {
		Random rnd = new Random();
		
		for (int i=array.length-1; i>0; i--) {
			swap(array, rnd.nextInt(i), i);
		}
	}
	
	public static void swap(Object[] array, int index1, int index2) {
		Object element = array[index1];
		array[index1] = array[index2];
		array[index2] = element;
	}



The highest rank being a million? That is not a problem either!
It scrambles an array pretty fast
import java.util.Random;


public class ScrambleUno {

	public static void main(String[] args) {
		final int highestRank = 1000000;
		Object[] cards = new Object[highestRank];
		
		for (int i=0; i<highestRank; i++)
			cards[i] = i;
		
		scramble(cards);
	}
	
	public static void scramble(Object[] array) {
		Random rnd = new Random();
		
		for (int i=array.length-1; i>0; i--) {
			swap(array, rnd.nextInt(i), i);
		}
	}
	
	public static void swap(Object[] array, int index1, int index2) {
		Object element = array[index1];
		array[index1] = array[index2];
		array[index2] = element;
	}

}


This post has been edited by CasiOo: 13 July 2013 - 09:57 AM

Was This Post Helpful? 0
  • +
  • -

#7 Dylsauce   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 98
  • Joined: 30-June 13

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 11:35 AM

View PostCasiOo, on 13 July 2013 - 09:44 AM, said:

The easy way?
Shuffle the array :)/>/>
		final int highestRank = 10;
		ArrayList<Object> cards = new ArrayList<>(highestRank);
		
		for (int i=0; i<highestRank; i++) {
			cards.add(i);
		}
		
		Collections.shuffle(cards);
		
		//Print out the scrambled cards
		System.out.println(cards);
		
		Queue<Object> deck = new LinkedList<>(cards);


Need two of the same card? Then just add it twice to the array. That will make no difference at all when shuffling



I definitely like this method best, it is far more elegant. I'v read around a bit and I think I understand how all this works. The ArrayList class I have doesnt have an add method, so I just had to import

This post has been edited by Dylsauce: 13 July 2013 - 11:37 AM

Was This Post Helpful? 0
  • +
  • -

#8 Dylsauce   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 98
  • Joined: 30-June 13

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 01:08 PM

View PostCasiOo, on 13 July 2013 - 09:44 AM, said:

The easy way?
Shuffle the array :)/>
		final int highestRank = 10;
		ArrayList<Object> cards = new ArrayList<>(highestRank);
		
		for (int i=0; i<highestRank; i++) {
			cards.add(i);
		}
		
		Collections.shuffle(cards);
		
		//Print out the scrambled cards
		System.out.println(cards);
		
		Queue<Object> deck = new LinkedList<>(cards);


Need two of the same card? Then just add it twice to the array. That will make no difference at all when shuffling


Hmm, I cannot at all seem to figure out how to add two of every card to a different spot on the array..
Was This Post Helpful? 0
  • +
  • -

#9 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1576
  • View blog
  • Posts: 3,548
  • Joined: 05-April 11

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 01:41 PM

What have you tried, and how is it not working? show us :)
Was This Post Helpful? 1
  • +
  • -

#10 Dylsauce   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 98
  • Joined: 30-June 13

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 01:50 PM

I think I just figured it out actually! I can't run it yet but here is what I did:

import java.util.*;
import java.util.ArrayList;

public class SimpleUnoGame {

	// Attributes

	private int highestRank;
	private int numberOfPlayers;
	private List<UnoPlayer> playerCollection;
	private List<UnoCard> faceUpCards;
	private List<UnoCard> faceDownCards;
	private static final int NUM_COLORS = 4;
	private static final int NUM_CC = 2;

	// Constructor
	public SimpleUnoGame(int numberOfPlayers, int highestRank) {


		//-----------------------------------------------------------------
		//  Creates a list of cards, 2 of every color-rank combination
		//  then it shuffles them and makes them the faceDownCards
		//-----------------------------------------------------------------
		List<UnoCard> deck = new ArrayList<UnoCard>(NUM_COLORS*NUM_CC*highestRank);
		char[] colors = new char[] { 'R', 'G', 'B', 'Y' };
		int secondHalf = NUM_COLORS*NUM_CC*highestRank/2;

		for (int p = 0; p < colors.length; p++) {

			for (int i = 0; i < highestRank; i++){

				deck.add(i, new UnoCard(colors[p], i+1));
				deck.add(i+secondHalf, new UnoCard(colors[p], i+1));
			}
		}

		Collections.shuffle(deck);
		this.faceDownCards = deck;


If you have any suggestions to clean it up I'd love to hear them - this code doesn't exactly scream "graceful" to me yet.

I think I just figured it out actually! I can't run it yet but here is what I did:

import java.util.*;
import java.util.ArrayList;

public class SimpleUnoGame {

	// Attributes

	private int highestRank;
	private int numberOfPlayers;
	private List<UnoPlayer> playerCollection;
	private List<UnoCard> faceUpCards;
	private List<UnoCard> faceDownCards;
	private static final int NUM_COLORS = 4;
	private static final int NUM_CC = 2;

	// Constructor
	public SimpleUnoGame(int numberOfPlayers, int highestRank) {


		//-----------------------------------------------------------------
		//  Creates a list of cards, 2 of every color-rank combination
		//  then it shuffles them and makes them the faceDownCards
		//-----------------------------------------------------------------
		List<UnoCard> deck = new ArrayList<UnoCard>(NUM_COLORS*NUM_CC*highestRank);
		char[] colors = new char[] { 'R', 'G', 'B', 'Y' };
		int secondHalf = NUM_COLORS*NUM_CC*highestRank/2;

		for (int p = 0; p < colors.length; p++) {

			for (int i = 0; i < highestRank; i++){

				deck.add(i, new UnoCard(colors[p], i+1));
				deck.add(i+secondHalf, new UnoCard(colors[p], i+1));
			}
		}

		Collections.shuffle(deck);
		this.faceDownCards = deck;


If you have any suggestions to clean it up I'd love to hear them - this code doesn't exactly scream "graceful" to me yet.
Was This Post Helpful? 0
  • +
  • -

#11 ConciselyVerbose   User is offline

  • D.I.C Regular

Reputation: 91
  • View blog
  • Posts: 315
  • Joined: 05-July 13

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 02:07 PM

Why doesn't it run?
Was This Post Helpful? 0
  • +
  • -

#12 Dylsauce   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 98
  • Joined: 30-June 13

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 02:12 PM

It doesn't have a main
Was This Post Helpful? 0
  • +
  • -

#13 Dylsauce   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 98
  • Joined: 30-June 13

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 02:12 PM

It doesn't have a main
Was This Post Helpful? 0
  • +
  • -

#14 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1576
  • View blog
  • Posts: 3,548
  • Joined: 05-April 11

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 02:23 PM

Why exactly do you need to have two of the same card? Is it a rule in the game?
Adding the second card to i+secondHalf makes no sense, why would you do that? You are shuffling the arraylist anyway, so it makes no difference
List<UnoCard> deck = new ArrayList<UnoCard>(NUM_COLORS*NUM_CC*highestRank);
char[] colors = new char[] { 'R', 'G', 'B', 'Y' };

for (char color : colors) {
	for (int i = 1; i <= highestRank; i++){
		deck.add(new UnoCard(color, i));
		deck.add(new UnoCard(color, i));
	}
}

Collections.shuffle(deck);



Don't have two references, there should be no face down and face up in your logic
Just simply remove from the head of the list and add it back at the end. That way it will turn itself when one stack is empty :)
Was This Post Helpful? 0
  • +
  • -

#15 Dylsauce   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 98
  • Joined: 30-June 13

Re: How can you populate a deck of cards with out knowing how many?

Posted 13 July 2013 - 02:37 PM

wow that is much cleverer. Yeah, it is a requirement of the game that there be 2 of every type. I had the second copy added halfway so the indices wouldn't overlap but it is much better to just not use indices - I didn't know I could! Thank you

wow that is much cleverer. Yeah, it is a requirement of the game that there be 2 of every type. I had the second copy added halfway so the indices wouldn't overlap but it is much better to just not use indices - I didn't know I could! Thank you
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2