原生JS实现黑猩猩测试

零、体验游戏

http://aring.3vfree.net/game/Chimpanzee-Test/index.html

一、实现效果

 

二、实现过程

看上图实现效果,大致的思路梳理:

1.设定一个表格,初始隐藏所有单元格

2.随机给单元格赋值以及添加边框

3.根据游戏难度等级循环赋值单元格

4.赋值完毕后为单元格添加点击事件以判断点击结果

5.判定尝试次数以及继续游戏/重新游戏功能

 

梳理好思路开始写脚本:

第一步

实现让单元格随机显示在表格中,如下图

首先,获取所有<td>标签,然后随机指定需要赋值的td,我这里做了30个单元格所以随机0~29

  const td = document.getElementsByTagName("td")  // 单元格
  // 随机指定需要赋值的td
  function randomTd() {
    const tdIndex = Math.floor(Math.random() * 29)
    return td[tdIndex]
  }

然后根据等级循环给td赋值

循环获取上文随机得到的td,然后给td设定文本为i,即第几次循环,td的文本就是几

然后给td加上设定好的边框class

最后,给每个td单独添加一个点击事件,并传参循环次数i 和该td本身,用以判断点击时的结果

  let level = 6  // 等级
  // 根据等级循环给td赋值
  function tdAssignment() {
    for (let i = 1; i < level; i++) {
      let slTd = randomTd()
      slTd.innerText = i
      slTd.classList.add("td-border")
    }
  }

但是这上文会出现一个问题,假如随机的td重复了怎么办呢?

为了解决这个问题可以循环判断td 当前文本不为空,即:假设td当前的文本已经被赋值,则再次随机,用循环是为了重复判断

      for (let i = 0; slTd.innerText != ""; i++) {  // 将要赋值的td如果不为空,则再次随机td的index
        slTd = randomTd()
      }

将该判断到tdAssignment()中 

  // 根据等级循环给td赋值
  function tdAssignment() {
    for (let i = 1; i < level; i++) {
      let slTd = randomTd()
      for (let i = 0; slTd.innerText != ""; i++) {  // 将要赋值的td如果不为空,则再次随机td的index
        slTd = randomTd()
      }
      slTd.innerText = i
      slTd.classList.add("td-border")
    }
  }

因此开始游戏按钮中的函数直接执行上文两个函数即可

  // 游戏开始
  function gameStart() {
    randomTd()
    tdAssignment()
  }

第二步

上文所说已经为td赋值了文本,接下来是定义td的点击事件

开始理思路:

1.给td 赋值的同时,添加点击事件

2.将td 赋的值和自身传给结果判断的函数中

      slTd.onclick = function() {  // 为每个td添加点击事件
        gameResult(i, this)
      }

3.定义一个点击次数的变量,初始为1,意为第一次点击

4.开始写判断结果的函数,很简单,得到传过来的参数 i ,将参数 i 和 count对比,如果是相同的,就隐藏对应的 td,并且将点击次数+1

  // 点击后判断结果
  function gameResult(index, obj) {
    if (index == count) {  // 判断td的值是否等于点击次数
      obj.classList.add("hidden")
    }
  count++  // 每次点击完,点击次数+1
  }

5.然后判断是否过关,即点击完所有数字,加一个判断,当参数 i == 等级时,就是正确点击了最后一个数字

顺便加上失败判断,以及切换结果页的函数goResult

  // 点击后判断结果
  function gameResult(index, obj) {
    if (index == count) {  // 判断td的值是否等于点击次数
      obj.classList.add("hidden")
      if (index == level - 1) {
        // 胜利
        isSuc = 1
        goResult()
      }
    } else {
      // 失败
      isSuc = 0
      tryCount++
      goResult()
    }
    count++
  }

6.开始第一次点击时,隐藏所有td ,采用遍历 td 将选中的td (判断其是否有边框即可) 为其添加一个新的class

加上level限制是为了第一次开始游戏时作为教程关卡不隐藏td

    if (index == 1 && level > 6) {  // 第一次点击时隐藏td(第一次开始游戏时不隐藏td)
      for (let i of td) {
        if (i.className == "td-border")
          i.classList.add("td-shade")
      }
    }

第三步

结果页的效果如下图

都是一些简单的写入参数的操作,这里不赘述,结合上文定义一个尝试次数(tryCount),当尝试次数达到3次时改变按钮文本为重新开始即可

第四步

重置游戏/继续游戏(上图“继续”按钮的功能)

最后的功能完善,同时也需要配合完善上文函数中的细节

1.首先遍历每个td,清空其class、文本和点击事件

    for (let i of td) {  // 遍历td以重置td的class、文本和点击事件
      i.classList.remove("td-border")
      i.classList.remove("td-shade")
      i.classList.remove("hidden")
      i.innerText = ""
      i.onclick = null  // 清理td的点击事件
    }

2.转到结果页面时,需要重置点击次数为1

3.判断尝试次数是否达到3次,如是,重置到开始页面;

如不是,根据是否胜利,胜利则加大难度/重置尝试次数 开始游戏,失败则保持当前难度继续 开始游戏

完整代码如下

  // 重置游戏(继续/重新开始)
  function gameReset(isCheater) {
    for (let i of td) {  // 遍历td以重置td的class、文本和点击事件
      i.classList.remove("td-border")
      i.classList.remove("td-shade")
      i.classList.remove("hidden")
      i.innerText = ""
      i.onclick = null  // 清理td的点击事件
    }
    count = 1  // 重置点击次数
    if (tryCount == 3) {  // 尝试次数达到最高次数
      result.classList.add("hide")
      cheater.classList.add("hide")
      info.classList.remove("hide")
      level = 6
      tryCount = 0
    } else {
      if (isSuc == 1) {  // 如果胜利
        level++
        tryCount = 0
        gameStart()
      } else 
        gameStart()
    }
  }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值