patternjavaModerate
Battle game simulation
Viewed 0 times
battlegamesimulation
Problem
Can someone tell me if my code is too long for what it does?
```
package Tests;
import java.util.Random;
import java.util.Scanner;
public class DuelMain {
public static void main(String[] args) {
Random battle = new Random();
@SuppressWarnings("resource")
Scanner input = new Scanner(System.in);
int hero, match, restart;
Duel valon = new Duel();
Duel rintar = new Duel();
Duel zersious = new Duel();
Duel balrock = new Duel();
Duel hawkeye = new Duel();
Duel yusef = new Duel();
valon.attack = 6;
valon.defense = 0;
valon.health = 19;
rintar.attack = 8;
rintar.defense = 1;
rintar.health = 16;
zersious.attack = 5;
zersious.defense = 2;
zersious.health = 18;
balrock.attack = 10;
balrock.defense =0;
balrock.health = 15;
hawkeye.attack = 7;
hawkeye.defense = 1;
hawkeye.health = 17;
yusef.attack = 13;
yusef.defense = 2;
yusef.health = 10;
System.out.println("Choose your HERO");
System.out.println("Press 1 for the Mage Lord Valon Press 2 for the Warrior Rintar");
System.out.println("Attack 6 Attack 8");
System.out.println("Defense 0 Defense 1");
System.out.println("Health 19 Health 16");
System.out.println("");
System.out.println("");
System.out.println("Press 3 for the Paladin Prince Zersious Press 4 for the Orc Balrock");
System.out.println("Attack 5 Attack 10");
System.out.println("Defense 2 Defense 0");
System.out.println("Health 18 Health 15");
System.out.println("");
System.out.println("");
System.out.println("Press 5 for the Elf Hawkeye Press 6 for the Dragon Summoner Yusef");
System.out.println("Attack 7 Attack 13");
System.out.pri
```
package Tests;
import java.util.Random;
import java.util.Scanner;
public class DuelMain {
public static void main(String[] args) {
Random battle = new Random();
@SuppressWarnings("resource")
Scanner input = new Scanner(System.in);
int hero, match, restart;
Duel valon = new Duel();
Duel rintar = new Duel();
Duel zersious = new Duel();
Duel balrock = new Duel();
Duel hawkeye = new Duel();
Duel yusef = new Duel();
valon.attack = 6;
valon.defense = 0;
valon.health = 19;
rintar.attack = 8;
rintar.defense = 1;
rintar.health = 16;
zersious.attack = 5;
zersious.defense = 2;
zersious.health = 18;
balrock.attack = 10;
balrock.defense =0;
balrock.health = 15;
hawkeye.attack = 7;
hawkeye.defense = 1;
hawkeye.health = 17;
yusef.attack = 13;
yusef.defense = 2;
yusef.health = 10;
System.out.println("Choose your HERO");
System.out.println("Press 1 for the Mage Lord Valon Press 2 for the Warrior Rintar");
System.out.println("Attack 6 Attack 8");
System.out.println("Defense 0 Defense 1");
System.out.println("Health 19 Health 16");
System.out.println("");
System.out.println("");
System.out.println("Press 3 for the Paladin Prince Zersious Press 4 for the Orc Balrock");
System.out.println("Attack 5 Attack 10");
System.out.println("Defense 2 Defense 0");
System.out.println("Health 18 Health 15");
System.out.println("");
System.out.println("");
System.out.println("Press 5 for the Elf Hawkeye Press 6 for the Dragon Summoner Yusef");
System.out.println("Attack 7 Attack 13");
System.out.pri
Solution
First, I'd like to start off by saying that if you've really only been coding in Java a few days -- well done. For "a few days'" worth of experience, having code that compiles and does what you want it to (and expect it to) is the most important thing. That being said, this is a code review site, so some suggestions....
The combatants
As others have mentioned, my first change would be to create a class to hold data for each participant of the Duel. The basic information for each participant is their name, and integer values for their attack, defense, and health. Since naming this class 'Character' would be in conflict with
Now we can create a Player object for each combatant:
Since a "Duel" will continue until one player is "dead", I'd add a utility method for determining if a player is dead (or alive, in this case.) This will allow us to change the criteria in the future in a more simple way:
Why? In object-oriented programming, a single "concept" is defined by a class, which defines its data fields and methods. Here, we are taking the "concept" of a player and putting the logic for each player into a single, well-defined object. Now the Player object for Hawkeye knows everything there is to know about Hawkeye, and it is no longer scattered throughout the code. If we want to make Hawkeye a little weaker by changing his attack value, we now only need to change it in all places instead of tracking down all the places in the code where we define him as a combatant.
The fight
From reading the code, it looks like a "duel" is supposed to proceed by each player attacking the other until one player is dead. That is, Player 1 attacks Player 2. Then Player 2 attacks Player 1. And so on. A Player's damage is defined as their "attack" value minus their opponent's "defense" value. The damage is then subtracted from the defender's health value. The duel continues until one or both players are "dead". Since the code allows for "draws", which appears intentional, then both the attack and the counter attack (player 1 attacks player 2, player 2 attacks player 1) happen in the same round, and only after both attacks are completed does the round end and the end conditions get checked.
The duel logic can therefore be consolidated into a small method that takes only two Player variables, the duel participants. (Here I left them named "you" and "enemy" but it's really not important.)
I have extracted the "attack" code into a single method called
There is one very important thing to note here, and that is damage calculation. Previously the code didn't take into account the possibility that the defender's defense value could be higher than the attacker's attack value, which would result in negative damage. Since having health go up after an attack made no sense, called the
(Another thing to note is that the concept of "you" and "your enemy" went away here and instead the attacker and defender are referred to by name. So instead of "Your attack does 20 damage!" it'll now print "Hawkeye's attack does 20 damage!")
Why? A Duel is a self-contained action between two Players, so it should be separate from the Player class itself. When we moved the logic for each combatant's stats and names into the Player object, we effectively anonymized the concept of a duel here as well. It no longer matters who "you" are and who your "enemy" is, but rather what two combatants are participating. This way we can simplify our code greatly and model an "attack" in a player-agnostic fashion.
The arena
Now that we've defined how a duel is performed, we need to take a step back and consider this class th
The combatants
As others have mentioned, my first change would be to create a class to hold data for each participant of the Duel. The basic information for each participant is their name, and integer values for their attack, defense, and health. Since naming this class 'Character' would be in conflict with
java.lang.Character, I figure "Player" would be a good name:public class Player {
private String name;
private int attack;
private int defense;
private int health;
// Contructor, getters, and setters here
}Now we can create a Player object for each combatant:
Player valon = new Player("Valon", 6, 0, 19);Since a "Duel" will continue until one player is "dead", I'd add a utility method for determining if a player is dead (or alive, in this case.) This will allow us to change the criteria in the future in a more simple way:
// in the Player class
public boolean isAlive() {
return health > 0;
}Why? In object-oriented programming, a single "concept" is defined by a class, which defines its data fields and methods. Here, we are taking the "concept" of a player and putting the logic for each player into a single, well-defined object. Now the Player object for Hawkeye knows everything there is to know about Hawkeye, and it is no longer scattered throughout the code. If we want to make Hawkeye a little weaker by changing his attack value, we now only need to change it in all places instead of tracking down all the places in the code where we define him as a combatant.
The fight
From reading the code, it looks like a "duel" is supposed to proceed by each player attacking the other until one player is dead. That is, Player 1 attacks Player 2. Then Player 2 attacks Player 1. And so on. A Player's damage is defined as their "attack" value minus their opponent's "defense" value. The damage is then subtracted from the defender's health value. The duel continues until one or both players are "dead". Since the code allows for "draws", which appears intentional, then both the attack and the counter attack (player 1 attacks player 2, player 2 attacks player 1) happen in the same round, and only after both attacks are completed does the round end and the end conditions get checked.
The duel logic can therefore be consolidated into a small method that takes only two Player variables, the duel participants. (Here I left them named "you" and "enemy" but it's really not important.)
public void duel(Player you, Player enemy) {
do {
attack(you, enemy);
attack(enemy, you);
} while (you.isAlive() && enemy.isAlive());
if (you.isAlive()) {
System.out.println("You win!");
} else if (enemy.isAlive()) {
System.out.println("You lose!");
} else {
System.out.println("Draw!");
}
}I have extracted the "attack" code into a single method called
attack. This method models the act of one Player attacking another Player, and it prints the result.private void attack(Player attacker, Player defender) {
int damage = Math.max(0, attacker.getAttack() - defender.getDefense());
int health = defender.getHealth() - damage;
System.out.println(attacker.getName() + "'s attack does " + damage + " damage!\n");
System.out.println(defender.getName() + "'s Health\n");
System.out.println(health);
defender.setHealth(health);
}There is one very important thing to note here, and that is damage calculation. Previously the code didn't take into account the possibility that the defender's defense value could be higher than the attacker's attack value, which would result in negative damage. Since having health go up after an attack made no sense, called the
Math.max method and passed it a 0, so that if the calculated damage was negative, to default to zero.(Another thing to note is that the concept of "you" and "your enemy" went away here and instead the attacker and defender are referred to by name. So instead of "Your attack does 20 damage!" it'll now print "Hawkeye's attack does 20 damage!")
Why? A Duel is a self-contained action between two Players, so it should be separate from the Player class itself. When we moved the logic for each combatant's stats and names into the Player object, we effectively anonymized the concept of a duel here as well. It no longer matters who "you" are and who your "enemy" is, but rather what two combatants are participating. This way we can simplify our code greatly and model an "attack" in a player-agnostic fashion.
The arena
Now that we've defined how a duel is performed, we need to take a step back and consider this class th
Code Snippets
public class Player {
private String name;
private int attack;
private int defense;
private int health;
// Contructor, getters, and setters here
}Player valon = new Player("Valon", 6, 0, 19);// in the Player class
public boolean isAlive() {
return health > 0;
}public void duel(Player you, Player enemy) {
do {
attack(you, enemy);
attack(enemy, you);
} while (you.isAlive() && enemy.isAlive());
if (you.isAlive()) {
System.out.println("You win!");
} else if (enemy.isAlive()) {
System.out.println("You lose!");
} else {
System.out.println("Draw!");
}
}private void attack(Player attacker, Player defender) {
int damage = Math.max(0, attacker.getAttack() - defender.getDefense());
int health = defender.getHealth() - damage;
System.out.println(attacker.getName() + "'s attack does " + damage + " damage!\n");
System.out.println(defender.getName() + "'s Health\n");
System.out.println(health);
defender.setHealth(health);
}Context
StackExchange Code Review Q#38105, answer score: 17
Revisions (0)
No revisions yet.