如何在二维数组中放置战舰?Ship与Gameboard工厂整合困惑
战舰游戏开发问题与解决方案
现有代码梳理
Ship工厂函数
你已经实现了基础的Ship工厂,但存在变量暴露的问题(timesHit和currentlySunk作为返回属性可被外部直接修改,不符合封装原则):
// Begin your app by creating the Ship factory function const Ship = (length, timesHit, currentlySunk) => { const hit = () => { timesHit++; }; const isSunk = () => { if (length === timesHit) { currentlySunk = true; } }; return { length, timesHit, currentlySunk, hit, isSunk }; };
使用示例:
let playerShip1 = Ship(3, 0, false); // length = 3, 0 times hit, not sunk
未完成的Gameboard工厂
你创建了10x10的游戏板数组,但尚未整合Ship工厂实现战舰放置等核心功能:
const Gameboard = () => { const rows = 10; const columns = 10; const coords = []; const placeCords = () => { for (let i = 0; i < rows; i++) { coords[i] = []; for (let j = 0; j < columns; j++) { coords[i][j] = null; } } }; };
问题解决步骤
1. 优化Ship工厂(封装私有变量)
将timesHit和currentlySunk改为内部私有变量,仅通过方法操作状态,避免外部篡改:
const Ship = (length) => { let timesHit = 0; let currentlySunk = false; const hit = () => { if (!currentlySunk) { timesHit++; checkIfSunk(); } }; const checkIfSunk = () => { currentlySunk = timesHit >= length; }; const isSunk = () => currentlySunk; return { length, hit, isSunk, getTimesHit: () => timesHit }; };
2. 完善Gameboard工厂
实现初始化、战舰放置、攻击接收、胜负判断等核心功能:
const Gameboard = () => { const rows = 10; const columns = 10; const board = []; const ships = []; // 存储当前游戏板的所有战舰 // 初始化空白游戏板 const initBoard = () => { for (let i = 0; i < rows; i++) { board[i] = []; for (let j = 0; j < columns; j++) { // 位置状态:null=未攻击,'miss'=未击中,Ship实例=已放战舰,'hit'=击中战舰 board[i][j] = null; } } }; // 验证战舰放置坐标是否合法(不越界、不重叠) const isValidPlacement = (startRow, startCol, length, isHorizontal) => { // 边界检查 if (isHorizontal) { if (startCol + length > columns) return false; } else { if (startRow + length > rows) return false; } // 重叠检查 for (let i = 0; i < length; i++) { const row = isHorizontal ? startRow : startRow + i; const col = isHorizontal ? startCol + i : startCol; if (board[row][col] !== null) return false; } return true; }; // 放置战舰 const placeShip = (startRow, startCol, length, isHorizontal = true) => { if (!isValidPlacement(startRow, startCol, length, isHorizontal)) { return false; // 放置失败 } const newShip = Ship(length); ships.push(newShip); // 在游戏板标记战舰位置 for (let i = 0; i < length; i++) { const row = isHorizontal ? startRow : startRow + i; const col = isHorizontal ? startCol + i : startCol; board[row][col] = newShip; } return true; // 放置成功 }; // 处理攻击 const receiveAttack = (row, col) => { // 坐标合法性检查 if (row < 0 || row >= rows || col < 0 || col >= columns) return null; // 重复攻击检查 if (board[row][col] === 'hit' || board[row][col] === 'miss') return null; const target = board[row][col]; if (target?.hit) { // 击中战舰 target.hit(); board[row][col] = 'hit'; return 'hit'; } else { // 未击中 board[row][col] = 'miss'; return 'miss'; } }; // 判断所有战舰是否沉没 const allShipsSunk = () => { return ships.every(ship => ship.isSunk()); }; // 初始化游戏板 initBoard(); return { placeShip, receiveAttack, allShipsSunk, getBoard: () => [...board] }; };
3. 使用示例
// 创建玩家游戏板 const playerBoard = Gameboard(); // 放置一艘长度为3的水平战舰,起始坐标(2,3) playerBoard.placeShip(2, 3, 3); // 攻击坐标(2,3) playerBoard.receiveAttack(2, 3); // 返回 'hit' // 攻击坐标(5,5) playerBoard.receiveAttack(5, 5); // 返回 'miss' // 检查所有战舰是否沉没 playerBoard.allShipsSunk(); // 返回 false
内容的提问来源于stack exchange,提问作者Dagger
相关产品推荐
相关产品推荐

