librejack

Blackjack clone written in java
git clone https://github.com/michaelneuper/librejack.git
README | Files | Log | Refs | LICENSE

commit 7a3e8fcee5048e7960ee1950c8e30d6e7a3671be
parent 81522dcbbed44cd59d3b4e2bcc760f553690cef0
Author: Michael Neuper <michael@michaelneuper.com>
Date:   Fri, 28 Apr 2023 16:42:49 +0200

Refactor

Diffstat:
Msrc/controller/Controller.java | 111+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/controller/Hand.java | 16++++++++--------
Msrc/controller/LoginController.java | 23++++++++++-------------
Msrc/model/Card.java | 1+
Msrc/model/Deck.java | 18++++++++++--------
Msrc/model/Player.java | 22+++++++++++-----------
Msrc/model/Statistics.java | 17++++++++++-------
7 files changed, 108 insertions(+), 100 deletions(-)

diff --git a/src/controller/Controller.java b/src/controller/Controller.java @@ -21,12 +21,14 @@ import model.Statistics; */ public class Controller { - private Deck deck, discarded; + private final Deck DECK; + private final Deck DISCARDED; + + private final Dealer DEALER; + private final Player PLAYER; + private final Statistics STATS; - private Dealer dealer; - private Player player; private double bet, balance; - private Statistics stats = new Statistics(); /** * Creates a new instance of the Controller class. Initializes the dealer @@ -34,20 +36,22 @@ public class Controller { * player. The deck is also populated and shuffled. */ public Controller() { + this.STATS = new Statistics(); + // create new dealer and player - dealer = new Dealer(); - player = new Player(); + DEALER = new Dealer(); + PLAYER = new Player(); - balance = player.getBalance(); + balance = PLAYER.getBalance(); bet = 100.0; // create new populated deck - deck = new Deck(); - deck.populate(); - deck.shuffle(); + DECK = new Deck(); + DECK.populate(); + DECK.shuffle(); // create new empty deck - discarded = new Deck(); + DISCARDED = new Deck(); } /** @@ -103,21 +107,21 @@ public class Controller { public void startRound() { // if we run out of cards - dealer.getHand().discardHandToDeck(discarded); - player.getHand().discardHandToDeck(discarded); + DEALER.getHand().discardHandToDeck(DISCARDED); + PLAYER.getHand().discardHandToDeck(DISCARDED); // make sure deck has at least 4 cards left - if (deck.cardsLeft() < 4) { - deck.reloadDeckFromDiscard(discarded); + if (DECK.cardsLeft() < 4) { + DECK.reloadDeckFromDiscard(DISCARDED); } // give the dealer 2 cards - dealer.getHand().takeCardFromDeck(deck); - dealer.getHand().takeCardFromDeck(deck); + DEALER.getHand().takeCardFromDeck(DECK); + DEALER.getHand().takeCardFromDeck(DECK); // give the player 2 cards - player.getHand().takeCardFromDeck(deck); - player.getHand().takeCardFromDeck(deck); + PLAYER.getHand().takeCardFromDeck(DECK); + PLAYER.getHand().takeCardFromDeck(DECK); } @@ -130,67 +134,68 @@ public class Controller { public String checkWhoWins() { // check if dealer has blackjack - if (dealer.hasBlackjack()) { - dealer.printHand(); // show full hand + if (DEALER.hasBlackjack()) { + DEALER.printHand(); // show full hand - if (player.hasBlackjack()) { - stats.incrementPushes(); + if (PLAYER.hasBlackjack()) { + STATS.incrementPushes(); return "You both have 21 - Push"; } else { balance -= bet; - player.setBalance(balance); - stats.incrementLosses(); - dealer.printHand(); + PLAYER.setBalance(balance); + STATS.incrementLosses(); + DEALER.printHand(); return "Dealer has BlackJack - You lose"; } } // check if player has blackjack - if (player.hasBlackjack()) { + if (PLAYER.hasBlackjack()) { balance += bet * 1.5; - player.setBalance(balance); - stats.incrementWins(); + PLAYER.setBalance(balance); + STATS.incrementWins(); return "You have BlackJack - You win"; } // check whether player busted - if (player.getHand().calculateValue() > 21) { + if (PLAYER.getHand().calculateValue() > 21) { balance -= bet; - player.setBalance(balance); - stats.incrementLosses(); + PLAYER.setBalance(balance); + STATS.incrementLosses(); return "Busted"; } // dealer's turn - dealer.printHand(); - while (dealer.getHand().calculateValue() < 17) { - dealer.hit(deck, discarded); + DEALER.printHand(); + while (DEALER.getHand().calculateValue() < 17) { + DEALER.hit(DECK, DISCARDED); } // check who wins - if (dealer.getHand().calculateValue() > 21) { + if (DEALER.getHand().calculateValue() > 21) { balance += bet; - player.setBalance(balance); - stats.incrementWins(); + PLAYER.setBalance(balance); + STATS.incrementWins(); return "Dealer busts - You win"; } - if (dealer.getHand().calculateValue() > player.getHand().calculateValue() && dealer.getHand().calculateValue() <= 21) { + if (DEALER.getHand().calculateValue() > PLAYER.getHand().calculateValue() + && DEALER.getHand().calculateValue() <= 21) { balance -= bet; - player.setBalance(balance); - stats.incrementLosses(); + PLAYER.setBalance(balance); + STATS.incrementLosses(); return "You lose"; } - if (player.getHand().calculateValue() > dealer.getHand().calculateValue()) { + if (PLAYER.getHand().calculateValue() > DEALER.getHand().calculateValue()) { balance += bet; - player.setBalance(balance); - stats.incrementWins(); + PLAYER.setBalance(balance); + STATS.incrementWins(); return "You win"; } - if (player.getHand().calculateValue() == dealer.getHand().calculateValue()) { - stats.incrementPushes(); + if (PLAYER.getHand().calculateValue() == DEALER.getHand().calculateValue()) { + STATS.incrementPushes(); return "Push"; } @@ -201,7 +206,7 @@ public class Controller { * Hits the player with a card. */ public void hitPlayer() { - player.hit(deck, discarded); + PLAYER.hit(DECK, DISCARDED); } /** @@ -209,7 +214,7 @@ public class Controller { * @return player hand */ public String displayPlayerHand() { - return player.printHand(); + return PLAYER.printHand(); } /** @@ -217,7 +222,7 @@ public class Controller { * @return the value of the player's hand */ public String displayPlayerHandValue() { - return Integer.toString(player.getHand().calculateValue()); + return Integer.toString(PLAYER.getHand().calculateValue()); } /** @@ -225,7 +230,7 @@ public class Controller { * @return dealer hand */ public String displayDealerHand() { - return dealer.printHand(); + return DEALER.printHand(); } /** @@ -233,7 +238,7 @@ public class Controller { * @return value of dealer's hand */ public String displayDealerHandValue() { - return Integer.toString(dealer.getHand().calculateValue()); + return Integer.toString(DEALER.getHand().calculateValue()); } /** @@ -241,7 +246,7 @@ public class Controller { * @return dealer's first card */ public String displayDealerFirstCard() { - return dealer.printFirstHand(); + return DEALER.printFirstHand(); } /** @@ -249,7 +254,7 @@ public class Controller { * @return value of the first card */ public String displayDealerFirstCardValue() { - return dealer.printFirstCardValue(); + return DEALER.printFirstCardValue(); } } diff --git a/src/controller/Hand.java b/src/controller/Hand.java @@ -14,13 +14,13 @@ import model.Deck; */ public class Hand { - private ArrayList<Card> hand; + private final ArrayList<Card> HAND; /** * Creates a new empty Hand object. */ public Hand() { - hand = new ArrayList<Card>(); + HAND = new ArrayList<>(); } /** @@ -29,7 +29,7 @@ public class Hand { * @param deck deck to take card from */ public void takeCardFromDeck(Deck deck) { - hand.add(deck.takeCard()); + HAND.add(deck.takeCard()); } /** @@ -41,7 +41,7 @@ public class Hand { int value = 0; // current total value int aceCount = 0; // number of aces - for (Card card : hand) { + for (Card card : HAND) { value += card.getValue(); // add card value to hand // count number of aces @@ -69,7 +69,7 @@ public class Hand { * @return the card at index i */ public Card getCard(int i) { - return hand.get(i); + return HAND.get(i); } /** @@ -80,8 +80,8 @@ public class Hand { * added */ public void discardHandToDeck(Deck discardDeck) { - discardDeck.addCards(hand); // copy cards from discardDeck - hand.clear(); // clear the hand + discardDeck.addCards(HAND); // copy cards from discardDeck + HAND.clear(); // clear the hand } /** @@ -93,7 +93,7 @@ public class Hand { public String toString() { String ret = ""; // holds string to return - for (Card card : hand) { + for (Card card : HAND) { ret += card + " - "; } diff --git a/src/controller/LoginController.java b/src/controller/LoginController.java @@ -52,26 +52,25 @@ public class LoginController { * @return true if the email is a valid email format, false otherwise */ private boolean isValidEmail(String email) { - // Check if email is null + // check if email is null if (email == null) { JOptionPane.showMessageDialog(null, "Please enter an email"); } - // Define regular expression pattern for valid email addresses + // define regular expression pattern for valid email addresses String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\." + "[a-zA-Z0-9_+&*-]+)*@" + "(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"; Pattern pattern = Pattern.compile(emailRegex); - // Check if email matches the pattern + // check if email matches the pattern boolean isValid = pattern.matcher(email).matches(); - // If email is not valid, show error message + // if email is not valid, show error message if (!isValid) { JOptionPane.showMessageDialog(null, "Please enter a valid email"); } - // Return whether email is valid return isValid; } @@ -84,16 +83,16 @@ public class LoginController { * false otherwise */ private boolean isValidSouthAfricanMobileNumber(String mobileNumber) { - // Remove any non-digit characters from the mobile number + // remove any non-digit characters from the mobile number mobileNumber = mobileNumber.replaceAll("[^\\d]", ""); - // Check if the mobile number is of the correct length + // check if the mobile number is of the correct length if (mobileNumber.length() != 10) { JOptionPane.showMessageDialog(null, "Your mobile number is too short"); return false; } - // Check if the mobile number starts with a valid South African country code + // check if the mobile number starts with a valid South African country code String[] validCountryCodes = {"+27", "27", "0"}; boolean validCountryCode = false; for (String code : validCountryCodes) { @@ -107,7 +106,6 @@ public class LoginController { return false; } - // If all checks pass, the mobile number is considered valid return true; } @@ -119,19 +117,19 @@ public class LoginController { * old, false otherwise */ private static boolean isValidDateAndAdult(Date date) { - // Check if the date is null + // check if the date is null if (date == null) { JOptionPane.showMessageDialog(null, "Please enter a date of birth"); return false; } - // Check if the date is in the past + // make sure the date is in the past if (date.after(new Date())) { JOptionPane.showMessageDialog(null, "You were not born in the future!"); return false; } - // Check if the person is at least 18 years old + // check if the person is at least 18 years old Calendar dob = Calendar.getInstance(); dob.setTime(date); Calendar now = Calendar.getInstance(); @@ -147,7 +145,6 @@ public class LoginController { return false; } - // If all checks pass, the date is valid and the person is at least 18 return true; } diff --git a/src/model/Card.java b/src/model/Card.java @@ -35,6 +35,7 @@ public class Card { * * @return the name of the suit */ + @Override public String toString() { return suitName; } diff --git a/src/model/Deck.java b/src/model/Deck.java @@ -27,7 +27,7 @@ public class Deck { * Deck constructor */ public Deck() { - this.deck = new ArrayList<Card>(); + this.deck = new ArrayList<>(); } /** @@ -47,17 +47,18 @@ public class Deck { * Shuffles deck using a temporary deck for storing cards in random order. */ public void shuffle() { - ArrayList<Card> shufDeck = new ArrayList<Card>(); // temporary deck for storing cards in random order + ArrayList<Card> shufDeck = new ArrayList<>(); // temporary deck for storing cards in random order Random random = new Random(); int randomCardIndex = 0; - while (deck.size() > 0) { + while (!deck.isEmpty()) { // generate random index randomCardIndex = random.nextInt(this.deck.size()); shufDeck.add(this.deck.get(randomCardIndex)); // add card to random index of temporary deck this.deck.remove(randomCardIndex); // remove card from original deck } + this.deck = shufDeck; } @@ -88,7 +89,7 @@ public class Deck { * @return true if the deck has cards in or false if the deck is empty */ public boolean hasCards() { - return deck.size() > 0; + return !deck.isEmpty(); } /** @@ -99,18 +100,18 @@ public class Deck { } /** - * Adds arraylist of cards to deck. + * Adds ArrayList of cards to deck. * - * @param cards arraylist of cards to be added to deck + * @param cards ArrayList of cards to be added to deck */ public void addCards(ArrayList<Card> cards) { deck.addAll(cards); } /** - * Returns arraylist containing all the cards in the deck. + * Returns ArrayList containing all the cards in the deck. * - * @return deck arraylist with the cards + * @return deck ArrayList with the cards */ public ArrayList<Card> getCards() { return deck; @@ -149,6 +150,7 @@ public class Deck { ret += card; ret += "\n"; } + return ret; } diff --git a/src/model/Player.java b/src/model/Player.java @@ -35,37 +35,37 @@ public class Player extends Person { } /** - * Gets the player's current balance from a file. + * Gets the player's current balance from a file. If a FileNotFoundException + * is thrown during the file reading process, it is caught and printed to + * the standard error stream. * * @return balance the player's current balance */ public double getBalance() { - try { - Scanner scFile = new Scanner(new File(BALANCE_FILE)); + try (Scanner scFile = new Scanner(new File(BALANCE_FILE))) { this.balance = scFile.nextDouble(); - scFile.close(); } catch (FileNotFoundException e) { - System.out.println("Error: " + BALANCE_FILE + " not found."); + System.err.println("Error reading " + BALANCE_FILE); } return this.balance; } /** - * Sets the player's balance and stores it in a file. + * Sets the player's balance and stores it in a file.If a + * FileNotFoundException is thrown during the file reading process, it is + * caught and printed to the standard error stream. * * @param balance the new balance to set */ public void setBalance(double balance) { - try { - PrintWriter outFile = new PrintWriter(new FileWriter(BALANCE_FILE), false); + try (PrintWriter outFile = new PrintWriter(new FileWriter(BALANCE_FILE), false)) { outFile.print(balance); - outFile.close(); } catch (IOException e) { - System.out.println("Error writing to " + BALANCE_FILE); + System.err.println("Error writing to " + BALANCE_FILE); } this.balance = balance; } - + } diff --git a/src/model/Statistics.java b/src/model/Statistics.java @@ -18,7 +18,8 @@ import com.opencsv.exceptions.CsvValidationException; * </ul> * * <p> - * The file is named `statistics.csv` and is stored in the 'db/' directory.</p> + * The file is named <code>statistics.csv</code> and is stored in the + * <code>db/</code> directory.</p> * * @author Michael Neuper * <a href="mailto:michael@michaelneuper.com">michael@michaelneuper.com</a> @@ -144,7 +145,7 @@ public class Statistics { * <p> * The method uses a CSVWriter object to write the data to the file. If an * IOException occurs during the file writing process, it is caught and - * ignored.</p> + * printed to the standard error stream.</p> */ private void save() { try (CSVWriter writer = new CSVWriter(new FileWriter(CSV_FILE))) { @@ -152,6 +153,7 @@ public class Statistics { String[] data = {String.valueOf(wins), String.valueOf(losses), String.valueOf(pushes)}; writer.writeNext(data); } catch (IOException e) { + System.err.println("Error writing to " + CSV_FILE); } } @@ -166,9 +168,9 @@ public class Statistics { * the CSV file.</p> * <p> * If an IOException occurs during the file reading process, it is caught - * and ignored. If a CsvValidationException is thrown during the file - * reading process, it is handled internally and an empty Statistics object - * is returned.</p> + * and printed to the standard error stream. If a CsvValidationException is + * thrown during the file reading process, it is handled internally and an + * empty Statistics object is returned.</p> * * @return a Statistics object with the values read from the CSV file, or an * empty Statistics object if there was a problem with the CSV file format @@ -193,9 +195,10 @@ public class Statistics { System.err.println("Error: invalid CSV file format"); } catch (IOException e) { // rethrow the IOException to the calling function - throw new IOException("Error reading CSV file", e); + throw new IOException("Error reading " + CSV_FILE, e); } + return stats; } - + }