bgb102 bgb102 - 19 days ago 5
Java Question

How to apply suits to the cards in matching game?

Basically, the project description asks the user to create a matching game, consisting of:


  1. A blueprint for the creation of playing card whose attributes are:
    suit, face value, faceUp status, and an optional unicode value for the suit icon

  2. A two dimensional playing table (4x4), 16 pairs of matching cards, and a running count of the number of face-down cards. Include a method to retrieve a specific card from the table at an input x,y position.

  3. A gameBoard, and loop that continues play until all cards remain face up.
    The loop includes an interface with the user to pick two cards (inputting x,y table positions), checking if two cards are equal, decrementing the count of faceDown cards, and setting the faceUp boolean of the cards.
    Essnetially, the program should run until all the cards are face up, and the game is won. I separated my program in to four separate classes below.



1.

public class Card {
private final int cardValue;
private boolean faceUp;

public Card(int value) {
cardValue = value;
faceUp = false;
}

public int getValue() {
return cardValue;
}

public boolean isFaceUp() {
return faceUp;
}

public void setFaceUp(boolean input) {
faceUp = input;
}

public static void printBoard(Card[][] cards) {
System.out.println("\t\t1\t2\t3\t4");
System.out.println("\t____________");

for(int i = 0; i < cards.length; i++) {
System.out.println((i + 1) + "\t|\t");

for(int j = 0; j < cards[0].length; j++)
if(cards[i][j].isFaceUp()) {
System.out.print(cards[i][j].getValue() + "\t"); }
else
System.out.println("*\t");

}
System.out.println();
}

}


2.

public class CreateBoard {

public static Card[][] createBoard() {
Card[][] board = new Card[4][4];

for(int i = 1; i <= 8; i++) {
for(int j = 1; j <= 2; j++) {

boolean boardLocation = false;

while(!boardLocation) {
int row = (int)(Math.random() * 4);
int column = (int)(Math.random() * 4);

if(board[row] == null && board[column] == null) {
boardLocation = true;
board[row][column] = new Card(i);
}
}
}
}
return board;
}
}


3.

public class Game {
public static boolean wonGame(Card[][] board) {
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[0].length; j++) {
if(!board[i][j].isFaceUp())
return false;
}
}
return true;
}

}


And finally, the main class:

public class GameDriver {
public static void main(String[] args) {
Card[][] board = CreateBoard.createBoard();
Scanner keyboard = new Scanner(System.in);

System.out.println("Starting Game...");

while(!Game.wonGame(board)) {
Card.printBoard(board);

System.out.println("Enter X-Coordinate #1 (1-4): ");
int column1 = keyboard.nextInt();

System.out.println("Enter Y-Coordinate #1 (1-4): ");
int row1 = keyboard.nextInt();

System.out.println("Enter X-Coordinate #2 (1-4): ");
int column2 = keyboard.nextInt();

System.out.println("Enter Y-Coordinate #2 (1-4): ");
int row2 = keyboard.nextInt();

Card card1 = board[row1][column1];
Card card2 = board[row2][column2];

if(card1.getValue() == card2.getValue() && !(row1 == row2 && column1 == column2))
{
card1.setFaceUp(true);
card2.setFaceUp(true);
}

else if(row1 == row2 && column1 == column2)
{
System.out.println("Points selected are the same, try again");
}

else
{
System.out.println(card1.getValue() + " and " + card2.getValue() + " do not match");

}
}
Card.printBoard(board);
}
}


Code runs perfectly, but I am mostly clueless on how to add suits to the card. I would just need two suits applied to every card on the board (Hearts and Diamonds for example, so if the code produced two 4s, one would get the hearts and one would get diamonds) I know I could use an enumeration, but I don't really understand how they work. Help would be much appreciated!

Answer

Here's a guide to enums I recommend you read. It's quick reading, plenty of examples. The Java Tutorials generally are pretty useful.

Here's some code you can use.

public enum Suit {
    HEARTS
    ,SPADES
    ,DIAMONDS
    ,CLUBS
}

public class Card {
    private final int cardValue;
    private final Suit suit;
    private boolean faceUp;

    public Card(int value, Suit suit) {
         this.cardValue = value;
         this.faceUp = false;
         this.suit = suit;
    }
    // ...snip...
    public Suit getSuit() {
        return this.suit;
    }
}

And you'd construct the card with a call like:

Card myCard = new Card(3, Suit.HEARTS);

I strongly recommend you not take the advice of just using a set of char values. Why? A bunch of reasons. For one thing, if you use an enum type, you know someone can't accidentally pass you an invalid value; a typo can't screw up your entire program. For another, you don't need to pass around the list of acceptable chars everywhere, or- worse- have a switch-case or an if-statement checking every possible value every time and throwing an error if someone uses an invalid value.

Then there's the fact that, if you use only one char per enum value, the enum values can't have meaningful names (how is someone supposed to figure out what 'C' and 'S' mean?), whereas there's very little ambiguity in Suit.CLUBS or Suit.SPADES (and, remember, code is written for people, not computers. Be very suspicious of anyone inexperienced enough to argue otherwise).

Comments