Сегодня вечером мне стало скучно, и я сам запрограммировал бой. Он не идеально смоделирован, но должен служить хорошей основой для расширения.
Главная
package stackoverflow.fight;
import java.io.BufferedReader;
import java.io.Console;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* this class runs the fight.
*
* It only deals with the input handling, all the rest is done in Fight.class
*/
public class Main {
private static enum Command {
F, // fight
R, // rest
B, // buy weapon
C, // status
Q, // quit
UNDEFINED;
}
public static void main(String... args) throws IOException {
// create the opponents:
final Opponent goodman = new Opponent("Goodman", 50, false);
final Opponent monster = new Opponent("Monster", 50, true);
// and init the fight
final Fight fight = new Fight(goodman, monster);
// input switch statement
// loop while both are alive
while (fight.isOngoing()) {
System.out.println("\n" + fight.getTitle());
System.out.println("\tF: Go out and Fight");
System.out.println("\tB: Buy Weapon");
System.out.println("\tR: Rest");
System.out.println("\tC: Check Stats");
System.out.println("\tQ: Quit");
switch (readCommand()) {
case F:
System.out.println("f: Continue the fight");
fight.fight();
if (!fight.isOngoing()) {
fight.end();
}
break;
case R:
fight.rest();
break;
case C:
System.out.println("c: Fight-Status:");
fight.status();
break;
case B:
System.out.println("b: Buy Weapon:");
System.out.println(Weapon.getBuyableWeapons());
Weapon weapon = readWeapon();
fight.buy(goodman, weapon);
break;
case Q:
System.out.println("q: You quit: Game over");
System.exit(0);
break;
default:
System.out.println("--> Invalid selection");
break;
}
}
}
private static String readLine(String message) throws IOException {
System.out.print("> "+ message.trim() +": ");
// readline from System.in
final String line = new BufferedReader(new InputStreamReader(System.in)).readLine();
if (line == null || "".equals(line.trim())) {
return readLine(message);
}
return line;
}
private static Weapon readWeapon() throws IOException {
Weapon weapon = Weapon.findByName(readLine("\tChoose your Weapon"));
if (weapon == null) {
readWeapon();
}
return weapon;
}
private static Command readCommand() throws IOException {
// transform to Command
try {
return Command.valueOf(readLine("Your Comand").toUpperCase());
} catch (RuntimeException e) {
// if command is null, empty or not one of F,R,C or Q
return readCommand(); // No match ... re-read
}
}}
Оппонент
package stackoverflow.fight;
/**
* modelling the Fighters
*/
public class Opponent {
private final String name;
private final int maxHitpoints;
private int currentHitpoints;
private Weapon weapon;
private final boolean isMonster;
private int currentMoney;
/**
* init the fighter
*
* @param name
* @param maxHitpoints
* - starting hitpoints
* @param isMonster
* - true for monster, false for goodman
*/
public Opponent(String name, int maxHitpoints, boolean isMonster) {
super();
this.name = name;
this.maxHitpoints = maxHitpoints;
this.isMonster = isMonster;
this.currentHitpoints = this.maxHitpoints; // currentHitpoints will
// decrease with hit
// Goodman starts with BAT, MOnster uses Claws
weapon = isMonster ? Weapon.CLAWS : Weapon.BAT;
// Monster has no money, Goodman starts with 10
currentMoney = isMonster ? 0 : 10;
}
/**
* @return the weapon the fighter uses
*/
public Weapon getWeapon() {
return weapon;
}
/**
* @param weapon
*/
public void setWeapon(Weapon weapon) {
if (this.weapon == weapon) {
return;
}
this.weapon = weapon;
this.currentMoney -= weapon.getCost();
System.out.println("\t" + name + " bought new weapon " + weapon.getName() + ". Money left: " + currentMoney);
}
/**
* @return name of the fighter
*/
public String getName() {
return name;
}
/**
* @return actual state
*/
public int getCurrentHitpoints() {
return currentHitpoints;
}
/**
* runs an attack with current weapon on the opponent
*
* @param opponent
* @return the damage done
*/
public void attack(Opponent opponent) {
// one can only attack while he's not dead! (giving an advantage to the first striker)
if (isAlive()) {
// calculate the damage
int damage = weapon.rollDamage();
opponent.wound(damage);
// output the dramatic scene
System.out.println("\t" + name + " attacks " + opponent.getName() + " with " + weapon.getName()
+ " and deals " + damage + " points of damage, leaving " + opponent.getCurrentHitpoints());
} else {
System.out.println("\t" + name + " would strike but unfortunately died trying!");
}
}
/**
* reduce currentHitpoints by damage
*
* @param damage
*/
public void wound(int damage) {
currentHitpoints -= damage;
}
/**
* @return true if the fighter still has more than 0 hitpoints
*/
public boolean isAlive() {
return currentHitpoints > 0;
}
/**
* recover hitpoints (to a max of maxHitpoints
* @param hitPoints
*/
public void recover(int hitPoints) {
currentHitpoints += hitPoints;
// dont go over maximum
if (currentHitpoints > maxHitpoints) {
currentHitpoints = maxHitpoints;
}
// message
System.out.println("\t" + name + " recovers " + hitPoints + " to a current of " + currentHitpoints);
}
/**
* @return is this a monster?
*/
public boolean isMonster() {
return isMonster;
}
/**
* @return how much money is left?
*/
public int getCurrentMoney() {
return currentMoney;
}
}
Оружие
package stackoverflow.fight;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Modeling the available weapons
*/
public enum Weapon {
BAT("Bat", 2, 4, 3), //
AXE("Axe", 4, 6, 6), //
SWORD("Sword", 6, 8, 10), //
CLAWS("Claws", 2, 15, -1), // cost=-1 indicating: not buyable!
;
private final String name;
private final int minDamage;
private final int maxDamage;
private final int cost;
private Weapon(String name, int minDamage, int maxDamage, int cost) {
this.name = name;
this.minDamage = minDamage;
this.maxDamage = maxDamage;
this.cost = cost;
}
public String getName() {
return name;
}
public int getMinDamage() {
return minDamage;
}
public int getMaxDamage() {
return maxDamage;
}
public int getCost() {
return cost;
}
/**
* @return calculates the number of damage dealt with weapon
*/
public int rollDamage() {
return getMinDamage()
+ Double.valueOf(
Math.random()
* (getMaxDamage() - getMinDamage())).intValue();
}
public static Weapon findByName(String name) {
for (Weapon weapon : getBuyableWeapons()) {
if (weapon.getName().equalsIgnoreCase(name)) {
return weapon;
}
}
return null;
}
public static Set<Weapon> getBuyableWeapons() {
Set<Weapon> buyableWeapons = new HashSet<Weapon>();
for (Weapon weapon : Weapon.values()) {
if (weapon.buyable()) {
buyableWeapons.add(weapon);
}
}
return buyableWeapons;
}
public boolean buyable() {
return cost > 0;
}
public String toString() {
return name + ", min:"+minDamage +", max:"+ maxDamage + ", cost:"+cost;
}
}
Сражайтесь
package stackoverflow.fight;
/**
* implements the neverending fight between good and evil
*/
public class Fight {
private int roundCount = 1;
private final Opponent opponentOne;
private final Opponent opponentTwo;
/**
* set up the fight between Opponents One and Two
*
* @param opponentOne
* @param opponentTwo
*/
public Fight(Opponent opponentOne, Opponent opponentTwo) {
super();
this.opponentOne = opponentOne;
this.opponentTwo = opponentTwo;
}
/**
* @return the fight is active while both opponents are alive
*/
public boolean isOngoing() {
return opponentOne.isAlive() && opponentTwo.isAlive();
}
/**
* perform the attack
*
* @param a
* @param b
*/
private void attack(Opponent a, Opponent b) {
a.attack(b);
}
private void roundBasedSuccess() {
// if Goodman survives round 2 print a message of encouragement
if (opponentOne.isAlive() && roundCount == 2) {
System.out
.print("\tThis is encouraging. Goodman has lasted past round 2!");
return;
}
// every 3 rounds, opponentA gains hitPoints
if (opponentOne.isAlive() && roundCount % 3 == 0) {
System.out
.print("\tGoodman is as strong as Samson. He has lasted round "
+ roundCount + " and still looks strong.");
opponentOne.recover(10);
}
}
/**
* Command.F: Fight
*/
public void fight() {
roundBasedSuccess();
// who attacks first (0 or 1)
switch (Double.valueOf(Math.random() * 2).intValue()) {
case 0:
System.out
.println("\t" + opponentOne.getName() + " strikes first.");
attack(opponentOne, opponentTwo);
attack(opponentTwo, opponentOne);
break;
case 1:
System.out.println("\t " + opponentTwo.getName()
+ " strikes first.");
attack(opponentTwo, opponentOne);
attack(opponentOne, opponentTwo);
break;
}
// print message if still in the game
if (opponentOne.isAlive()) {
System.out.println("\t" + opponentOne.getName() + " has "
+ opponentOne.getCurrentHitpoints()
+ " points left. Not bad, Man! ");
}
if (opponentTwo.isAlive()) {
System.out.println("\tWait, " + opponentTwo.getName()
+ " has a total of " + opponentTwo.getCurrentHitpoints()
+ " points and is still in the game");
}
System.out.println("This is the end of round " + roundCount++ + " "); // increase
// roundCount
}
/**
* Command.R: rest
*/
public void rest() {
System.out.println("r: Opponents should rest (regaining 2 hitpoints");
opponentOne.recover(2);
opponentTwo.recover(2);
}
/**
* Command.C: Status
*/
public void status() {
System.out.println("\tChecking the status of the game: Round "
+ getRoundCount() + ": " + opponentOne.getName() + " has "
+ opponentOne.getCurrentHitpoints() + " points and "
+ opponentTwo.getName() + " has "
+ opponentTwo.getCurrentHitpoints() + " points\n");
}
/**
* @return actual number of rounds
*/
public int getRoundCount() {
return roundCount;
}
/**
* @return title of the fight (A vs. B)
*/
public String getTitle() {
return opponentOne.getName() + " vs. " + opponentTwo.getName()
+ " - Round " + roundCount + ": ";
}
/**
* what happens if the fight is over
*/
public void end() {
if (isOngoing()) {
return; // Oops ... still alive
}
// opponentOne lost?
if (!opponentOne.isAlive()) {
System.out.println("\t" + opponentOne.getName()
+ " you are out of the game! " + opponentTwo.getName()
+ " will take over the village. This is sad!");
System.out.println("Game Over!");
} else if (!opponentTwo.isAlive()) {
System.out.println("\t" + opponentOne.getName()
+ " has been victorious");
System.out.println("\t" + opponentTwo.getName()
+ " is dead. The people live!!!!");
System.out.println("Game Over!");
}
}
/**
* Non-Monsters may switch weapons!
*
* @param opponent
* @param weapon
*/
public void buy(Opponent opponent, Weapon weapon) {
if (opponent.isMonster()) {
System.out.println("\tMonsters cannot buy weapons!");
return;
}
// too expensive
if (opponent.getCurrentMoney() < weapon.getCost()) {
System.out.println("\t" + opponent.getName() + " has only " + opponent.getCurrentMoney() + " left. " + weapon.getName() + " costs " + weapon.getCost() + "!");
return;
}
opponent.setWeapon(weapon);
}
}