Trying to Make a Game

Since the entire world has been forced into a mass quarantine, I had a lot of free time on my hands and decided to make a game. But not through a dedicated game maker where I didn’t need to code. I wanted to get my hands dirty and build it from the ground up. There was only one problem: I don’t know how to code.


But how hard could it be? It’s worth a shot. In the end, I decided to learn Java not just because it was well known and would have lots of resources to use, but it used “Object Oriented Programming” or OOP for short. Of course, that probably sounds like gibberish to you, so let me explain.

OOP

To understand OOP, you have to know the difference between objects and classes. A class is a group of objects. For example, the class Animals contains Dog, Cat, and Fish. If you look closely, you’ll notice that the class Animals has some common features that Dog, Cat, and Fish all have. This is because a class is a template for objects and objects inherit the template.

There are other aspects of OOP, especially in Java but this game was quite simple and I didn’t need to use them. As a result, I won’t be explaining them here.

Picking a game

Since I had no experience in programming (except for some basic games using Scratch) I decided to replicate an existing game. The only problem was that most games are visual and I had no idea how to create a program that could draw to the screen and then get user input and all the other complicated stuff. Naturally, I decided to try and pick a game that could still be played via text. By that, I mean it had to be simple enough that I could write out all the information the player would need.

I considered picking Hangman but the more I thought about it, the more complicated it became. First, I would have to randomly pick a word. Then I’d have to display it letter by letter based on what the player had guessed. After that, the player should be told what letters have already been guessed and which ones hadn’t, which could easily make the game hard to read. In short, it was too difficult for me to make.

Thinking about Hangman made me realise that I had to have randomness. After all, who would want to play the same scenario over and over again? This lead me to think of games that had randomness built in. Could I put dice into the game? No. Could I put cards into the game? No. Could I put– wait a second, cards, that’s it!

But which card game? Poker meant that I would have to make an AI and calculate the highest card combination so that went out the window. What about Blackjack? Simple rules, don’t go over 21 or 5 cards. Blackjack it is.

Making the game

I decided to start off by making a menu screen with three options:

  1. Start the game
  2. Instructions
  3. Exit the game

Instructions

Starting the game was a task for later, so I focussed on making the instructions. I ended up with this code:

System.out.println("The aim of blackjack is to " +
        "\nmake your card values add up to 21." +
        "\nAny card with a number is worth that much." +
        "\nA Jack, King, or Queen is worth 10." +
        "\nAn Ace is worth 1 or 11 depending on what you choose." +
        "\nIf you go over 21, you have 'gone bust'." +
        "\nYou start with two cards and can draw up to five cards." +
        "\nIf your total is less than or equal to 21 after drawing your fifth card," +
        "\nyou still win.");

I didn’t want to use lots of different print statements, so I used \n. This creates a line break. Unfortunately, I couldn’t add a space after \n as it would make the text line up wonky to the player. Moving on, now that the actual instructions were complete, I had to return the player to the menu screen.

static void menuReturn(){
        int input = 0;
        Scanner s = new Scanner(System.in);

        System.out.println("To return to the menu, enter any number");

        while(true){
            try{
                input = s.nextInt();
                Menu.menu();
                break;
            } catch(InputMismatchException e){
                System.out.println("Please enter a number");
                s.next();
            }
        }
    }

I decided it was easier to make a method to return the player to the menu. The method is quite simple, but there is one part which is complicated: the try-catch statement. What it does is stops the program from crashing if the player enters a letter or symbol. To make sure that the player could still return to the menu, even if they’d entered a letter, I put the try-catch block inside an infinite loop. Unsurprisingly, I had a problem with infinite looping. To fix this, I added “s.next();” which pauses the loop and let’s the player try again.

Exiting the game

To (almost) finish the menu screen, I had to make a way for the player to exit the program. This turned out to be pretty simple and only took one line of code.

System.exit(0);

This was by far the fastest and easiest part of the game to code, but it still took a lot longer than it should’ve. That’s because I originally typed it as:

System.exit();

But the program didn’t know why the program was closing itself and was panicking because of that. By adding the “0”, the program is told that it Is closing normally and that nothing’s wrong.

The actual game

Now for the difficult part. I had to make a way for the player to get random cards and then decide whether or not to open the next card or to call it quits. Sounds easy right? Well, not exactly.

I decided to start by nibbling the easiest part: shuffling the cards. Of course, the program doesn’t know what the cards are. This meant I had to manually type out every single card. After that, I needed a way to shuffle the cards. But I didn’t want to have it shuffled anywhere, so I made another method called “shuffle”.

static void shuffle() {
        Collections.shuffle(Arrays.asList(cards));
    }

Fortunately, Java had a way to shuffle the cards built in so I just popped that line right in and voila, shuffle() was complete. Now that that’s done, I needed to show the player their first two cards. So I typed in:

System.out.println("Your first card is " + cards[0]);
System.out.println("Your second card is " + cards[1];

This worked, but didn’t give me an easy way to check whether the player wanted to see the next card and then show it. To do this, I ended up making a method called “nextCard()”.

static void nextCard() {
        System.out.println("Card number " + (counter + 1) + " is the ");
        System.out.println(cards[counter]);
        cardValue();

        System.out.println("Your score is " + score);
        scoreCheck();

        counter += 1;

        if (counter == 4) {
            System.out.println("Congratulations! You won!");
            gameEnd();
        }
    }

This method was able to see which card the player was about to see, display it, check the card value, add the value to the total score, display the score, check whether the score was over 21, and see whether the player had won by drawing five cards. Of course, it doesn’t do all that by itself, it goes to another method in the program and asks them. Let’s go through each method.

static void cardValue() {
        int a = 0;
        int in = 0;
        Scanner s = new Scanner(System.in);

        switch (cards[counter]) {
            case "2 of Spades":
            case "2 of Hearts":
            case "2 of Clubs":
            case "2 of Diamonds":
                score += 2;
                break;

            case "3 of Spades":
            case "3 of Hearts":
            case "3 of Clubs":
            case "3 of Diamonds":
                score += 3;
                break;

            case "4 of Spades":
            case "4 of Hearts":
            case "4 of Clubs":
            case "4 of Diamonds":
                score += 4;
                break;

            case "5 of Spades":
            case "5 of Hearts":
            case "5 of Clubs":
            case "5 of Diamonds":
                score += 5;
                break;

            case "6 of Spades":
            case "6 of Hearts":
            case "6 of Clubs":
            case "6 of Diamonds":
                score += 6;
                break;

            case "7 of Spades":
            case "7 of Hearts":
            case "7 of Clubs":
            case "7 of Diamonds":
                score += 7;
                break;

            case "8 of Spades":
            case "8 of Hearts":
            case "8 of Clubs":
            case "8 of Diamonds":
                score += 8;
                break;

            case "9 of Spades":
            case "9 of Hearts":
            case "9 of Clubs":
            case "9 of Diamonds":
                score += 9;
                break;

            case "10 of Spades":
            case "10 of Hearts":
            case "10 of Clubs":
            case "10 of Diamonds":

            case "Jack of Spades":
            case "Jack of Hearts":
            case "Jack of Clubs":
            case "Jack of Diamonds":

            case "Queen of Spades":
            case "Queen of Hearts":
            case "Queen of Clubs":
            case "Queen of Diamonds":

            case "King of Spades":
            case "King of Hearts":
            case "King of Clubs":
            case "King of Diamonds":
                score += 10;
                break;

            case "Ace of Spades":
            case "Ace of Hearts":
            case "Ace of Clubs":
            case "Ace of Diamonds":
                while (a == 0) {
                    System.out.println("1 or 11?");
                    try {
                        in = s.nextInt();
                    } catch (InputMismatchException ignored) {

                    }
                    if ((in == 1) || (in == 11)) {
                        score += in;
                        a += 1;
                    } else {
                        System.out.println("Please enter a valid number");
                        s.next();
                    }
                }
        }
    }

Now that’s a very long block of code. What it does is check which card it’s meant to value ( via cards[counter]), then see which card it is (all the case statements) and increase the score by the card’s value. But towards the end, things get interesting with the aces. See, in Blackjack, you can choose whether to have an ace worth 1 or worth 11. To do this, I used the same technique as the one in the instructions screen but with an if statement to increase the score by whatever amount the player wanted.

static void scoreCheck() {
        if (score > 21) {
            gameOver();
        } else if (score == 21) {
            System.out.println("Congratulations! You won!");
            gameEnd();
        }
    }

This method is pretty simple because it doesn’t need any player input, it just sees whether the score is over 21 and the player has lost or whether the score is equal to 21 and the player has won. If the score is less than 21, it does nothing. It does use some new methods which are pretty similar and either return the player to the menu screen or exit the game, both of which you’ve already seen before. But you haven’t actually seen the code that does most of the work.

static void gameStart() {
        int in;
        Scanner s = new Scanner(System.in);

        shuffle();
        nextCard();
        nextCard();

        while (true) {
            System.out.println("To see your next card, enter 1");
            System.out.println("To end the game, enter 2");

            try {
                in = s.nextInt();

                if (in == 1) {
                    nextCard();
                } else if (in == 2) {
                    gameEnd();
                    break;
                } else {
                    throw new InputMismatchException();
                }
            } catch (InputMismatchException e) {
                System.out.println("Please enter a valid number");
                s.next();
            }
        }
    }

Everything the player sees is because of this code, which sees what method should be used when.


That just about wraps up this post. If there’s something you want to take away from this post it’s this: just because it looks simple, doesn’t mean it is. Also, here’s another thing you might want to take: all of the code I’ve written, available here.

Leave a comment