liquardo
liquardo

Reputation: 103

How to properly end simple card game?

I'm creating a simple high/low card game as my first game mode, where you need to guess if the next card is higher or lower then the current card. I've implemented a GUI as a JPanel and the game logic mostly resides in a separate class.

My problem is that I can't get the game to halt at Game Over properly. As in, if the guess is correct, the score on GUI updates and the cards move to the next one. If answer is wrong, show final score and replace high/low buttons with restart button. Currently there's something wrong in the logic and I can't figure out what it is, as the game seems to end quite randomly, even if answer should be correct, and sometimes it doesn't end, when it should.

Can someone help me spot the problem?

What is generally the best way to track if a game is over in java?

This is the game's JPanel

/*imports were here*/
public class gamePanel_highLow extends javax.swing.JPanel {

    private highLow game = new highLow();
    private boolean playedGame = false;


    /**
     * Initializes the game view and makes restart button invisible
     */
    public gamePanel_highLow() {
        initComponents();
        restartButton.setVisible(false);
    }

    /* stuff for init components made by gui editor were here */                        

    private void lowerButtonActionPerformed(java.awt.event.ActionEvent evt) {                                            
        Card card = game.getCurrentCard();        
        BufferedImage cardIMG = card.getCardImage();
        Image scaledCard = cardIMG.getScaledInstance( 90, 138,  java.awt.Image.SCALE_SMOOTH ) ;
        cardImage.setIcon(new ImageIcon(scaledCard));               
        currentCard.setText(game.getCurrentCard().toString() + " [" + game.getCurrentCard().getCardIntValue() + "]");                      

        playedGame = game.chooseLow();

            if(playedGame == true) { // maybe not best wording, as check is gameOver = true
                score.setText("---");
                cardIMG = card.getCardBackImage();
                scaledCard = cardIMG.getScaledInstance( 90, 138,  java.awt.Image.SCALE_SMOOTH ) ;
                cardImage.setIcon(new ImageIcon(scaledCard));             
                lowerButton.setVisible(false);
                higherButton.setVisible(false);
                text_or.setVisible(false);
                restartButton.setVisible(true);
                currentCard.setText(game.getCurrentCard().toString() + " [" + game.getCurrentCard().getCardIntValue() + "]" + "final score: " + game.getCurrentScore());
            }
            else {
                score.setText(game.getCurrentScore() + "");
            }
    }                                           

    private void higherButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
        Card card = game.getCurrentCard();        
        BufferedImage cardIMG = card.getCardImage();
        Image scaledCard = cardIMG.getScaledInstance( 90, 138,  java.awt.Image.SCALE_SMOOTH ) ;
        cardImage.setIcon(new ImageIcon(scaledCard));               
        currentCard.setText(game.getCurrentCard().toString() + " [" + game.getCurrentCard().getCardIntValue() + "]");                      

        playedGame = game.chooseHigh();

            if(playedGame == true) {
                score.setText("---");
                cardIMG = card.getCardBackImage();
                scaledCard = cardIMG.getScaledInstance( 90, 138,  java.awt.Image.SCALE_SMOOTH ) ;
                cardImage.setIcon(new ImageIcon(scaledCard));             
                lowerButton.setVisible(false);
                higherButton.setVisible(false);
                text_or.setVisible(false);
                restartButton.setVisible(true);
                currentCard.setText(game.getCurrentCard().toString() + " [" + game.getCurrentCard().getCardIntValue() + "]" + "final score: " + game.getCurrentScore());
            }
            else {
                score.setText(game.getCurrentScore() + "");
            }
    }                                            

    private void restartButtonActionPerformed(java.awt.event.ActionEvent evt) {                                              
        lowerButton.setVisible(true);
        higherButton.setVisible(true);
        text_or.setVisible(true);
        restartButton.setVisible(false);

        Card card = game.getCurrentCard();
        BufferedImage cardIMG = card.getCardImage();
        Image scaledCard = cardIMG.getScaledInstance( 90, 138,  java.awt.Image.SCALE_SMOOTH ) ;
        cardImage.setIcon(new ImageIcon(scaledCard));

        currentCard.setText(game.getCurrentCard().toString() + " [" + game.getCurrentCard().getCardIntValue() + "]");

        playedGame = false;
        game = new highLow();
    }

And here is the game logic class:

public class highLow {

      private int correctGuesses = 0;      
      private CardDeck deck;           
      private Card currentCard;
      private Card nextCard;      
      private Boolean gameOver = false;

    /**
     * Initializes the game
     */
    public highLow() {
        deck = new CardDeck();
        deck.fillDeck();
        deck.shuffleDeck();
        correctGuesses = 0;
        gameOver = false;
        currentCard = deck.dealCard();
        nextCard = null;
    }

    public Card getCurrentCard() {
        return currentCard;
    }

    public Card getNextCard() {
        return nextCard;
    }

    public int getCurrentScore() {
        return correctGuesses;
    }

    public boolean getGameOver() {
        return gameOver;
    }

    /**
     * Guesses next card is higher than current card.
     * @return If correct, add 1 to correctGuesses and return 1.
     * @return If wrong, set game over and return 0.
     */
    public boolean chooseHigh() {   

        nextCard = deck.dealCard();

        if(nextCard.getCardIntValue() > currentCard.getCardIntValue()) {
                correctGuesses++;
                gameOver = false;
        }
        else {
            gameOver = true;
        }
    currentCard = nextCard;
    return gameOver;
}    

    /**
     * Guesses next card is lower than current card.
     * @return If correct, add 1 to correctGuesses and return 1.
     * @return If wrong, set game over and return 0.
     */
    public boolean chooseLow() {

       nextCard = deck.dealCard();

        if(nextCard.getCardIntValue() < currentCard.getCardIntValue()) {
                correctGuesses++;
                gameOver = false;
        }
        else {
            gameOver = true;
        }
    currentCard = nextCard;
    return gameOver;
} 
}

This is very barebones, sure, but I don't see why the gameOver doesn't work nor how I could fix it. Been at if for quite a while, but a new fix breaks something else.

Edit: Here's the Card class:

/*imports*/

public class Card implements Comparable {
private CardSuit  suit;
private CardValue value;
private BufferedImage image;
private static boolean sortByValue = true;

/**
 *
 * @param card_suit     Suit of the card (clubs, spades, diamonds, hearts) 
 * @param card_value    Value of the card (1-14)
 * @param card_image    Image file used in GUI
 */
public Card (CardSuit card_suit, CardValue card_value, BufferedImage card_image) {
    suit  = card_suit;
    value = card_value;
    image = card_image;
}

/**
 *
 * @return The card's suit
 */
public CardSuit getCardSuit() {
    return suit;
}

/**
 *
 * @return The card's value
 */
public CardValue getCardValue() {
    return value;
}

/**
 *
 * @param suit  Card suit for filename
 * @param value Card value for filename
 * @return The specific filename located in cardImages folder 
 */
public static String getImageFilename( CardSuit suit, CardValue value ) {
    return suit.getSuitAcronym() + value.getValueAcronym() + ".png";
}

/**
 *
 * @return Buffered image of a specific card to be used in GUI
 */
public BufferedImage getCardImage() {
    return image;
}

/**
 *
 * @return get image representing back of the card
 */
public BufferedImage getCardBackImage() {

    String imageFile = "src/main/java/cardImages/back.png";   // Stores image filename.
                BufferedImage img = null; // Initializes image as null.
                try {
                    img = ImageIO.read(new File(imageFile));    // Places proper image path to img variable
                }
                catch (IOException e) {
                    e.printStackTrace();  // Traces any errors
                }
    return img;                   
}

/**
 *
 * @return Cards value in integer form for easier comparison
 */
public int getCardIntValue() {
    return value.getCardInt();
}

/**
 *
 * @return prints suit name
 */
public String suitToString() { 
    return suit.toString();
}

/**
 *
 * @return prints card value
 */
public String valueToString() {
    return value.getValue();
}

public String toString() { //print card suit and value
    return value.toString() + " of " + suit.toString();
}

/**
 *
 * @return
 */
public String toStringWithIntegers() { //print card suit and numerical version of value
    return value.getCardInt() + " of " + suit.toString();
}

/**
 *  card sorting aid for deck and shuffle
 */
public static void sortCardsBySuit() { 
        sortByValue = false;
}

/**
 *  card sorting aid for deck and shuffle
 */
public static void sortCardsByValue() { 
        sortByValue = true;
}

/**
 *
 * @param card card object to compare with
 * @return compares suit and value to another card object.
 */
public boolean sameAs( Card card ) {
  if ( ( value != card.value ) || ( suit != card.suit ) )
     return false;
  else
     return true;
}

public int compareTo(Object otherCardObj) { //another comparison used only for sorting cards and creating a deck.
    Card otherCard = (Card) otherCardObj;
    int value_difference =  value.compareTo(otherCard.value);
    int suit_difference =   suit.compareTo(otherCard.suit);

    if ( sortByValue ) {
     if ( value_difference != 0 )
        return value_difference;
     else
        return suit_difference;
  }
  else {
     if ( suit_difference != 0 )
        return suit_difference;
     else
        return value_difference;
  }
}
}

And CardValue class which assigns value to the cards. SuitValue is not really used in this game so pretty sure not needed here:

/*imports*/

public class CardValue implements Comparable {
private String name;     // full name of value
private String acronym;  // acronym of value, used in the image files

private CardValue( String value_name, String value_acronym ) {
  name    = value_name;
  acronym = value_acronym;
}

// All card values

public final static CardValue TWO   = new CardValue("Two",   "2" );
public final static CardValue THREE = new CardValue("Three", "3" );
public final static CardValue FOUR  = new CardValue("Four",  "4" );
public final static CardValue FIVE  = new CardValue("Five",  "5" );
public final static CardValue SIX   = new CardValue("Six",   "6" );
public final static CardValue SEVEN = new CardValue("Seven", "7" );
public final static CardValue EIGHT = new CardValue("Eight", "8" );
public final static CardValue NINE  = new CardValue("Nine",  "9" );
public final static CardValue TEN   = new CardValue("Ten",   "10");
public final static CardValue JACK  = new CardValue("Jack",  "11");
public final static CardValue QUEEN = new CardValue("Queen", "12");
public final static CardValue KING  = new CardValue("King",  "13");
public final static CardValue ACE   = new CardValue("Ace",   "14");

String getValue() {
    return name;
}

/**
 *
 * @return get value acronym
 */
public String getValueAcronym() {
    return acronym;
}

/**
 *
 * @return get value as int
 */
public int getCardInt() {
    return Integer.parseInt(acronym);
}

/**
 *
 * @return print name of value eg. Jack
 */
  @Override
public String toString() {
  return name;
}

// All values in a list for comparison.

    public final static java.util.List VALUES =
  Collections.unmodifiableList( Arrays.asList( new CardValue[] { TWO, THREE, FOUR, FIVE, SIX, SEVEN,
                                                                 EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE }));
@Override
public int compareTo(Object otherValueObj) {
  CardValue otherValue = (CardValue) otherValueObj;
  return VALUES.indexOf( this ) - VALUES.indexOf( otherValue );
}
}

Edit 2: Removed the new game from choose low/high buttons, now it's only on the restart button. I also added Rihards' ideas into the logic, still not quite functioning properly.

Here's what the layout looks like: http://gyazo.com/b8b5fe50185a134cc1cf0c320d8597d1

Dies after 1-3 clicks and even those might be just luck/random.

Upvotes: 2

Views: 198

Answers (1)

Rihards Fridrihsons
Rihards Fridrihsons

Reputation: 854

I see 2 problems here, those might cause some issues:

1)you are initiating dealing new cards

currentCard = deck.dealCard(); 
nextCard = deck.dealCard(); 

and then on chosing if higher or lower you draw a card again, so 1 card is wasted.

2)You are always checking nextCard as current card, so you do not actually see the nextCard in output, you see CurrentCard and previousCard

try this:

public boolean chooseHigh() {
        nextCard = deck.dealCard();

            if(nextCard.getCardIntValue() > currentCard.getCardIntValue()) {
                    correctGuesses++;
                    gameOver = false;
            }
            else {
                gameOver = true;
            }
        currentCard = nextCard;
        return gameOver;
    }   

and change this on init:

public highLow() {
    ...
    nextCard = null;
}

Edit1: Okay, i just noticed that you check the next card, but you display the previous card, the new card gets updated only on the next round or after you lose try this:

    private void lowerButtonActionPerformed(java.awt.event.ActionEvent evt) {                                            

            playedGame = game.chooseLow();

                if(playedGame == true) { // maybe not best wording, as check is gameOver = true
                    score.setText("---");
                    cardIMG = card.getCardBackImage();
                    scaledCard = cardIMG.getScaledInstance( 90, 138,  java.awt.Image.SCALE_SMOOTH ) ;
                    cardImage.setIcon(new ImageIcon(scaledCard));             
                    lowerButton.setVisible(false);
                    higherButton.setVisible(false);
                    text_or.setVisible(false);
                    restartButton.setVisible(true);
                    currentCard.setText(game.getCurrentCard().toString() + " [" + game.getCurrentCard().getCardIntValue() + "]" + "final score: " + game.getCurrentScore());
                }
                else {
                    score.setText(game.getCurrentScore() + "");
                }

            Card card = game.getCurrentCard();        
            BufferedImage cardIMG = card.getCardImage();
            Image scaledCard = cardIMG.getScaledInstance( 90, 138,  java.awt.Image.SCALE_SMOOTH ) ;
            cardImage.setIcon(new ImageIcon(scaledCard));               
            currentCard.setText(game.getCurrentCard().toString() + " [" + game.getCurrentCard().getCardIntValue() + "]");    
        }  

Upvotes: 3

Related Questions