I have a lab for class (we are allowed to seek outside help) creating klondike solitaire. I am a total noob when it comes to programming (this is my first ever class in programming). We just learned about enums, and I have to build a deck using them (I've reviewed other questions about this, but I haven't found a solution that matches what I need yet). We have two enums (rank and suit):
public enum Rank {
ACE,
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
TEN,
JACK,
QUEEN,
KING;}
and
public enum Suit {
CLUBS,
SPADES,
HEARTS,
DIAMONDS;}
Now, I need to combine them into an array called Deck, which stands as such:
public Deck() {
cards = new Card[52];
}
To put the cards into the deck, I've been trying to use the ".values" but I can't get it right. There is a testing code with this lab and it says I'm not getting any of the points for this. What am I doing wrong?
public void fill() {
for (int i = 0; i<52;i++){
for (Suit s : Suit.values()) {
for (Rank r : Rank.values()) {
cards[i]= new Card(r,s);
}
}
}
}
Any help is much appreciated. Thanks!
You state,
Now, I need to combine them into an array called Deck, which stands as such:
No, you need to create a class Card that has one field of each of the enums. Only after doing that can you create a Deck of your Cards. So do that -- create a Card class, give it at least two fields, one for each enum, plus an appropriate constructor, plus getters, plus a decent toString() and then you're set.
Also, this is wrong:
public void fill() {
for (int i = 0; i<52;i++){ // get rid of this loop
for (Suit s : Suit.values()) {
for (Rank r : Rank.values()) {
cards[i]= new Card(r,s);
}
The code above will try to stuff 52 cards into each index spot. For instance, it will try to stuff all 52 cards into the cards[0] spot, same for the cards[1] item, and only the last Card will be added. You'll have an array of 52 King of Diamonds -- not what you want.
Instead, get rid of the outer loop, and instead increment the i inside your loop:
public void fill() {
int i = 0;
for (Suit s : Suit.values()) {
for (Rank r : Rank.values()) {
cards[i]= new Card(r,s);
i++; // increment i here
}
}
}
Related
I have two files PokerCards and Frame.
PokerCards is enumeration *my suits work fine*
enum Number {
Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King;
public static final Number[] numbers = Number.values();
public static Number getNumber(int n){
return Number.numbers[n];
}
}
private final Number number;
//constructor
public PokerCards(final Suit suit, final Number number){
this.suit = suit;
this.number = number;
}
public Number getNumber(){
return this.number;
}
Below is Frame which is to be my GUI. My error checking for suits work perfectly but my numbers...not so much. I am trying to use an enhanced for-loop to match the corresponding enumeration
//card1Num is the value of the card such as Ace, Three, King and is recorded via a TextField via the GUI.
card1Num = card1TextFieldNum.getText();
if (card1Suit.equalsIgnoreCase("Diamonds")){
for (PokerCards.Number n : PokerCards.Number.values()) { //GETS STUCK
if(n.name().equals(card1Num)) {
card1 = new PokerCards(PokerCards.Suit.Diamonds, PokerCards.Number.valueOf(card1Num));
System.out.println("Card 1 good to GO");
card1Good = true;
} else {
JFrame popUpError2 = new JFrame();
JOptionPane.showMessageDialog(popUpError2, "Incorrect Input, Number Input for First Card is incorrect! Please double check" +
" your input", "ERROR", JOptionPane.ERROR_MESSAGE);
break;
}
}
Everything works lovely except the enhanced for-loop. As i test other cards i get prompted by my error. It only accepts 'Ace', the first element. Why is my enhanced for-loop getting stuck?
The problem is that you should fail only if no cards match, not if only the first card doesn't, so you want to move the failing code to outside the loop like so:
for (PokerCards.Number n : PokerCards.Number.values()) {
if(n.name().equals(card1Num)) {
card1 = new PokerCards(PokerCards.Suit.Diamonds, PokerCards.Number.valueOf(card1Num));
System.out.println("Card 1 good to GO");
card1Good = true;
}
}
if (!card1Good)
{
JFrame popUpError2 = new JFrame();
JOptionPane.showMessageDialog(popUpError2, "Incorrect Input, Number Input for First Card is incorrect! Please double check" +
" your input", "ERROR", JOptionPane.ERROR_MESSAGE);
}
The for loop works fine, the if/else logic is the issue behind errors being thrown on cards other then 'Ace'.
As you mentioned yourself - if you use 'Ace' your code will work without error because 'Ace' is the first element in Number.values() and the check n.name().equals(card1Num) will be true, triggering the code in your if statement. All other cards will fail on this and throw an error because they will be first matched against 'Ace'. If I understand correctly what you want to do I think you should use findAny() instead of your for loop. The code would be something like this:
PokerCards.Number.values().stream().filter(number ->
number.name().equals(card1Num)).findAny().ifPresentOrElse(card ->
{your_if_logic_here},
{your_else_logic_here})
I am creating a simplistic poker game in Java that will create a deck of cards, let you draw a hand and display what kind of suit you have. Here is what I have so far and have run into a problem.
I have 3 different Array Lists, one for the card values, one for the card suits, and one to hold the actual card objects once the card suit and value is applied. I created a loop that is supposed to add a suit to each value (13 values) and add them into the newCards ArrayList (it is of type CARD, a different class I have that allows the objects to have both an integer and a string). After I try to print out newCards to see if it works properly. I get quite a few exception errors.
I'm not sure how to efficiently create a loop like this so any help is appreciated.
import java.util.*;
public class pokerMain {
public static void main (String [] args){
ArrayList<String> suits = new ArrayList<String>();//array list for the card suits
ArrayList<Integer> val = new ArrayList<Integer>();//array list for card values
ArrayList<CARDS> newCards = new ArrayList<CARDS>();//array list for cards with assigned val/suits
suits.add("Clubs");//These are the suits, added to the suits ArrayList
suits.add("Hearts");
suits.add("Diamonds");
suits.add("Spades");
System.out.println("suits contains: " + suits );//Testing for suit
for(int i = 1; i <= 13; i ++){//loop that adds all 13 values to to the val ArrayList
val.add(i);
}
System.out.println("val contains " + val);//Testing for val
This is the loop
for(int i = 0; i <= val.size(); i ++){//This loop will be used to add a suit to every card value
newCards.add(new CARDS(suits.get(0), val.get(i)));//assigns hearts
newCards.add(new CARDS(suits.get(1), val.get(i)));//assigns hearts
newCards.add(new CARDS(suits.get(2), val.get(i)));//assigns diamonds
newCards.add(new CARDS(suits.get(3), val.get(i)));//assigns spades
}
-------------------------------------------------------------------------
System.out.println(newCards.toString());//prints newCards arrayList
//newCards.add(card);// puts card object into array list newCards
To prevent code duplication you could try two loops and use for each
for(String s : suits) {
for(Integer i : val) {
newCards.add(new CARDS(s, i));
}
}
Firstly, as John Mercier said, for:each is the way to go here.
Secondly, and this isn't causing your problem, but CARDS is not exactly a conventional class name. Something like Card or Cards (or wrap the Card in a Deck class...).
Thirdly, and most importantly, the main() doesn't seem to be your problem, as far as I can tell. Check your CARDS class.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Hey im trying to make a card of deck
the deck should contain 52 cards,
ofc with spade,diamonds,heart,clubs
with ranks ,
this is my code so far i havent gotten any longer
Thanks for help in advance.
get the deck to shuffle cards ,Create a class that represents a deck containing 52 cards, When a new object
of this class is created, the deck is initialized with the cards that it will contain.
public class Card {
int[] deck = new int[52];
String[] suits = {"Spades", "Hearts", "Diamonds", "Clubs"};
String[] ranks = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
Card() {
for (int i = 0; i < deck.length; i++) {
deck[i] = i;
}
}
}
A Card is a not a Deck of Cards. A Card has attributes (i.e. member variables) like suit and rank (although for comparing it is usually useful to use integers - or enums - for the rank and then change how they are displayed).
A Deck of Cards is many cards; usually with restrictions established when the deck is created. In this case the suits[] and ranks[] can be used to build the many Cards in the deck (giving each Card a particular suit and rank when it is created). The easiest way to do this in Java is to use nested loops - once for each dimension.
The "color" of each card is derived from the suit and does not need to be stored as it can be determined given a suit. If enums are used this can be merely assigned as an attribute.
Going by the above logic, here is a sample set of classes:
class Card {
final public String suit;
final public String rank;
public Card(String suit, String rank) {
// Assign suit/rank from arguments
}
String getColor() {
// Return the color based on suit (effectively "for free" if
// using an enumeration)
}
}
class DeckOfCards {
String[] suits = {..};
String[] ranks = {..};
// Arrays are icky to deal with; favor Lists/Collections.
List<Card> cards = new ArrayList<Card>();
public DeckOfCards () {
// For each suit/rank pair, create a Card and add it
// to the cards collection.
// You'll want nested loops, as shown by another answer.
}
public List<Card> getCards () {
// Return cards, perhaps
}
// Other methods relating to the Deck of Cards
public void shuffle () {
}
}
While I would recommend looking into enums, the above should indicate the difference between the two distinct "things" - Cards and a Deck (or Collection) of Cards. The other answer contains code showing how to generate cards from the cross product of the two input arrays.
First of all, make suits[] and ranks[] into int arrays. Make deck an array of cards, and make deck and the constructor you are using in a different calss (Called deck) The change the constructor to Card(int suit, int name)Just do this:
for(int i = 0; i < 4; i++) for(int j = 0; j < 13; j++){
Cards[13*i + j] = new Card(i, j);
}
Create a Card Object which has a suit and value property.
Create a method to create a List of all 52 Cards.
For your deck, I suggest using a Deque, Often pronounced "Deck" and has likeness to a deck of cards.
Then to create shuffled deck
//Create a List of cards
List<Card> deckList = ... //A method to create your 52 cards
Collections.shuffle(deckList);
Deque<Card> deck = new ArrayDeque<Card>(deckList);
I am a complete beginner with Java and am having trouble understanding how to pass objects around between classes and methods. I have made some progress, however my app now fails when I try to create playing cards inside a for loop. It works fine if I remove the loop. Here is the first part of the class that contains the error:
public class Testing
{
public static void main(String[] args)
{
int Deal = 1;
for(int Hand = 0; Hand < Deal; ++Hand)
{
//instantiate and derive values for Player
Card card1 = new Card();
card1.setSuit(); //assign card 1's suit
card1.setValue(); //asign card 1's value
//instantiate and derive values for Computer
Card card2 = new Card();
card2.setSuit(); //assign card 2's suit
card2.setValue(); //assign card 2's suit
//compare the two cards and make sure they are different
cardCompare(card1,card2);
}
//output the two cards to the screen
output(card1,card2);
}
This is the error I get:
Testing.java:26: error: cannot find symbol
output(card1,card2);
^
symbol: variable card1
location: class Testing
Testing.java:26: error: cannot find symbol
output(card1,card2);
^
symbol: variable card2
location: class Testing
2 errors
Since the code works if I remove the for loop, I'm assuming that somehow the names card1 and card2 are not visible outside the loop? If I wanted to create ten or twenty cards, I'd want to do that in a loop, so I must be missing something about instantiating new objects and using them elsewhere in the program.
Thanks for your help.
**Update: thanks for the initial feedback. I see now that if I move my instantiate statements outside the for loop, I could theoretically assign new values for those objects over and over again using a loop, which is all I need to complete this particular task.
I'm still curious though, is it not possible to instantiate new objects inside a loop, but still use them outside the loop? It seems like this must be possible somehow.
public class Testing
{
public static void main(String[] args)
{
int Deal = 1;
//instantiate and derive values for Player
Card card1 = new Card();
//instantiate and derive values for Computer
Card card2 = new Card();
for(int Hand = 0; Hand < Deal; ++Hand)
{
card1.setSuit(); //assign card 1's suit
card1.setValue(); //asign card 1's value
card2.setSuit(); //assign card 2's suit
card2.setValue(); //assign card 2's value
//compare the two cards and make sure they are different
cardCompare(card1,card2);
}
//output the two cards to the screen
output(card1,card2);
}
The card1 and card variables are declared inside the for loop and is thus only visible inside of the loop. To use it outside of the loop, you must declare it before the loop. Please read up on Java scoping rules.
Both card1 and card2 are in scope of the for loop, not the rest of main(). Move your initialization to before the for.
Well, as it stands, its going to keep trying to overwrite card1 and card2 since you'll both declare and initialize them "deal" times. Additionally, and more importantly, they'll be out of scope. Instead, declare it beforehand and only initialize them inside the loop.
What you probably want here is:
public class Testing
{
public static void main(String[] args)
{
int Deal = 1;
ArrayList<Card> playerCards = new ArrayList<Card>();
ArrayList<Card> computerCards = new ArrayList<Card>();
//instantiate and derive values for Player
Card card1;
//instantiate and derive values for Computer
Card card2;
for(int Hand = 0; Hand < Deal; ++Hand)
{
card1 = new Card();
card1.setSuit(); //assign card 1's suit
card1.setValue(); //asign card 1's value
card2 = new Card();
card2.setSuit(); //assign card 2's suit
card2.setValue(); //assign card 2's value
//compare the two cards and make sure they are different
cardCompare(card1,card2);
playerCards.Add(card1);
computerCards.Add(card2);
}
//output the two cards to the screen
output(card1,card2);
}
Haven't tested it, but it should work.
You also need to rethink your use of your Output method, too. Since you're going to have ~20 cards per person, when do you think you need to show them to the user? Currently, you have it outside of the for loop, so it's only going to display the LAST value assigned to each one. If you want to show them each card they're getting, put the output call inside the for loop, and maybe use Thread.Sleep() to pause the program for a half second or so so that they can see each card they get. That, or write an overload of output that accepts an ArrayList of cards, and prints all of them at the same time. Once again, if you need help with that, ask me.
By the way, im not sure what cardcompare() is really doing behind the scenes, but you probably want to make it return a bool representing whether or not they were different. something like:
bool areCardsDistinct = cardcompare(card1,card2);
That way, you can use the result to decide whether or not to get random new cards again
I have this Java class:
class Card
{
private Suit suit;
private int rank;
}
(Suit is an enum)
There are four suits with ranks 1-9 each and four suits with a single possible rank 0. Each card exists in an unknown but constant among all cards number of copies. How would I sort a deck in a set order of suits, and by increasing rank in each suit?
You'll need to either
implement the Comparable interface on the card object: add a compareTo function that determines whether another card should be before or after this one in the sort order
implement a Comparator object that accepts two cards and indicates which order they should appear in
and then you can use Collections.sort on your list.
Have a look at implementing Comparable on the enum.
Make Rank an enum too and you can deal a sorted deck as such:
for (Suit suit : Suit.values())
for (Rank rank : Rank.values())
deck.add(new Card(rank, suit));
make it implement the Comparable interface. Theres only only one method you'll need to write. Then they can be compared to each other, and you have a number of existing sort options, such as static Arrays.sort if you have an array or Collections.sort if its any kind of Collection (List, Vector, etc)
Besides implementing on Card you might have to do the same for Suit depending on how its done.
Here would be an example of the Card Class. As the questions states the Suit would be of a specific class while the Rank would be an integer (in this example I didn't implement rank validation). Implementing the Comparable class allows a Card class to compare another Card Class. So that a List/Set of Cards can be sorted.
public class Card implements Comparable<Card>{
private SUIT cardSuit;
private int cardRank;
public enum SUIT {SPADE, CLUB, HEART, DIAMOND};
public Card(int cardRank, SUIT cardSuit) {
this.cardSuit = cardSuit;
this.cardRank = cardRank;
}
/**
* Generates a random card
*/
public Card(){
this((int) (Math.random() * 9) , SUIT.values()[(int) (Math.random() * SUIT.values().length)]);
}
public String getSuit() {
return cardSuit.toString();
}
public int getRank() {
return cardRank;
}
#Override
public int compareTo(Card2 o) {
if (this.cardRank == o.cardRank) {
return this.cardSuit.compareTo(o.cardSuit);
} else {
return o.cardRank - this.cardRank;
}
}
}
A fast way to accomplish this task is by Radix Sort. Set up an array of lists of card values, then walk through your deck, placing each card into the appropriate list as you encounter it. Then merge all the lists together into a partially sorted deck. Now do the same thing, only with an array of lists of suits. Merge all the lists together and you should have a sorted deck.
Although I don't see it posted now, I believe that the original poster was working with a representation of cards that is very similar to the one that I worked with. Specifically, I remember seeing cards in the original post similar to the following format:
[ 'As', 'Kd', '4c', '6h' . . ..], i.e., Ace of Spades, King of Diamonds, 4 of Clubs, and 6 of Hearts, etc.
In my case, I was working with a whole deck of cards represented as follows:
[AcQhJd8h9c9h6d3cTc3dQdKhJs6h3hThQc7d3sJc4h2h6c8d7c5c7s8cAd4dTd9sKs5h8s2c4c2d2s5sAhKd9dKcQs4s5dAs7hJhTs6s]
This deck is one of hundreds of thousands of decks found by Mathematician Jeremy Kun where a two player game of Texas Holdem always results in a win for Player #1 no matter where the deck is cut (but not shuffled). For more details, see, https://jeremykun.com/2012/04/09/optimal-stacking-hold-em/
I found that reading each card as text and trying to figure who won and who lost with what hole cards, burn cards, and community cards (flop, turn and river) was well nigh impossible. I wanted to see actual cards separated for each player's hole cards, the community cards, etc.
The format of the deck of cards is understandable, but it is not in the form of an actual array that would be recognized using JavaScript. So, I started by turning it into a string by replacing the square brackets with quote marks. From there, I could use string methods to take two characters at a time and translate them into visible cards. I could have done that any number of ways, but I chose to use Unicode card characters since they behave just like text and can be resized and be given different colors with CSS, just like text.
The format for displaying a Unicode card character within the inner html of an element, e.g., a span element, is to use the code pattern ǰ_ _ ; where the two blanks will be first a hex number for the suit and then a hex number for the rank of the card.
The possible hex numbers for the suits are 'a' = spades, 'b' = hearts, 'c' = diamonds, and 'd' = clubs.
The possible hex numbers for the rank of each card are:
'1' = ace, '2' = 2, . . . 'a' = 10, 'b' = Jack, 'c' = "Count" (not used in poker, as in Count Dracula never gets invited to poker games), 'd' = Queen, and 'e' = King.
When using the code pattern ǰ_ _; the length of the characters will be 9 characters when first coded, but after the card is displayed on an html page, the browser converts the code into two characters, which will change the length of your html element for each card. For example, a span element with no attributes and inner html code for a card would be 22 characters long, but after being displayed on an html page, the length would change to 7 less (i.e., 15).
My code for displaying the above deck as Unicode card characters is fairly short:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Display Deck</title>
<style type="text/css">
body {
font-size: 21pt;
}
span {
background-color: white;
}
.aspade {
color: black;
}
.bheart {
color: red;
}
.cdiams {
color: mediumvioletred;
}
.dclubs {
color: blue;
}
</style>
</head>
<body>
<p id="displayPoint"></p>
<script type="text/javascript">
let holdemWinDeck = 'AcQhJd8h9c9h6d3cTc3dQdKhJs6h3hThQc7d3sJc4h2h6c8d7c5c7s8cAd4dTd9sKs5h8s2c4c2d2s5sAhKd9dKcQs4s5dAs7hJhTs6s';
let displayDeck = [];
let rankTranslate = {'A':'1', '2':'2', '3':'3', '4':'4', '5':'5', '6':'6', '7':'7', '8':'8', '9':'9', 'T':'a', 'J':'b', 'Q':'d', 'K':'e'};
let suitTranslate = {'h':'b', 'c':'d', 'd':'c', 's':'a'};
for (let i = 0; i < holdemWinDeck.length; i += 2) {
let unicodeCardRank = rankTranslate[holdemWinDeck.slice(i, i + 1)];
let unicodeCardSuit = suitTranslate[holdemWinDeck.slice(i + 1, i + 2)];
let plainSuitNameTranslate = {'b':'bheart', 'd':'dclubs', 'c':'cdiams', 'a':'aspade'};
let className = plainSuitNameTranslate[unicodeCardSuit];
let card = (`<span onclick='cutCards(this.outerHTML);' class='${className}'>ǰ${unicodeCardSuit}${unicodeCardRank};</span>`);
displayDeck.push(card);
}
document.getElementById('displayPoint').innerHTML=displayDeck.join('');
</script>
</body>
</html>
When I first tried to use the string method, .slice(), to access the suit and rank number for each card, I hit a wall. The two characters are actually four characters each, which are known as the "surrogate pair" of Unicode codes that are used under the hood of the browser to display a card since the longer code first written has to be translated by the browser into two shorter codes to represent and display the card. Worse, when you query for the length of either surrogate pair of four characters, you will get back a length of one. You will not be allowed to use slice() among the four characters of either surrogate pair.
The first surrogate (called the "high surrogate") is always the same four characters for any Unicode card character, and the second surrogate (called the "low surrogate" has the same first two characters for any Unicode card character, but the last two characters are where the magic happens, they are the very same two characters for suit and rank as in the original code.
I knew that I would need to access those two codes so that I could ask questions about suit or rank in any given sequence of cards. For example, to determine whether a player's two hole cards and five community cards hold a Royal Flush, I would need to ask if there were five cards of the same suit and whether those cards were in a numerical sequence of one number apart with an ace at the top. (Ultimately, I did it differently, and plan to change it yet again, but I still need access to suit and rank information among the cards.)
I searched the Internet and found my solution in two methods that I had never really used or understood before:
for (let i = 0; i < arr7.length; i++) {
suit[i] = arr7[i].slice(57, 59).codePointAt(0).toString(16).slice(3, 4);
rank[i] = lowAcesAnd_C_Gap[arr7[i].slice(57, 59).codePointAt(0).toString(16).slice(4, 5)];
}
The variable arr7 is an array of a player's two hole cards concatenated with the community cards and then sorted (.sort() ), which puts the cards into suit order first and then into rank order within each suit. So, my new arrays of suit and rank will follow the same order as the original sorted arr7. I may then ask suit and rank questions in my JavaScript code, and, if satisfied, pull actual cards from the same positions in the original arr7.
I have found that I need to sort purely by rank but still have access to the card, so I have also created an array that puts the rank before the actual card so that I will still have access to the card after I sort purely by rank.