Exercise 1: Creating the PlayableCharacter class We will now he creating the PlayableCharacter class. This class will co
-
- Site Admin
- Posts: 899603
- Joined: Mon Aug 02, 2021 8:13 am
Exercise 1: Creating the PlayableCharacter class We will now he creating the PlayableCharacter class. This class will co
G. To accomplish our previous point, add the following code to your class: //Lower our current hitpoints by the damageTaken argument public void receiveDamage (int damageTaken) { this.currentHitPoints damageTaken; } //Object interaction. The parameter is an Enemy object //We call the enemy's receiveDamage method within this attackEnemy method public void attackEnemy (Enemy enemy) { enemy.receiveDamage (this.weaponDamage); } public String toString() { //%s means String //%d means decimal number (integer) return String.format("%s location: %d, %d. HitPoints: %d\n", this.getName(), this.getLocationX(), this.getLocationY(), this.getCurrentHitPoints()); } public boolean equals(Object other) { //Cast the Object parameter to a PlayableCharacter so we can access its name //If the name of the current PlayableCharacter equals the other PlayableCharacter being passed as a parameter, return true. Else, return false. PlayableCharacter tempCast = (PlayableCharacter)other; if (this.name.equals(tempCast.getName())) { return true; } else { } return false; } H. Finally, let's create our class constructor. It should do the following: A. Take a String that represents the playable character's name and assign the value to the name variable. I. With all of the previous step, we can create our constructor with the following code: public PlayableCharacter (String name) { this.name = name; //Alternatively, you could have used setName to set the name } J. We have finished the PlayableCharacter class! Make sure there are no syntax errors (red underlines) outside of receiveDamage (since we use Enemy as a parameter type and we haven't created that class yet) and make sure to save the file.
Exercise 2: Creating the Enemy class We will now be creating the Enemy class. This class will contain methods that will allow it to interact with the PlayableCharacter. B. Add our class fields to the Enemy.java class. Remember to use the "private" access modifier as we are continuing to practice encapsulation. These fields are chosen to represent a bare-minimum Enemy, but this list of variables can be expanded in the future. //class fields private String name; private int currentHitPoints = 4; private int weaponDamage 2; private int locationX = 0; private int location = 0; C. Just like in exercise 1, generate getters and setters for each of these fields. D. Now, we want to create methods that will handle some logic for enemics. We want to make methods that do the following: A. Receive damage, lowering the enemy's hitpoints by the damage amount B. Attack a playable character, causing the playable character to take damage equal to the enemy's weapon damage. C. Override the toString method, so that we can show the current status of the enemy. We will use String.format here to create a formatted String. D. Override the equals method, so that we can determine if one Enemy is "equivalent" to another Enemy based on their names. It will take an Object as a parameter and we will cast it to an Enemy object so we can use its getName() method. F. As you may notice, we created methods in PlayableCharacter that were nearly identical to these. Implement these methods and feel free to reuse code! Here are the method headers and empty method bodies for those two methods: public void receiveDamage(int damageTaken) { } public void attackPlayableCharacter (PlayableCharacter player) { } public String toString() { } public boolean equals(Object other) { } F. Let's create our class constructor. It should do the following: A. Take a String that represents the enemy's name and assign the value to the name variable.
E. As you may notice, we created methods in PlayableCharacter that were nearly identical to these. Implement these methods and feel free to reuse code! Here are the method headers and empty method bodies for those two methods: public void receiveDamage(int damageTaken) { } public void attackPlayableCharacter (PlayableCharacter player) { } public String toString() { } public boolean equals(Object other) { } F. Let's create our class constructor. It should do the following: A. Take a String that represents the enemy's name and assign the value to the name variable. B. Take an int that represents the enemy's X location and assign the value to the locationX variable. C. Take an int that represents the enemy's Y location and assign the value to the location Y variable. F. With all of the previous step, we can create our constructor. Create the constructor for the Enemy class on your own. G. Finally, let's create another constructor that will use constructor chaining so we can provide some default values. It should do the following: A. Take a String as a parameter that represents the enemy's name. B. Call the other class constructor using the String parameter as the name argument, 2 as the locationX argument, and 3 as the location Y argument. Remember that you can use this(arguments here) within a constructor to call another constructor (constructor chaining). II. We have finished the Enemy class! Make sure there are no syntax errors (red underlines) and make sure to save the file. The syntax errors in PlayableCharacter should have been resolved now too.
Exercise 3: Creating the Game class We will now be creating the Game class. This class will contain the game logic tuses the PlayableCharacter and Enemy classes to create a simple game. A. We want the main method to use a Scanner object to ask for the player's name. This Scanner object will also be used later for playing the game. Let's add the code for creating a Scanner object and asking for the player's name: Scanner input = new Scanner(System.in); System.out.print("Welcome to the Dungeon! What is your character's name? (Input name then press enter): "); String playerName input.nextLine(); //Create instance of PlayableCharacter with inputed name PlayableCharacter pc = new PlayableCharacter (playerName); System.out.println("Hello, " + pc.getName()); B. We will now create a simple Enemy object called zombie. We will use the constructor with "Zombie" as the name, 2 as the locationX, and 3 as the location Y. /" Enemy class constructor has 3 arguments. Argument 1: String name Argument 2: int locationX Argument 3: int locationY Enemy zombie = new Enemy ("Zombie", 2, 3); C. Now, we will create the "game loop". This loop will handle the turns of the player and enemy while the player's hitpoints are not below 0 and while the player's location is not where the "stairs" are located (at 6,6). The condition of this loop will do the following three things: A. Check if the player's X location is 6 B. Check if the player's Y location is 6 C. Check if the player's current hitpoints is above 0 //GAME LOOP START while (!(pc.getLocationX() == 6 && pc.getLocationY() == 6) && pc.getCurrentHitPoints() > 0) { A. Let us print out both the player and the zombie (only if the zombie's current hitpoints are above 0: System.out.print (pc); if (zombie.getCurrentHitPoints() > 0 ) System.out.print(zombie);
A. Let us print out both the player and the zombie (only if the zombie's current hitpoints are above 0: System.out.print(pc); if (zombie.getCurrentHitPoints() > 0 ) System.out.print(zombie); B. We now want to go through the player's turn. The player should be prompted with instructions on how to move the character in this grid-based game. After getting the input from the player, a good option for moving the player based on their entry is to use a switch statement. (Note: The String in the switch expression is compared with the expressions associated with each case label as if the String.equals method were being used). Here is the incomplete code for this: //Player's turn System.out.println("Where to move? u for up, d for down, 1 for left, r for right. Any other key will skip the turn."); String in switch (in) { case "U": input.nextLine(); pc.setLocationY(pc.getLocationY() + 1); break; case "p": pc.setLocationX(pc.getLocationX() + 1); break; default: System.out.println("Turn Skipped. u for up, d for down, 1 for left, r for right. Any other key will skip the turn."); C. Finish this code to handle down and left. D. Next, we want the player to attack the zombie if the player moves to the same location as the zombie. We will check if the position of player is the same as the zombie and if the zombie's health is above 0. We will call pe.attackEnemy(zombic) to actually "attack" the enemy as the player. If the player's attack causes the zombie's health to go below 0, we will print a message saying the player defeated the zombie. if (pc.getLocationX() == zombie.getLocationX() && pc.getLocationY() == zombie.getLocationY() && zombie.getCurrentHitPoints() > 0) { System.out.printf("%s attacked %s\n", pc.getName(), zombie.getName()); pc.attackEnemy (zombie); if (zombie.getCurrentHitPoints() <= 0) { System.out.printf("%s defeated %s\n", pc.getName(), zombie.getName()); E. Now, we want to do the same thing as the previous two steps, but for the zombie. In this case, we will use a Random object so we can randomly generate the next direction the zombie should move in. We want to create a Random object so we can use it later. Add this to your code inside of your main method: Random rand new Random(); F. Now, lets add the code for the zombie's turn: if (zombie.getCurrentHitPoints() > 0) { int direction = rand.nextInt (4); switch (direction) { case 0: zombie.setLocationY(zombie.getLocationY() + 1);
E. Now, we want to do the same thing as the previous two steps, but for the zombie. In this case, we will use a Random object so we can randomly generate the next direction the zombie should move in. We want to create a Random object so we can use it later. Add this to your code inside of your main method: Random rand new Random(); F. Now, lets add the code for the zombie's turn: if (zombie.getCurrentHitPoints() > 0) { int direction = rand.nextInt (4); switch (direction) { case 0: zombie.setLocationY(zombie.getLocationY() + 1); break; case 1: zombie.setLocationY(zombie.getLocationY() - 1); 20 break; case 2: zombie.setLocationX(zombie.getLocationX() - 1); break; case 3: zombie.setLocationX(zombie.getLocationX() + 1); break; } if (pc.getLocationX() == zombie.getLocationX() && pc.getLocationY() == zombie.getLocationY() && pc.getCurrentHitPoints() > 0) { System.out.printf("%s attacked %s\n", zombie.getName(), pc.getName()); zombie.attackPlayableCharacter (pc); if (pc.getCurrentHitPoints() <= 0) { System.out.printf("%s defeated %s\n", zombie.getName(), pc.getName()); G. And that's it! This logic should handle moving the player and enemy throughout the grid. If the player or enemy moves into the other one, they should attack and remove health, and if the player moves to 6,6 (where our "stairs" are), then the game ends. To make it clear to the player that the game is over (whether they were defeated or if they reached the goal), we should print a few things about the player and zombie to show their status. After the closing curly brace of the while loop, add this code: System.out.println("Game Over!"); System.out.println("Character: " + pc.getName()); System.out.println("Remaining hitpoints: " + pc.getCurrentHitPoints()); System.out.println("Zombie hitpoints: " + zombie.getCurrentHitPoints()); input.close(); H. For the final step, add another enemy (in addition to the zombie) and write the code to handle the logic for it. It should follow the same logic as the zombie (moving in a random direction and attacking the player). (All you will have to do is create a new Enemy object, not make a new class.)