Flow of control in java - multiple classes - java

I am a beginner to java and have been going through oracle's java tutorial. In those tutorials I came across a question involving multiple classes. The class called Deck uses class called Cards. I want to know if the class Deck ever uses the main method in class Cards. Does the line of flow ever go through the main method of Cards.
public class Card {
private final int rank;
private final int suit;
// Kinds of suits
public final static int DIAMONDS = 1;
public final static int CLUBS = 2;
public final static int HEARTS = 3;
public final static int SPADES = 4;
// Kinds of ranks
public final static int ACE = 1;
public final static int DEUCE = 2;
public final static int THREE = 3;
public final static int FOUR = 4;
public final static int FIVE = 5;
public final static int SIX = 6;
public final static int SEVEN = 7;
public final static int EIGHT = 8;
public final static int NINE = 9;
public final static int TEN = 10;
public final static int JACK = 11;
public final static int QUEEN = 12;
public final static int KING = 13;
public Card(int rank, int suit) {
assert isValidRank(rank);
assert isValidSuit(suit);
this.rank = rank;
this.suit = suit;
}
public int getSuit() {
return suit;
}
public int getRank() {
return rank;
}
public static boolean isValidRank(int rank) {
return ACE <= rank && rank <= KING;
}
public static boolean isValidSuit(int suit) {
return DIAMONDS <= suit && suit <= SPADES;
}
public static String rankToString(int rank) {
switch (rank) {
case ACE:
return "Ace";
case DEUCE:
return "Deuce";
case THREE:
return "Three";
case FOUR:
return "Four";
case FIVE:
return "Five";
case SIX:
return "Six";
case SEVEN:
return "Seven";
case EIGHT:
return "Eight";
case NINE:
return "Nine";
case TEN:
return "Ten";
case JACK:
return "Jack";
case QUEEN:
return "Queen";
case KING:
return "King";
default:
//Handle an illegal argument. There are generally two
//ways to handle invalid arguments, throwing an exception
//(see the section on Handling Exceptions) or return null
return null;
}
}
public static String suitToString(int suit) {
switch (suit) {
case DIAMONDS:
return "Diamonds";
case CLUBS:
return "Clubs";
case HEARTS:
return "Hearts";
case SPADES:
return "Spades";
default:
return null;
}
}
public static void main(String[] args) {
// must run program with -ea flag (java -ea ..) to
// use assert statements
assert rankToString(ACE) == "Ace";
assert rankToString(DEUCE) == "Deuce";
assert rankToString(THREE) == "Three";
assert rankToString(FOUR) == "Four";
assert rankToString(FIVE) == "Five";
assert rankToString(SIX) == "Six";
assert rankToString(SEVEN) == "Seven";
assert rankToString(EIGHT) == "Eight";
assert rankToString(NINE) == "Nine";
assert rankToString(TEN) == "Ten";
assert rankToString(JACK) == "Jack";
assert rankToString(QUEEN) == "Queen";
assert rankToString(KING) == "King";
assert suitToString(DIAMONDS) == "Diamonds";
assert suitToString(CLUBS) == "Clubs";
assert suitToString(HEARTS) == "Hearts";
assert suitToString(SPADES) == "Spades";
}
}
import java.util.*;
public class Deck {
public static int numSuits = 4;
public static int numRanks = 13;
public static int numCards = numSuits * numRanks;
private Card[][] cards;
public Deck() {
cards = new Card[numSuits][numRanks];
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++) {
for (int rank = Card.ACE; rank <= Card.KING; rank++) {
cards[suit-1][rank-1] = new Card(rank, suit);
}
}
}
public Card getCard(int suit, int rank) {
return cards[suit-1][rank-1];
}
}

No, it does not. The main method implemented in this example is intended for testing purposes (note the asserts).

It's very typical, however I'd say a very bad, custom to have the main method in all the possible tutorials and examples. And yes, it confuses beginners.
Testing code should always be separated from the tested code. In a "normal" code for the good design. In a "school" code for the didactical reason, so the learners are not confused and see the good design even in the school code :)

Related

ArrayList Novice Error in Java

I am trying to get more proficient with Java. I am making a simple card game to test my basic skills. I have come across a problem in my Deck class. The for-loops are not creating new card objects in my arraylist even though they should. When I call getTotalCards the size of the arraylist is always 0. Any ideas of what I am doing wrong?
Main Class:
package gameofcards;
import java.util.Random;
import static gameofcards.Card.*;
public class GameOfCards {
public static void main(String[] args) {
Deck d1 = new Deck();
System.out.println(d1.getTotalCards());
}
}
Deck Class:
package gameofcards;
import java.util.ArrayList;
public class Deck {
private ArrayList<Card> cards;
public Deck(){
cards = new ArrayList<Card>();
for(int i = 1; i >=4; i++){
for(int j = 1; j >=13; j++){
cards.add(new Card(i,j));
}
}
}
public int getTotalCards(){
return cards.size();
}
}
Card Class:
package gameofcards;
public class Card {
private int Suite;
private int Rank;
public static final int Club = 1;
public static final int Diamond = 2;
public static final int Hearts = 3;
public static final int Spade = 4;
public static final int Jack = 10;
public static final int Queen = 11;
public static final int King = 12;
public static final int Ace = 13;
public void setSuite(int cardSuite){
Suite=cardSuite;
}
public int getSuite(){
return Suite;
}
public void setRank(int cardRank){
Rank=cardRank;
}
public int getRank(){
return Rank;
}
public Card(int Suite, int Rank){
this.Suite = Suite;
this.Rank = Rank;
}
public String cardSuite(){
switch(Suite){
case Club: return "Clubs";
case Diamond: return "Diamonds";
case Hearts: return "Hearts";
case Spade: return "Spades";
default: return "Joker";
}
}
public String cardRank() {
switch(Rank){
case 2: return "2";
case 3: return "3";
case 4: return "4";
case 5: return "5";
case 6: return "6";
case 7: return "7";
case 8: return "8";
case 9: return "9";
case 10: return "Jack";
case 11: return "Queen";
case 12: return "King";
case 13: return "Ace";
default: return "Joker";
}
}
}
Your loop conditions are wrong.
Instead of:
for(int i = 1; i >=4; i++){
It should be:
for(int i = 1; i <=4; i++){
And a similar problem with the inner loop condition.
You want to loop while i is less than or equal to 4.
It wasn't adding cards because it never entered the loop in the first place.
An easy way to have figured this out would have been to put a println inside the loop and see what happens. You would have noticed that it never printed.
The conditions in for loop are wrong. should be i<=4 and j<=13
for(int i = 1; i <=4; i++){
for(int j = 1; j <=13; j++){
cards.add(new Card(i,j));
}
}

Highest value card found in deck

In a Java program I am trying to return the largest value card in a deck.
Diamonds are the lowest valued suit. Then clubs, then hearts and finally spades have the largest value. As you can see I have a section of code that simply says largest = in the findLargest methods. I am not sure where to go with the rest of this method.
public class Card {
private int number;
private String suit;
/*
* Randomly creates a card numbered 1 to 13 (ace = 1!) and labelled "Hearts","Clubs","Diamonds" or "Spades".
*/
public Card() {
double randomNum = Math.random() * 4.0;
if (randomNum < 1.0)
suit = "Hearts";
else if (randomNum < 2.0)
suit = "Clubs";
else if (randomNum < 3.0)
suit = "Diamonds";
else
suit = "Spades";
randomNum = Math.random() * 13.0;
number = (int) randomNum + 1;
}
/*
* Creates a card with specified number and suit
*/
public Card (int n, String s) {
number = n;
suit = s;
}
public int getNumber() {
return number;
}
public String getSuit () {
return suit;
}
public String cardString() {
// System.out.println(number + " " + suit);
String stringNum = "";
switch (number) {
case 1:
stringNum = "Ace";
break;
case 2:
stringNum = "Two";
break;
case 3:
stringNum = "Three";
break;
case 4:
stringNum = "Four";
break;
case 5:
stringNum = "Five";
break;
case 6:
stringNum = "Six";
break;
case 7:
stringNum = "Seven";
break;
case 8:
stringNum = "Eight";
break;
case 9:
stringNum = "Nine";
break;
case 10:
stringNum = "Ten";
break;
case 11:
stringNum = "Jack";
break;
case 12:
stringNum = "Queen";
break;
case 13:
stringNum = "King";
break;
default:
System.out.println("Error in Card - illegal number");
}
return stringNum + " of " + suit;
}
}
public class PackCards {
private ArrayList<Card> pack;
/*
* Create a random pack of size n
*/
public PackCards(int n) {
Card c;
pack = new ArrayList<Card>();
for (int i = 1; i <= n; i++) {
c = new Card();
pack.add(c);
}
}
public void printPack() {
for (Card c : pack) {
System.out.println(c.cardString());
}
}
public Card findLargest() {
if ( c.getNumber() > largest.getNumber() )
largest =
else if (c.getNumber() == largest.getNumber() ) {
if (largest.getSuit().equals("Diamonds"))
largest = largest.getNumber;
}
else if (c.getNumber() == largest.getNumber() ) {
if (largest.getSuit().equals("Clubs"))
largest = largest.getNumber;
}
else if (c.getNumber() == largest.getNumber() ) {
if (largest.getSuit().equals("Hearts"))
largest = largest.getNumber;
}
else return;
}
I would simplify the code to make it easier to see what you are trying to achieve. In Java 8 you can do.
import java.util.Random;
public class Card {
enum Suit {
// must be in increasing order.
Spades, Diamonds, Clubs, Hearts
}
static final Suit[] SUITS = Suit.values();
private final int number;
private final Suit suit;
/*
* Randomly creates a card numbered 1 to 13 (ace = 1!) and labelled "Hearts","Clubs","Diamonds" or "Spades".
*/
public Card() {
Random rand = new Random();
suit = SUITS[rand.nextInt(SUITS.length)];
number = rand.nextInt(13) + 1;
}
public int getNumber() {
return number;
}
public Suit getSuit() {
return suit;
}
static final String[] NAMES = ",Ace,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack,Queen,King".split(",");
public String cardString() {
assert number > 1 && number < NAMES.length;
return NAMES[number] + " of " + suit;
}
}
This simplifies your pack as well
public class PackOfCards {
private final List<Card> cards;
public PackOfCards(int size) {
// note duplicates are possible, i.e. ever card could be the same.
cards = IntStream.range(0, size)
.mapToObj(n -> new Card())
.collect(Collectors.toList());
}
public Card findLargest() {
return cards.stream().max(Comparator.comparing(Card::getNumber)
.thenComparing(Card::getSuit)).get();
}
}
You can change the Card class to implements the Comparable interface. For example:
public class Card implements Comparable<Card> {
....// your current implementation for the Card class
public int compareTo(Card another) {
if (this.suit.compareTo(another.suit) == 0) {
if (this.number < another.number) {
return -1;
} else if (this.number > another.number) {
return 1;
} else {
return 0;
}
} else if (this.suit.compareTo("Diamonds") == 0) {
// Diamonds being the lowest valued suit ...
return -1;
} else if (this.suit.compareTo("Clubs") == 0) {
// ... then Clubs ...
if (another.suit.compareTo("Diamonds") == 0) {
return 1;
} else {
return -1;
}
} else if (this.suit.compareTo("Hearts") == 0) {
// ... Hearts ...
if (another.suit.compareTo("Spades") == 0) {
return -1;
} else {
return 1;
}
} else {
// ... and largest values, Spades
return 1;
}
}
}
Then, you can modify the PackCards to store the cards in an ordered collection. For example:
pack = new TreeSet<Card>();
That way, the cards in the pack are ordered, and the last one is the largest.
If you want to mantain the order in wich the cards was added to the list, you can obtain the largest one in this way:
largest = Collections.max(pack);
For this sort of work, you want to leverage the object-oriented nature of Java and utilize Enums for both the FaceValue and the Suit. Enums are 'naturally ordered' in the order you list them, making your construction and string output a LOT easier:
public class Card implements Comparable<Card> {
private FaceValue faceValue;
private Suit suit;
/*
* Randomly creates a card numbered 1 to 13 (ace = 1!)
* labelled "Hearts","Clubs","Diamonds" or "Spades".
*/
public Card() {
int randomSuit = (int)Math.floor(Math.random() * 4.0); //Number between 0 and 3, inclusive.
int randomFace = (int)Math.floor(Math.random() * 13.0);
this.faceValue = FaceValue.values()[randomFace];
this.suit = Suit.values()[randomSuit];
}
public Card(FaceValue value, Suit suit) {
this.faceValue = value;
this.suit = suit;
}
// TODO Constructor that convert ints and strings to proper enums and call previous constructor
public int compareTo(Card that) {
int comparison = this.suit.compareTo(that.suit);
return (comparison != 0) ? comparison : this.faceValue.compareTo(that.faceValue);
}
public String cardString() {
return this.faceValue + " of " + this.suit;
}
public enum Suit{
DIAMOND, CLUB, HEART, SPADE;
}
public enum FaceValue {
ACE, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING;
} // You can modify this enum if you need to give back something more specific as the string value.
}
Then for your Deck you can simplify things as well by choosing a good data structure, in this case a TreeSet, which will automatically use the compareTo function you've provided for cards to sort the cards.:
public class Deck {
//By using a Set we eliminate duplicates
private final TreeSet<Card> cards;
public Deck(int size) {
cards = Sets.newTreeSet(IntStream.range(0, size)
.mapToObj(n -> new Card())
.collect(Collectors.toList());
}
//Because this is a TreeSet, finding the largest value is trivial.
public Card findLargest() {
return this.cards.last();
}
}
If you need special strings for the cards in your deck, you would do the following modification to FaceValue:
public enum FaceValue {
ACE {
public String toString() { return "Ace"; }
},
ONE {
public String toString() { return "One"; }
},
... // Fill out the rest in the same manner.
KING {
public String toString() { return "King"; }
}
}
Remember that in Object-Oriented programming, the number one rule is that an object should know how behave. Thus, if you find yourself writing a switch statement, chances are you can defer the behavior to the objects themselves. In this case, you need to create sub-objects (the FaceValue and Suit enums) that you assign to a given card. The card asks those sub parts how they are ordered, and how they should respond to a toString request.

Modify a .java file to change constants to enums

I'm trying to finish this homework but it has been a little bit challenging so far, I'm quite new at java:
1). I have to create enums to replace the named constants for rank and suit in Card.java.
2).Make the changes necessary in Deck.java and DisplayDeck.java so they will work with the new Card.java.
This is my code so far for my three classes: Card.java, Deck.java and DisplayDeck.java
Original Card.java
public class Card {
private final int rank;
private final int suit;
// Kinds of suits
public final static int DIAMONDS = 1;
public final static int CLUBS = 2;
public final static int HEARTS = 3;
public final static int SPADES = 4;
// Kinds of ranks
public final static int ACE = 1;
public final static int DEUCE = 2;
public final static int THREE = 3;
public final static int FOUR = 4;
public final static int FIVE = 5;
public final static int SIX = 6;
public final static int SEVEN = 7;
public final static int EIGHT = 8;
public final static int NINE = 9;
public final static int TEN = 10;
public final static int JACK = 11;
public final static int QUEEN = 12;
public final static int KING = 13;
public Card(int rank, int suit) {
assert isValidRank(rank);
assert isValidSuit(suit);
this.rank = rank;
this.suit = suit;
}
public int getSuit() {
return suit;
}
public int getRank() {
return rank;
}
public static boolean isValidRank(int rank) {
return ACE <= rank && rank <= KING;
}
public static boolean isValidSuit(int suit) {
return DIAMONDS <= suit && suit <= SPADES;
}
public static String rankToString(int rank) {
switch (rank) {
case ACE:
return "Ace";
case DEUCE:
return "Deuce";
case THREE:
return "Three";
case FOUR:
return "Four";
case FIVE:
return "Five";
case SIX:
return "Six";
case SEVEN:
return "Seven";
case EIGHT:
return "Eight";
case NINE:
return "Nine";
case TEN:
return "Ten";
case JACK:
return "Jack";
case QUEEN:
return "Queen";
case KING:
return "King";
default:
//Handle an illegal argument. There are generally two
//ways to handle invalid arguments, throwing an exception
//(see the section on Handling Exceptions) or return null
return null;
}
}
public static String suitToString(int suit) {
switch (suit) {
case DIAMONDS:
return "Diamonds";
case CLUBS:
return "Clubs";
case HEARTS:
return "Hearts";
case SPADES:
return "Spades";
default:
return null;
}
}
public static void main(String[] args) {
// must run program with -ea flag (java -ea ..) to
// use assert statements
assert rankToString(ACE) == "Ace";
assert rankToString(DEUCE) == "Deuce";
assert rankToString(THREE) == "Three";
assert rankToString(FOUR) == "Four";
assert rankToString(FIVE) == "Five";
assert rankToString(SIX) == "Six";
assert rankToString(SEVEN) == "Seven";
assert rankToString(EIGHT) == "Eight";
assert rankToString(NINE) == "Nine";
assert rankToString(TEN) == "Ten";
assert rankToString(JACK) == "Jack";
assert rankToString(QUEEN) == "Queen";
assert rankToString(KING) == "King";
assert suitToString(DIAMONDS) == "Diamonds";
assert suitToString(CLUBS) == "Clubs";
assert suitToString(HEARTS) == "Hearts";
assert suitToString(SPADES) == "Spades";
}
}
My modified Card.java so far:
public class Card {
public enum Suit
{
DIAMONDS(1),
CLUBS(2),
HEARTS(3),
SPADES(4);
private final int suit;
private Suit(int suit)
{
this.suit = suit;
}
public int getSuit()
{
return suit;
}
} //end enum suit
public enum Rank
{
ACE(1),
DEUCE(2),
THREE(3),
FOUR(4),
FIVE(5),
SIX(6),
SEVEN(7),
EIGHT(8),
NINE(9),
TEN(10),
JACK(11),
QUEEN(12),
KING(13);
private final int rank;
private Rank(int rank)
{
this.rank = rank;
}
public int getRank()
{
return rank;
}
}//end enum rank
public static String rankToString(Rank rank) {
switch (rank) {
case ACE:
return "Ace";
case DEUCE:
return "Deuce";
case THREE:
return "Three";
case FOUR:
return "Four";
case FIVE:
return "Five";
case SIX:
return "Six";
case SEVEN:
return "Seven";
case EIGHT:
return "Eight";
case NINE:
return "Nine";
case TEN:
return "Ten";
case JACK:
return "Jack";
case QUEEN:
return "Queen";
case KING:
return "King";
default:
//Handle an illegal argument. There are generally two
//ways to handle invalid arguments, throwing an exception
//(see the section on Handling Exceptions) or return null
return null;
}
}
public static String suitToString(Suit suit) {
switch (suit) {
case DIAMONDS:
return "Diamonds";
case CLUBS:
return "Clubs";
case HEARTS:
return "Hearts";
case SPADES:
return "Spades";
default:
return null;
}
}
}//end class
And this are the original Deck.java and DisplayDeck.java:
Original Deck.java
import java.util.*;
public class Deck {
public static int numSuits = 4;
public static int numRanks = 13;
public static int numCards = numSuits * numRanks;
private Card[][] cards;
public Deck() {
cards = new Card[numSuits][numRanks];
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++) {
for (int rank = Card.ACE; rank <= Card.KING; rank++) {
cards[suit-1][rank-1] = new Card(rank, suit);
}
}
}
public Card getCard(int suit, int rank) {
return cards[suit-1][rank-1];
}
}
Modified Deck.java:
import java.util.*;
public class Deck {
public static int numSuits = 4;
public static int numRanks = 13;
public static int numCards = numSuits * numRanks;
private Card[][] cards;
public Deck() {
cards = new Card[numSuits][numRanks];
for (Card.Suit suit : Card.Suit.values()) {
for (Card.Rank rank : Card.Rank.values()) {
// I dont know how to change this to work with Card.java
cards[suit-1][rank-1] = new Card(rank, suit);
}
}
}
public Card getCard(int suit, int rank) {
return cards[suit-1][rank-1];
}
}
and DisplayDeck.java
import java.util.*;
public class DisplayDeck {
public static void main(String[] args) {
Deck deck = new Deck();
/// how can i modify this code to work with both Card.java and Deck.java?
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++) {
for (int rank = Card.ACE; rank <= Card.KING; rank++) {
Card card = deck.getCard(suit, rank);
System.out.format("%s of %s%n",
card.rankToString(card.getRank()),
card.suitToString(card.getSuit()));
}
}
}
}
I update my code on what I got so far.
Get rid of all your int representations for rank and suit. You can replace loops like this:
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++) { ...
with an enhanced for loop:
for (Suit suit : Card.Suit.values()) { ...
Replace mappings from int to String with EnumMap<Suit,String> or EnumMap<Rank,String> as appropriate. Methods for checking whether an int value is valid can be disposed of, as a non-null enum is guaranteed to be a legal value.
EDIT (in response to comment): You can define your deck as simply an array of Card objects:
public class Deck {
private List<Card> cards;
public Deck() {
cards = new ArrayList<>();
for (Card.Suit suit : Card.Suit.values()) {
for (Card.Rank rank : Card.Rank.values()) {
cards.add(new Card(suit, rank));
}
}
}
}
With this, you can use the Collections utility class to trivially implement shuffling:
public class Deck {
. . . // as above
public void shuffle() {
Collections.shuffle(cards);
}
}
Since every enum type comes with a built-in compareTo() method that tells you the relative order of two enum values (of the same type). You can build on this to make the Card class implement Comparable<Card>. (This is left as an exercise for the reader :-)). Then you can trivially sort the deck back into its "brand new" order or even sort hands drawn randomly from the deck.
I see that you are currently retrieving a card by suit and rank. That's a weird way to access cards in a deck, especially since you just turn around and use the Card object to retrieve its suit and rank. But if you really need that kind of retrieval, you can expand the Deck definition to include internally an EnumMap<Suit, EnumMap<Rank, Card>> to allow you to quickly retrieve a card that way. (Yes, each card would then be stored in two distinct data structures inside the Deck object.) A better approach, in my view, is to add a method to retrieve a card by offset into the deck (and another method to tell you the deck size):
public class Deck {
. . .
public Card getCard(int index) {
return cards.get(index);
}
public int cardCount() {
return cards.size();
}
}
To be fancier, you can define a method that returns an iterator over all the cards:
public class Deck {
. . .
public Iterator<Card> iterator() {
return cards.iterator();
}
}
Even fancier yet, you could declare Deck to implement Iterable<Card>. Then you can print the deck contents very simply:
Deck deck = new Deck();
for (Card card : deck) {
// print the card
}

Null Pointer exception error with no obvious code errors

I have an error here and I don't know where it is coming from. I am in a beginner's java class is High School so I don't yet have much experience here. I have 3 programs that incorporate each other.
I have a card class that creates a playing card
//********************************************************************
// Card.java Author: Lewis and Loftus
//
// Solution to Programming Project 4.5
//********************************************************************
import java.util.*;
public class Card
{
public final static int ACE = 1;
public final static int TWO = 2;
public final static int THREE = 3;
public final static int FOUR = 4;
public final static int FIVE = 5;
public final static int SIX = 6;
public final static int SEVEN = 7;
public final static int EIGHT = 8;
public final static int NINE = 9;
public final static int TEN = 10;
public final static int JACK = 11;
public final static int QUEEN = 12;
public final static int KING = 13;
public final static int CLUBS = 1;
public final static int DIAMONDS = 2;
public final static int HEARTS = 3;
public final static int SPADES = 4;
private final static int NUM_FACES = 13;
private final static int NUM_SUITS = 4;
private int face, suit;
private String faceName, suitName;
private int myInt1, myInt2;
Random rand = new Random();
//-----------------------------------------------------------------
// Creates a random card.
//-----------------------------------------------------------------
public Card ()
{
face = rand.nextInt(4) + 1;
setFaceName();
suit = rand.nextInt(13) + 1;
setSuitName();
}
//-----------------------------------------------------------------
// Sets the string representation of the face using its stored
// numeric value.
//-----------------------------------------------------------------
private void setFaceName()
{
switch (face)
{
case 1:
faceName = "Ace";
break;
case 2:
faceName = "Two";
break;
case 3:
faceName = "Three";
break;
case 4:
faceName = "Four";
break;
case 5:
faceName = "Five";
break;
case 6:
faceName = "Six";
break;
case 7:
faceName = "Seven";
break;
case 8:
faceName = "Eight";
break;
case 9:
faceName = "Nine";
break;
case 10:
faceName = "Ten";
break;
case 11:
faceName = "Jack";
break;
case 12:
faceName = "Queen";
break;
case 13:
faceName = "King";
break;
}
}
//-----------------------------------------------------------------
// Sets the string representation of the suit using its stored
// numeric value.
//-----------------------------------------------------------------
private void setSuitName()
{
switch (suit)
{
case 1:
suitName = "Clubs";
break;
case 2:
suitName = "Diamonds";
break;
case 3:
suitName = "Hearts";
break;
case 4:
suitName = "Spades";
break;
}
}
//-----------------------------------------------------------------
// Determines if this card is higher than the passed card. The
// second parameter determines if aces should be considered high
// (beats a King) or low (lowest of all faces). Uses the suit
// if both cards have the same face.
//-----------------------------------------------------------------
public boolean isHigherThan (Card card2, boolean aceHigh)
{
boolean result = false;
if (face == card2.getFace())
{
if (suit > card2.getSuit())
result = true;
}
else
{
if (aceHigh && face == ACE)
result = true;
else
if (face > card2.getFace())
result = true;
}
return result;
}
//-----------------------------------------------------------------
// Determines if this card is higher than the passed card,
// assuming that aces should be considered high.
//-----------------------------------------------------------------
public boolean isHigherThan (Card card2)
{
return isHigherThan (card2, true);
}
//-----------------------------------------------------------------
// Returns the face (numeric value) of this card.
//-----------------------------------------------------------------
public int getFace ()
{
return face;
}
//-----------------------------------------------------------------
// Returns the suit (numeric value) of this card.
//-----------------------------------------------------------------
public int getSuit ()
{
return suit;
}
//-----------------------------------------------------------------
// Returns the face (string value) of this card.
//-----------------------------------------------------------------
public String getFaceName ()
{
return faceName;
}
//-----------------------------------------------------------------
// Returns the suit (string value) of this card.
//-----------------------------------------------------------------
public String getSuitName ()
{
return suitName;
}
//-----------------------------------------------------------------
// Returns the string representation of this card, including
// both face and suit.
//-----------------------------------------------------------------
public String toString ()
{
return faceName + " of " + suitName;
}
}
I have a Deck Of cards file that creates 52 cards
import java.util.*;
public class DeckOfCards
{
private Card deckOfCards[];
private int currentCardUsed;
private final int NumberOfCards = 52;
private int nextCard;
private Random rand;
String myString = "All Cards have been dealt.";
public DeckOfCards()
{
deckOfCards = new Card[NumberOfCards];
currentCardUsed = 0;
Random rand = new Random();
for(int index = 0; index < deckOfCards.length; index ++)
{
deckOfCards[index] = new Card();
}
}
public void shuffleCards()
{
currentCardUsed = 0;
for(int newCard = 0; newCard < deckOfCards.length; newCard ++)
{
int nextCard = rand.nextInt(NumberOfCards);
Card temporaryDeck = deckOfCards[newCard];
deckOfCards[newCard] = deckOfCards[nextCard];
deckOfCards[nextCard] = temporaryDeck;
}
}
public Card dealCard()
{
if(currentCardUsed < deckOfCards.length)
{
return deckOfCards[currentCardUsed ++];
}
else
{
return null;
}
}
}
And finally I have a driver class
public class DeckTester
{
public static void main(String [] args)
{
DeckOfCards deck = new DeckOfCards();
deck.shuffleCards();
System.out.println(deck.dealCard());
System.out.println(deck.dealCard());
System.out.println(deck.dealCard());
System.out.println(deck.dealCard());
System.out.println(deck.dealCard());
System.out.println(deck.dealCard());
}
}
None of them have errors. But when I run the driver I get this for the output
Exception in thread "main" java.lang.NullPointerException
at DeckOfCards.shuffleCards(DeckOfCards.java:39)
at DeckTester.main(DeckTester.java:8)
I have tried changing the Null in the deal Method to no avail.
It looks like you are declaring a local Random object in your constructor.
Try changing line 25 to be:
rand = new Random();
The line Random rand = new Random(); in your constructor creates a local object rand whose scope is limited to constructor only. You have two options to fix this issue :-
1) Change line in your constructor to
Random rand = new Random(); ---> this.rand = new Random()
2) Initialize your instance object at the time of declaration only. Change line
private Random rand; ---> private Random rand = new Random();

How can I declare the suits Diamond and Hearts?

Okay in the code below I want to declare that "Diamonds" and "Hearts" are red.
Code Here
if (card.getCardFace() == || card.getCardFace() == )
g.setColor(Color.red);
else
g.setColor(Color.black);
I was wondering on how I could do that if I declared them as chars in my Card class. Do I have to change that ?
Card Class
// Instance Data - all things common to all cards
private String cardFace; // king, q, j, 10 - 2, A
private int faceValue; // numberic value of the card
private char cardSuit; // hold suit of the card
private char suits[] = {(char)(003), (char)(004), (char)(005), (char)(006)};
// Constructor
public PlayingCard(int value, int suit)
{
faceValue = value;
setFace();
setSuit(suit);
}
// helper setFace()
public void setFace()
{
switch(faceValue)
{
case 1:
cardFace = "A";
faceValue = 14;
break;
case 11:
cardFace = "J";
break;
case 12:
cardFace = "Q";
break;
case 0:
cardFace = "K";
faceValue = 13;
break;
default:
cardFace = ("" + faceValue);
}
}
public void setSuit(int suit) // suit num between 0 and 3
{
cardSuit = suits[suit];
}
// other helpers
public int getFaceValue()
{
return faceValue;
}
public String getCardFace()
{
return cardFace;
}
public String toString()
{
return (cardFace + cardSuit);
}
}
(Also let me know if you need more code)
You should use Enums to define types for ranks and suits, something like:
public static enum Suit {
CLUB, DIAMOND, SPADE, HEART
}
public static enum Rank {
TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), SIX("6"), SEVEN("7"),
EIGHT("8"), NINE("9"), TEN("10"), JACK("J"), QUEEN("Q"), KING("K"),
ACE("A");
private final String symbol;
Rank(String symbol) {
this.symbol = symbol;
}
public String getSymbol() {
return symbol;
}
}
---
class Card {
Suit suit;
Rank rank;
}
Then just compare the values:
if (card.suit == Suit.DIAMONDS || card.suit == Suit.HEARTH) {
color = Color.RED;
} else {
color = Color.BLACK;
}
Or define a color as a property of Suit and then just use:
color = card.suit.getColor();

Categories