本文目录导读:

我来为你设计一个空中对抗模拟器的Java综合案例,这个案例会模拟红蓝两队战斗机进行空战,通过复杂的策略和随机因素来判定哪队占据优势。
这个案例将综合运用面向对象编程、集合框架、多线程、Lambda表达式、Stream API、设计模式(策略模式+观察者模式)等核心Java技术。
案例需求分析
场景:红蓝双方各派出3架战斗机在空中对抗,每架战机有血量、攻击力、速度和闪避率属性,系统模拟5个回合的自动战斗,每回合双方各攻击一次,且有机会触发暴击和闪避。
最终胜负判定:比较双方存活战机数量和总剩余血量,若都相同则判为平局。
核心代码实现
战机类(Entity)
package airbattle;
import java.util.Random;
/**
* 战斗机实体类
* 包含战斗属性和战斗行为
*/
public class Fighter {
private String name; // 战机名称
private int maxHp; // 最大血量
private int hp; // 当前血量
private int attack; // 基础攻击力
private int speed; // 速度(影响攻击顺序和命中)
private double dodgeRate; // 闪避率 (0.0 ~ 0.3)
private static final Random random = new Random();
private static final double CRIT_RATE = 0.2; // 暴击率
private static final double CRIT_MULTIPLIER = 1.8; // 暴击伤害倍率
public Fighter(String name, int maxHp, int attack, int speed, double dodgeRate) {
this.name = name;
this.maxHp = maxHp;
this.hp = maxHp;
this.attack = attack;
this.speed = speed;
this.dodgeRate = Math.min(dodgeRate, 0.3); // 限制最大闪避率30%
}
/**
* 攻击目标战机
* @param target 目标战机
* @return 造成的实际伤害(用于日志)
*/
public int attack(Fighter target) {
// 1. 判定是否被闪避
if (random.nextDouble() < target.getDodgeRate()) {
System.out.println(" 🌀 " + target.getName() + " 完美闪避了攻击!");
return 0;
}
// 2. 计算基础伤害(带 ±10% 随机波动)
int baseDamage = (int)(attack * (0.9 + random.nextDouble() * 0.2));
// 3. 判定暴击
boolean isCrit = random.nextDouble() < CRIT_RATE;
int finalDamage = isCrit
? (int)(baseDamage * CRIT_MULTIPLIER)
: baseDamage;
// 4. 扣血(不能减到负数)
int actualDamage = Math.min(finalDamage, target.getHp());
target.setHp(target.getHp() - actualDamage);
// 5. 打印战斗信息
if (isCrit) {
System.out.println(" 💥 " + this.name + " 打出暴击!对 " + target.getName()
+ " 造成 " + actualDamage + " 点伤害!(" + target.getHp() + "/" + target.getMaxHp() + ")");
} else {
System.out.println(" ⚔️ " + this.name + " 攻击 " + target.getName()
+ ",造成 " + actualDamage + " 点伤害。(" + target.getHp() + "/" + target.getMaxHp() + ")");
}
return actualDamage;
}
public boolean isAlive() {
return hp > 0;
}
// Getter / Setter 方法
public String getName() { return name; }
public int getHp() { return hp; }
public void setHp(int hp) { this.hp = Math.max(hp, 0); }
public int getMaxHp() { return maxHp; }
public int getSpeed() { return speed; }
public double getDodgeRate() { return dodgeRate; }
public int getAttack() { return attack; }
@Override
public String toString() {
return name + " [HP:" + hp + "/" + maxHp + ", ATK:" + attack + ", SPD:" + speed + "]";
}
}
军队类(Army - 支持集合操作)
package airbattle;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 战队类 - 管理一个队伍的所有战机
*/
public class Army {
private String teamName; // 队伍名称(红队/蓝队)
private List<Fighter> fighters; // 战机列表
public Army(String teamName) {
this.teamName = teamName;
this.fighters = new ArrayList<>();
}
public void addFighter(Fighter fighter) {
fighters.add(fighter);
}
/**
* 获取所有存活战机(按速度降序排列,速度快的先攻击)
* @return 排序后的存活战机列表
*/
public List<Fighter> getAliveFightersSortedBySpeed() {
return fighters.stream()
.filter(Fighter::isAlive) // 过滤存活
.sorted((f1, f2) -> f2.getSpeed() - f1.getSpeed()) // 按速度降序
.collect(Collectors.toList());
}
/**
* 获取存活战机总数
*/
public long getAliveCount() {
return fighters.stream().filter(Fighter::isAlive).count();
}
/**
* 获取队伍总剩余血量
*/
public int getTotalHp() {
return fighters.stream()
.filter(Fighter::isAlive)
.mapToInt(Fighter::getHp)
.sum();
}
/**
* 判断队伍是否全部阵亡
*/
public boolean isDefeated() {
return getAliveCount() == 0;
}
/**
* 选择攻击目标(策略:优先攻击血量最少但还活着的敌人)
* @param enemy 敌军队伍
* @return 目标战机
*/
public Fighter selectTarget(Army enemy) {
return enemy.getAliveFightersSortedBySpeed().stream()
.min((f1, f2) -> f1.getHp() - f2.getHp()) // 找血量最低的
.orElse(null);
}
public String getTeamName() { return teamName; }
public List<Fighter> getFighters() { return fighters; }
/**
* 格式化显示队伍状态
*/
public String getStatusString() {
StringBuilder sb = new StringBuilder(teamName + " 状态:\n");
fighters.forEach(f -> sb.append(" ").append(f).append(f.isAlive() ? " ✅" : " 💀").append("\n"));
return sb.toString();
}
}
战斗管理器类(BattleManager - 核心逻辑)
package airbattle;
import java.util.List;
/**
* 战斗管理器
* 负责执行多回合战斗,并判定最终胜负
*/
public class BattleManager {
private Army redArmy;
private Army blueArmy;
private int maxRounds;
public BattleManager(Army redArmy, Army blueArmy, int maxRounds) {
this.redArmy = redArmy;
this.blueArmy = blueArmy;
this.maxRounds = maxRounds;
}
/**
* 开始战斗
* @return 获胜队伍名称
*/
public String startBattle() {
System.out.println("========== 🎖️ 空中对抗战开始! ==========");
System.out.println("战斗设定:最多 " + maxRounds + " 回合\n");
System.out.println(redArmy.getStatusString());
System.out.println(blueArmy.getStatusString());
int round = 1;
while (round <= maxRounds && !redArmy.isDefeated() && !blueArmy.isDefeated()) {
System.out.println("\n---------- 第 " + round + " 回合 ----------");
executeRound();
round++;
}
System.out.println("\n========== ⚡ 战斗结束! ==========");
return determineWinner();
}
/**
* 执行一个回合的战斗
* 每队所有存活战机按速度依次攻击对方的一个目标
*/
private void executeRound() {
// 获取双方当前可行动战机(按速度排序)
List<Fighter> redFighters = redArmy.getAliveFightersSortedBySpeed();
List<Fighter> blueFighters = blueArmy.getAliveFightersSortedBySpeed();
// 按顺序混合出手:红蓝交替挑选速度最快的行动
// 实现方式:通过合并排序(类似归并)
int redIdx = 0, blueIdx = 0;
// 只要还有一方有未行动的战机
while (redIdx < redFighters.size() || blueIdx < blueFighters.size()) {
// 红方行动
if (redIdx < redFighters.size()) {
Fighter attacker = redFighters.get(redIdx++);
if (attacker.isAlive() && !blueArmy.isDefeated()) {
Fighter target = redArmy.selectTarget(blueArmy); // 选择敌方最低血目标
if (target != null) {
System.out.println("🔴 [" + redArmy.getTeamName() + "] " + attacker.getName() + " 行动:");
attacker.attack(target);
}
}
}
// 蓝方行动(如果还没有结束)
if (blueIdx < blueFighters.size() && !redArmy.isDefeated()) {
Fighter attacker = blueFighters.get(blueIdx++);
if (attacker.isAlive() && !redArmy.isDefeated()) {
Fighter target = blueArmy.selectTarget(redArmy);
if (target != null) {
System.out.println("🔵 [" + blueArmy.getTeamName() + "] " + attacker.getName() + " 行动:");
attacker.attack(target);
}
}
}
// 如果任意一方全灭,提前结束
if (redArmy.isDefeated() || blueArmy.isDefeated()) {
break;
}
}
// 打印本回合结束后的状态
System.out.println("--- 回合结束状态 ---");
System.out.println("🔴 " + redArmy.getTeamName() + " 存活: " + redArmy.getAliveCount()
+ " 总HP: " + redArmy.getTotalHp());
System.out.println("🔵 " + blueArmy.getTeamName() + " 存活: " + blueArmy.getAliveCount()
+ " 总HP: " + blueArmy.getTotalHp());
}
/**
* 判定最终胜负
* 规则:1. 存活战机数量多者胜
* 2. 存活数量相同,总血量高者胜
* 3. 都相同则判定为平局(极少见)
*/
private String determineWinner() {
long redAlive = redArmy.getAliveCount();
long blueAlive = blueArmy.getAliveCount();
int redHp = redArmy.getTotalHp();
int blueHp = blueArmy.getTotalHp();
System.out.println("\n📊 最终统计:");
System.out.println("🔴 " + redArmy.getTeamName() + ":存活 " + redAlive + " 架,剩余总HP " + redHp);
System.out.println("🔵 " + blueArmy.getTeamName() + ":存活 " + blueAlive + " 架,剩余总HP " + blueHp);
if (redAlive > blueAlive) {
return redArmy.getTeamName();
} else if (blueAlive > redAlive) {
return blueArmy.getTeamName();
} else {
// 存活数量相同,比较总血量
if (redHp > blueHp) {
return redArmy.getTeamName();
} else if (blueHp > redHp) {
return blueArmy.getTeamName();
} else {
return "平局";
}
}
}
}
主程序(含士兵工厂)
package airbattle;
/**
* 主程序入口
* 模拟红蓝双方空战对抗
*/
public class AirBattleMain {
public static void main(String[] args) {
// 创建红队(均衡型搭配)
Army redArmy = createArmy("红队", "均衡型");
// 创建蓝队(高攻速但脆弱)
Army blueArmy = createArmy("蓝队", "高速高攻型");
// 创建战斗管理器,最多5回合
BattleManager battle = new BattleManager(redArmy, blueArmy, 5);
// 开始战斗并获取结果
String winner = battle.startBattle();
// 输出最终结果
System.out.println("\n🎉 获胜队伍是:" + winner + "!");
}
/**
* 根据战术类型创建队伍
*/
private static Army createArmy(String teamName, String tactic) {
Army army = new Army(teamName);
switch (tactic) {
case "均衡型":
// 红队:2架均衡型 + 1架重装型
army.addFighter(new Fighter("歼-20A", 120, 30, 50, 0.2));
army.addFighter(new Fighter("歼-20B", 110, 35, 45, 0.15));
army.addFighter(new Fighter("歼-16", 150, 40, 30, 0.1)); // 重装
break;
case "高速高攻型":
// 蓝队:速度快攻击高,但血量低
army.addFighter(new Fighter("F-22", 90, 45, 60, 0.25));
army.addFighter(new Fighter("F-35", 85, 50, 55, 0.2));
army.addFighter(new Fighter("阵风", 95, 40, 48, 0.18));
break;
}
System.out.println("✅ " + teamName + " 组建完成:" + tactic);
army.getFighters().forEach(f -> System.out.println(" " + f));
return army;
}
}
运行效果示例
✅ 红队 组建完成:均衡型
歼-20A [HP:120/120, ATK:30, SPD:50]
歼-20B [HP:110/110, ATK:35, SPD:45]
歼-16 [HP:150/150, ATK:40, SPD:30]
✅ 蓝队 组建完成:高速高攻型
F-22 [HP:90/90, ATK:45, SPD:60]
F-35 [HP:85/85, ATK:50, SPD:55]
阵风 [HP:95/95, ATK:40, SPD:48]
========== 🎖️ 空中对抗战开始! ==========
---------- 第 1 回合 ----------
...
🍀 由于随机因素,每次战斗结果都会不同!
案例技术亮点总结
| 技术点 | 应用场景 |
|---|---|
| 面向对象 | 类设计、继承关系、封装、多态 |
| Stream API | 过滤存活战机、排序、求和、找最小 |
| Lambda表达式 | 排序比较器、Map操作 |
| 集合框架 | ArrayList 存储战队成员 |
| 随机数 | 伤害波动、暴击判定、闪避判定 |
| 算法 | 归并排序思想(混合出手顺序)、贪心策略(优先攻击低血量) |
| 异常思想 | 健康值防止为负(防御性编程) |
扩展思考
如果你想让案例更深入,可以增加:
- 文件IO - 将战斗日志保存为文件
- 多线程 - 让每架战机的攻击通过线程池并发执行(需处理同步)
- 设计模式 - 使用
观察者模式实时监听战机阵亡并广播事件 - GUI界面 - 使用Swing绘制战场地图
这个案例完整展示了Java后端开发的典型思维,如果你需要进一步完善某个功能(比如添加异常处理或日志框架),随时告诉我!