7
\$\begingroup\$

So this is a blackjack game, any feedback or tips on what I should remove from the code that is not needed is very appreciated.

Note: some of the names of classes or variables are in Swedish but it should not interfere with understanding the code I think.

Blackjack.java

import java.util.Scanner;
class Card {
 private final Face face;
 private final Suit suit;
 public Card(Face face, Suit suit) {
 this.face = face;
 this.suit = suit;
 }
 public Face getFace() {
 return face;
 }
 public Suit getSuit() {
 return suit;
 }
 @Override
 public String toString() {
 return face + " of " + suit;
 }
}
enum Face {
 Ace(11), Deuce(2), Three(3), Four(4), Five(5), Six(6), Seven(7), Eight(8), Nine(9), Ten(10), Jack(10), Queen(10), King(10);
 private final int value;
 private Face(int value) {
 this.value = value;
 }
 
 public int getValue() {
 return value;
 }
}
enum Suit {
 hearts, spades, diamonds, clubs;
}
public class BlackJack {
 public static void main(String[] args) {
 int wins = 0;
 int losses = 0;
 Scanner scanner = new Scanner(System.in);
 String input;
 
 //Clear Terminal from file paths
 System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");
 
 //Start loop
 do {
 //Clear Terminal from last game
 System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");System.out.println(" ");
 //Create players, shuffle deck and turn gameOver off
 Player player = new Player("You");
 Player dealer = new Player("Dealer");
 Deck deck = new Deck();
 deck.shuffle();
 boolean gameOver = false;
 //Get cards for player
 player.addCard(deck.draw());
 player.addCard(deck.draw());
 System.out.print(player.getHandAsString(false));
 System.out.println("Total: " + player.getHandSum());
 System.out.println("");System.out.println("");
 //Get cards for dealer
 dealer.addCard(deck.draw());
 dealer.addCard(deck.draw());
 
 //Player turn
 do {
 if (player.getHandSum() == 21) {
 System.out.println("Super lucky Blackjack! You win.");
 wins = wins + 1;
 gameOver = true;
 break;
 }
 if (player.getHandSum() > 21) {
 System.out.println("Super unlucky! You lost.");
 losses = losses + 1;
 gameOver = true;
 break;
 }
 System.out.println("");System.out.println("");
 System.out.println("Draw or stay?");
 do {
 input = scanner.nextLine();
 } while (!input.equalsIgnoreCase("Draw") && !input.equalsIgnoreCase("Stay"));
 //Draw
 if (input.equalsIgnoreCase("Draw")) {
 player.addCard(deck.draw());
 System.out.println("");
 System.out.print(player.getHandAsString(false));
 System.out.println("Total: " + player.getHandSum());
 System.out.println("");System.out.println("");
 if (player.getHandSum() == 21) {
 System.out.println("Blackjack! You win.");
 wins = wins + 1;
 gameOver = true;
 }
 if (player.getHandSum() > 21) {
 System.out.println("You busted with " + player.getHandSum() + " in your hand. Dealer wins!");
 losses = losses + 1;
 gameOver = true;
 }
 }
 //Stay
 if (input.equalsIgnoreCase("stay")) {
 System.out.println("You have chosen to stay. Your hand: " + player.getHandSum());
 }
 } while (input.equalsIgnoreCase("Draw") && !gameOver);
 //Dealer turn
 if (!gameOver) {
 System.out.println("");System.out.println("");System.out.println("");System.out.println("");System.out.println("");
 System.out.println("________________________________________________________________________");
 System.out.println("Dealers turn");
 System.out.println("________________________________________________________________________");
 
 System.out.println("");
 System.out.print(dealer.getHandAsString(false));
 
 System.out.println(dealer.getHandSum());
 System.out.println("");System.out.println(""); 
 if (dealer.getHandSum() == 21) {
 System.out.println("Blackjack! Dealer won.");
 losses = losses + 1;
 gameOver = true;
 }
 }
 while (!gameOver) {
 if (dealer.getHandSum() <= 17) {
 //Draw card
 dealer.addCard(deck.draw());
 System.out.println(dealer.getVem() + " drew another card");
 System.out.println("");
 System.out.print(dealer.getHandAsString(false));
 System.out.println(dealer.getHandSum());
 System.out.println("");System.out.println(""); 
 
 if (dealer.getHandSum() == 17) {
 if (player.getHandSum() == 17) {
 System.out.println("Dealer won.");
 losses = losses + 1;
 gameOver = true;
 }
 }
 if (dealer.getHandSum() == 18) {
 if (player.getHandSum() == 18) {
 System.out.println("Dealer won.");
 losses = losses + 1;
 gameOver = true;
 }
 }
 if (dealer.getHandSum() == 19) {
 if (player.getHandSum() == 19) {
 System.out.println("Dealer won.");
 losses = losses + 1;
 gameOver = true;
 }
 }
 
 if (dealer.getHandSum() == 20) {
 if (player.getHandSum() == 20) {
 System.out.println("It's a draw!");
 gameOver = true;
 }
 }
 if (dealer.getHandSum() == 21) {
 System.out.println("Blackjack! Dealer won.");
 losses = losses + 1;
 gameOver = true;
 }
 if (dealer.getHandSum() > 21) {
 System.out.println("Dealer busted with " + dealer.getHandSum() + " in their hand. You win!");
 wins = wins + 1;
 gameOver = true;
 }
 } else {
 //Stay
 System.out.println("Dealer chose to stay!");
 System.out.println("");
 int totalDealerSum = dealer.getHandSum();
 int totalPlayerSum = player.getHandSum();
 if (totalDealerSum > totalPlayerSum) {
 System.out.println("Both players decided to stay. The Dealer won with a total of " + totalDealerSum + " in their hand.");
 losses = losses + 1;
 } else {
 System.out.println("Both players decided to stay. You win with a total of " + totalPlayerSum + " in your hand.");
 wins = wins + 1;
 }
 gameOver = true;
 }
 }
 //New game? And Score
 System.out.println("");System.out.println("");System.out.println("");
 
 if(wins==1 && losses==0){
 System.out.println("You have won " + wins + " time and lost " + losses + " times.");
 }
 if(wins==0 && losses==1){
 System.out.println("You have won " + wins + " times and lost " + losses + " time.");
 }
 
 if(wins>1 && losses>1){
 System.out.println("You have won " + wins + " times and lost " + losses + " times.");
 }
 if(wins==0 && losses>1){
 System.out.println("You have won " + wins + " times and lost " + losses + " times.");
 }
 if(wins>1 && losses==0){
 System.out.println("You have won " + wins + " times and lost " + losses + " times.");
 }
 if(wins>1 && losses==1){
 System.out.println("You have won " + wins + " times and lost " + losses + " time.");
 }
 if(wins==1 && losses==1){
 System.out.println("You have won " + wins + " time and lost " + losses + " time.");
 }
 if(wins==1 && losses>1){
 System.out.println("You have won " + wins + " time and lost " + losses + " times.");
 }
 System.out.println("");
 System.out.println("Play again?");
 do {
 input = scanner.nextLine();
 } while (!input.equalsIgnoreCase("Yes") && !input.equalsIgnoreCase("No"));
 
 } while (input.equalsIgnoreCase("Yes"));
 
 scanner.close();
 }
}

Deck.java

import java.util.ArrayList;
import java.util.Collections;
public class Deck {
 private final ArrayList<Card> cards;
 public Deck() {
 cards = new ArrayList<Card>();
 // populate deck with cards
 for (Suit suit : Suit.values()) {
 for (Face face : Face.values()) {
 cards.add(new Card(face, suit));
 }
 }
 }
 public void shuffle() {
 Collections.shuffle(cards);
 }
 public Card draw() {
 return cards.remove(0);
 }
 @Override
 public String toString() {
 StringBuilder sb = new StringBuilder();
 for (int i = 0; i < cards.size(); i++) {
 sb.append(i + 1);
 sb.append('/');
 sb.append(cards.size());
 sb.append(' ');
 sb.append(cards.get(i));
 sb.append('\n');
 }
 return sb.toString();
 }
}

Player.java

import java.util.ArrayList;
//Player class
public class Player {
 private final String vem;
 private final ArrayList<Card> hand;
 public Player(String vem) {
 this.vem = vem;
 this.hand = new ArrayList<Card>();
 }
 public String getVem() {
 return vem;
 }
 public void addCard(Card card) {
 hand.add(card);
 }
 public int getHandSum() {
 int handSum = 0;
 for (Card card : hand) {
 handSum += card.getFace().getValue();
 }
 return handSum;
 }
 public String getHandAsString(boolean b) {
 StringBuilder sb = new StringBuilder();
 sb.append(vem); //'s'\
 sb.append('\n');
 for (int i = 0; i < hand.size(); i++) {
 if (i == 0 && b) {
 sb.append('\n');
 } else {
 sb.append(hand.get(i));
 sb.append('\n');
 }
 }
 return sb.toString();
 }
}

Thank you for any help, tips or feedback!

asked Jan 20, 2021 at 19:21
\$\endgroup\$
5
  • \$\begingroup\$ Welcome to CodeReview@SE. Please (re)visit How do I ask a Good Question? to find why at least one used wants to change the title of this question. \$\endgroup\$ Commented Jan 20, 2021 at 21:43
  • \$\begingroup\$ The Main function in your Blackjack class has a lot going on. You should think about how you can break down what's going on the the loops into smaller functions. You could also add some additional objects to help with that, for example one to manage and store the Win & Loss counts could help keep that part organised. \$\endgroup\$ Commented Jan 20, 2021 at 22:06
  • \$\begingroup\$ It's necessary to say that enum items should be in upper snake case. Example: Ace should be ACE or hearts should be HEARTS, the reason why is because the items inside an enumeration are constants. Btw nice project. \$\endgroup\$ Commented Jan 21, 2021 at 3:45
  • \$\begingroup\$ Once you have an answer please don't edit the question. Please see What should I do after after someone answers?. With 4 up votes on this question there isn't really a good reason to delete it. \$\endgroup\$ Commented Jan 21, 2021 at 21:53
  • \$\begingroup\$ In the future if you want to delete your question, you should look to the Delete Link to the right of the Edit link. \$\endgroup\$ Commented Jan 21, 2021 at 21:57

1 Answer 1

7
\$\begingroup\$

Nice project, find below my suggestions.

Clearing the terminal

There are more than 20 System.out.println(" ") in one line and then again a few lines below. Create a method to clear the terminal and shorten the code with a for-loop. There are also other ways to clear the terminal.

Duplicated code

  • Requesting the input from the user is duplicated more than once. You can create a method for that which accepts a custom question.
  • Boolean operators: there are many if conditions that test only with ==. Make use of && and || in combination with <= and >= to reduce duplicated code.

Formatting with correct plurals

This part:

if(wins==1 && losses==0){
 System.out.println("You have won " + wins + " time and lost " + losses + " times.");
}
if(wins==0 && losses==1){
 System.out.println("You have won " + wins + " times and lost " + losses + " time.");
}
if(wins>1 && losses>1){
 System.out.println("You have won " + wins + " times and lost " + losses + " times.");
}
if(wins==0 && losses>1){
 System.out.println("You have won " + wins + " times and lost " + losses + " times.");
}
if(wins>1 && losses==0){
 System.out.println("You have won " + wins + " times and lost " + losses + " times.");
}
if(wins>1 && losses==1){
 System.out.println("You have won " + wins + " times and lost " + losses + " time.");
}
if(wins==1 && losses==1){
 System.out.println("You have won " + wins + " time and lost " + losses + " time.");
}
if(wins==1 && losses>1){
 System.out.println("You have won " + wins + " time and lost " + losses + " times.");
}

Can be shortened to:

String pluralWins = wins == 1 ? "" : "s";
String pluralLosses = losses == 1 ? "" : "s";
System.out.printf("You have won %d time%s and lost %d time%s.%n", wins, pluralWins, losses, pluralLosses);

Design

The main method seems to have a lot of responsibility. It includes:

  1. Requesting the input from the user
  2. Playing the game
  3. Updating the score
  4. Printing the output to the console

This makes BlackJack hard to:

  • Test: there is no easy way to unit test the game, only manually.
  • Extend: for example, adding a player.
  • Reuse: it's not easy to reuse BlackJack in another application where for example the user interacts via the network.

To improve it, part of step 2 can be moved into the BlackJack class. Ideally, there shouldn't be user interaction in the BlackJack class, only in the main. This is an idea:

main method
 initialize score
 while user wants to play
 create a new BlackJack object
 while !blackJack.isGameOver()
 play game
 update score

A BlackJack object represents one game, and its methods allow one to start and play the game.

In this way, the methods of BlackJack can be unit tested, and the class can be reused and extended more easily.

Naming

A more common name for face (in the class Card) is rank. The name face can be confused with face-up/down.

Performance

The method Player#getHandSum is called often and every time it calculates the sum iterating on all the cards. Consider to cache the sum and update it only when Player#addCard is called.

answered Jan 21, 2021 at 6:56
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.