Java 两回合制游戏:首回合部署方案
下面以一个 回合制战棋/卡牌对战 的通用 Java 案例,讲解首回合部署的设计与实现,你可以按需裁剪。

核心设计思路
首回合部署通常需要解决三件事:
- 先手判定(谁先部署)
- 部署资源限制(首回合可上场的单位数/费用)
- 部署合法区域(己方半场、指定格子等)
设计原则:首回合特殊规则用"独立的部署阶段策略"封装,避免污染后续回合逻辑。
领域模型
// 单位
public class Unit {
private final String id;
private final int cost; // 部署费用
private final int hp;
private final int atk;
private int x, y; // 棋盘坐标
private boolean deployed;
// 构造、getter/setter 省略
}
// 玩家
public class Player {
private final String name;
private int resource; // 资源/费用
private final List<Unit> hand = new ArrayList<>(); // 手牌
private final List<Unit> field = new ArrayList<>(); // 场上单位
// ...
}
// 棋盘
public class Board {
public static final int WIDTH = 8, HEIGHT = 8;
private final Unit[][] grid = new Unit[HEIGHT][WIDTH];
public boolean inOwnHalf(int playerIndex, int x, int y) {
// 玩家0占下半场(y>=4),玩家1占上半场(y<4)
return playerIndex == 0 ? y >= HEIGHT / 2 : y < HEIGHT / 2;
}
public boolean isEmpty(int x, int y) { return grid[y][x] == null; }
public void place(Unit u, int x, int y) { grid[y][x] = u; u.setX(x); u.setY(y); }
}
部署阶段策略(核心)
用策略模式区分"首回合部署"与"常规部署":
public interface DeployStrategy {
/** 本回合允许部署的最大单位数 */
int maxUnitsThisTurn(int turnNo);
/** 校验一次部署是否合法 */
boolean canDeploy(Player p, Board b, Unit u, int x, int y, int turnNo);
}
首回合部署策略
public class FirstTurnDeployStrategy implements DeployStrategy {
private static final int FIRST_TURN_MAX_UNITS = 2; // 首回合最多上 2 个单位
@Override
public int maxUnitsThisTurn(int turnNo) {
return turnNo == 1 ? FIRST_TURN_MAX_UNITS : Integer.MAX_VALUE;
}
@Override
public boolean canDeploy(Player p, Board b, Unit u, int x, int y, int turnNo) {
// 1. 资源足够
if (u.getCost() > p.getResource()) return false;
// 2. 格子空闲且在己方半场
if (!b.isEmpty(x, y) || !b.inOwnHalf(playerIndex(p), x, y)) return false;
// 3. 首回合单位数上限
if (p.getField().size() >= maxUnitsThisTurn(turnNo)) return false;
return true;
}
private int playerIndex(Player p) { /* 由 Game 注入或查询 */ return 0; }
}
常规回合策略
public class NormalDeployStrategy implements DeployStrategy {
@Override public int maxUnitsThisTurn(int t) { return 1; } // 每回合 1 个
@Override
public boolean canDeploy(Player p, Board b, Unit u, int x, int y, int t) {
return u.getCost() <= p.getResource()
&& b.isEmpty(x, y)
&& b.inOwnHalf(0, x, y);
}
}
游戏主循环
public class Game {
private final Board board = new Board();
private final Player[] players = new Player[2];
private int turnNo = 1;
private int currentPlayer = 0;
private DeployStrategy strategy = new FirstTurnDeployStrategy();
private final Map<Integer, Integer> deployedThisTurn = new HashMap<>();
public void start() {
// 先手判定:可随机 / 掷骰 / 固定
currentPlayer = decideFirstPlayer();
runTurn();
}
private void runTurn() {
Player p = players[currentPlayer];
deployedThisTurn.put(currentPlayer, 0);
// ===== 部署阶段(首回合重点)=====
deployPhase(p);
// ===== 战斗阶段 =====
battlePhase(p);
// ===== 回合结束,切换 =====
endTurn();
}
private void deployPhase(Player p) {
int limit = strategy.maxUnitsThisTurn(turnNo);
for (Unit u : new ArrayList<>(p.getHand())) {
if (deployedThisTurn.get(currentPlayer) >= limit) break;
// 这里可改为等待玩家输入坐标;示例自动选己方空格
int[] pos = findFreeSlot(p);
if (pos != null && strategy.canDeploy(p, board, u, pos[0], pos[1], turnNo)) {
board.place(u, pos[0], pos[1]);
p.getHand().remove(u);
p.getField().add(u);
p.setResource(p.getResource() - u.getCost());
deployedThisTurn.merge(currentPlayer, 1, Integer::sum);
}
}
}
private void endTurn() {
currentPlayer = 1 - currentPlayer;
if (currentPlayer == 0) {
turnNo++;
strategy = new NormalDeployStrategy(); // 首回合后切换策略
}
}
}
首回合部署的关键规则(可按游戏自定义)
| 规则项 | 常见做法 | 代码位置 |
|---|---|---|
| 先手判定 | 随机/掷骰/固定玩家0 | decideFirstPlayer() |
| 首回合可上场数 | 1~2 个(比常规少) | maxUnitsThisTurn(1) |
| 初始资源 | 通常给较少费用,防止一波铺场 | Player.resource 初始化 |
| 部署区域 | 仅己方半场 / 后排 2 行 | Board.inOwnHalf() |
| 是否可攻击 | 首回合通常只能部署,不能攻击 | 战斗阶段加 if (turnNo>1) |
| 手牌抽牌 | 首回合可能少抽或不抽 | 抽牌阶段判断 turnNo==1 |
首回合"只部署不攻击"的写法
private void battlePhase(Player p) {
if (turnNo == 1) {
System.out.println("首回合仅部署,跳过战斗阶段");
return; // 关键:首回合无战斗
}
// 正常攻击逻辑...
}
可扩展点
- 把策略注入 Game:
Game.setStrategy(new FirstTurnDeployStrategy()),方便测试。 - 部署校验链:把"资源、区域、数量、冷却"拆成多个
DeployRule,用责任链组合,首回合只需增删规则。 - 回放/日志:记录首回合部署快照,便于复盘。
小结
首回合部署 = 独立的
DeployStrategy+ 回合数判断 + 跳过战斗阶段 + 区域/资源/数量三重校验。
这样首回合的特殊性被封装在策略里,后续回合走常规逻辑,代码清晰、易扩展、易测试,需要我把它补成可运行的完整单文件 Demo(含 main 方法)吗?