This question already has answers here:
How to make toString method within object?
(4 answers)
Closed 7 years ago.
import java.util.ArrayList;
public class Card {
int number;
String suit;
public Card(int number, String suit) {
this.number = number;
this.suit = suit;
}
public static void main(String[] args) {
String[] suit = {
"Clubs",
"Diamonds",
"Spades",
"Hearts"
};
String[] high = {
"Jack",
"Queen",
"King"
};
ArrayList<Card> deckOfCards = new ArrayList<Card>(52);
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 13; i++) {
deckOfCards.add(new Card (i+1, suit[j]));
}
}
#Override
public String toString(Card card) {
this.suit = suit;
this.number = number;
String type;
if (number < 10) {
type = Integer.toString(number);
}
else {
type = high[i-number];
}
return suit + " of " + type;
}
}
}
So I have the object called card and I want to print the suit (the string) and the number on it (the int) with the method at the bottom but I'm not 100% sure how to do it. Needless to say, the part at the bottom doesn't compile or work
Thanks
This should go inside your Card class:
#Override
public String toString() {
return String.valueOf(this.number) + " of " + this.suit;
}
Call the function like this:
currentCard.toString();
or print it out to the console like this:
System.out.println(currentCard.toString());
toString method doesn't take any arguments and should be inside your card object. It's a string representation of the object. The values are set by the constructor.
Place the suit and high array in your card class at the top with the other variables, so your code looks like this:
int number;
String cardSuit; //renamed this variable because you have an array with the same name
String[] suit = {
"Clubs",
"Diamonds",
"Spades",
"Hearts"
};
String[] high = {
"Jack",
"Queen",
"King"
};
#Override
public String toString()
{
String type;
if (number < 10) {
type = Integer.toString(number);
}
else {
type = high[i-number];
}
return "Suit " + this.suit + " and Number " + this.type;
}
Side Note: It's a good idea to make your variables private and use getters/setters to set and access them. Also, override equals as well. If you're using eclipse it can generate it for you automatically.
Related
So I am building up to a card game but, but I am having some trouble building the deck of cards and OOP in general so I was wondering if I could get some help. This is what I have so far.
public class Card {
String[] rank = {"Ace", "2", "3", "4", "5", "6",
"7", "8", "9", "10", "Jack", "Queen", "King"};
String suit;
int value;
String color;
public Card(String suit, int value) {
this.suit = suit;
this.value = value;
if (suit.equals("Hearts") || suit.equals("Diamonds")) {
color = "red";
} else {
color = "black";
}
}
public int getValue() {
return value;
}
public String getColor() {
return color;
}
public String getSuit() {
return suit;
}
public String getName() {
name = rank[(value - 1)];
return name;
}
public String toString() {
return name + " of " + suit;
}
}
The class for my deck of cards (so far) is as follows:
public class Deck {
String[] suits = {"Hearts", "Diamonds", "Clubs", "Spades"};
static String[] cards = new String[52];
public Deck() {
int index = 0;
for (int i = 0; i < 4; i++) {
// For each value of card with this suit.
for (int j = 1; j <= 13; j++) {
Card card = new Card(suits[i], j);
cards[index] += card;
index += 1;
}
}
}
public static void all() {
for (int i = 0; i < cards.length; i++) {
System.out.println(cards[i]);
}
}
}
So my question was when I print out the cards, I get something like
nullnull of Hearts
nullnull of Hearts
nullnull of Hearts
nullnull of Hearts....
nullnull of Diamonds
nullnull of Diamonds
nullnull of Diamonds
nullnull of Diamonds
nullnull of Diamonds... etc.
Why am I getting these nulls? What am I doing wrong? Also, any other tips to improve my code would be greatly appreciated.
Your problem is the following line of code from the constructor of class Deck.
cards[index] += card;
You need to remove the +.
An array of objects in java is always initialized such that every element is null. Hence you are appending a card to null.
If you would step through your code with a debugger, you would have discovered that. All good IDEs have a debugger. You should learn to use it.
Note that the code in your question does not compile but I figured out how to fix it since the problems are minor.
For the sake of completeness. Here is your code with my fixes. Compare it to your code.
Class Card
public class Card {
String[] rank = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
String suit;
int value;
String color;
public Card(String suit, int value) {
this.suit = suit;
this.value = value;
if (suit.equals("Hearts") || suit.equals("Diamonds")) {
color = "red";
}
else {
color = "black";
}
}
public int getValue() {
return value;
}
public String getColor() {
return color;
}
public String getSuit() {
return suit;
}
public String getName() {
String name = rank[(value - 1)];
return name;
}
public String toString() {
return getName() + " of " + suit;
}
}
Class Deck
(Note that I added a main() method just for testing purposes.)
public class Deck {
String[] suits = {"Hearts", "Diamonds", "Clubs", "Spades"};
Card[] cards = new Card[52];
public Deck() {
int index = 0;
for (int i = 0; i < 4; i++) {
// For each value of card with this suit.
for (int j = 1; j <= 13; j++) {
Card card = new Card(suits[i], j);
cards[index] = card;
index += 1;
}
}
}
public void all() {
for(int i = 0; i < cards.length; i++) {
System.out.println(cards[i]);
}
}
public static void main(String[] args) {
new Deck().all();
}
}
Your example does not look complete, as I don't see name field in Card class defined. But what I see is that name is initialized in getName methods. I guess you don't initialize it.
Either use getName in toString:
public String toString(){
return getName() + " of " + suit;
}
or initialize name in the constructor: name = rank[(value - 1)]
Prefer initialization in the constructor, otherwise if you refer to name in some other place you can get the same issue.
I need to create a deck of cards by using two string: "HSCD" and "A2345678910JQK".
public class Deck {
Random random=new Random();
Queue cards=new Queue(112);
String suits="HSCD";
String rands="A2345678910JQK";
public Deck() {
for (int i = 0; i < suits.length(); i++) {
for (int j = 0; j < rands.length(); j++) {
char suit = suits.charAt(random.nextInt(suits.length()));
char rand = rands.charAt(random.nextInt(rands.length()));
if (rand == '1' || rand == '0') {
String s = Integer.toString(10);
cards.enqueue(new Card(suit, s));
} else {
String s1 = Character.toString(rand);
cards.enqueue(new Card(suit, s1));
}
}
}
}
public void display(){
for (int i = 0; i < cards.size(); i++) {
System.out.print(cards.peek());
cards.enqueue(cards.dequeue());
}
}
public Queue getCards() {
return cards;
}
public void setCards(Queue cards) {
this.cards = cards;
}
public String getSuits() {
return suits;
}
public void setSuits(String suits) {
this.suits = suits;
}
public String getRands() {
return rands;
}
public void setRands(String rands) {
this.rands = rands;
}}
I have Deck and Card classes.
public class Card {
private char rand;
private String suit;
public Card(char rand, String suit) {
this.rand = rand;
this.suit = suit;
}
public Card(){}
public char getRand() {
return rand;
}
public void setRand(char rand) {
this.rand = rand;
}
public String getSuit() {
return suit;
}
public void setSuit(String suit) {
this.suit = suit;
}
public String toString(){
return "\t"+rand + suit;
}}
But i couldn't solve that every suits must have 13 rands. In my program my deck is randomly created. And my deck must be shuffled. I can't use list or array structures because teacher told us so :). Can you help me?
You are creating 14 cards per suit, not 13: you're creating 10 twice. Remove with 0 or 1 from rands.
It will be easier if you first create the cards, then shuffle them.
Creation of cards should be similar to what you're already doing, minus the randomization - just go through suits and values in order:
for each suit:
for each value:
sortedCards.add(new Card(suit, value));
Then, shuffle the cards as follows:
while (sortedCards is not empty):
shuffledCards.add(sortedCards.get(random.nextInt(sortedCards.size())))
Just duplicate four time the second string. After you take two random numbers one correspond to the sign and one to the number. Finally you put sign+number in memory and you remove the number in the string :
String signs = "HSCD";
String numbersH = "A2345678910JQK";
String numbersS = "A2345678910JQK";
String numbersC = "A2345678910JQK";
String numbersD = "A2345678910JQK";
ArrayList<String> deck = new ArrayList<String>();
Random random = new Random();
while(deck.size()<52){
int sign = random.nextInt(signs.lenght());
if(sign==0 && numbersH.lenght()>0){
int number = random.nextInt(numbersH.lenght());
deck.add(signs.charAt(sign)+numbersH.charAt(number));
numbersH = numbersH.substring(0,number)+numberH.substring(number+1);
}//here the same for other signs
}
Another method : Create your deck like iluxa say you and shuffle with this :
Random rand = new Random();
for(int i=0;i<300;i++){
int a = rand.nextInt(deck.size());
int b = rand.nextInt(deck.size());
Card cA = deck.get(a);
deck.set(a, deck.get(b));
deck.set(b, cA);
}
That's code will suffle your deck by switch two random cards many times.
You haven't included the Queue class so help is going to be limited. Here are some other suggestions.
String suits="HSCD";
String ranks="A23456789TJQK";
for (int i = 0; i < 52; i++) {
int suit = i/13; // index into suit 0 to 3 inclusive
int rank = i%13; // index into rank 0 to 12 inclusive
cards.enqueue(new Card(suits.charAt(suit), ranks.charAt(rank));
}
Also, quite often, card game software uses a T for ten, which is what I did in this example. It can be changed but in your implementation you can't store 10 as as a single character and it is cumbersome to maintain two types for card ranks. So you should probably make all your ranks and suits as type String.
I am trying to create a poker game in which I create the deck in the Card class, and use a comparator to sort the deck in alphabetical order. I'm having trouble with what to put in the comparator, and in my dealer class, (this is where I create the deck, shuffle, as well as calling the comparator). When my CompareCards does compile, my Dealer class will give me the error of:
Dealer.java:24: error: incompatible types: void cannot be converted to String
String s = Collections.sort(deck);
^
Note: Dealer.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
I know that when doing the sort, you have to include the Comparator name, but in this case it doesn't work either way. Here is my card class:
import java.util.*;
public class Card{
String suit = null;
String value = null;
String rank = null;
public static final String[] SUIT = {"C", "D", "H", "S" };
public static final String[] RANK = {"A","2","3","4","5","6","7","8","9","T","J","Q","K"};
public Card(int i, int j){
suit = RANK [i];
rank = SUIT [j];
value = rank + suit;
}
public String getSuit(){
return suit;
}
public String getRank(){
return rank;
}
public String toString(){
return(value);
}
}
Here is my Comparator and CompareCards class:
public interface Comparator <Card>{
public int compare(Card o1, Card o2);
}
public class CompareCards implements Comparator<Card>{
public int compare(Card c1, Card c2){
int x = 0;
int y = 0;
int dx = c1.getRank() - c2.getRank();
if(dx == 0){
x = c1.getRank()-c2.getRank();
}
else{
y = c1.getSuit() - c2.getSuit();
}
return x;
}
And here is the dealer class:
import java.util.*;
public class Dealer{
public static void main(String[]args){
// creating deck
List<Card> deck= new ArrayList<Card>();
// calling Card
for(int i = 0; i < 13 ; i++){
for(int j = 0; j < 4 ; j++){
// String s = RANK[i] +SUIT[j];
deck.add(new Card(i, j));
}
}
finding21(deck);
}
public static void finding21 (List deck){
String s = Collections.sort(deck);
System.out.println("Sorted deck: " + s);
// After I sort the deck I am supposed to do a binary search
// for the queen of hearts
/* Collections.shuffle(deck);
System.out.println("Shuffled deck: " + deck);
String HQ = Collections.binarySearch(deck, "HQ");
System.out.print(HQ);
System.out.println(queenH);*/
}
}
Collections.sort does an in-place sort and does not return a value.
That's why the compiler says you can't convert a void to a String.
The void type is used for functions with no return value.
Just use:
Collections.sort(deck);
If you want to print the sorted deck after, you can use:
System.out.println("Sorted deck: " + deck);
I'm struggling to add together values that I've declared within ENUMS. I basically need to add together values of each card within a hand of cards based on rank.
I've tried a few things but not actually got anywhere. I can display the ENUM's but they have no value.
Here is my code:
Card Class
public class Card {
private Suit suit;
private Rank rank;
int totalValue;
public Card (Suit suit, Rank rank) {
this.suit = suit;
this.rank = rank;
}
public Suit getSuit(){
return suit;
}
public void setSuit(Suit suit)
{
this.suit = suit;
}
public Rank getRank()
{
return rank;
}
public void setRank(Rank rank)
{
this.rank = rank;
}
#Override
public String toString ( ) { return ( rank + " of " + suit); }
}
Suit Class
public enum Suit {
HEARTS , SPADES , CLUBS , DIAMONDS
}
Rank Class
public enum Rank {
ACE(1),
TWO(2),
THREE(3),
FOUR(4),
FIVE(5),
SIX(6),
SEVEN(7),
EIGHT(8),
NINE(9),
TEN(10),
JACK(10),
QUEEN(10),
KING(10);
private int RankValue;
private Rank (int rValue)
{
RankValue = rValue;
}
public int getRankValue()
{
return RankValue;
}
}
Hand Class
public class Hand {
private Card theCards[ ];
private int numCards;
private int totalValue;
private static final int max = 5;
private Rank rank;
private Suit suit;
public Hand ( )
{
theCards = new Card [max];
numCards = 0;
}
public void addCard( Card aCard )
{
if (numCards < max) theCards[numCards++] = aCard;
}
public void setRank(Rank rank){
this.rank = rank;
}
public void setSuit(Suit suit){
this.suit = suit;
}
public int totalValue() {
int totalValue = 0;
for (Card card : theCards) {
totalValue += card.getRank().getRankValue();
}
return totalValue;
}
#Override
public String toString ( )
{
String s = "Rank: " + rank + "Suit: " + suit;
for (int i = 0; i < numCards; ++i) {
s += "\n" + theCards[i] + "\n" + totalValue;
}
return s;
}
}
Finally my Hand Driver with the main method
public class HandDriver {
public static void main( String[] args ){
Hand h1 = new Hand();
Card c1 = new Card(Suit.valueOf("HEARTS"),Rank.valueOf("TEN"));
Card c2 = new Card(Suit.valueOf("SPADES"),Rank.valueOf("ACE"));
Card c3 = new Card(Suit.valueOf("DIAMONDS"),Rank.valueOf("SEVEN"));
Card c4 = new Card(Suit.valueOf("HEARTS"),Rank.valueOf("NINE"));
Card c5 = new Card(Suit.valueOf("HEARTS"),Rank.valueOf("THREE"));
h1.addCard(c1);
h1.addCard(c2);
h1.addCard(c3);
h1.addCard(c4);
h1.addCard(c5);
System.out.print (h1.toString());
;
}
}
I'm basically looking for someone who is able to point me in the right direction to display the total value of all cards
In your Hand class, you are using int totalValue, which is then "shadowed" in your function totalValue(), so totalValue will be zero. Then, in toString() you are using totalValue, which is never calculated. First, remove "int" here:
public int totalValue() {
//removed "int", so you are not declaring local totalValue variable
//but using your class variable
totalValue = 0;
for (Card card : theCards) {
totalValue += card.getRank().getRankValue();
}
return totalValue;
}
Then, in your toString(), call the above function, so that totalValue is calculated, and then you can use it in your loop:
#Override
public String toString ( )
{
String s = "Rank: " + rank + "Suit: " + suit;
//call totalValue() to calculate totalValue
totalValue();
for (int i = 0; i < numCards; ++i) {
//now you can use totalValue, because it's been calculated in totalValue()
s += "\n" + theCards[i] + "\n" + totalValue;
}
return s;
}
As noticed by Holger, you can also use Suit.HEARTS instead of Suit.valueOf("HEARTS").
EDIT: As noticed by Grove, totalValue() doesn't have to be called for every card. Call it before you build your string, and then you can use totalValue variable in your for loop.
There are a few problems with your code.
I agree with "Holger" you should not be using
Suit.valueOf("HEARTS") and
Rank.valueOf("TEN")
Instead it should be
Suit.HEARTS
Rank.TEN
Then in the Card and Hand classes you should probably be calculating the value of that Card or value of that Hand as the suit and rank is added to the Card and as a Card is added to the Hand, that way when you get the total value of the Hand or want to do toString() you only need to read the value rather than calculate it every time.
In the Hand class the way you are adding a Card to the "theCards" array should be like so:
if (numCards < max) {
theCards[numCards] = aCard;
numCards++;
}
Then as I mentioned before you should probably in this if block also call another method which you will need to create to update the total value.
Finally, to calculate the total of a Card you may want to do something like,
int suitVal = suit.ordinal(); // This returns a number which is the position of the enum value
int rankVal = rank.getRankValue();
totalValue = suitVal + rankVal;
I could have just changed all your code and pasted it in here for you but that I think would not be good for learning.
Hope this helps.
I've fixed it exactly how I want it now. If anyone else has the same issue I think this is the easiest and most efficient way of trying to set up a deck of cards. You can pick out individual cards using a random variable in deck[random][0] and deck[random][1].
Thanks for all the help, here is my code:
public class NewDeck {
public static void main(String[] args) {
String[] suits = new String[] { "Clubs", "Diamonds", "Spades", "Hearts" };
String[] faces = new String[] { "Ace", "King", "Queen", "Jack" };
String[][] deck = new String[suits.length * (faces.length + 9)][2];
int a = 0;
for (String y : suits) {
for (String x : faces) {
deck[a][0] = x;
deck[a][1] = y;
a++;
}
}
for (String y : suits) {
for (int p = 2; p < 11; p++) {
deck[a][1] = y;
String pp = Integer.toString(p);
deck[a][0] = pp;
a++;
}
}
for (int p = 0; p < deck.length; p++) {
System.out.print(deck[p][0] + " of ");
System.out.println(deck[p][1]);
}
}
}
You should add parameter types to your strings and create a Pair class. Note that you will need a Java compiler of version 1.5 or higher for the generics.
class Pair {
private final String face;
private final String suit;
Pair(String suit, String face) {
this.face = face;
this.suit = suit;
}
#Override
public String toString() {
return "(" + suit + ", " + face + ")";
}
}
Then you can use this Pair class as follows, using the appropriate List methods get and size:
List<Pair> deck = new ArrayList<Pair>();
List<String> suits = new ArrayList<String>();
suits.add("Hearts");
suits.add("Diamonds");
suits.add("Clubs");
suits.add("Spades");
List<String> faces = new ArrayList<String>();
faces.add("Ace");
faces.add("King");
faces.add("Queen");
faces.add("Jack");
for(int suit = 0; suit < suits.size(); suit++){
for(int face = 0; face < faces.size(); face++){
deck.add(new Pair(suits.get(suit), faces.get(face)));
}
}
If you override the toString method of Pair you can also System.out.println(deck) to get your desired string representation of the ArrayList.
Probably you need to change this
deck.add(suits[suit], faces[face]);
with
deck.add(suits[suit] + faces[face]);
as your idea is to concatenate elements from the list and add it the deck list.
You can not store two values at one index of List. But what you can do is
Option 1
Store concatenated \string like
Change
deck.add(suits[suit], faces[face]);
with
deck.add(suits[suit] + "," + faces[face]);
then output deck[2] = suit, face
Option 2
Change list of string to list of Object and this object contains detail of suit and face
public class Deck {
private String suit;
private String face;
// getter and setters;
}
and list become
List<Deck> deck
and add entry as
deck.add(new Deck(suits[suit], faces[face]))