Reputation: 103
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
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