js实现五子棋

主要分几个步骤:

  1. 首先先画棋盘
  2. 保存所有赢法
  3. 监听点击, 每次点击画出棋子, 并遍历赢法,查看游戏是否结束
  1. 画棋盘
<canvas id="chessboard" width="460" height="460">
    您的浏览器不支持canvas,请升级到最新的浏览器
</canvas>
<script>
//绘制棋盘
let chessboard = document.getElementById("chessboard")
    let ctx = chessboard.getContext('2d')
    ctx.lineWidth = '1'
    ctx.beginPath()
    for (let i = 0; i < 15; i++) {
      //绘制横线
      ctx.moveTo(20, 20 + i * 30)
      ctx.lineTo(440, 20 + i * 30)
      //绘制竖线
      ctx.moveTo(20 + i * 30, 20)
      ctx.lineTo(20 + i * 30, 440)
    }
    ctx.stroke()
<script>
  1. 保存所有赢法
 /*
    赢法格式 wins[i][j][k]  
    如wins[0][0][0] 
    wins[1][0][0] 
    wins[2][0][0] 
    wins[3][0][0] 
    wins[4][0][0]  为第一种赢法 第一个为x坐标,第二个为y坐标 第三个为赢法序号

    */
let wins = []
    for (let i = 0; i < 15; i++) {
      wins[i] = []
      for (let j = 0; j < 15; j++) {
        wins[i][j] = []
      }
    }

    // 赢法个数
    let count = 0

    // 横线赢法
    for (let i = 0; i < 15; i++) {
      for (let j = 0; j < 11; j++) {
        wins[j + 0][i][count] = true
        wins[j + 1][i][count] = true
        wins[j + 2][i][count] = true
        wins[j + 3][i][count] = true
        wins[j + 4][i][count] = true
        count++
      }
    }
    // 竖线赢法
    for (let i = 0; i < 15; i++) {
      for (let j = 0; j < 11; j++) {
        wins[i][j + 0][count] = true
        wins[i][j + 1][count] = true
        wins[i][j + 2][count] = true
        wins[i][j + 3][count] = true
        wins[i][j + 4][count] = true
        count++
      }
    }
    // 斜线赢法  左上到右下
    for (let i = 0; i < 11; i++) {
      for (let j = 0; j < 11; j++) {
        wins[j + 0][i + 0][count] = true
        wins[j + 1][i + 1][count] = true
        wins[j + 2][i + 2][count] = true
        wins[j + 3][i + 3][count] = true
        wins[j + 4][i + 4][count] = true

        count++
      }
    }
    // 斜线赢法  左下到右上
    for (let i = 0; i < 11; i++) {
      for (let j = 14; j > 3; j--) {
        wins[i + 0][j - 0][count] = true
        wins[i + 1][j - 1][count] = true
        wins[i + 2][j - 2][count] = true
        wins[i + 3][j - 3][count] = true
        wins[i + 4][j - 4][count] = true

        count++
      }
    }

这里需要使用一个二维数组保存所有落子,默认为0没有棋子, 1为黑子 2为白子
使用一个变量over保存游戏是否结束
使用一个变量isblackchess 保存落子颜色
新建数组记录当前黑白棋子 赢法完成度

   // 保存所有落子
    let chessmen = []
    for (let i = 0; i < 15; i++) {
      chessmen[i] = []
      for (let j = 0; j < 15; j++) {
        chessmen[i][j] = 0
      }
    }

    // 使用变量保存是否结束
    let over = false
    //保存当前落子的颜色
    let isblackchess = true

// 新建数组记录当前黑白棋子 赢法完成度
    let blackWinArr = Array(count)
    let whiteWinArr = Array(count)
    blackWinArr.fill(0)
    whiteWinArr.fill(0)
  1. 监听棋盘的点击
chessboard.onclick = function (e) {
      if (over) {
        return
      }
      let i = ((e.offsetX - 20) / 30).toFixed(0)
      let j = ((e.offsetY - 20) / 30).toFixed(0)
    //如果当前位置没有棋子 则
      if (chessmen[i][j] == 0) {
      //step接收三个参数: x坐标, y坐标, 是否是黑子, 然后画出黑子/白字
        step(i, j, isblackchess)
        if (isblackchess) {
          chessmen[i][j] = 1
        //addBlack 将落下的黑子放入黑子的赢法数组中
          addBlack(i, j)
          
        } else {
          chessmen[i][j] = 2
         //addBlack 将落下的白子放入黑子的赢法数组中
          AddWhite(i, j)
        }
      }
      isblackchess = !isblackchess
    }

函数

    //单击后画棋子
    function step(i, j, me) {
      let x = 20 + i * 30
      let y = 20 + j * 30
      ctx.beginPath()
      ctx.arc(x, y, 13, 0, 2 * Math.PI)
      ctx.closePath()
      let gradient = ctx.createRadialGradient(x, y, 0, x, y, 8)
      if (me) {
        gradient.addColorStop(0, '#636766')
        gradient.addColorStop(1, '#0a0a0a')
      } else {
        gradient.addColorStop(0, "#f9f9f9");
        gradient.addColorStop(1, "#d1d1d1");
      }
      ctx.fillStyle = gradient
      ctx.fill()
    }
    // 记录黑棋赢法的完成度, 某个赢法达到 5则游戏结束
    function addBlack(i, j) {
      for (let k = 0; k < count; k++) {
        if (wins[i][j][k]) {
          blackWinArr[k]++
          if (blackWinArr[k] == 5) {
            setTimeout(() => {alert("黑棋赢了")}) //这里添加个定时器, 不然第五个棋子会后面显示
            over = true
          }
        }
      }
    }

    //记录白棋所在赢法 的完成度
    function AddWhite(i, j) {
      for (let k = 0; k < count; k++) {
        if (wins[i][j][k]) {
          whiteWinArr[k]++
          if (whiteWinArr[k] == 5) {
            setTimeout(() => {alert("白棋赢了")})  
            over = true
          }
        }
      }
    }

注意点:

  1. 使用canvas画图在script标签里加上一下代码, 不然没有提示
/** @type {HTMLCanvasElement} */
  1. alert会先于棋子显示, 要加个setTimeout
  2. 关于赢法


    Snipaste_2020-07-14_10-23-54.png

    以左上角为(0, 0) 那么:

//横线第1个赢法
wins[0][0][0]
wins[1][0][0]
wins[2][0][0]
wins[3][0][0]
wins[4][0][0]
//横线第2个赢法
wins[1][0][1]
wins[2][0][1]
wins[3][0][1]
wins[4][0][1]
wins[5][0][1]

可以看出第一个数一次循环+1 ,第二个不变,第三个为次数,每次循环+1
所以第一个为内层循环, 第二个外层循环, 内层循环一次count+1
而当x坐标>=11时,是不能凑成一个赢法的,那么第一个数小于11,也就是内层循环小于11
所以有:

    for (let i = 0; i < 15; i++) {
      for (let j = 0; j < 11; j++) {
        wins[j + 0][i][count] = true
        wins[j + 1][i][count] = true
        wins[j + 2][i][count] = true
        wins[j + 3][i][count] = true
        wins[j + 4][i][count] = true
        count++
      }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。