控制台程序模擬三職業(BM、DH、MK)回合制 PK。每職業擁有屬性(HP、攻擊力、攻擊間隔)、主動技能(攻擊觸發)、被動技能(受擊觸發),戰鬥過程實時輸出日誌,直到一方陣亡。
| 職業 | HP | 攻擊力 | 攻擊間隔 | 主動技能 (30%) | 被動技能 (30%/60%) |
|---|---|---|---|---|---|
| BM (劍聖) | 650 | 40 | 1.5s | 跳劈:雙倍傷害 | 反彈:受傷害反彈給攻擊者 (不疊加) |
| DH (惡魔獵手) | 600 | 30 | 1.0s | 吸血:傷害轉化為自身 HP (上限 600) | 閃避:完全免疫本次傷害 |
| MK (武僧) | 700 | 50 | 2.5s | 重擊:眩暈 3s (不可疊加,重置冷卻) | 天神:減免 50% 傷害 (60%) |
// 抽象基類
abstract class Person {
int val; // 當前 HP
double coldTime; // 攻擊間隔 (秒)
int waitTime; // 眩暈剩餘時間 (秒)
int fight; // 攻擊力
int chanceHit; // 主動觸發概率 (0-10 對應 0%-100%)
int chanceDefense;// 被動觸發概率
abstract void hit(Person target); // 攻擊邏輯
abstract int defense(Person attacker); // 防禦邏輯,返回實際傷害
}
// 具體職業:BM, DH, MK (見下方完整代碼)
public class Rpg {
public static void main(String[] args) throws Exception {
// 1. 讀取用戶輸入 "BM,DH" 等
// 2. 反射實例化兩個 Person 對象
Person p1 = c1.newInstance();
Person p2 = c2.newInstance();
long now = System.currentTimeMillis();
long next1 = now + (long)(p1.coldTime * 1000);
long next2 = now + (long)(p2.coldTime * 1000);
System.out.println("---遊戲開始---");
while (true) {
now = System.currentTimeMillis();
if (next1 <= now) {
p1.hit(p2);
next1 = now + (long)(p1.coldTime * 1000) + p1.waitTime * 1000;
p1.waitTime = 0;
}
if (next2 <= now) {
p2.hit(p1);
next2 = now + (long)(p2.coldTime * 1000) + p2.waitTime * 1000;
p2.waitTime = 0;
}
// 適當 sleep 避免佔滿 CPU
Thread.sleep(10);
}
}
}
class BM extends Person {
int count = 0; // 反彈次數限制
boolean hitFlag, defenseFlag;
public void hit(Person p) {
if (rand.nextInt(10) < chanceHit) { fight *= 2; hitFlag = true; }
int hurt = p.defense(this);
p.val -= hurt;
fight = 40; // 恢復基礎攻擊力
if (p.val <= 0) win();
log(hitFlag, defenseFlag, p);
hitFlag = defenseFlag = false;
}
public int defense(Person p) {
if (rand.nextInt(10) < chanceDefense) {
if (count != 0) { // 已反彈過,不再反彈
p.val -= p.fight; count++; defenseFlag = true;
if (p.val <= 0) win();
}
}
return p.fight;
}
}
class DH extends Person {
boolean hitFlag, defenseFlag;
public void hit(Person p) {
if (rand.nextInt(10) < chanceHit) { // 吸血
int hurt = p.defense(this);
p.val -= hurt;
val += hurt; if (val > 600) val = 600;
hitFlag = true;
} else {
int hurt = p.defense(this);
p.val -= hurt;
}
if (p.val <= 0) win();
log(hitFlag, defenseFlag, p);
hitFlag = defenseFlag = false;
}
public int defense(Person p) {
if (rand.nextInt(10) < chanceDefense) { defenseFlag = true; return 0; } // 閃避
return p.fight;
}
}
class MK extends Person {
boolean hitFlag, defenseFlag;
public void hit(Person p) {
if (rand.nextInt(10) < chanceHit) { p.waitTime = 3; hitFlag = true; } // 眩暈 3s
int hurt = p.defense(this);
p.val -= hurt;
if (p.val <= 0) win();
log(hitFlag, defenseFlag, p);
hitFlag = defenseFlag = false;
}
public int defense(Person p) {
if (rand.nextInt(10) < chanceDefense) { defenseFlag = true; return p.fight / 2; } // 減半
return p.fight;
}
}
BM攻擊DH,BM觸發主動技能 DH未觸發被動技能 BM:350,DH:200 DH攻擊BM,DH未觸發主動技能 BM觸發被動技能 DH:200,BM:350 ... BM勝出!
輸入文件已包含完整 Person、BM、DH、MK、Rpg 五個類代碼,可直接複製編譯運行。主類 Rpg 使用反射根據輸入字符串動態加載職業類,體現開閉原則。
Random 實例化在每個方法中(應提為字段);System.exit(0) 直接結束 JVM(建議拋出事件由主循環處理);眩暈機制未完全阻止被動技能(需在 defense 中判斷 waitTime>0);控制台輸出與邏輯耦合(可抽離 Logger)。