I am a new programmer (I've been doing Java for about 7 weeks) and I am of the type who wants to get it right straight away, so I wonder how this code:
- Compares to the common practice
- is structured. Is it a good structure?
- Readability. Is it easy to read?
- The JavaDoc; what could I improve?
(I am not including the package or imports for space reasons)
This code has a recursive call back to main()
. I have understood that that is bad and I understand why, so you needn't bother with that.
Main:
In this game I have chosen to make it as simple as I can whilst still functional. There are two players; dealer and user. User goes first, then the dealer has her turn.
The game lets the other player auto-win if the hand-total is more than 21. That same function also assures that no player will have a hand higher than 21.
The game compares the users results to each other and the highest hand wins. If there's a stalemate, dealer wins.
public class BlackJackGame {
// Contains the players for comparing who won.
private final Player[] players = new Player[2];
public static void main(String[] args){
BlackJackGame game = new BlackJackGame();
Scanner sc = new Scanner(System.in);
System.out.println(" ___________________________________________\n" +
"| |\n" +
"| Welcome to the Gemtastic BlackJack Game! |\n" +
"|___________________________________________|\n");
System.out.println("What is your name?");
String userName = sc.nextLine();
System.out.println("Hello " + userName + "! Let's play!\n");
// Gets an input fromt he user which will represent the user in the game.
// Create the players and add them to array.
Player user = new User(userName);
game.players[0] = user;
Player dealer = new Dealer();
game.players[1] = dealer;
// Time to get this game going! And user goes always first.
user.gameStartup();
boolean userLoseByDefault = game.playerTurn(user, dealer);
if(userLoseByDefault){
game.lostByDefault(sc);
}
// Dealer's turn
dealer.gameStartup();
boolean dealerLoseByDefault = game.playerTurn(dealer, user);
if(dealerLoseByDefault){
game.lostByDefault(sc);
}
Player winner = game.whoWon(game.players, dealer);
System.out.println(user + "'s total is: " + user.getTotal() + ".\n" +
dealer + "'s total is : " + dealer.getTotal() + ".\n");
System.out.printf("%s WIN!\n\n", winner);
if (game.goAgain(sc) == true){
main(null);
}
}
/**
* This method handles the player's turn.<p>
*
* Parameters sends in the one playing and the other player. This method
* calls for the {@code wantToStay()} method repeatedly until it returns
* {@code true}. It then evaluates if the player's hand is more than 21
* and if so, it's an auto-loss for the player.<p>
*
* it returns {@code loseByDefault} to tell the caller if the player have
* already lost or not.
*
* @param player
* @param otherPlayer
* @return
*/
private boolean playerTurn(Player player, Player otherPlayer){
boolean endTurn = false;
boolean loseByDefault = false;
while(endTurn == false){
endTurn = player.wantToStay();
if(endTurn == false){
player.drawCard();
System.out.println(player + "'s total is: " + player.getTotal() + "\n");
}
}
if(player.getTotal() > 21){
System.out.println(player + "'s total is more than 21, " + player + " lose by default.\n" +
otherPlayer + " WIN!\n");
loseByDefault = true;
}
return loseByDefault;
}
/**
* This method iterates through the players and compare their hands. The
* highest hand wins. It returns the winner.
*
* @param players
* @param dealer
* @return
*/
private Player whoWon(Player[] players, Player dealer){
Player winner = players[0];
for(int i = 1; i < players.length; i++){
Player elem = players[i];
if(elem.getTotal() > winner.getTotal()){
winner = elem;
}
else if(elem.getTotal() == winner.getTotal()){
winner = dealer;
}
}
return winner;
}
/**
* This method calls for {@code goAgain()} if either player has lost by default,
* if not, it ends the game.
*
* @param sc
*/
private void lostByDefault(Scanner sc){
if(goAgain(sc) == true){
main(null);
}
System.exit(0);
}
/**
* The method for taking the input and evaluate if the user wants to play
* another round.
*
* @param sc
* @return
*/
private boolean goAgain(Scanner sc){
Boolean goAgain = null;
while(goAgain == null){
System.out.println("Would you like to play another round? \"yes\"/\"no\": ");
String input = sc.nextLine();
String answer = input.toLowerCase();
switch(answer){
case "y":
case "yes":
goAgain = true;
break;
case "n":
case "no":
goAgain = false;
break;
default:
System.out.println("Invalid answer. Please answer only \"yes\" or \"no\"");
break;
}
System.out.println();
}
return goAgain;
}
}
Card:
public class Card {
private final int value;
Card(){
value = randomCard();
}
public int getValue(){
return value;
}
/**
* This method randomizes a value between 2 and 11.
*
* @return
*/
private int randomCard(){
int min = 2;
int max = 11;
int range = (max - min);
int random = new Random().nextInt(range + 1) + min;
return random;
}
}
Player:
public interface Player {
// Player hand as an array.
// Player name as a String.
/**
* What will happen at start of a player's turn.
*/
void gameStartup();
/**
* Generate a card and add it to the player's hand.
*/
void drawCard();
/**
* Ask player if (s)he wants to hit or stay, returns a boolean on the choice of staying.
* @return
*/
boolean wantToStay();
/**
* Retrieves the total of the player's hand.
* @return
*/
int getTotal();
}
Dealer:
public class Dealer implements Player {
private final String dealer = "Dealer";
Card[] dealerHand = new Card[0];
/**
* Dealer constructor draws the two initial cards for the hand and displays one of them.
*/
Dealer(){
dealerHand = Arrays.copyOf(dealerHand, dealerHand.length + 2);
dealerHand[0] = new Card();
dealerHand[1] = new Card();
System.out.println("The dealer has a " + dealerHand[0].getValue() + " showing, and a hidden card.");
System.out.println("Her total is hidden too.\n");
}
/**
* Displays the hidden card and total
*/
@Override
public void gameStartup(){
System.out.println("Okay, Dealer's turn!\n");
int total = getTotal();
System.out.println("Her hidden card was a " + dealerHand[1].getValue() + "\n" +
"Her total was " + total + ".\n");
}
/**
* Will draw a card and add it to the hand.
*/
@Override
public void drawCard() {
dealerHand = Arrays.copyOf(dealerHand, dealerHand.length + 1);
dealerHand[dealerHand.length - 1] = new Card();
int lastCard = dealerHand.length - 1;
System.out.println("Dealer drew a " + dealerHand[lastCard].getValue());
}
/**
* The dealer's decision of whether to hit. She will hit until her hand is 16.
* @return
*/
@Override
public boolean wantToStay() {
boolean stay = false;
int total = getTotal();
if(total > 16){
stay = true;
System.out.println("Dealer stays.\n");
}
else{
System.out.println("Dealer hits.");
}
return stay;
}
/**
* Get the hand's total value
* @return
*/
@Override
public int getTotal() {
int totalValue = 0;
for (Card c : dealerHand) {
int cardValue = c.getValue();
totalValue = totalValue + cardValue;
}
return totalValue;
}
/**
* Returns the dealer's name.
* @return
*/
@Override
public String toString(){
return dealer;
}
}
User:
public class User implements Player {
private final String user;
private Card[] userHand = new Card[0];
/**
* User constructor will add the string user inputed as its nickname in
* this game. It will then draw and display the initial hand of two cards.
*
* @param name
*/
User(String name){
user = name;
userHand = Arrays.copyOf(userHand, userHand.length + 2);
userHand[0] = new Card();
userHand[1] = new Card();
System.out.println("You get a " + userHand[0].getValue() + " and a " + userHand[1].getValue() + ".");
int total = getTotal();
System.out.println("Your total is: " + total + "\n");
}
/**
* Message upon User's turn.
*/
@Override
public void gameStartup(){
System.out.println("Your turn!");
}
/**
* Retrieves the total of the User's hand.
* @return
*/
@Override
public int getTotal(){
int totalValue = 0;
for (Card c : userHand) {
int cardValue = c.getValue();
totalValue = totalValue + cardValue;
}
return totalValue;
}
/**
* Generates a card and adds it to the hand.
*/
@Override
public void drawCard() {
userHand = Arrays.copyOf(userHand, userHand.length + 1);
userHand[userHand.length - 1] = new Card();
int lastCard = userHand.length - 1;
System.out.println("You drew a " + userHand[lastCard].getValue());
}
/**
* Asks player if (s)he wants to hit or stay, returns a boolean for if the
* player chose stay or not.
*
* @return
*/
@Override
public boolean wantToStay() {
Boolean stay = null;
while(stay == null){
Scanner sc = new Scanner(System.in);
System.out.print("Would you like to \"hit\" or \"stay\"? ");
String input = sc.nextLine();
String hitOrStay = input.toLowerCase();
switch(hitOrStay){
case "hit":
stay = false;
break;
case "stay":
stay = true;
break;
default:
System.out.println("That is not a valid option.");
break;
}
}
return stay;
}
/**
* Prints the user's nickname.
*
* @return
*/
@Override
public String toString(){
return user;
}
}