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.
Related
I'm pretty new to Java but I'm trying to fix this stack overflow error. Essentially, I'm trying to create a deck of cards using a constructor call in main: Deck newDeck = new Deck();
Then, creating the Cards array of 52 elements (cards) in the base class "Deck", and populating the array at each index with two int values, representing the rank and suit of each card.
I believe the stack overflow error is occurring due to a recursive constructor call between the base class and extended class, though I might be wrong. Can anyone provide a suggestion on how to fix this error, or populate the Cards array in a different way? The base class and extended class format is necessary for my project. Thanks.
Error:
Exception in thread "main" java.lang.StackOverflowError
at java.base/java.util.Random.<init>(Random.java:105)
at Deck.<init>(Deck.java:12)
at Cards.<init>(Cards.java:19)
at Deck.<init>(Deck.java:27)
at Cards.<init>(Cards.java:19)
at Deck.<init>(Deck.java:27)
at Cards.<init>(Cards.java:19)
at Deck.<init>(Deck.java:27)
at Cards.<init>(Cards.java:19)
at Deck.<init>(Deck.java:27)
at Cards.<init>(Cards.java:19)
Main:
import java.util.Random;
import java.util.Scanner;
public class PokerProgram {
public static void main(String[] args) {
// CREATING SCANNER OBJECT
Scanner scnr = new Scanner(System.in);
Random random = new Random();
// INITIALIZING VARIABLES
String play = "y";
double blind = 10;
double playerBalance = 1000;
double playerBet;
double pot;
int playerScore = 0;
int compScore = 0;
String[] Hands = {"Equal hand", "One Pair", "Two Pair", "Three of a Kind", "Straight", "Flush", "Full House", "Four of a Kind", "Straight Flush", "Royal Flush"};
Deck newDeck = new Deck();
Base class:
import java.util.Random;
public class Deck{
// Creating Random object
Random random = new Random();
// FIELD VARIABLES
public static int handScore;
public static int cardValue;
private static final Cards[] newDeck = new Cards[52];
// CONSTRUCTORS
// For Deck
public Deck () {
int i = 0;
for (int j = 0; j < 13; j++) {
for (int k = 0; k < 4; k++) {
newDeck[i] = new Cards(j, k);
i++;
}
}
}
Extended Class :
public class Cards extends Deck{
// Field Variables
private int rank;
private int suit;
// Rank and Suit Arrays
private static String [] ranks = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"};
private static String [] suits = {"Hearts", "Diamonds", "Clubs", "Spades"};
// CONSTRUCTOR
public Cards (int rank, int suit) {
this.rank = rank;
this.suit = suit;
}
Cards extend Deck. Upon creating a Deck you invoke the Cards constructor which happen to be a Deck which invokes the Cards constructor...
This question already has answers here:
"Non-static method cannot be referenced from a static context" error
(4 answers)
Closed 3 years ago.
I would like my dealer class in a BlackJack project to print the top two "cards" of an arrayList "theDeck". I am getting a compiler error (shown later) and can't figure out what it means. This is my code for a class "Deck" that makes a deck of cards, shuffles them, and puts them in an arrayList "theDeck":
* Compilation: javac Deck.java
* Execution: java Deck
* Author: Aidan Hill
* Status: Working
* Priority: None
*
******************************************************************************/
import java.util.ArrayList;
/******************************************************************************/
public class Deck extends Game {
int n;
//Deck deck = new Deck();
String[] deckArray = new String[n];
String[] SUITS = {
"Diamonds", "Clubs", "Spades", "Hearts"
};
String[] RANKS = {
"2", "3", "4", "5", "6", "7", "8", "9", "10",
"Jack", "Queen", "King", "Ace"
};
public Deck() {
// constructor
n = SUITS.length * RANKS.length;
deckArray = new String[n];
for (int i = 0; i < RANKS.length; i++) {
for (int j = 0; j < SUITS.length; j++) {
deckArray[SUITS.length*i + j] = RANKS[i] + " of " + SUITS[j];
}
}
}
public String shuffleDeck() {
// shuffle the deck
int i;
for (i = 0; i < n; i++) {
int r = i + (int) ((n - i) * Math.random());
String temporary = deckArray[r];
deckArray[r] = deckArray[i];
deckArray[i] = temporary;
}
return deckArray[i - 1];
}
public ArrayList<String> theDeck() {
// save shuffled deck in an arraylist
ArrayList<String> theDeck = new ArrayList<String>();
for (int i = 0; i < n; i++) {
theDeck.add(deckArray[i]);
}
return theDeck;
}
}
This is my code for another class "Dealer" that will take the top two elements of arrayList "theDeck" and print them to the console:
/******************************************************************************
* Compilation: javac Dealer.java
* Execution: java Dealer
* Author: Aidan Hill
* Status: Under Construction
* Priority: !
*
******************************************************************************/
import java.util.ArrayList;
import java.util.ArrayList;
/******************************************************************************/
public class Dealer extends Game {
public ArrayList<String> dealSumCards() {
ArrayList<String> hand = new ArrayList<String>();
hand.add(Deck.theDeck().toString());
System.out.println("The first hand is: " + hand);
return hand;
}
}
When I attempt to compile, I get this error message:
----jGRASP exec: javac -encoding UTF-8 -g #BlackJack_source_files_1638219710914506414jgr
Dealer.java:20: error: non-static method theDeck() cannot be referenced from a static context
hand.add(Deck.theDeck().toString());
^
1 error
----jGRASP wedge2: exit code for process is 1.
----jGRASP: operation complete.
Whats my error? Neither method is static... Am I big stupid?
I tried changing dealer to extend game instead of deck and vise versa, same problem.
(If you need any more code, let me know, and I will edit the post.)
Edit: I realize now that there are many many related questions. Sorry lol. Please be patient with me, new to coding and this website.
Deck is the name of a class. theDeck() is not a class method; you have to call it on an instance of the class.
There are two ways you could get this to work. One way would be to instantiate a Deck object, and call theDeck() on it:
Deck deck = new Deck();
hand.add(deck.theDeck().toString());
Another would be to make theDeck() static:
public static ArrayList<String> theDeck() {
// save shuffled deck in an arraylist
ArrayList<String> theDeck = new ArrayList<String>();
for (int i = 0; i < n; i++) {
theDeck.add(deckArray[i]);
}
return theDeck;
}
This would make Deck.theDeck() work - except that n is a non-static field; you'd need to make it static or pass it in as a method parameter.
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.
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...