I am working on a poker program. I am having some issues figuring out how to shuffle. I have to use arrays. I can't use enums or Lists. i know there are much better ways to make this program but the point is to understand arrays.
I am having some issues figuring out how to shuffle my deck of cards. I'm trying to keep this as simple as possible so I have one class to get the cards of the deck and shuffle them.
import java.util.Arrays;
import java.util.Random;
public class Card
{
String[] suits = { "Spades", "Clubs", "Hearts", "Diamonds" };
String[] values = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"};
public Card()
{
}
public void getCards()
{
for(int indexSuit = 0; indexSuit < suits.length; indexSuit++)
{
String suit = suits[indexSuit];
System.out.print(suit + " ");
for(int indexType = 0; indexType < values.length; indexType++)
{
String type = values[indexType];
System.out.print(type + " ");
}
}
}
public void shuffle(String[] suit, String[] value)
{
Random rndSuits = new Random();
Random rndType = new Random();
for(int indexSuit = suits.length - 1; indexSuit > 0; indexSuit--)
{
int index = rndSuits.nextInt(indexSuit + 1);
String temp = suits[indexSuit];
suits[indexSuit] = suit[index];
suit[index] = temp;
System.out.print(temp);
for(int indexType = values.length -1; indexType > 0; indexType--)
{
int index2 = rndType.nextInt(indexType + 1);
String temp2 = values[indexType];
values[indexType] = value[index2];
value[index2] = temp2;
System.out.print(temp2);
}
}
}
public void deal()
{
}
}
Here is my main:
public class FiveCardPoker
{
public static void main(String[] args){
Card timsCards = new Card();
timsCards.getCards();
timsCards.shuffle(args, args);
}
}
I was trying to write the shuffle method based on another question I found on here, but it was only for a single array. I'm not sure if logic is correct for the shuffle method. I'm also not exactly sure how to call it in my main method.
How Do I get my arrays from the Card class to the Main class when I call timsCards.shuffle?
EDIT: So I have tried editing it like this, but it doesn't seem to be doing anything.
public void shuffle()
{
Collections.shuffle(Arrays.asList(suits));
Collections.shuffle(Arrays.asList(values));
System.out.println(Arrays.toString(values) + " of " + Arrays.toString(suits));
}
Ideal way that I can think of is, You can create some Collection out of these arrays and use
Collections.shuffle() method.
Code -
String[] suits = {"Spades", "Clubs", "Hearts", "Diamonds"};
List<String> list = Arrays.asList(suits);
Collections.shuffle(list);
System.out.println(list); //Prints shuffled list
Javadoc
As for your last question, regarding how to get the array from inside the shuffle function into the main function, you should have your shuffle function return an array, and call it like this:
shuffledCards[] = timsCards.Shuffle(...);
I realize that other people have provided other solutions, but you mentioned the purpose is to understand arrays so I figured I'd mention that this will accomplish the same thing.
Also, although I admittedly haven't tested it, it seems as if your shuffle array will shuffle each suit within itself, but not the deck as a whole. You may want to think about a more creative solution to that (If you aren't going to use Collections.shuffle())
If you want to write a shuffle method yourself you could do it like this.
static Random rnd = new Random();
static void shuffle(Object[] array) {
for(int index1 = array.length - 1; index1 > 0; index1--) {
int index2 = rnd.nextInt(index1 + 1);
Object temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
}
public static void main(String[] args) {
String[] suits = { "Spades", "Clubs", "Hearts", "Diamonds" };
String[] values = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"};
shuffle(suits);
shuffle(values);
}
That way you are able to shuffle arrays of any arbitrary objects, not just strings. You may want to fill an array with objects representing cards and then shuffle that.
There are several thing to improve in your example.
Firstly, suits ("Spades", "Clubs", "Hearts", "Diamonds") and values should be manipulated with an Enum type and not a String. It will be easier to read and debug. You can implement an array of enum if you want.
Only ONE Random object is good enough. And you should use a seed if you hope an unpredictable shuffle...
How you shuffle each array is correct, but NOT the global one. Here you suffle suits, and inside a suit you shuffle the values, but all diamonds stay together...
If you want to shuffle a deck of cards (as I imagine) then you should implement only ONE collection/array: an array of Cards and each Card is a uniq couple suit,value.
For your last question, I recommand to implement 'shuffle' as a factory (so it should be static) that returns a shuffle deck of cards. If you prefer an object method (NO STATIC) then you should implement a Deck class, then shuffle will mean shuffle THIS deck.
Related
I am trying to create a constructor that creates an array and fills that array with custom objects. This array would represent a deck of cards.
public class DeckOfCards {
public static Card[] deck = new Card[52];
//constructor
DeckOfCards(){
Card[] deck = new Card[52];
deck[0]=new Card("Ace","Clubs"); deck[1]=new Card("Two","Clubs");
deck[2]=new Card("Three","Clubs");..(ect)...deck[49]=new
Card("Jack","Diamonds");
deck[50]=new Card("Queen","Diamonds"); deck[51]=new Card("King","Diamonds");
}
I feel like this constructor should create an array and fill it with card objects but it doesn't recognize any objects instantiated from DeckOfCards() as arrays.
You are declaring the deck again inside your constructor. I would initialize the deck this way. Iterating through two arrays, simplest one.
DeckOfCards(){
suit = ['Hearts','Diamonds','Clubs','Spades'];
number=['Ace','One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King'];
for (int i=0;i<4;i++){
for (int j=0;j<13;j++){
deck[i+j]=new Card(number[j],suit[i]);
}
}
}
You have an scope problem since you are declaring again
Card[] deck = new Card[52];
inside the constructor, leaving without effect the global member, do instead use the deck object.... (by the way, no need for static objects...)
DeckOfCards(){
deck[0]=new Card("Ace","Clubs"); deck[1]=new Card("Two","Clubs");
deck[2]=new Card("Three","Clubs");..(ect.).deck[49]=new
Card("Jack","Diamonds");
deck[50]=new Card("Queen","Diamonds"); deck[51]=new Card("King","Diamonds");
}
First, you don't need to initialise deck again in the constructor. Just use the class-level variable you defined.
Second, deck should not be static, so remove that word.
Third, make the constructor public.
And last but not least, you should probably initialise the deck in a smarter way.
public class DeckOfCards {
public Card[] deck = new Card[52];
//constructor
public DeckOfCards(){
String[] numbers = { "Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };
String[] suits = { "Spades", "Clubs", "Diamonds", "Hearts" };
int i = 0;
for (String suit: suits) {
for (String number: numbers) {
deck[i] = new Card(number, suit);
i++;
}
}
}
}
Delete that line and it will be fine :
Card[] deck = new Card[52];
I'm working on a poker project that just deals the 5 top cards from a shuffled deck and lets the user to reject all, some, or none. I understand that there should be ideally 2-3 classes, one with the actual main and the other two being the card and deck. I have created the Deck class and a very basic Tester program that is just supposed to print the shuffled cards. However, when I print the deck, I get something along the lines of "Deck####d##a". What am I doing wrong?
import java.util.Random;
public class Deck {
// Constructing a deck from two arrays
String[] suit = { "Clubs", "Diamonds", "Hearts", "Spades" };
String[] rank = { "Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King" };
String[] deck = new String[suit.length * rank.length];
// Storing public variables
int suits = suit.length;
int ranks = rank.length;
int deckSize = deck.length;
public Deck()
{
for(int i = 0; i < suits; i++)
{
for(int j = 0; j < ranks; j++)
{
deck[ranks*i + j] = rank[j] + " of " + suit[i];
}
}
}
// Fisher-Yates Shuffle
public void shuffle()
{
Random rand = new Random();
for (int i = 0; i < deckSize; i++)
{
int x = rand.nextInt(deckSize);
String temp = deck[x];
deck[x] = deck[i];
deck[i] = temp;
}
}
}
And the tester class:
import java.util.Scanner;
public class DeckTester {
public static void main(String[] args) {
Deck deck = new Deck();
System.out.println(deck);
}
}
Output: Deck####d###a
You're seeing the default `toString() method from the Object class, and you're finding that it's not too helpful. You're also not creating a Card or a true Deck class and so you can't give any class a decent toString() method.
Solutions:
Create a Card class.
Give it a rank and a value field.
Give it a toString() method.
Create a Deck class
Give it a collection of Cards.
Give it a decent toString() method.
e.g.,
// for Deck
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Card card: cards) {
sb.append(card.toString() + ", ");
}
return sb.toString();
}
Printing an object calls its toString() method. If your class or any of its ancestors do not override toString(), it calls the default, which is the toString() method of Object.
But the default toString() is not very clever - it just gives you the name and hash code of the deck.
So it is very recommended, for any class that you're going to print (and even for those you don't, but you may want to debug) to override the toString() method. In the overridden method, you should construct a string that represents the contents of your class. It could be as simple as calling Arrays.toString() in your case.
Also, note that you have defined a shuffle() method, but you are not actually calling it from anywhere, so once you do succeed in printing your deck, it will not be shuffled.
So the project is to make a deck of cards, create methods to shuffle and deal the cards and compare.
Not even going that far, I'm having an issue displaying the contents of the Stack.
I'm getting the output randomdeck.Card#10ed7f5c but with different addresses for every card.
I did a size check and there are 52 objects in the stack, meaning I filled it and it actually exists.
Looking at my Card constructor I know I'm not actually filling it with the cSuit/cRank String array. My original code had it so I would fill it with the integers then have a method to read those integers and put those integers into a the String arrays displaying the String.
But I had to partially scrap that because it was just an array, not a Stack.
If there was a way to directly pass the String array into the Card so what it's pushed into the Deck I could pop it off and instantly see the contents that would be great. But I fear that's not possible and I'm failing to grasp something fundamental about Stacks/Queues.
I wish I kept my old code completely intact to show what I was previously doing, but I don't think it matters at this point.
Here is my current code.
package randomdeck;
//import java.util.Arrays;
import java.util.Stack;
public class Card
{
int Suit;
int Rank;
public Card(int Rank, int Suit)
{
this.Suit=Suit;
this.Rank=Rank;
}
public String[] cSuit = new String[4];
{
cSuit[0]="Hearts";
cSuit[1]="Spades";
cSuit[2]="Diamonds";
cSuit[3]="Clubs";
}
public String[] cRank = new String[13];
{
cRank[0]="Ace";
cRank[1]="2";
cRank[2]="3";
cRank[3]="4";
cRank[4]="5";
cRank[5]="6";
cRank[6]="7";
cRank[7]="8";
cRank[8]="9";
cRank[9]="10";
cRank[10]="Jack";
cRank[11]="Queen";
cRank[12]="King";
}
void displayCard()
{
//System.out.println(cRank + " Of " + cSuit);
System.out.println(cRank[Rank] + " of " + cSuit[Suit]);
}
}
Here is the Deck class
package randomdeck;
//import java.util.Arrays;
import java.util.Stack;
public class Deck
{
int cardNum=0;
//static int DeckSize=52;
Stack<Card> Deck = new Stack<Card>();
public Deck()
{
for(int rank=0; rank<13; rank++)
{
for(int suit=0; suit<4; suit++)
{
Deck.push(new Card(rank,suit));
System.out.println(Deck.peek());
//System.out.println(Deck.size());
//Deck[cardNum] = new Card(rank,suit);
//cardNum++;
}
}
}
public void Peek()
{
System.out.println(Deck.peek());
}
public void Size()
{
System.out.println(Deck.size());
}
}
Here is the last class
package randomdeck;
//import java.util.Arrays;
import java.util.Stack;
public class RandomDeck {
public static void main(String[] args)
{
Deck testDeck= new Deck();
testDeck.Size();
}
}
I think you want to add a toString() method to your Card class like so,
public String toString() {
return cRank[Rank] + " of " + cSuit[Suit];
}
Also, I think you should rename Rank and Suit to rank and suit respectively.
Finally, a more idiomatic String array initialization would be
public String[] cSuit = new String[] { "Hearts",
"Spades", "Diamonds", "Clubs" };
public String[] cRank = new String[] { "Ace", "2",
"3", "4", "5", "6", "7", "8", "9", "10", "Jack",
"Queen", "King" };
This program is supposed to use ArrayList to create a deck of cards. The user enters how many cards to draw and those cards are printed, then the rest of the cards that are remaining in the deck are printed. I got the user's cards to print but I cant figure out how to get the remaining cards in the deck to print. Any help would be appreciated.
public class Card
{
private int type, value;
private String[] cardType = {"Clubs", "Spades", "Diamonds", "Hearts"};
private String[] cardValue = {"Ace", "King", "Queen", "Jack", "10",
"9", "8", "7", "6", "5", "4", "3", "2"};
public Card(int types, int values)
{
type = types;
value = values;
}
public String toString()
{
String finalCard = cardValue[value] + " of " + cardType[type];
return finalCard;
}
}
import java.util.Random;
import java.util.ArrayList;
public class Deck
{
private ArrayList<Card> cards;
public Deck()
{
cards = new ArrayList<Card>();
for(int a =0; a<=3; a++)
{
for(int b =0; b<=12;b++)
{
cards.add(new Card(a,b));
}
}
}
public Card drawRandomCard()
{
Random generator = new Random();
int index = generator.nextInt(cards.size());
return cards.remove(index);
}
public String toString()
{
String result = "Cards remaining in deck: " + cards;
return result;
}
}
import java.util.Scanner;
public class CardProgram
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
Card C;
Deck deck = new Deck();
System.out.println("Enter number of cards to be dealt: ");
int numberCards = scan.nextInt();
System.out.println("Cards drawn: ");
for(int i=0; i<numberCards; i++)
{
C = deck.drawRandomCard();
System.out.println(C.toString());
}
//C = deck.toString();
//System.out.println(cards.toString());
// System.out.println(C.toString());
}
}
I think this should do your work
System.out.println(deck.toString());
//System.out.println(deck); // Note : this will also work
Though I think creating a new method remainingCard and returning the cards ArrayList makes sense rather than Overriding toString with remaining cards.
for(int i=0; i<deck.cards.size(); i++)
{
System.out.println(deck.cards.get(i).toString());
}
Try this for loop right after you have a for loop printing out the cards you have drawn
You have a deck in the main method...a deck has cards...you draw some cards out of your deck....then you say deck.cards which gives you the decks array list of cards...then you say .get(i) to get each card in that deck...and finally .toString() to print out the content of the card
Note: you would have to make the private array list of cards in your deck class public or add a public getter method in the deck class to get the arraylist of cards...
This question already has answers here:
Random shuffling of an array
(31 answers)
Closed 5 years ago.
I am having a tough time trying to create a "shuffleDeck()" method.
What I am trying to do is create a method that will take an array parameter (which will be the deck of cards) shuffle the cards, and return the shuffled array list.
This is the code:
class Card
{
int value;
String suit;
String name;
public String toString()
{
return (name + " of " + suit);
}
}
public class PickACard
{
public static void main( String[] args)
{
Card[] deck = buildDeck();
// display Deck(deck);
int chosen = (int)(Math.random()* deck.length);
Card picked = deck[chosen];
System.out.println("You picked a " + picked + " out of the deck.");
System.out.println("In Blackjack your card is worth " + picked.value + " points.");
}
public static Card[] buildDeck()
{
String[] suits = {"clubs", "diamonds", "hearts", "spades" };
String[] names = {"ZERO", "ONE", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "Jack", "Queen", "King", "Ace" };
int i = 0;
Card[] deck = new Card[52];
for ( String s: suits )
{
for ( int v = 2; v<=14; v++)
{
Card c = new Card();
c.suit = s;
c.name = names[v];
if ( v == 14)
c.value = 11;
else if ( v>10)
c.value = 10;
else
c.value = v;
deck[i] = c;
i++;
}
}
return deck;
}
public static String[] shuffleDeck( Card[] deck)
{
/** I have attempted to get two index numbers, and swap them.
I tried to figure out how to loop this so it kind of simulates "shuffling".
*/
}
public static void displayDeck( Card[] deck)
{
for ( Card c: deck)
{
System.out.println(c.value + "\t" + c);
}
}
}
How about:
List<Card> list = Arrays.asList(deck);
Collections.shuffle(list);
Or one-liner:
Collections.shuffle(Arrays.asList(deck));
One way is to convert the array to a list, and use java.util.Collections.shuffle(array) to shuffle it:
Card[] deck = ...;
List<Card> list = Arrays.asList(deck);
Collections.shuffle(list);
If you do still need an array instead of a List, you can add:
list.toArray(deck);
Here is a TIO (Try-it-online) link to see the array to list conversion and shuffling in action.
Code of the TIO copied below as reference:
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
class M{
public static void main(String[] a){
// Original array
Integer[] array = new Integer[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
System.out.println("before: " + Arrays.toString(array));
// Convert array to list
List<Integer> list = Arrays.asList(array);
// And shuffle that list
Collections.shuffle(list);
System.out.println("after as list: " + list);
// (Optional) then convert the list back to an array,
// and save it in its initial variable (`array` in this case)
list.toArray(array);
System.out.println("after as array: " + Arrays.toString(array));
}
}
I see two ways to do it:
-> You can use a shuffle algorithm like the Fisher-Yates shuffle algorithm if you want to implement yourself the method.
-> You can use the shuffle method from Collections
If this is for a school project (as I think it is), you might not be allowed to use built-in functions such as Collections::shuffle(). If this is the case, then you must try to simulate randomness (which in programming can be surprisingly hard).
The most common way to create a sense of randomness is to use an RNG (random number generator).
As you said
I have attempted to get two index numbers, and swap them.
Correct. One way to shuffle is to pick one card at a time and randomly select another card to swap the position with.
You know the deck always has 52 cards.
You have a random generator
to select a random index.
You have a programming language with
loop-structures.
With these tools you can implement your own shuffle-function quite easily.