使用原生JS快速写出一个五子棋小游戏

目录
  • 1.棋盘和棋子的绘制。
  • 2.轮流下棋的点击事件
  • 3.获胜条件判断
    • 3.1横轴获胜
    • 3.2数轴获胜
    • 3.3正斜轴获胜
    • 3.4反斜轴获胜
  • 4.悔棋功能
  • 总结

1.棋盘和棋子的绘制。

 let arr = [
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
      [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
    ]
    //封装渲染函数
    const render = () => {
      document.querySelector('table').innerHTML = ''
      arr.forEach((item, index) => {
        let tr = document.createElement('tr')
        item.forEach((item2, index2) => {
          let td = document.createElement('td')//遍历数组,绘制棋盘
          //给td标签设置自定义属性,用来作为坐标使用
          td.dataset.y = index
          td.dataset.x = index2
          tr.appendChild(td)
          //给数组里面的对象做条件判断,这样就能渲染出颜色
          if (item2.num === 1) {
            td.classList.add('bgc1')
          }
          else if (item2.num === 2) {
            td.classList.add('bgc2')
          }
        })
        document.querySelector('table').appendChild(tr)
      })
    }
    render()

先创建一个15 * 15的二维数组,通过对数组的两层遍历,创建出一个15*15的表格,这样棋盘就有了。用数组来绘制棋盘的好处是便于查找和筛选。 每一个td都对应着一个空对象,下棋的时候通过给这个对象添加一个num的属性,num为1时,就渲染成黑色,2就渲染成白色,再稍微调整一下css样式,这样棋盘和棋子就绘制好了。每一个td都有自己的自定义属性x和y,类似于坐标,这样就可以很方便的把td标签和数组里对应的值联系起来。 下面是css代码

<style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      list-style: none;
    }
    table {
      position: relative;
      width: 730px;
      height: 730px;
      margin: 0 auto;
      border: 5px solid black;
      background: url(./src=http___pic45.nipic.com_20140804_2372131_155038114014_2.jpg&refer=http___pic45.nipic.webp) no-repeat;
      background-size: 100%;
      background-position: center;
      padding: 24px 12px;
    }
    td {
      width: 35px;
      height: 35px;
      border-radius: 50%;
      margin-right: 13px;
      margin-bottom: 11px;
      cursor: pointer;
    }
    .bgc1 {
      background-color: black;
    }
    .bgc2 {
      background-color: white;
    }
    button {
      position: absolute;
      width: 200px;
      height: 100px;
      bottom: 100px;
      right: 200px;
      text-align: center;
      line-height: 100px;
      font-size: 25px;
    }
  </style>
<table></table>
  <button>悔棋</button>

2.轮流下棋的点击事件

下棋的逻辑很简单,就是点击棋盘的时候,给点击的td对应的那个对象添加一个num属性,黑棋就是1,白棋就是2,然后渲染出来就可以了。下棋顺序可以通过一个全局变量flag来控制,同时声明两个全局数组,用来存放所有的黑棋和白棋。后面判断胜负时,要对这两个数组先进行遍历。

//判断下棋顺序的全局变量
    let flag = true
    //所有黑棋数组
    let blackArr = []
    //所有白棋数组
    let whiteArr = []
    //轮流下棋逻辑
    document.querySelector('table').addEventListener('click', function (e) {
      if (e.target.dataset.x) {
        let td = e.target
        //判断黑白棋子的顺序
        if (flag) {
          //判断点击的地方是否已经有棋子了,避免棋子覆盖
          if (!arr[td.dataset.y][td.dataset.x].num) {
            flag = !flag
            arr[td.dataset.y][td.dataset.x].num = 1
            //每走一步,就将其添加至对应的数组当中
            blackArr.push([td.dataset.y, td.dataset.x])
          }
        } else {
          if (!arr[td.dataset.y][td.dataset.x].num) {
            flag = !flag
            arr[td.dataset.y][td.dataset.x].num = 2
            whiteArr.push([td.dataset.y, td.dataset.x])
          }
        }
        //调用判断胜负的函数
        XWin(td)
        YWin(td)
        X_YWin(td)
        Y_XWin(td)
      }
      render()
    })

3.获胜条件判断

接下来就是写获胜条件了。我分成了4种情况,横轴,数轴,正斜轴和反斜轴。这4种情况逻辑和方法大致都是相同的,就是里面的数据有些细微差别。

3.1横轴获胜

以横轴为例,如何判断获胜,先判断是黑棋还是白棋,然后遍历对应的数组。已黑棋为例,遍历之后把y值相同的黑棋筛选出来都放入一个数组中,也就是同一行的黑棋。接着比较这一行的这些黑棋的x值,如果有5个连续的x值,则说明横轴上有5个连续的黑棋,就可以判断获胜了。怎么比较这些x值呢,我的做法是先将他们用sort()方法排序,接着从小到大依次比较。建一个新数组,第二个值等于第一个值加1,就把他们扔到这个新数组中,如果出现某个值不连续了,就将这个数组清空,这样通过判断这个数组的长度,就能判断胜负了。

//横轴获胜逻辑
  function XWin(td) {
      //当前X轴的所有棋子集合
      let xAllArr = []
      //判断横轴胜负逻辑的X轴棋子
      let xWinArr = []
      //判断下的是黑棋还是白棋
      if (!flag) {
        blackArr.map(item => {
          if (item[0] == td.dataset.y) {
            //将当前排的所有棋子加入对应数组
            xAllArr.push(item[1])
          }
        })
      } else {
        whiteArr.map(item => {
          if (item[0] == td.dataset.y) {
            xAllArr.push(item[1])
          }
        })
      }
      //把横排总数组排序,方便比较
      xAllArr.sort((a, b) => a - b)
      for (let i = 1; i < xAllArr.length; i++) {
        // console.log(xAllArr[i]);
        if (xAllArr[i] == (+xAllArr[i - 1] + 1)) {
          //如果相邻的两个棋子数量相差1,就将其添加至胜负逻辑数组
          xWinArr.push(xAllArr[i])
        } else {
          //否则得清空
          xWinArr = []
        }
      }
      //获胜条件
      if (xWinArr.length == 4) {
        //这里要用定时器将弹框变成异步任务,否则第五颗棋子渲染不出来就提示获胜了
        if (!flag) {
          setTimeout(function () {
            alert('黑棋获胜!')
            location.reload()
          }, 100)
        } else {
          setTimeout(function () {
            alert('白棋获胜!')
            location.reload()
          }, 100)
        }
      }
    }

3.2数轴获胜

竖轴和横轴代码基本上也相同

只是换了个条件,把if (item[0] == td.dataset.y) 换成了if (item[1] == td.dataset.x),意思就是选出这一列所有的棋子。后面的逻辑和代码就和横轴一样了。

//竖轴获胜逻辑
    function YWin(td) {
      //当前Y轴的所有棋子集合
      let yAllArr = []
      //判断竖轴胜负逻辑的X轴棋子
      let yWinArr = []
      if (!flag) {
        blackArr.map(item => {
          if (item[1] == td.dataset.x) {
            yAllArr.push(item[0])
          }
        })
      } else {
        whiteArr.map(item => {
          if (item[1] == td.dataset.x) {
            yAllArr.push(item[0])
          }
        })
      }
      //竖排总数组排序
      yAllArr.sort((a, b) => a - b)
      for (let i = 1; i < yAllArr.length; i++) {
        // console.log(xAllArr[i]);
        if (yAllArr[i] == (+yAllArr[i - 1] + 1)) {
          yWinArr.push(yAllArr[i])
        } else {
          yWinArr = []
        }
      }
      if (yWinArr.length == 4) {
        if (!flag) {
          setTimeout(function () {
            alert('黑棋获胜!')
            location.reload()
          }, 100)
        } else {
          setTimeout(function () {
            alert('白棋获胜!')
            location.reload()
          }, 100)
        }
      }
    }

3.3正斜轴获胜

斜轴困难一点的地方就是,怎么筛选出这一条斜线上的所有棋子。

只要能把这条斜线上的棋子给找出来,后面的逻辑判断就都一样了。所有的斜线都是45度角,也就是说斜线上的任意两个棋子,他们的x值之差于y值之差是相等的。这样的话,判断起来就简单了。 if ((item[0] - td.dataset.y) == (item[1] - td.dataset.x))这样就可以了。斜线上的棋子找出来后,后面的步骤就都一样了,复制粘贴即可。

//正斜轴获胜逻辑
    function X_YWin(td) {
      //当前X轴的所有棋子集合
      let x_yAllArr = []
      //判断横轴胜负逻辑的X轴棋子
      let x_yWinArr = []
      if (!flag) {
        blackArr.map(item => {
          //判断斜轴棋子,斜轴棋子的x和y之差都是相同的
          if ((item[0] - td.dataset.y) == (item[1] - td.dataset.x)) {
            x_yAllArr.push(item[1])
          }
        })
      } else {
        whiteArr.map(item => {
          if ((item[0] - td.dataset.y) == (item[1] - td.dataset.x)) {
            x_yAllArr.push(item[1])
          }
        })
      }
      x_yAllArr.sort((a, b) => a - b)
      for (let i = 1; i < x_yAllArr.length; i++) {
        if (x_yAllArr[i] == (+x_yAllArr[i - 1] + 1)) {
          //如果相邻的两个棋子数量相差1,就将其添加至胜负逻辑数组
          x_yWinArr.push(x_yAllArr[i])
        } else {
          //否则得清空
          x_yWinArr = []
        }
      }
      //获胜条件
      if (x_yWinArr.length == 4) {
        if (!flag) {
          setTimeout(function () {
            alert('黑棋获胜!')
            location.reload()
          }, 100)
        } else {
          setTimeout(function () {
            alert('白棋获胜!')
            location.reload()
          }, 100)
        }
      }
    }

3.4反斜轴获胜

反斜轴同理,条件改成 if (0 - (item[0] - td.dataset.y) == (item[1] - td.dataset.x)),其余的复制粘贴。

 //反斜轴获胜逻辑
    function Y_XWin(td) {
      //当前X轴的所有棋子集合
      let y_xAllArr = []
      //判断横轴胜负逻辑的X轴棋子
      let y_xWinArr = []
      if (!flag) {
        blackArr.map(item => {
          //判断斜轴棋子
          if (0 - (item[0] - td.dataset.y) == (item[1] - td.dataset.x)) {
            y_xAllArr.push(item[1])
          }
        })
      } else {
        whiteArr.map(item => {
          if (0 - (item[0] - td.dataset.y) == (item[1] - td.dataset.x)) {
            y_xAllArr.push(item[1])
          }
        })
      }
      y_xAllArr.sort((a, b) => a - b)
      for (let i = 1; i < y_xAllArr.length; i++) {
        if (y_xAllArr[i] == (+y_xAllArr[i - 1] + 1)) {
          //如果相邻的两个棋子数量相差1,就将其添加至胜负逻辑数组
          y_xWinArr.push(y_xAllArr[i])
        } else {
          //否则得清空
          y_xWinArr = []
        }
      }
      //获胜条件
      if (y_xWinArr.length == 4) {
        if (!flag) {
          setTimeout(function () {
            alert('黑棋获胜!')
            location.reload()
          }, 100)
        } else {
          setTimeout(function () {
            alert('白棋获胜!')
            location.reload()
          }, 100)
        }
      }
    }

把这些函数放到下棋事件里面调用,整个功能就完成了。

4.悔棋功能

最后写一下悔棋功能,点击悔棋,把对应数组里面的数据删除,然后重新渲染棋盘就完事了。

 //悔棋
    document.querySelector('button').addEventListener('click', function () {
      //判断前面一步是黑棋还是白棋
      if (!flag) {
        //黑棋
        //获取对应棋子总数组的最后一个数据的值
        const y = blackArr[blackArr.length - 1][0]
        const x = blackArr[blackArr.length - 1][1]
        //将对应的对象里的num值删除,这样渲染出来对应棋子就消失了
        delete arr[y][x].num
        //删除总数组里的最后一个数据,否则胜负逻辑会有问题
        blackArr.splice(blackArr.length - 1, 1)
        //重置下棋顺序
        flag = !flag
      } else {
        //白棋
        const y = whiteArr[whiteArr.length - 1][0]
        const x = whiteArr[whiteArr.length - 1][1]
        delete arr[y][x].num
        whiteArr.splice(whiteArr.length - 1, 1)
        flag = !flag
      }
      render()
    })

总结

整个代码写下来,都是些js的基本语法,几个数组的方法来回用,希望能给js初学者一些帮助。

到此这篇关于使用原生JS快速写出一个五子棋小游戏的文章就介绍到这了,更多相关原生JS写五子棋小游戏内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • js实现双人五子棋小游戏

    本文实例为大家分享了js实现双人五子棋小游戏的具体代码,供大家参考,具体内容如下 这是自己自学js的时候,在网上找的js源码,由于是自学,花了数小时才把这个源码大致弄明白. 大致算法 自定义棋盘规格,直接在棋盘建新div就可以,长度宽度用计算就可以了.下棋,在div里再建class,这里要给每个class标一个site值,由site值写出该棋子竖直方向和横向的坐标,由坐标可以写出棋子胜利的条件.而棋子的黑白走是用标识符,偶的标识符则是白棋子的class.奇的标识符则是黑棋子的class. ps

  • JavaScript实现五子棋小游戏

    本文实例为大家分享了JavaScript实现五子棋小游戏的具体代码,供大家参考,具体内容如下 HTML部分 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>五子棋</title> <style> * { padding: 0; margin: 0; } body{ padding-top: 1

  • js+canvas实现五子棋小游戏

    本文实例为大家分享了js+canvas实现五子棋小游戏的具体代码,供大家参考,具体内容如下 效果展示: 源码展示: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>五子棋</title> <style> * { margin: 0; padding: 0; } body { margin-to

  • 使用原生JS快速写出一个五子棋小游戏

    目录 1.棋盘和棋子的绘制. 2.轮流下棋的点击事件 3.获胜条件判断 3.1横轴获胜 3.2数轴获胜 3.3正斜轴获胜 3.4反斜轴获胜 4.悔棋功能 总结 1.棋盘和棋子的绘制. let arr = [ [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},], [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},], [{}, {}, {}, {}, {},

  • 教你用Vue基础语法来写一个五子棋小游戏

    目录 前言 1.绘制游戏区域和游戏元素 2.点击事件 3.悔棋功能 4.判断胜负 写在最后 前言 在之前的文章中,用JS的基础语法写了一个五子棋小游戏# 如何使用原生JS,快速写出一个五子棋小游戏今天用Vue的基础语法来写一个,感受一下两者的区别..至于怎么判断胜负,我还是把上篇文章的方法复制粘贴过来了,如果想了解这个逻辑,可以看我之前的那篇文章. 1.绘制游戏区域和游戏元素 开始写代码之前,一定要记得先导包Vue文件.棋盘还是用二维数组来渲染,可以使用Array(15).fill(0).map

  • java五子棋小游戏实现代码

    前言 之前学完java基础课程,试着简单做了一下java的一个五子棋小游戏,记录下来. 界面 由于直接用的java库中的一些基本控件写的一个GUI,并没有做过多优化,感觉比较丑 下面是界面展示: 黑子先行,但是我这边简化规则,并没有考虑黑子先行的一些禁手. 下面直接贴代码 接口类 我把五子棋界面的一些常量都定义在了这个接口类中,包括棋盘的起始坐标,棋盘线的间距和棋子半径 public interface constant { int[][] chessLocation = new int[15]

  • 基于JS实现弹出一个隐藏的div窗口body页面变成灰色并且不可被编辑

    当需要实现如下图操作,点击服务评分,出现一个服务评分窗口用来填入相关表单信息 可是这会让我们打开服务评分界面时还可以点击body主界面中的购物车等链接,这是不对的,因此我们可以使用层叠样式表来指定外围的div的z-index低于当前服务评分表单页面,不能被点击,如下: /* 定义一个div用于覆盖整个页面,这个div的z-index大于body,小于服务评分div */ #temp{ background-color: #000; opacity: 0.3; width: 100%; heigh

  • 原生js基于canvas实现一个简单的前端截图工具代码实例

    这篇文章主要介绍了原生js基于canvas实现一个简单的前端截图工具代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 先看效果 代码如下 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> *{

  • 教你用Js写一个简单的五子棋小游戏

    目录 棋盘绘制 棋子的绘制 在点击 canvas 的时候获取相对于棋盘数据的坐标点 是否结束 悔棋功能 总结 这里的五子棋只做一些基础的功能,对于相对专业的规则不做处理. 那么该五子棋实现的规则和功能如下: 整体功能采用canvas实现 行列都规定 20 个数量,那么棋子的行列数量是 20 + 1 棋盘数据采用稀疏数组格式 棋子:0 为黑色,1 为白色 可以悔棋 胜负结束判断 棋盘绘制 <template> <div class="gobang"> <ca

  • 原生js实现的贪吃蛇网页版游戏完整实例

    本文实例讲述了原生js实现的贪吃蛇网页版游戏.分享给大家供大家参考.具体实现方法如下: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>原生js写的贪吃蛇网页版游戏</title> </head> <body> </body> <sc

  • 基于flask实现五子棋小游戏

    本文实例为大家分享了基于flask实现五子棋小游戏的具体代码,供大家参考,具体内容如下 前言 首先说明一下,本人方向是java后端,只因老师布置了一个作业,要用flask来做一个五子棋,没办法被逼上梁山,程序不太美观,但是应付作业还是够了的. 废话不多说,下面开锤! 首先整个程序是一个web应用,前端html+css+javaScript(有用到jquery)(基本都是现学的,所以程序很多注释也很丑),后端用的flask框架. 准备工作 **1.**python环境.安装flask **2.**

随机推荐