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 practiceis 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 than21. That same function also assures that no player will have a hand higherthan 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;    }}
Text-based BlackJack game
java;beginner;game;console;playing cards
To other reviewers: I've tackled design and the use of arrays. I didn't touch much on the actual code, although I do hint at things.Recursive Main and DesignYou can easily remove the recursive call to main by having main consist of the following:public static void main(String[] args){    BlackJackGame game = new BlackJackGame();    do{        game.playGame();    } while (game.goAgain());}And by doing so, some interesting things surface.Does BlackJackGame represent a single hand or a set of hands?Why does BlackJackGame need to be prompted to ask for a new game... and then have someone else handle the result?Well, if I were designing this... I'd abuse a physical object. Blackjack comes with a table. And the dealer and the player join this table. That's when they're greeted. And then they can play hands. At some point, people leave and the hands end. So perhaps a class like BlackJackTable can be responsible for a lot of things. At the very least it could take the responsibility of passing messages around and handling the game's progression.To play Blackjack at a casino, you need to place a bet. When you're done playing, you can collect your chips and you just walk away. Sadly, you don't have a betting system, so there's no easy way of simply betting 0 and making that a way to leave the table. (Then again, card counters might favor just waiting a couple hands to get the better cards... and they do so by simply not betting.)So yeah, you'll have to make something ask the user. I'd make that the table's responsibility. Leave the round of hands out of it.Future FeaturesYou have Cards. Why not a Deck? Right now, you can get a hand that contains 9 2's. That'd be beyond silly in a casino. You'd call them out on it for sure.Blackjack has a split feature. You can split a pair into two hands. And some casinos will let you split again if you get more pairs. (That'd imply you get 4 of a kind; 77 split to 7 and 7, get two cards, you have 77 77, split again to 7 7 7 7.) ... but you don't support multiple hands right now.Blackjack in casino's has betting, of course. That's the point of playing blackjack.Other features I can think of:Print the message Dealer stands on X - for blackjack, dealer rules are usually fixed.Allow the game to print some helpHave other players play next to you, each with some silly strategy (and voila, you have something to score your betting mechanic against)Aces have a value of either 1 or 11. Right now, one can draw two aces and immediately be bust.When the dealer has blackjack, the dealer immediately reveals their hand. Player can't do anything about it and just loses.Library UsageNo, not books. Java has gone through quite some versions, and certain common problems have been solved for you already. Specifically, I'd like to point you to java.util.Collection and it's subclasses. Take a look at a List, Set and Map. Right now, you have to do these weird things with copying arrays. You don't wanna bother with that, do you? With a List, you can have an ever expanding array without having to copy things around (Java will do that for you, internally). You just have to call List.add to add things to a List.Code shortcutsHere's some shortcuts you can use that are well-known:/** * Get the hand's total value * @return  */@Overridepublic int getTotal() {    int totalValue = 0;    for (Card c : dealerHand) {        int cardValue = c.getValue();        totalValue = totalValue + cardValue;    }    return totalValue;}x = x + y and x += y are the same thing. I'd rewrite the function like this:/** * Get the hand's total value * @return  */@Overridepublic int getTotal() {    int totalValue = 0;    for (Card card : dealerHand) {        totalValue += card.getValue();    }    return totalValue;}Another shortcut:if (game.goAgain(sc) == true){    main(null);}if(x == true), where x is of type boolean (not Boolean!), can be shortened to if(x). So this becomesif (game.goAgain(sc)){    main(null);}The reason you do this is to simplify reading of your code.Constantsif(player.getTotal() > 21){    System.out.println(player + 's total is more than 21,  + player +  lose by default.\n +                       otherPlayer +  WIN!\n);    loseByDefault = true;}You should try to label your constants. This has three benefits:Readability. If the statement player.getTotal() > BLACKJACK_LIMIT is true, it carries semantic value (The player is over the limit). The statement player.getTotal() > 21 is abstract and doesn't carry semantic value.Maintainability. Your game now has Decks, Splits, betting, multiple players, logging, statistics, save and load, ASCII card images and basically so much features that your text-based game is now 10K lines. (At least, that's where my text-based game ended up when I started to learn programming.) How will you increase a minimum bet from 1 to 5? You can't just search your code for 1.Reusabilty. Kinda like maintainability, but when you're typing new code, rather than making changes, you don't have to go and look up the minimum bet value or the blackjack limit (or worse, think you know what it was and get it wrong). You can just type BLACKJACK_LIMIT and it'll always be correct.JavaDocClass documentation should tell you what it is.Function documentation should tell you what it does.Variable documentation should tell you what it means.And any in-code comments should tell you why it does.These statements generally hold true. You seem to follow these statements, ... mostly.Be careful of comments like this:/** * What will happen at start of a player's turn. */void gameStartup();This comment doesn't say what the function does. It's also contradictory to the function name - game start up and start player turn... When I start up a game, I grab a deck, maybe shuffle it and give people cards.Your IDE generates things like @param and @return. These are for documenting your arguments or parameters and your return value.So a comment like this.../** * Ask player if (s)he wants to hit or stay, returns a boolean on the choice of staying. * @return  */boolean wantToStay();really ought to be like this./** * Ask player if (s)he wants to hit or stay * @return a boolean on the choice of staying */boolean wantToStay();This also directly reveals to you when you are unclear.Right now, you've mapped a boolean to hit and stay. I have to read both the function name and the javadoc to figure out that false maps to hit. What happens if we add split, and double down? Then we can't be sure that false means hit anymore. For now, revising the comment to /** * Ask player if (s)he wants to hit or stay * @return Whether the player wants to stay */boolean wantToStay();will do. But in the future, I think this method will change to some PlayerAction getAction() where PlayerAction is an enumeration of actions a Player could take.I have many, many, many more words for those that make games to learn. I like such exercises. However, I think that this is enough for today. I hope you get more answers and use these in your learning project to post a follow-up question. Questions like these are fun to answer.