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++
      }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355