Lesson 2 - frc2052/2023-KnightKrawlerJavaTraining GitHub Wiki

In this lesson, we will begin working on a text adventure game! Text adventure games rely on what is referred to as a state machine. A state machine is a system with multiple states it can be in and logic for transferring between states. In our case, this could be different rooms within the game, enemies you have to fight, or treasures you need to find. Text adventure games are some of the oldest computer games ever created. Before computers even had a monitor, programmers created text adventure games that computer users could play by connecting a terminal to a phone modem. The users would input commands in their terminal, which would be transmitted over the phone line. The mainframe computer would calculate the outcome. The main frame would return a text description of what happened, but because the terminal didn't have a monitor, a printer would print the returned result on a spool of paper.
We've refactored the code for the following assignment slightly for the purposes of the next lessons. Replace the code within your Main.Java file with the following code.
import java.util.Scanner; public class Main { // Variable to store our instanced class for receiving input // NOTE: notice this variable has yet to be set equal to anything, this is done on line 13 private Scanner input; private String inputValue; // Variable to store the users name once they provide it private String name; public Main() { // ASSIGNMENT A: System.out.println("Hello world!"); // ASSIGNMENT B: // Here we "initialize" or set our variable (input) equal to a new Scanner instance that receives input from 'System.in' input = new Scanner(System.in); // Asks the user to input their name through the console System.out.println("Please enter your name below:"); // Gets the next available user input and sets the name variable to that input name = input.nextLine(); // Prints a customized welcome message for the user System.out.println("Welcome, " + name + "!"); // ASSIGNMENT C: } // This method is the singular starting point of our application public static void main(String[] args) throws Exception { new Main(); } }
If you payed close attention you'll notice we've moved our code out of the main method and into the class Main's constructor. You'll also notice that we've removed the static keyword from all the class level variables like input
and name
. Although this isn't super important to understand just know that by moving our code out of the Main method we are able to remove the static keyword which, as a general rule of thumb, should usually be avoided in most situations. Because we create a new instance of Main in the main method the constructor of the Main class gets called in effect making the Main class's constructor as being our new main method.
Through the next lessons we'll be assigning code to write without giving the code to you directly. If you get stuck or confused solutions will usually be provided at the bottom of the lesson or you can go to the
lessons
folder within your project and go to the specific lesson you're stuck on to view the final product.
The next step in this assignment is to create the game loop of our text adventure game. In order to accomplish this we need a loop that runs until a certain condition is met like the player winning or dying. First we'll set up our conditions. At the top of the Main class create two boolean variables: isDead
and hasWon
, and set them both equal to false
. These will be the conditions of our game loop. Also create a int variable named currentPosition
and set it equal to zero. To create the game loop go below the Assignment C comment and create a while loop. For the conditions in the while loop put !isDead && !hasWon
this will check each loop to see if the player is not dead and if the player has not won. If either of these conditions are true the statement becomes false and the loop is broken ending the game. Below is an example of what your code could look like at this point.
import java.util.Scanner; public class Main { // Variable to store our instanced class for receiving input // NOTE: notice this variable has yet to be set equal to anything, this is done on line 13 private Scanner input; // Variable stores the input recieved from our input instance for easy access private String inputValue; // Variable to store the users name once they provide it private String name; // Keeps track of the current location, 0 is the beginning of the dungeon private int currentPosition = 0; private Boolean isDead = false; private Boolean hasWon = false; public Main() { // ASSIGNMENT A: System.out.println("Hello world!"); // ASSIGNMENT B: // Here we "initialize" or set our variable (input) equal to a new Scanner instance that receives input from 'System.in' input = new Scanner(System.in); // Asks the user to input their name through the console System.out.println("Please enter your name below:"); // Gets the next available user input and sets the name variable to that input name = input.nextLine(); // Prints a customized welcome message for the user System.out.println("Welcome, " + name + "!"); // ASSIGNMENT C: while (!isDead && !hasWon) { } } // This method is the singular starting point of our application public static void main(String[] args) throws Exception { new Main(); } }
For simplicity copy and paste the template code below into your while loop that we created earlier.
switch (currentPosition) { case 0: System.out.println("You are at the entrance, you can only go north. Type \"N\" to go north."); inputValue = input.nextLine(); if (inputValue.toLowerCase().trim().equals("n")) { currentPosition = 1; } else { System.out.println("Invalid direction. Only \"N\" is valid"); } break; case 1: System.out.println("You are standing at a hallway intersection that moves in all four directions; north, south, east and west."); inputValue = input.nextLine(); if (inputValue.toLowerCase().trim().equals("e")) { currentPosition = 2; } else if (inputValue.toLowerCase().trim().equals("n")) { currentPosition = 3; } else if (inputValue.toLowerCase().trim().equals("w")) { currentPosition = 4; } else if (inputValue.toLowerCase().trim().equals("s")) { currentPosition = 0; } else { System.out.println("Invalid direction. Only \"N\", \"S\", \"E\", \"W\", are valid"); } break; case 2: System.out.println("You have found a large wooden door that is latched from the outside. Do you enter \"E\" or Go Back \"B\""); inputValue = input.nextLine(); if (inputValue.toLowerCase().trim().equals("e")) { System.out.println("You unlock the door and slowly push the door open."); System.out.println("As you enter the room a small candle on the table catches your attention."); System.out.println("As you are mesmerized by the flame, you fail to notice the witch who casts a spell to turn you to stone."); System.out.println("You will forever adorn her room. You have died."); isDead = true; } else if (inputValue.toLowerCase().trim().equals("b")) { currentPosition = 2; } else { System.out.println("Invalid direction. Only \"E\" and \"B\" are valid"); } break; }
This is the implementation of our state machine. The state (our current position) determines which case we go into. These cases contain logic depending on user input. This logic determines from user input which room the user wants to travel to as well as winning and losing conditions. When the user goes to a different room the current position is changed to reflect the room they want to go to. Then the loop iterates and a different case statement gets used.
Continue off the code you just created and create more cases (rooms) that you can go to. Implement a room that you win by going to. Another idea is creating a boolean called hasSword
that can be set to true by going to a specific sword room. Once you have the sword maybe you'll be able to defeat a monster room (up to you how to implement through text) that stands between you and the winning room. Get creative!
Make sure to commit and push your code!