You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在二维数组中放置战舰?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 17:31:15