Let's Make a Virtual Dog Game with Java! πŸ•

christine - Jun 10 '22 - - Dev Community

Today we are going to make a little "virtual dog" game that is based in the command-line using Java. That's right, open up your code editor (I used IntelliJ Community Edition for this one 😊), make a nice cup of coffee, and pour it all over your computer! My work is done here, you're welcome. 😎
Java Virtual Dog

Jokes aside, this is a pretty easy game to make. It will take you less than an hour if you don't take bathroom breaks, and who knows, you might have fun along the way. When you're ready, open up your code editor and let's get coding!

(The concepts that I will be discussing in this tutorial assumes that you know the basics of Java. No in-depth knowledge or even experience is needed, but go here to revisit the basics of classes, variables and conditionals if needed πŸ™‚).

Step One: Setting up our project

Open up IntelliJ (or your desired code editor) and select the option to create a new project. Make sure you have your Java environment set up (having the appropriate JDK and SDK's). If you need help, I listed some links below!


IntelliJ

With IntelliJ, you just need to enter your project name, select Java and IntelliJ (no need to select Maven or Gradle for this one).
Java Virtual Dog

Then, when you're in the editor, you need to right click on the src folder and create two new Java classes: DogNeedsand DogApplication. You're all set up for now!
Java Virtual Dog
Java Virtual Dog

To run the project from here on out for testing, simple go here:
Java Virtual Dog


VS Code

With VS Code, after you've installed the necessary prerequisites, you can also just select the Create Java Project option with the no build tools project type selected.
Java Virtual Dog

Then, when you're in the editor, you need to right click on the src folder and create two new files: DogNeeds.javaand DogApplication.java. You're all set up for now!
Java Virtual Dog

To run the project from here on out for testing, simple go here:
Java Virtual Dog


Step Two: DogNeeds.java

From here on out I will be working from IntelliJ. Before we do anything, we need to head over to DogNeeds.java and make some declarations. In this file, we will declare all our variables needed to change our needs, get our needs and set our needs, as well as create our class constructor.

Let's start by declaring our variables for our needs. Our dogs' needs will consist of hunger, thirst, attention, bladder, energy, and hygiene. We will also declare our string object for our dogs name.


public class DogNeeds {

    //main needs of our virtual dog (what we need to do to fulfill them alive!)
    private String dogName;
    private int hunger;
    private int thirst;
    private int attention;
    private int bladder;
    private int energy;
    private int hygiene;
}
Enter fullscreen mode Exit fullscreen mode

Then we need to define our constructor underneath all these variables. Our constructorwill help us initialize our objects by assigning default values to them. For example, our needs will all start at 1, so when our game starts our dog will have 1 point assigned to each need. πŸ“Š

public DogNeeds(String d){
        dogName = d;
        hunger = 1;
        thirst = 1;
        attention = 1;
        bladder = 1;
        energy = 1;
        hygiene = 1;
    }
Enter fullscreen mode Exit fullscreen mode

Once that is done, we need to set our getter, setter, and change methods. The getmethod returns the variable values for our dogs' needs, and the setmethod sets the values. The changemethod is our own custom method that will allow us to change these values upon each round.

    //methods needed to increase/decrease our dog's needs
    public void changeHunger(int h){
        hunger += h;
    }

    public void changeThirst(int t){
        thirst += t;
    }

    public void changeAttention(int a){
        attention += a;
    }

    public void changeEnergy(int e){
        hunger += e;
    }

    public void changeBladder(int b){
        hunger += b;
    }

    public void changeHygiene(int g)
    {
        hygiene += g;
    }

    //mandatory getter methods
    public String getDogName() {
        return dogName;
    }

    public int getAttention() {
        return attention;
    }

    public int getBladder() {
        return bladder;
    }

    public int getEnergy() {
        return energy;
    }

    public int getHunger() {
        return hunger;
    }

    public int getThirst() {
        return thirst;
    }

    public int getHygiene() {
        return hygiene;
    }

    //mandatory setter methods
    public void setAttention(int attention) {
        this.attention = attention;
    }

    public void setBladder(int bladder) {
        this.bladder = bladder;
    }

    public void setDogName(String dogName) {
        this.dogName = dogName;
    }

    public void setEnergy(int energy) {
        this.energy = energy;
    }

    public void setHunger(int hunger) {
        this.hunger = hunger;
    }

    public void setThirst(int thirst) {
        this.thirst = thirst;
    }

    public void setHygiene(int hygiene) {
        this.hygiene = hygiene;
    }
Enter fullscreen mode Exit fullscreen mode

Finally, we can create a tick method, which will randomise our dogs' needs upon each round so that it isn't as "predictable". For example, our dog won't always be 100% full, it will be random.

 //on-tick method that will generate randomized game loop
    public void tick(){
        //we add 1 each time a user does something (need max = 5)
        hunger += 1;
        thirst += 1;
        bladder += 1;
        energy += 1;
        attention += 1;
        hygiene += 1;
    }
Enter fullscreen mode Exit fullscreen mode

Complete DogNeeds.java

public class DogNeeds {

    //main needs of our virtual dog (what we need to do to fulfill them alive!)
    private String dogName;
    private int hunger;
    private int thirst;
    private int attention;
    private int bladder;
    private int energy;
    private int hygiene;
    //dog Constructor
    public DogNeeds(String d){
        dogName = d;
        hunger = 1;
        thirst = 1;
        attention = 1;
        bladder = 1;
        energy = 1;
        hygiene = 1;
    }

    //methods needed to increase/decrease our dog's needs
    public void changeHunger(int h){
        hunger += h;
    }

    public void changeThirst(int t){
        thirst += t;
    }

    public void changeAttention(int a){
        attention += a;
    }

    public void changeEnergy(int e){
        hunger += e;
    }

    public void changeBladder(int b){
        hunger += b;
    }

    public void changeHygiene(int g)
    {
        hygiene += g;
    }

    //on-tick method that will generate randomized game loop
    public void tick(){
        //we add 1 each time a user does something (need max = 5)
        hunger += 1;
        thirst += 1;
        bladder += 1;
        energy += 1;
        attention += 1;
        hygiene += 1;
    }

    //mandatory getter methods
    public String getDogName() {
        return dogName;
    }

    public int getAttention() {
        return attention;
    }

    public int getBladder() {
        return bladder;
    }

    public int getEnergy() {
        return energy;
    }

    public int getHunger() {
        return hunger;
    }

    public int getThirst() {
        return thirst;
    }

    public int getHygiene() {
        return hygiene;
    }

    //mandatory setter methods
    public void setAttention(int attention) {
        this.attention = attention;
    }

    public void setBladder(int bladder) {
        this.bladder = bladder;
    }

    public void setDogName(String dogName) {
        this.dogName = dogName;
    }

    public void setEnergy(int energy) {
        this.energy = energy;
    }

    public void setHunger(int hunger) {
        this.hunger = hunger;
    }

    public void setThirst(int thirst) {
        this.thirst = thirst;
    }

    public void setHygiene(int hygiene) {
        this.hygiene = hygiene;
    }
}

Enter fullscreen mode Exit fullscreen mode

Step Three: DogApplication.java

With our objects and methods defined, it's now time to code the logic of our application (game). Head over to your DogApplication.java file and create your main method. This is where we will call all other methods.

public class DogApplication {
    public static void main(String[] args) {
    }
}
Enter fullscreen mode Exit fullscreen mode

Now for the logic part of it. Our game will need to do the following:

  1. Get user input to set the dog's name.
  2. Return the game instructions.
  3. Return the menu of options and allow the player to select options.
  4. Randomize the needs and alter them according to what the player chose.
  5. Return current needs + return value of previous option.

Let's go ahead and get the user input first. We will have to ask the player to enter their dog's name, and then assign that value to our dogName string object (that we defined in DogNeeds.java). We can get user input via the scanner object.

import java.util.Scanner;

public class DogApplication {

    public static void main(String[] args) {
        int select;

        //allow us to get user input
        Scanner input = new Scanner(System.in); //creates a scanner object
        System.out.println("Who is the goodest boy ever? (Enter your dogs name)");
        String dogName = input.nextLine();

        //create a new dog with needs object 
        DogNeeds dog = new DogNeeds(dogName);
    }
}
Enter fullscreen mode Exit fullscreen mode

Then we can go ahead and print out our game instructions. This is basically where we will tell the player what they need to do in order to keep the dog happy. You can enter here what you want! ☺

import java.util.Scanner;

public class DogApplication {

    public static void main(String[] args) {
        ...
        //instructions
        needsMenu(dogName);
    }

    //method needed to print out game instructions
    public static void needsMenu(String dogName)
    {
        System.out.println(
                "-----------------------------------------------------------------------------------------------" +
                        "\n>> Welcome to parenthood! You are now the proud new owner of "  + dogName + "!" +
                        "                                  \n" +
                        "                            |' \\ \n" +
                        "         _                  ; : ; \n" +
                        "        / `-.              /: : | \n" +
                        "       |  ,-.`-.          ,': : | \n" +
                        "       \\  :  `. `.       ,'-. : | \n" +
                        "        \\ ;    ;  `-.__,'    `-.| \n" +
                        "         \\ ;   ;  :::  ,::'`:.  `. \n" +
                        "          \\ `-. :  `    :.    `.  \\ \n" +
                        "           \\   \\    ,   ;   ,:    (\\ \n" +
                        "            \\   :., :.    ,'o)): ` `-. \n" +
                        "           ,/,' ;' ,::\"'`.`---'   `.  `-._ \n" +
                        "         ,/  :  ; '\"      `;'          ,--`. \n" +
                        "        ;/   :; ;             ,:'     (   ,:) \n" +
                        "          ,.,:.    ; ,:.,  ,-._ `.     \\\"\"'/ \n" +
                        "          '::'     `:'`  ,'(  \\`._____.-'\"' \n" +
                        "             ;,   ;  `.  `. `._`-.  \\\\ \n" +
                        "             ;:.  ;:       `-._`-.\\  \\`. \n" +
                        "              '`:. :        |' `. `\\  ) \\ \n" +
                        "                ` ;:       |    `--\\__,' \n" +
                        "                   '`      ,' \n" +
                        "                        ,-' " +
                        "\n>> Remember, " + dogName + " has needs! Being a pet owner is a lot of work." +
                        "\n>> " + dogName + " needs clean water, food, sleep, grooming, playtime, and lot's of attention." +
                        "\n>> Good luck!" +
                        "\n-----------------------------------------------------------------------------------------------"
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, the long part comes. We now need to create a select integer which we will assign to an array of options, and create a bunch of conditionals to see whether or not the dogs' needs are full, and if it's not, how the option selected will affect the dog. This seems more complex than it is - believe me! We will wrap all of this in a do while loop, which is randomised by our tick() method defined above.

Okay, let's take this step by step. First, create the array of options that the user can select:

import java.util.Scanner;

public class DogApplication {

    public static void main(String[] args) {
        int select;

        //allow us to get user input
        Scanner input = new Scanner(System.in); //creates a scanner object
        System.out.println("Who is the goodest boy ever? (Enter your dogs name)");
        String dogName = input.nextLine();

        //create a new dog with needs object
        DogNeeds dog = new DogNeeds(dogName);

        //instructions
        needsMenu(dogName);

        do {
            System.out.println("What do you want to do today?");
            System.out.println(">> [0] Take " + dogName + " for a walk.");
            System.out.println(">> [1] Feed " + dogName + " their favorite treats.");
            System.out.println(">> [2] Refill " + dogName + "'s water bowl.");
            System.out.println(">> [3] Groom " + dogName + "'s coat.");
            System.out.println(">> [4] Take " + dogName + " out to potty.");
            System.out.println(">> [5] Play with " + dogName + ".");
            System.out.println(">> [6] Let " + dogName + " get some sleep.");
            System.out.println(">> [7] Quit.");

            //will select the int[0-7] that user chose 
            select = input.nextInt();

            //enables dogs' needs change upon each selection
            dog.tick();
       } while (select != 7); //because 7 means quit
}
Enter fullscreen mode Exit fullscreen mode

Then, we create our conditionals which will a) check if the array index is selected, b) check if the need is too high, c) affect other needs if it isn't too high, and d) print out the current need values (we'll define that next in a separate method).

import java.util.Scanner;

public class DogApplication {

    public static void main(String[] args) {
        int select;

        //allow us to get user input
        Scanner input = new Scanner(System.in); //creates a scanner object
        System.out.println("Who is the goodest boy ever? (Enter your dogs name)");
        String dogName = input.nextLine();

        //create a new dog with needs object
        DogNeeds dog = new DogNeeds(dogName);

        //instructions
        needsMenu(dogName);

        do {
            System.out.println("What do you want to do today?");
            System.out.println(">> [0] Take " + dogName + " for a walk.");
            System.out.println(">> [1] Feed " + dogName + " their favorite treats.");
            System.out.println(">> [2] Refill " + dogName + "'s water bowl.");
            System.out.println(">> [3] Groom " + dogName + "'s coat.");
            System.out.println(">> [4] Take " + dogName + " out to potty.");
            System.out.println(">> [5] Play with " + dogName + ".");
            System.out.println(">> [6] Let " + dogName + " get some sleep.");
            System.out.println(">> [7] Quit.");

            //will select the int[0-7] that user chose
            select = input.nextInt();

            //exit the console, hence quitting the game
            if (select == 7) {
                continue;
            }

            //Take dog for walk
            else if (select == 0) {
                //if the attention is full, the dog won't want to walk
                if (dog.getAttention() < 5) {
                    System.out.println(">> Mmh, it doesn't seem like " + dogName + " wants to go for a walk right now. Try again later.");
                    continue;
                }

                System.out.println(">> " + dogName + " really enjoyed that walk!");
                //alter needs
                dog.changeAttention(+1);
                dog.changeEnergy(-1);
                dog.changeHygiene(-1);
                showDogCurrentNeeds(dog);
            }

            //Feed the dog their favorite treats
            else if (select == 1) {
                if (dog.getHunger() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " is too full to eat right now. Try again later.");
                    continue;
                }

                System.out.println(">> " + dogName + " really enjoyed that treat!");
                //alter needs
                dog.changeHunger(+1);
                dog.changeEnergy(+1);
                dog.changeThirst(-1);
                dog.changeAttention(+1);
                showDogCurrentNeeds(dog);
            }

            //Refill the dogs' water bowl
            else if (select == 2) {

                if (dog.getThirst() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " is not really thirsty.");
                    continue;
                }

                System.out.println(">> " + dogName + " really enjoyed the clean water!");
                //alter needs
                dog.changeThirst(+1);
                dog.changeBladder(-1);
                showDogCurrentNeeds(dog);
            }

            //groom dog
            else if (select == 3) {
                if (dog.getHygiene() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " is not that dirty right now.");
                    continue;
                }

                System.out.println(">> " + dogName + " smells much better now!");
                //change needs
                dog.changeHygiene(+1);
                dog.changeEnergy(-1);
                showDogCurrentNeeds(dog);
            }

            //Take dog out to potty
            else if (select == 4) {

                if (dog.getBladder() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " does not need to potty right now.");
                    continue;
                }

                System.out.println(">> Phew, that was close. " + dogName + " really had to go!");
                //change needs
                dog.changeHygiene(-1);
                dog.changeBladder(+1);
                showDogCurrentNeeds(dog);
            }

            //Play with dog
            else if (select == 5) {

                if (dog.getAttention() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " is a little annoyed now. Maybe give them some space.");
                    continue;
                }

                System.out.println(">> " + dogName + " loved spending time with you!");
                //change needs
                dog.changeAttention(+1);
                dog.changeEnergy(-1);
                showDogCurrentNeeds(dog);
            }

            //Let dog sleep
            else if (select == 6) {

                if (dog.getEnergy() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " is not really tired.");
                    continue;
                }

                System.out.println(">> Zzzzzzzz");
                //change needs
                dog.changeEnergy(+1);
                dog.changeHunger(-1);
                dog.changeThirst(-1);
                dog.changeBladder(-1);
                showDogCurrentNeeds(dog);
            }

            //if nothing was chosen
            else {
                System.out.println(">> You need to choose something to do with " + dogName + " first!");
            }
            //enables dogs' needs change upon each selection
            dog.tick();
        } while (select != 7); //because 7 means quit

    }
}
Enter fullscreen mode Exit fullscreen mode

Finally, we can print out the current needs in a method named showDogCurrentNeeds(). Pass in the DogNeeds dog parameter so that we can call on our getter methods.

import java.util.Scanner;

public class DogApplication {

    public static void main(String[] args) {
        ...
    }

    //displays current needs
    private static void showDogCurrentNeeds(DogNeeds dog) {
        //displays current needs
            System.out.println(">> Hunger: " + dog.getHunger());
            System.out.println(">> Thirst: " + dog.getThirst());
            System.out.println(">> Attention: " + dog.getAttention());
            System.out.println(">> Bladder: " + dog.getBladder());
            System.out.println(">> Hygiene: " + dog.getHygiene());
            System.out.println(">> Energy: " + dog.getEnergy());
    }
}
Enter fullscreen mode Exit fullscreen mode

And with that, we can run and test our game!

Complete DogApplication.java

import java.util.Scanner;

public class DogApplication {

    public static void main(String[] args) {
        int select;

        //allow us to get user input
        Scanner input = new Scanner(System.in); //creates a scanner object
        System.out.println("Who is the goodest boy ever? (Enter your dogs name)");
        String dogName = input.nextLine();

        //create a new dog with needs object
        DogNeeds dog = new DogNeeds(dogName);

        //instructions
        needsMenu(dogName);

        do {
            System.out.println("What do you want to do today?");
            System.out.println(">> [0] Take " + dogName + " for a walk.");
            System.out.println(">> [1] Feed " + dogName + " their favorite treats.");
            System.out.println(">> [2] Refill " + dogName + "'s water bowl.");
            System.out.println(">> [3] Groom " + dogName + "'s coat.");
            System.out.println(">> [4] Take " + dogName + " out to potty.");
            System.out.println(">> [5] Play with " + dogName + ".");
            System.out.println(">> [6] Let " + dogName + " get some sleep.");
            System.out.println(">> [7] Quit.");

            //will select the int[0-7] that user chose
            select = input.nextInt();

            //exit the console, hence quitting the game
            if (select == 7) {
                continue;
            }

            //Take dog for walk
            else if (select == 0) {
                //if the attention is full, the dog won't want to walk
                if (dog.getAttention() < 5) {
                    System.out.println(">> Mmh, it doesn't seem like " + dogName + " wants to go for a walk right now. Try again later.");
                    continue;
                }

                System.out.println(">> " + dogName + " really enjoyed that walk!");
                //alter needs
                dog.changeAttention(+1);
                dog.changeEnergy(-1);
                dog.changeHygiene(-1);
                showDogCurrentNeeds(dog);
            }

            //Feed the dog their favorite treats
            else if (select == 1) {
                if (dog.getHunger() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " is too full to eat right now. Try again later.");
                    continue;
                }

                System.out.println(">> " + dogName + " really enjoyed that treat!");
                //alter needs
                dog.changeHunger(+1);
                dog.changeEnergy(+1);
                dog.changeThirst(-1);
                dog.changeAttention(+1);
                showDogCurrentNeeds(dog);
            }

            //Refill the dogs' water bowl
            else if (select == 2) {

                if (dog.getThirst() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " is not really thirsty.");
                    continue;
                }

                System.out.println(">> " + dogName + " really enjoyed the clean water!");
                //alter needs
                dog.changeThirst(+1);
                dog.changeBladder(-1);
                showDogCurrentNeeds(dog);
            }

            //groom dog
            else if (select == 3) {
                if (dog.getHygiene() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " is not that dirty right now.");
                    continue;
                }

                System.out.println(">> " + dogName + " smells much better now!");
                //change needs
                dog.changeHygiene(+1);
                dog.changeEnergy(-1);
                showDogCurrentNeeds(dog);
            }

            //Take dog out to potty
            else if (select == 4) {

                if (dog.getBladder() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " does not need to potty right now.");
                    continue;
                }

                System.out.println(">> Phew, that was close. " + dogName + " really had to go!");
                //change needs
                dog.changeHygiene(-1);
                dog.changeBladder(+1);
                showDogCurrentNeeds(dog);
            }

            //Play with dog
            else if (select == 5) {

                if (dog.getAttention() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " is a little annoyed now. Maybe give them some space.");
                    continue;
                }

                System.out.println(">> " + dogName + " loved spending time with you!");
                //change needs
                dog.changeAttention(+1);
                dog.changeEnergy(-1);
                showDogCurrentNeeds(dog);
            }

            //Let dog sleep
            else if (select == 6) {

                if (dog.getEnergy() > 5) {
                    System.out.println(">> Mmh, it seems like " + dogName + " is not really tired.");
                    continue;
                }

                System.out.println(">> Zzzzzzzz");
                //change needs
                dog.changeEnergy(+1);
                dog.changeHunger(-1);
                dog.changeThirst(-1);
                dog.changeBladder(-1);
                showDogCurrentNeeds(dog);
            }

            //if nothing was chosen
            else {
                System.out.println(">> You need to choose something to do with " + dogName + " first!");
            }
            //enables dogs' needs change upon each selection
            dog.tick();
        } while (select != 7); //because 7 means quit

    }

    //displays current needs
    private static void showDogCurrentNeeds(DogNeeds dog) {
        //displays current needs
            System.out.println(">> Hunger: " + dog.getHunger());
            System.out.println(">> Thirst: " + dog.getThirst());
            System.out.println(">> Attention: " + dog.getAttention());
            System.out.println(">> Bladder: " + dog.getBladder());
            System.out.println(">> Hygiene: " + dog.getHygiene());
            System.out.println(">> Energy: " + dog.getEnergy());
    }

    //method needed to print out game instructions
    public static void needsMenu(String dogName)
    {
        System.out.println(
                "-----------------------------------------------------------------------------------------------" +
                        "\n>> Welcome to parenthood! You are now the proud new owner of "  + dogName + "!" +
                        "                                  \n" +
                        "                            |' \\ \n" +
                        "         _                  ; : ; \n" +
                        "        / `-.              /: : | \n" +
                        "       |  ,-.`-.          ,': : | \n" +
                        "       \\  :  `. `.       ,'-. : | \n" +
                        "        \\ ;    ;  `-.__,'    `-.| \n" +
                        "         \\ ;   ;  :::  ,::'`:.  `. \n" +
                        "          \\ `-. :  `    :.    `.  \\ \n" +
                        "           \\   \\    ,   ;   ,:    (\\ \n" +
                        "            \\   :., :.    ,'o)): ` `-. \n" +
                        "           ,/,' ;' ,::\"'`.`---'   `.  `-._ \n" +
                        "         ,/  :  ; '\"      `;'          ,--`. \n" +
                        "        ;/   :; ;             ,:'     (   ,:) \n" +
                        "          ,.,:.    ; ,:.,  ,-._ `.     \\\"\"'/ \n" +
                        "          '::'     `:'`  ,'(  \\`._____.-'\"' \n" +
                        "             ;,   ;  `.  `. `._`-.  \\\\ \n" +
                        "             ;:.  ;:       `-._`-.\\  \\`. \n" +
                        "              '`:. :        |' `. `\\  ) \\ \n" +
                        "                ` ;:       |    `--\\__,' \n" +
                        "                   '`      ,' \n" +
                        "                        ,-' " +
                        "\n>> Remember, " + dogName + " has needs! Being a pet owner is a lot of work." +
                        "\n>> " + dogName + " needs clean water, food, sleep, grooming, playtime, and lot's of attention." +
                        "\n>> Good luck!" +
                        "\n-----------------------------------------------------------------------------------------------"
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

If we now test our game, we can see that it opens up the command line and asks us for our dog's name.
Java Virtual Dog

Our menu is printed with our array of options.
Java Virtual Dog

And our needs change upon each round of options!
Java Virtual Dog

I hope this was easy enough to follow. I'm no Java master, but for me this was good enough. I do want to improve on this game, maybe bring it out of the command-line, but hey, that's for future me to worry about! Until next time, happy coding. 😁

The full source code can be found on my GitHub.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .