My card class where the method is defined.
package blackjackgamemodel;
public class Card {
protected Rank rank;
protected Suit suit;
public Card(Card.Rank rank, Card.Suit suit) {
this.rank = rank;
this.suit = suit;
}
public String toString() {
return "" + rank + " of " + suit;
}
public Card.Rank rank() {
return rank;
}
public Card.Suit suit() {
return suit;
}
public enum Rank {
ACE (1), TWO (2), THREE (3), FOUR (4), FIVE (5), SIX (6), SEVEN (7),
EIGHT (8), NINE (9), TEN (10), JACK (11), QUEEN (12), KING (13);
private int value;
Rank(int value) {
this.value = value;
}
public int value() {
return value;
}
}
public enum Suit {
SPADES, HEARTS, CLUBS, DIAMONDS
}
}
The game class where the error is
package blackjackgamemodel;
import blackjackgamemodel.Card;
import blackjackgamemodel.Deck;
public class Game {
protected Deck deck;
protected int sum;
protected int aces;
public Game() {
// Initialize deck, sum and aces.
deck = new Deck();
sum = 0;
aces = 0;
}
public Card draw() {
// Draw a card from the deck
Card drawn_card = deck.draw();
// Calculate the value to add to sum
int v = drawn_card.value();
if (v == 1) {
v = 11;
// If the card is an ace, increase the count of aces.
aces++;
}
else if (v > 10) {
v = 10;
}
// Now v is the Blackjack value of the card.
// If the sum is greater than 21 and there are aces,
// Then decrease the sum by 10 and the aces by 1.
if (aces > 0 && sum > 21) {
sum = sum - 10;
aces = aces - 1;
}
// Return the card that was drawn.
return drawn_card;
}
public int sum() {
// Getter for sum.
return sum;
}
}
ERROR
Description Resource Path Location Type
The method value() is undefined for the type Card Game.java /BlackJack/src/blackjackgamemodel line 25 Java Problem
It's the Card.Rank enum that has the value() method, not the Card class.
Try:
int v = drawn_card.rank().value()
Indeed Card has no value method: It has a rank method and Card.Rank has a value method.
value() isn't a method on Card it is on Card.Rank in your included code.
The message is correct, Card does not have a value() method. Did you mean to get the card's rank and then get that value? That's looks like the intent.
Does your Card have a value method? It looks like Card's rank has a value method.
Try:
int v = drawn_card.rank().value();
Related
I do not get how to put the Card class into the Deck. Would you please explain how I can fix this?
Here are the instructions:
You need to rewrite the constructor so that all 52 cards of a normal card deck are assigned to the cards array. Keep in mind that card information needs to be stored inside the Deck class and is not passed by parameter. Additionally, you need to re-define the toString method for the Deck class so that it can be used to display the attribute values in a convenient manner. Make sure to take advantage of the toString method that already exists in the Card class.
(You also need to add a shuffle method, which is called from the constructor. The shuffle method is a private helper method in the Deck class. For this version you need to shuffle the deck by swapping the cards. Generate two random numbers in the [0..51] number range that will represent the indexes of the cards array and swap the cards. Make 1000 swaps and then display the cards. Use Math.random to generate random numbers.) <-This is a part of the instructions, but I don't think it matters in this situation because I what I want to know is how to do put the Card class in to the Deck.(but i still put it in just in case)
public class Lab11bvst
{
public static void main(String[] args)
{
Deck deck = new Deck();
System.out.println(deck);
}
}
class Deck
{
private Card[] cards;
private int size;
private String[ ] suits = {"Clubs","Diamonds","Hearts","Spades"};
public Deck()
{
size = 52;
cards = new Card[size];
}
private shuffle(){
}
}
the Card class:
public class Card
{
private String suit;
private String rank;
private int value;
public Card(String s, String r, int v)
{
suit = s;
rank = r;
value = v;
}
public String getSuit() { return suit; }
public String getRank() { return rank; }
public int getValue() { return value; }
public void setSuit(String s) { suit = s; }
public void setRank(String r) { rank = r; }
public void setValue(int v) { value = v; }
public String toString()
{
return "[" + suit + ", " + rank + ", " + value + "]";
}
public boolean matches(Card otherCard)
{
return otherCard.getSuit().equals(this.suit)
&& otherCard.getRank().equals(this.rank)
&& otherCard.getValue() == this.value;
}
}
"rewrite the constructor so that all 52 cards of a normal card deck are assigned to the cards array"
Right now, the constructor is setting the size of the deck to 52 cards, and then it initializes an array to hold 52 elements. You'll need to populate the cards array by creating cards for all 52 cards normally found in a deck. The constructor of your Card class helps you do this.
For example, you could start by adding an Ace of Diamonds and adding it to the cards array:
Card aceD = new Card("Diamonds", "Ace", 1);
cards[0] = aceD;
and then add all 52 cards to your cards array.
//** The code below is broken up into 2 classes and 2 Enums respectively: Card, Deck, Suit and Rank.
I'm having confusion on intertwining a for loop and toString method as asked in the instructions:
Create a toString() method in the Deck class, using another for loop to print all the Cards in the array by calling the toString() method on each card. This method “asks” the Card to print its rank and suit by only calling toString() on the Card object. There should be no reference to Rank or Suit anywhere in this method. Let Card's toString() method do the work (Delegation).
public class Card {
public static void main(String[] args) {
Card myCard = new Card();
System.out.println(myCard.toString());
System.out.println(new Card(Rank.KING, Suit.CLUBS));
}
public Rank rank;
public Suit suit;
public Rank getRank() {
return rank;
}
private void setRank(Rank rank) {
this.rank = rank;
}
public Suit getSuit() {
return suit;
}
private void setSuit(Suit suit) {
this.suit = suit;
}
// Constructor assigning attributes to rank and suit
public Card(Rank rank, Suit suit) {
setRank(rank);
setSuit(suit);
}
public Card() {
this(Rank.ACE, Suit.SPADES);
}
#Override
public String toString() {
// TODO Auto-generated method stub
String result= rank.toString() + " of " + suit.toString();
return result; }
}
public enum Suit {
NONE, CLUBS, HEARTS, SPADES, DIAMONDS
}
public enum Rank {
JOKER, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN,
KING, ACE
}
public class Deck {
public void main(String[] args) {
int[] DeckArray = new int[54];
int count = 2;
System.out.println(count);
for (count = 0; count <= 54; count++)
{
System.out.println(DeckArray);
}
}
public Card cards[];
public void DeckOfCards() {
this.cards = new Card[52];
Card myCard = new Card();
for (int i = 0; i < 0; i++) {
Card card = new Card(Rank.ACE, Suit.CLUBS);
if (Rank.JOKER != null) {
System.out.println("JOKER");
} else {
System.out.println(myCard);
}
}
for (int i = 0; i < 52; i++) {
String Deck = Arrays.toString(DeckArray)
}
}
}
Let me answer this is Psudo-code so that I won't do your homework for you :)
class Deck {
...
public String toString() {
for every item in this.cards {
currentItem.toString() // prints
}
}
}
Best of luck! Once you get the hang of it programming can be really fun.
Since the original code shows some confusion over how to define the condition that ends the for-loop, you may prefer to use this idiom instead:
for ( Card c : cards ) {
// do your work here
}
You can use the Java 8 Streams API, too, although in this case it feels unnecessarily complex:for-
Arrays.asList(cards).stream().forEach(c -> System.out.println(c.toString()));
Granted, this is probably something rather simple I have looked over by mistake, but I have to be sure.
I am working on getting a classic PlayingCard class running with a PlayingCard Tester to test it as an assignment. Now, when the whole thing is done, I will have a Pack class as well for producing a pack of cards and shuffling it, along with an equals method in the PlayingCard class, but for now, I just want to get basic PlayingCard class to work with the tester.
This is the current set up for the PlayingCard Class, ignore the int statement for i, as that was for a random numbers generator with the aid of a for loop, but that has been or rather, should be rendered redundent with the PlayingCard constructor.
public class PlayingCard
{
public PlayingCard(int rank, int suit)
{
this.rank = rank;
this.suit = suit;
}
// Values for rank
public final int TWO = 2;
public final int THREE = 3;
public final int FOUR = 4;
public final int FIVE = 5;
public final int SIX = 6;
public final int SEVEN = 7;
public final int EIGHT = 8;
public final int NINE = 9;
public final int TEN = 10;
public final int JACK = 11;
public final int QUEEN = 12;
public final int KING = 13;
public final int ACE = 14;
// Values for suits
public final int CLUBS = 0;
public final int DIAMONDS = 1;
public final int HEARTS = -1;
public final int SPADES = -2;
// Set random Rank and Suit values
public int rank;
public int suit;
public int i;
public int getRank()
{
return rank;
}
public int getSuit()
{
return suit;
}
#Override
public String toString()
{
return getClass().getName() + "[rank " + rank + "suit " + suit + "]";
}
public void format()
{
System.out.format(rank + " of " + suit);
}
}
And this is the current tester, note I have used a set of values based of the values for rank and suit in the class.
public class PlayingCardTester
{
public static void main(String[] args)
{
PlayingCard test;
test = new PlayingCard(14, 1);
test.getRank();
test.getSuit();
test.toString();
test.format();
System.out.println("");
}
}
The values put into the constructor should be being used in the methods of the class. The output I want from the actual tester and class is something like this:
Ace of Diamonds
Instead, I get this:
0 of 0
What I am asking is, how can I use the values given in the constructor in the methods implemented in the tester and class so I can get the output I want? The values used a meant to be related to those specified in the class, but something tells me they are effectivly useless or not being used in the actual class. It's probably something rather simple I have missed but unable to find, or myself being incredably stupid about it, but I want to be sure in case something more complex is required.
Advice?
EDIT: Added the details to the constructor, now I have the output:
14 of 1
You actually have two separate problems. The first issue is, as noted in another answer, that you do not assign the variables passed to the constructor of your class to the corresponding instance variables.
The second issue you have is that you are setting int values to represent the Rank and Suit but do not provide corresponding String representation in your PlayingCard class.
You could do this for ranks by creating an array like:
String ranks [] = {"TWO","THREE"...};
and using ranks[rank -2] in format();
As suit integer representations have non sequential values you would need to use another data structure (such as a Map).
An easier way of doing all of this however is to creating two enums as below. You would then create a new card like:
PlayingCard card = new PlayingCard(Rank.ACE, Suit.SPADES);
Enum for Suit:
public enum Suit {
HEARTS(0), SPADES(-2), CLUBS(-1), DIAMONDS(1);
private int value;
private Suit(int value){
this.value = value;
}
public int getValue(){
return value;
}
}
Enum For Rank:
public enum RANK {
TWO(2), THREE(3), ACE(14);
private int value;
private Suit(int value){
this.value = value;
}
public int getValue(){
return value;
}
}
Playing Card:
public class PlayingCard
{
private Rank rank;
private Suit suit;
public PlayingCard(Rank rank, Suit suit)
{
this.rank = rank;
this.suit = suit;
}
public Rank getRank()
{
return rank;
}
public Suit getSuit()
{
return suit;
}
#Override
public String toString()
{
return getClass().getName() + "[rank " + rank + "suit " + suit + "]";
}
public void format()
{
System.out.format(rank + " of " + suit);
}
}
You need to set parameters from constructor to your instance.
public PlayingCard(int rank, int suit)
{
this.rank = rank;
this.suit = suit;
}
cause this constructor takes two parameters but dont do anything with them.
public PlayingCard(int rank, int suit)
{
}
and because int is naturally set to 0 thats why you get two 0.
I am creating a deck of poker cards (52 cards). I want to be able to print it out for example:
2 of Club, 3 of Club......
2 of Diamond, 3 of Diamond....
Queen of Diamond, King of Diamond
and so on for the 52 cards.
I am able to do this now but having problem when it comes to the face cards which are the Jack, Queen, King and Ace. Currently I am using numbers to represent them. so instead of printing Jack of Clubs, it shows as 11 of Clubs which is wrong. I tried to store the face cards in an enum and tried to loop them but can't really get around to do it.
Can I get some advice on how I could get my face cards in instead of representing them as numbers. I have attached my main method and the class below. Thanks for help.
//Card Class
import java.util.Objects;
public class Card {
public enum Suits{
CLUBS, DIAMONDS, HEARTS, SPADES;
}
public enum Faces{
JACK, QUEEN, KING, ACE;
}
private int rank;
private String suit;
public Card(int rank, String suit){
this.rank = rank;
this.suit = suit;
}
public int getRank(){
return rank;
}
public String getSuit(){
return suit;
}
public String format(){
return String.format("%d of %s, ", getRank(), getSuit());
}
}
//Main method
public class CardTester {
public static void main(String[] args) {
Card[] cards = new Card[52];
int i = 0;
for (Card.Suits suit : Card.Suits.values()) {
for (int y = 2; y < 15; y++) {
cards[i] = new Card(y, suit.name());
i++;
}
}
for(Card p : cards){
System.out.print(p.format() + " ");
}
}
}
Change your format() method to:
public String format(){
if (getRank() < 11) {
return String.format("%d of %s, ", getRank(), getSuit());
}
else {
Faces face = Faces.values()[getRank() - 11];
return String.format("%s of %s, ", face, getSuit());
}
}
Alternatively, here's a better implementation for Card:
import java.util.Objects;
public class Card {
public enum Suit {
CLUBS, DIAMONDS, HEARTS, SPADES;
}
public enum Rank {
TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN,
JACK, QUEEN, KING, ACE;
}
private final Suit suit;
private final Rank rank;
public Card(Suit suit, Rank rank) {
this.suit = suit;
this.rank = rank;
}
public Suit getSuit(){
return suit;
}
public Rank getRank(){
return rank;
}
#Override
public String toString() {
return rank + " of " + suit;
}
#Override
public int hashCode() {
int hash = 5;
hash = 97 * hash + Objects.hashCode(this.suit);
hash = 97 * hash + Objects.hashCode(this.rank);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Card other = (Card) obj;
if (this.suit != other.suit) {
return false;
}
if (this.rank != other.rank) {
return false;
}
return true;
}
}
You can use it like this:
import java.util.ArrayList;
import java.util.List;
public class CardTester {
public static void main(String[] args) {
List<Card> cardList = new ArrayList<>();
Card lastCard = new Card(Card.Suit.SPADES, Card.Rank.ACE);
for (Card.Suit suit : Card.Suit.values()) {
for (Card.Rank rank : Card.Rank.values()) {
Card card = new Card(suit, rank);
cardList.add(card);
if (!card.equals(lastCard)) {
System.out.print(card + ", ");
}
else {
System.out.print(card);
}
}
}
// use cardList
}
}
Your modelling of cards is flawed, and your problem highlights this. Rank is not numeric and should not be an 'int'. You might want to use an enum for the rank.
You might be tempted to give your rank an integer value, but this is probably not a good idea. The value is generally defined by the game you are playing, and not by the deck of cards. For example in poker a king is ranked higher than a jack, but in blackjack they are ranked the same.
May be source code shown below will help you:
public enum Faces
{
JACK( 1, "Jack" ), QUEEN( 2, "Queen" ), KING( 3, "King" ), ACE( 4, "Ace" );
public int GetNumber()
{
return m_number;
}
public String GetName()
{
return m_name;
}
private Faces( int number_, String name_ )
{
m_number = number_;
m_name = name_;
}
private int m_number;
private String m_name;
}
you may delete the enum Faces you already have and add the following method to class Card:
public String getFace(int rank){
String result = "";
switch (rank){
case 11: result = "Jack"; break;
case 12: result = "QUEEN"; break;
case 13: result = "KING"; break;
case 14: result = "ACE"; break;
default:{
result = Integer.toString(rank);
break;
}
}
return result;
}
and modify your format() method to look like this:
public String format(){
return String.format("%s of %s, ", getFace(getRank()), getSuit());
}
This will do the job ;-)
A card consists of RANK and SUIT. Common poker software convention is to represent cards as SUIT+RANK Strings, as in 3c for 3 of clubs and Kd for king of diamonds. (see pokerstove or most hand history producers and consumers)
You need to expand the concept of RANK beyond faces. I've been using the Steve Brecher poker eval library, and his RANK class looks like this:
A simple lookup of the string "23456789TJQKA" converts between the enum and the RANK. There is a similar SUIT enum and a pretty reasonable Comparable class that combines the two.
public static enum Rank {
TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE;
/**
* #return the character in {#link #RANK_CHARS} denoting this rank.
*/
public char toChar() {
return RANK_CHARS.charAt(this.ordinal());
}
/**
* #param c
* a character present in {#link #RANK_CHARS} (case
* insensitive)
* #return the Rank denoted by character.
* #throws IllegalArgumentException
* if c not in {#link #RANK_CHARS}
*/
public static Rank fromChar(char c) {
int i = RANK_CHARS.indexOf(Character.toUpperCase(c));
if (i >= 0)
return Rank.values()[i];
throw new IllegalArgumentException("'" + c + "'");
}
/**
* #return the pip value of this Rank, ranging from 2 for a
* <code>TWO</code> (deuce) to 14 for an <code>ACE</code>.
*/
public int pipValue() {
return this.ordinal() + 2;
}
public static final String RANK_CHARS = "23456789TJQKA";
}
You can find his old but still perfectly serviceable libraries here: http://www.brecware.com/Software/software.html or http://pokersource.sourceforge.net/
U can try this solution which uses enum. First of all you need to create two enums. One for suits and the other for cards.
The enum for suits is:
public enum suits
{
club, diamond,heart,spades
}
The enum for cards is:
public enum cards
{
two(2), three(3), four(4), five(5), six(6), seven(7), eight(8),nine(9),
ten(10), jack(11), queen(12), king(13),ace(14);
int number;
private cards(int number)
{
this.number=number;
}
public int getNumber()
{
return this.number;
}
}
THen in your main class you can loop through both the enums to get your result as follows:
public class Javaclass
{
public static void main(String[] args)
{
int count=2;
for(suits suit:suits.values())
{
for(cards card: cards.values())
{
if(count<=10)
System.out.println(card.getNumber()+" of "+suit);
else
System.out.println(card+" of "+suit);
count++;
}
count=2;
System.out.println("");
}
}
}
Hope this helps.
I am using the class card example from java website to try to build a game.
http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html
I am taking in the number of hands and the number of cards per hands as arguments
like: java -jar a02.jar 4 3
I have added values to the ranks and suits. I am printing the DECK then the HAND...
What i am trying to do is print the deck first
with their values times together.
for example: Ten of Hearts
Ten = 10
Hearts = 4
So, i print out Ten of Hearts(40)
When i print the deck, I am having a problem getting them to print on one line by the number of cards per hand. like:
eight of spades(8), ten of hearts(40), deuce of hearts(8)
What can i do to fix this?
My other issue is that is there a better way of retrieving the values of the cards than what i am doing? could i use some type of compare?
because when i print out the hand after the deck i am having a hard time getting the values and the hand right ( so i commented out the code )
I also commented the part of code in main() where i am retrieving the values.
how could i do this differently?
Keep in mind i want the values printed also with the Hand like i am doing with deck
I will shorted the output..
here is the output:
C:\Java\a02>java -jar a1.jar 3 4
THREE of SPADES(3), // i would like this to print out like hand does below
FIVE of HEARTS(20),
DEUCE of DIAMONDS(6),
KING of CLUBS(20),
DEUCE of HEARTS(8),
TEN of HEARTS(40),
JACK of HEARTS(40),
ACE of HEARTS(44),
NINE of CLUBS(18),
EIGHT of SPADES(8),
QUEEN of SPADES(10),
KING of HEARTS(40),
NINE of SPADES(9),
SEVEN of SPADES(7),
SEVEN of HEARTS(28),
EIGHT of HEARTS(32),
TEN of SPADES(10),
DEUCE of CLUBS(4),
EIGHT of DIAMONDS(24),
// here is the hand - which i also want the values
[SIX of CLUBS, SEVEN of DIAMONDS, TEN of DIAMONDS, TEN of CLUBS]
[SIX of HEARTS, THREE of HEARTS, SIX of SPADES, DEUCE of SPADES]
[JACK of SPADES, NINE of DIAMONDS, SEVEN of CLUBS, THREE of DIAMONDS]
C:\Java\a02>
here is the code:
import java.util.*;
public class Cards{
public enum Rank { DEUCE(2), THREE(3), FOUR(4), FIVE(5), SIX(6),
SEVEN(7), EIGHT(8), NINE(9), TEN(10), JACK(10), QUEEN(10), KING(10), ACE(11);
private int Rankpoints;
private Rank(int points)
{
this.Rankpoints = points;
}
public int getRankpoints()
{
return Rankpoints;
}
}
public enum Suit { CLUBS(2), DIAMONDS(3), HEARTS(4), SPADES(1);
private int Suitpoints;
Suit(int points)
{
Suitpoints = points;
}
public int getSuitpoints()
{
return Suitpoints;
}
}
private final Rank rank;
private final Suit suit;
private Cards(Rank rank, Suit suit)
{
this.rank = rank;
this.suit = suit;
}
public Rank rank()
{
return this.rank;
}
public Suit suit()
{
return this.suit;
}
public String toString()
{
return rank + " of " + suit;
}
private static final List<Cards> protoDeck = new ArrayList<Cards>();
// Initialize prototype deck
static {
for (Suit suit : Suit.values())
for (Rank rank : Rank.values())
protoDeck.add(new Cards(rank, suit));
}
public static ArrayList<Cards> newDeck()
{
return new ArrayList<Cards>(protoDeck); // Return copy of prototype deck
}
}
and here is main()
import java.util.*;
public class Deal {
public static void main(String args[])
{
int numHands = Integer.parseInt(args[0]);
int cardsPerHand = Integer.parseInt(args[1]);
List<Cards> deck = Cards.newDeck();
Collections.shuffle(deck);
int total = 0;
// ArrayList<Cards> hand = new ArrayList<Cards>();
// this is how i am handling the values.. which is not good.
for (Cards card : deck)
{
for(Cards.Suit a : Cards.Suit.values())
{
for(Cards.Rank b : Cards.Rank.values())
{
if(card.rank() == b)
{
if(card.suit() == a) // as you can see this works. theres got to be a better way??
{
total = b.getRankpoints();
// hand.add(card);
System.out.println(card.rank() + " of " + card.suit() + "(" + a.getSuitpoints() * total + ")" + ",");
}
}
}
}
}
for (int i=0; i < numHands; i++)
System.out.println(deal(deck, cardsPerHand)); // prints the hand
//deal(deck,cardsPerHand,numHands);
}
// hand
public static ArrayList<Cards> deal(List<Cards> deck, int n) {
int deckSize = deck.size();
List<Cards> handView = deck.subList(deckSize-n, deckSize);
ArrayList<Cards> hand = new ArrayList<Cards>(handView);
handView.clear();
// Map<String, Map<String, Integer>> inputWords = new HashMap<String, Map<String, Integer>>();
int total = 0;
return hand;
}
}
//for (Cards card : hand)
//{
// for(Cards.Suit a : Cards.Suit.values())
// {
//for(Cards.Rank b : Cards.Rank.values())
// {
// if(card.rank() == b)
// {
// if(card.suit() == a)
//{
// total = b.getRankpoints();
// System.out.println("card.rank() + " of " + card.suit() + "(" + a.getSuitpoints() * total + ")" + ",");
// return hand;
//}
//}
//}
//}
//}
//return hand;
//}
//}
Any help is much appreciated. code snippets or hints are very welcome =)
Keep in mind i am pretty new to Java..
Thank you
Try changing your Card classes toString() method to something like this:
public String toString()
{
return rank + " of " + suit+ "(" + suit.getSuitpoints() * rank.getRankpoints() + ")" + ",");
}
Then this:
System.out.println(card.rank() + " of " + card.suit() + "(" + a.getSuitpoints() * total + ")" + ",");
Can become:
System.out.println(card);
In regard to getting it all to print on one line you're looking for System.out.print() rather than System.out.println().