Getting null with OOP Deck of Cards Java - java

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.

Related

toString method of a class

I have a card class that looks like this:
public class Card
{
//instance variables
private String faceValue; //the face value of the card
private String suit; //the suit of the card
String[] ranks = {"Ace", "2", "3", "4", "5", "6","7", "8", "9", "10", "Jack", "Queen", "King"};
String[] suits = {"Clubs", "Diamonds", "Hearts", "Spades"};
/**
* Constructor
*/
public Card()
{
for (int i = 0; i < 13; i++)
{
for (int j = 0; j < 4; j++)
{
faceValue = ranks[i];
suit = suits[j];
}
}
}
//getters
/**
* Getter for faceValue.
*/
public String getFaceValue()
{
return faceValue;
}
/**
* Getter for suit.
*/
public String getSuit()
{
return suit;
}
//end of getters
//methods
/**
* This method returns a String representation of a Card object.
*
* #param none
* #return String
*/
public String toString()
{
return "Dealed a card: " + faceValue + " of " + suit;
}
}
And another Deck class that uses the Card class to create an array:
public class Deck
{
//instance variables
private Card[] deck;
/**
* Constructor for objects of class Deck
*/
public Deck()
{
deck = new Card[52];
}
/**
* String representation.
*/
public String toString()
{
return "Dealed a card: " + deck.getFaceValue() + " of " + deck.getSuit();
}
}
My toString method is giving me the error "cannot find symbol - method getFaceValue()". Same for getSuit(). Any ideas why?
deck is an array of Card[] deck. Hence, you can't call the method getFaceValue() nor getSuit() on it, because those 2 methods are part of the Card class and NOT of the array of Cards.
here some possible solutions to your problem as suggested:
public String toString()
{
return Arrays.toString(deck);
}
or for loop through the entire deck
public String toString()
{
String deckInStringForm = "[ ";
for(int indexOfCard = 0; indexOfCard < deck.length; indexOfCard++)
{
deckInStringForm += deck[indexOfCard] + " ";
}
deckInStringForm += "]";
return deckInStringForm;
}
or change/add a function to take an index like so
public String toString(int index)
{
return "Card " + index + ": " + deck[index].toString();
}

Creating a deck of cards in java with a two dimensional array

I am attempting to create a deck and apply a suite to each one, for example:
cardValue[0][1] and convert it into cardValue[Spade][1]
but I don't understand how to convert it. What I have currently:
int cardValues[][];
for(int a = 0; a <= 3; a++)
{
for(int b = 0; b <= 12; b++)
{
cardValues[][] += cardValues[a][b];
if(cardValues[a][b] == cardValues[a][0])
{
cardValues[a][b] = 5;
}
else if(cardValues[a][b] > cardValues[a][0] || cardValues[a][b] < cardValues[a][10])
{
cardValues[a][b] = 1;
}
else if(cardValues[a][b] == cardValues[a][10])
{
cardValues[a][b] = 2;
}
else if(cardValues[a][b] == cardValues[a][11])
{
cardValues[a][b] = 3;
}
else if(cardValues[a][b] == cardValues[a][12])
{
cardValues[a][b] = 4;
}
}
}
I don't understand how to convert the 0, 1, 2, and 3 into spades, diamonds, clubs, hearts.
I would do something like that:
Suit.java
public enum Suit {
SPADES, DIAMONDS, CLUBS, HEARTS
}
Card.java
public class Card {
private Suit suit;
private String value;
public Card(Suit suit, String value) {
this.suit = suit;
this.value = value;
}
public Suit getSuit() {
return suit;
}
public void setSuit(Suit suit) {
this.suit = suit;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Main.java
public class Main {
public static void main(String[] args) {
String[] values = new String[]{"K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3", "2", "A"};
Card[] deck = new Card[52];
int i = 0;
for (Suit suit : Suit.values()) {
for (String value : values) {
deck[i++] = new Card(suit, value);
}
}
for (Card card : deck) {
System.out.println(card.getValue() + " of " + card.getSuit());
}
}
}

How to print different primitive values from an object [duplicate]

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.

Having trouble creating Card class

Im having trouble converting the r[rank] to String. Eclipse keeps saying it needs to be resolved to an array. Also having trouble with Cards[13*i + j] = new Card(i, j); it just keeps saying cannot be resolved to a variable. Heres my code...
public class Card {
private String suit;
private String rank;
private static String[] s = { "hearts", "spades", "diamonds", "clubs" };
private static String[] r = { "Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King" };
public Card(int suit, int deck){
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 13; j++){
Cards[13*i + j] = new Card(i, j);
}
}
}
public Card(String r, String s, String suit){
for(int rank = 0; rank < r.length(); rank+=1){
if( rank.equals(r[rank]) ){
this.rank = r+1;
}
}
this.suit = suit;
}
public String getSuit(){
return suit;
}
public void setSuit(String a, String suit) {
this.suit = suit;
}
public String getRank(){
return rank;
}
public void setRank( String s, String rank){
this.rank= rank;
}
public String toString(){
return String.valueOf(this.getRank()) + String.valueOf(this.getSuit().charAt(0));
}
}
public class Deck {
private Card[] deck;
private int inDeck;
private final int SIZE_OF_DECK = 52;
private int currentCard;
public Deck(){
deck = new Card[deck];
}
private void init(){
}
public void shuffle(int num){
int i,j,k;
for (k = 0; k < num; k++)
{
i = (int) (SIZE_OF_DECK * Math.random()*100);
j = (int) (SIZE_OF_DECK * Math.random()*100);
Card tmp = deck[i];
deck[i] = deck[j];
deck[j] = tmp;
}
currentCard = 0;
}
public Card getCard(){
if (currentCard<SIZE_OF_DECK)
{
return deck[currentCard++];
}
else
{
System.out.print("out of cards error");
return null;
}
}
public int totalCards(){
return SIZE_OF_DECK ;}
}
You never initialize your card array... try something along the lines of this before you create each individual object with your loops.
Card[] cards = new Card[52];

A pack of playing cards, difficulty in methods and the Pack and PlayingCard Classes

I have to develop a class called Pack and it needs to be able to generate a pack of 52 playing cards sorted by Suit and Rank. It also needs to be able to shuffle that pack of cards with another method. Finally, it has to return the String repesentation of that pack of cards.
This is the catch though, I have to somehow use another class I have done, PlayingCard, with this Pack class. And this is when I run into dead ends, I can't figure out a way of shuffling the cards in the arrays I use, and I can't use PlayingCard due to incompatability issues.
This is the current Pack Class:
import java.util.Random;
public class Pack {
int[] cards = new int[52];
public Pack() {
// Setting up array
String[] suits = {"SPADES", "CLUBS", "HEARTS", "DIAMONDS"};
String[] ranks = {"TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN", "JACK", "QUEEN", "KING", "ACE"};
// Intialising array
{
for (int i = 0; i < cards.length; i++) {
cards[i] = i;
}
}
}
public void shuffle() {
for (int i = 0; i < 52; i++) {
Random random = new Random();
int rand = random.nextInt(50)+1;
cards[i] = rand;
}
}
#Override
public String toString() {
return getClass().getName() + "[suit[]= " + suit[] + "rank[]= " + rank[] + "]";
}
}
This is the another Pack Class based of advice, note the lack of toString():
import java.util.Random;
public class Pack {
PlayingCard[] cards = new PlayingCard[52];
public Pack() {
// Setting up array
String[] suits = {"SPADES", "CLUBS", "HEARTS", "DIAMONDS"};
String[] ranks = {"TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN", "JACK", "QUEEN", "KING", "ACE"};
// Initialising array
for (int i = 0; i < cards.length; i++) {
cards[i] = i;
}
}
public void shuffle() {
for (int i = 0; i < 52; i++) {
Random random = new Random();
int rand = random.nextInt(50) + 1;
cards[i] = rand; // Error 3
}
}
#Override
public String toString() {
This is the template I have been using for all the good it has done:
Using the class PlayingCard develop another class called Pack.
An outline for this class is provided below:
public class Pack
{
PlayingCard[] cards = new PlayingCard[];
/**
* Constructs a pack of 52 cards.
* Sorted by suit Clubs, Diamonds, Hearts, Spades.
* Sorted ascending.
*/
public Pack()
{
}
/**
* Shuffles cards in pack.
*/
public void shuffle()
{
}
/**
* #return string representation of 52 card pack.
*/
public String toString()
{
}
}
And finally, here is the PlayingCard class that Pack must somehow use.
import java.util.Objects;
public class PlayingCard {
private Rank rank;
private Suit suit;
public PlayingCard(Rank rank, Suit suit) {
this.rank = rank;
this.suit = suit;
}
public Rank getRank() {
System.out.println(rank);
return rank;
}
public Suit getSuit() {
System.out.println(suit);
return suit;
}
public String toString() {
return getClass().getName() + "[rank= " + rank + "suit= " + suit + "]";
}
public void format() {
System.out.format(rank + " OF " + suit);
System.out.println();
}
#Override
public boolean equals(Object otherObject) {
if (otherObject == null) {
return false;
}
if (!(otherObject instanceof PlayingCard)) {
return false;
}
if (this == otherObject) {
return true;
}
PlayingCard other = (PlayingCard) otherObject;
return suit.equals(other.suit) && rank == other.rank;
}
#Override
public int hashCode() {
return Objects.hash(suit, rank);
}
}
So, how can I use the PlayingCard class with Pack, and how can I get the shuffle class in Pack to function with my arrays etc as all it is going to achieve at the moment is putting in random numbers into the cards array.
If more infomation is needed, tell me, and I will add it.
EDIT 1:
In response to the first answer, here is the enum of suit just for showing a potential problem, and the current version of Pack that I did before the answer. How does it hold out?
Enum:
public enum Suit
{
SPADES(-2), CLUBS(-1), HEARTS(0), DIAMONDS(1);
private int value;
private Suit(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
}
Updated Pack:
import java.util.Random;
public class Pack
{
int[] cards = new int[52];
public void Deck()
{
// Setting up array
String[] suits = {"SPADES", "CLUBS", "HEARTS", "DIAMONDS"};
String[] ranks = {"TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
"EIGHT", "NINE", "TEN", "JACK", "QUEEN", "KING", "ACE"};
// Intialising array
{
for (int i = 0; i < cards.length; i++)
{
cards[i] = i;
}
}
}
public void shuffle()
{
for (int i = 0; i < 52; i++)
{
Random random = new Random();
int rand = random.nextInt(50)+1;
int temp = cards[i];
cards[i] = cards[rand];
cards[rand] = temp;
}
}
#Override
public String toString()
{
return
}
}
Notice Rank and Suit in the PlayingCard class. It's hint to define 2 enum classes (show only Suit class) :
public enum Suit {
SPADE("Spade"),
HEART("Heart"),
DIAMOND("Diamond"),
CLUB("Club");
private String name;
private Suit(String name) { this.name = name; }
public String toString() {return name;}
}
You can declare these 2 enums as public static enum {...} into the Pack class. The reason to use enums in this case is we know in advance all the cards and this is safer to handle strongly type objects than just Integers or String for ranks and suits.
You can then initialise the Pack of cards with a double loop on Suit and Rank values, e.g.
public Pack() {
int i = 0;
for (Rank r : Rank.values()) {
for (Suit s : Suit.values()) {
cards[i] = new PlayingCard(r, s);
i++;
}
}
}
For shuffling the pack, just use Collections.shuffle(), e.g.
public void shuffle() {
List<Card> newDeck = Arrays.asList(cards);
Collections.shuffle(newDeck);
}
The List<Card> is backed by the array ; the shuffling is then propagated to the array of cards.

Categories