原生JS战舰游戏:如何让Ship实例调用GameBoard的placeShip方法?
解决战舰游戏中Ship实例调用placeShip方法的问题
核心思路
要实现battleShip.placeShip(),需要让Ship实例与GameBoard实例建立关联——战舰的放置逻辑本质是游戏棋盘(GameBoard)的功能,Ship作为实体需要依托具体棋盘完成放置操作。我们可以通过让Ship持有GameBoard的引用,在Ship类中新增代理方法,调用GameBoard的placeShip逻辑。
修改后的代码实现
1. 调整Ship类
添加GameBoard引用存储、关联方法,以及代理的placeShip方法:
class Ship { constructor(name, ...args) { this.name = name; this.x = null; // 存储验证后的x坐标 this.y = null; // 存储验证后的y坐标 this.gameBoard = null; // 关联的GameBoard实例 } // 设置当前战舰所属的游戏棋盘 setGameBoard(board) { if (!(board instanceof GameBoard)) { throw new Error('必须传入有效的GameBoard实例'); } this.gameBoard = board; } updateCoord(x, y) { // 原有的坐标验证逻辑示例 const validX = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'].includes(x.toLowerCase()); const validY = y >= 1 && y <= 10; if (validX && validY) { this.x = x.toLowerCase(); this.y = y; return true; } throw new Error('坐标格式无效,请输入如{x: "a", y: 2}的格式'); } // 代理调用GameBoard的placeShip方法 placeShip() { if (!this.gameBoard) { throw new Error('请先通过setGameBoard关联游戏棋盘'); } if (!this.x || !this.y) { throw new Error('请先通过updateCoord设置战舰坐标'); } // 将当前Ship实例传入GameBoard处理放置 return this.gameBoard.placeShip(this); } }
2. 调整GameBoard类
修改placeShip方法,接收Ship实例并处理放置逻辑:
class GameBoard { constructor() { this.ships = []; // 存储已放置的战舰 this.grid = {}; // 棋盘网格,记录坐标占用情况,示例结构:{a2: 'battleship'} } placeShip(ship) { if (!(ship instanceof Ship)) { throw new Error('只能放置Ship实例'); } const coordKey = `${ship.x}${ship.y}`; // 检查坐标是否已被占用 if (this.grid[coordKey]) { throw new Error(`坐标(${ship.x}, ${ship.y})已被占用`); } // 完成放置逻辑 this.ships.push(ship); this.grid[coordKey] = ship.name; console.log(`${ship.name}成功放置在坐标(${ship.x}, ${ship.y})`); return true; } }
3. 使用示例
// 创建游戏棋盘实例 const mainBoard = new GameBoard(); // 创建战舰实例 const battleShip = new Ship("BattleShip"); // 关联棋盘 battleShip.setGameBoard(mainBoard); // 设置战舰坐标 battleShip.updateCoord("c", 2); // 调用放置方法 battleShip.placeShip();
逻辑说明
- Ship类的
placeShip是代理方法,真正的放置逻辑由GameBoard实现,符合单一职责原则(Ship负责自身属性与状态,GameBoard负责棋盘管理)。 - 通过
setGameBoard建立关联,支持一个GameBoard关联多个Ship,或者Ship切换不同的GameBoard,灵活性更高。
内容的提问来源于stack exchange,提问作者Niko17x
相关产品推荐
相关产品推荐

