《重温JavaScript五子棋》

本文通过实现一个基本的五子棋游戏,展示了如何使用HTML、CSS和JavaScript来构建一个简单的交互式游戏。虽然这里提供的实现较为基础,但它为理解和进一步开发更复杂的版本打下了良好的基础。
在这里插入图片描述

未来还可以考虑添加以下功能:

  1. 更复杂的AI算法,如Minimax算法或Alpha-Beta剪枝。
  2. 多个难度级别的选择。
  3. 用户界面改进,如动画效果和音效。
  4. 在线多人游戏支持。

全部运行代码:

五子棋游戏的基本步骤:

  1. 初始化游戏界面

    • 创建棋盘画布(Canvas)。
    • 设置画布的尺寸和样式。
    • 绘制棋盘。
  2. 管理游戏状态

    • 创建数据结构来存储棋盘的状态。
    • 定义玩家顺序和当前玩家。
    • 管理游戏是否结束。
  3. 玩家交互

    • 监听鼠标点击事件。
    • 计算点击位置对应的棋盘坐标。
    • 验证点击位置是否合法。
    • 更新棋盘状态,并绘制棋子。
  4. 电脑AI

    • 实现简单的AI算法,如随机选择落子位置。
    • 更新棋盘状态,并绘制棋子。
  5. 胜负判定

    • 检查是否有玩家获胜。
    • 如果有玩家获胜,则显示胜利消息,并提供重新开始游戏的选项。
  6. 游戏控制

    • 提供重新开始游戏的功能。
    • 清除画布,重置游戏状态。

代码剖析:

1. 初始化游戏界面
// 获取画布元素
const canvas = document.getElementById('board');
const context = canvas.getContext('2d');

// 设置画布尺寸
canvas.width = 450; // 15格 * 30px每格 + 15px边距
canvas.height = 450; // 同上

// 定义棋盘格子的大小
const gridSize = 30;
const boardSize = 15;

// 绘制棋盘
function drawBoard() {
  context.strokeStyle = '#000';
  context.lineWidth = 1;
  
  // 绘制垂直线
  for (let i = 0; i <= boardSize; i++) {
    context.beginPath();
    context.moveTo(15 + i * gridSize, 15); // 增加15px边距
    context.lineTo(15 + i * gridSize, boardSize * gridSize + 15); // 增加15px边距
    context.stroke();
  }
  
  // 绘制水平线
  for (let i = 0; i <= boardSize; i++) {
    context.beginPath();
    context.moveTo(15, 15 + i * gridSize); // 增加15px边距
    context.lineTo(boardSize * gridSize + 15, 15 + i * gridSize); // 增加15px边距
    context.stroke();
  }
}

// 调用绘制函数
drawBoard();
2. 管理游戏状态
// 创建数据结构来存储棋盘的状态
let board = Array.from({length: boardSize}, () => Array(boardSize).fill(null));

// 定义玩家顺序和当前玩家
let currentPlayer = 'black';

// 游戏是否结束
let gameEnded = false;

// 重置游戏
function resetGame() {
  board = Array.from({length: boardSize}, () => Array(boardSize).fill(null));
  currentPlayer = 'black';
  gameEnded = false;
  context.clearRect(0, 0, canvas.width, canvas.height);
  drawBoard();
}
3. 玩家交互
// 添加鼠标点击事件监听器
canvas.addEventListener('click', (event) => {
  if (!gameEnded && currentPlayer === 'black') { // 只有在游戏未结束且当前玩家是黑方时才允许点击
    const x = Math.floor((event.offsetX - 15) / gridSize); // 减去15px边距
    const y = Math.floor((event.offsetY - 15) / gridSize); // 减去15px边距
    
    if (board[x][y] === null) {
      drawChess(x * gridSize + 15, y * gridSize + 15, currentPlayer); // 加上15px边距
      board[x][y] = currentPlayer;
      
      if (checkWin(x, y, currentPlayer)) {
        gameEnded = true;
      } else {
        currentPlayer = 'white'; // 切换到白方
        computerMove(); // 电脑自动下棋
      }
    }
  }
});

// 绘制棋子
function drawChess(x, y, color) {
  context.fillStyle = color;
  context.beginPath();
  context.arc(x, y, 13, 0, Math.PI * 2, false);
  context.fill();
}

// 检查是否有五个连续的棋子
function checkWin(x, y, player) {
  // 这里可以实现一个简单的检查方法
  // 例如,检查行、列、对角线上是否有五个连续的棋子
  // 本例中省略具体实现
  return false;
}
4. 电脑AI
// 电脑自动下棋
function computerMove() {
  if (!gameEnded && currentPlayer === 'white') {
    let bestMove = findBestMove();
    if (bestMove) {
      drawChess(bestMove.x * gridSize + 15, bestMove.y * gridSize + 15, currentPlayer); // 加上15px边距
      board[bestMove.x][bestMove.y] = currentPlayer;
      
      if (checkWin(bestMove.x, bestMove.y, currentPlayer)) {
        gameEnded = true;
      } else {
        currentPlayer = 'black'; // 切换到黑方
      }
    }
  }
}

// 找到最佳移动位置
function findBestMove() {
  // 简单的随机选择一个空位
  const availableMoves = [];
  for (let x = 0; x < boardSize; x++) {
    for (let y = 0; y < boardSize; y++) {
      if (board[x][y] === null) {
        availableMoves.push({x, y});
      }
    }
  }
  
  return availableMoves[Math.floor(Math.random() * availableMoves.length)];
}
5. 胜负判定
// 检查是否有五个连续的棋子
function checkWin(x, y, player) {
  // 检查行
  let count = 1;
  for (let i = 1; i < 5; i++) {
    if (x - i >= 0 && board[x - i][y] === player) count++;
    if (x + i < boardSize && board[x + i][y] === player) count++;
  }
  
  // 检查列
  for (let i = 1; i < 5; i++) {
    if (y - i >= 0 && board[x][y - i] === player) count++;
    if (y + i < boardSize && board[x][y + i] === player) count++;
  }
  
  // 检查正对角线
  for (let i = 1; i < 5; i++) {
    if (x - i >= 0 && y - i >= 0 && board[x - i][y - i] === player) count++;
    if (x + i < boardSize && y + i < boardSize && board[x + i][y + i] === player) count++;
  }
  
  // 检查反对角线
  for (let i = 1; i < 5; i++) {
    if (x - i >= 0 && y + i < boardSize && board[x - i][y + i] === player) count++;
    if (x + i < boardSize && y - i >= 0 && board[x + i][y - i] === player) count++;
  }
  
  return count >= 5;
}
6. 游戏控制
// 胜利消息
function showVictoryMessage(player) {
  alert(`玩家 ${player} 获胜!`);
  resetGame();
}
  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水煮白菜王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值