2D网格游戏开发中placeMine方法的类归属架构选型问题
最优实现方案:按单一职责做三层逻辑拆分
核心思路是让每个类仅负责自己管辖范围内的逻辑,既符合现实直觉,又保证低耦合、易扩展。
各层职责划分
- Board 类:仅负责网格状态的基础操作,不需要感知玩家、游戏规则这类上层逻辑,只提供「在合法坐标放置地雷」的原子能力
- Player 类:作为放雷动作的发起方,仅校验自身状态(比如剩余地雷数、是否被禁止操作),向所属游戏实例发起放雷请求
- Game 类:作为全局流程编排者,负责校验放雷的全局规则(比如当前阶段是否允许放雷、坐标是否属于玩家可操作范围),校验通过后调用Board的能力完成状态修改
完整代码实现
Cell 类
补充必要的getter/setter用于封装内部状态:
public class Cell { private boolean containsMine; public boolean containsMine() { return containsMine; } public void setContainsMine(boolean containsMine) { this.containsMine = containsMine; } }
Board 类
提供原子性的放雷操作,仅做坐标合法性校验:
public class Board { private Cell[][] board; private int width; private int height; public boolean placeMine(int x, int y) { // 校验坐标合法 if (x < 0 || x >= width || y < 0 || y >= height) { return false; } Cell targetCell = board[x][y]; // 已有雷的情况下无需重复放置 if (targetCell.containsMine()) { return false; } targetCell.setContainsMine(true); return true; } }
Player 类
持有所属游戏实例的引用(玩家从属某一局游戏是完全合理的依赖关系),对外暴露符合直觉的placeMine方法:
public class Player { private Game currentGame; private int remainingMines; // 玩家剩余可放置的地雷数量 public boolean placeMine(int x, int y) { // 仅校验玩家自身相关的状态 if (remainingMines <= 0) { return false; } // 向游戏发起放雷请求 boolean placeSuccess = currentGame.handlePlaceMineRequest(this, x, y); if (placeSuccess) { remainingMines--; } return placeSuccess; } }
Game 类
做全局规则校验和流程编排:
public class Game { private Board board; private Player player; // 多人游戏可替换为 List<Player> playerList public boolean handlePlaceMineRequest(Player requester, int x, int y) { // 此处添加全局规则校验,例如: // 1. 当前是否处于允许放置地雷的游戏阶段 // 2. 目标坐标是否属于 requester 可操作的范围 // 3. 放雷操作是否在冷却时间内 // 所有校验通过后调用Board的原子操作 return board.placeMine(x, y); } }
方案优势
- 符合直觉:上层调用只需要写
player.placeMine(x,y),完全符合「玩家放置地雷」的认知逻辑 - 低耦合:Player和Board没有直接依赖,后续修改Board实现(比如改为3D网格)、修改Player属性都不会互相影响
- 易扩展:后续要加特殊炸弹、多人放雷权限控制等功能时,只需要在对应层级添加逻辑即可,不需要重构原有代码
- 易测试:每个类的逻辑独立,可以单独写单元测试,不需要依赖其他层的实现
内容的提问来源于stack exchange,提问作者Tom Clabault
相关产品推荐
相关产品推荐

