微信小程序实现window经典的扫雷游戏

这篇具有很好参考价值的文章主要介绍了微信小程序实现window经典的扫雷游戏。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

打开手机游戏列表发现了一款经典的扫雷游戏,在玩的过程中发现游戏逻辑应该不难,想着是不是能自己写写这个游戏,后来用了1天实现了整体游戏开发,于是有了这篇文章来总结整体的游戏开发思路。


一、扫雷游戏规则是什么?

1、游戏为在10*10或其它排序组合网格中找雷
2、网格中隐藏着一定数量的雷,点击到雷即为输
3、点击无雷的网格会显示其临近8个方向上的总雷数,若为0则临近8个方向上的网格也会自动显示雷数,以此类推,直到出现不为0的网格
4、长按网格可以标记网格为雷
5、找出所有的雷即为胜利

二、开发前准备

1.创建小程序项目

使用微信开发者工具创建一个小程序项目。推荐使用官方推荐模板(此游戏项目使用js来实现)
微信小程序实现window经典的扫雷游戏

2.开始开发

2.1.实现网格地图

页面初始数据:

groundSize: [16, 16], // 地图大小
minePosition: [], // 保存雷的位置
secondInterval: 0, // 时间定时器
data: {
  second: 0, // 游戏时间
  mineCount: 24, // 雷总数
  markMineCount: 0, // 已标记雷数
  renderGridList: [], // 网格列表
},

此地图为16*16的地图,行列大小根据 groundSize 来,后续可以设置不同的地图大小。
微信小程序实现window经典的扫雷游戏

地图wxml代码(具体样式自行规划):

<view class="play-ground">
  <view class="play-ground__row" wx:for="{{renderGridList}}" wx:for-item="row" wx:key="index">
     <view class="play-ground__col {{col.showNum && col.mineNum === 0 ? 'play-ground__col--empty' : ''}}" wx:for="{{row}}" wx:for-item="col" wx:key="index" data-value="{{col.value}}" bindlongpress="setMineTag" bindtap="clearBox">
       <!-- 标记雷图标 -->
       <image wx:if="{{col.mineTag}}" class="play-ground__col-boom" src="../../static/image/mine/mine.png"></image>
       <!-- 点击到雷图标 -->
       <image wx:if="{{!col.mineTag && col.isBoom && col.isMine}}" class="play-ground__col-boom" src="../../static/image/mine/boom.png"></image>
       <!-- 周围雷数 -->
       <text wx:if="{{col.showNum && col.mineNum}}" class="play-ground__col-num play-ground__col-num--{{col.mineNum}}">{{col.mineNum}}</text>
     </view>
   </view>
</view>

renderGridList 渲染列表结构(二维数组):

[
  [
    {
      isMine: false, // 是否为雷
      mineTag: false, // 手动添加是否是雷的标识
      isBoom: false, // 是否点击到了雷
      mineNum: 0, // 周围雷数
      showNum: false, // 是否显示雷数
      value: 0, // 等同于id
      position: [0, 0], // 标志在第几行第几列
    },
    ...
  ],
  ...
]

初始化网格方法:

initGrid() {
  const gridList = [];
   // 当前遍历gridList到第几个元素
   let currentNum = 0;
   // 当前遍历minePosition到第几个元素
   let currentMineIndex = 0;
   for (let i = 0; i < this.groundSize[0]; i++) {
     const row = [];
     for (let j = 0; j < this.groundSize[1]; j++) {
       let isMine = false;
       // 判断是否是雷
       if (currentNum === this.minePosition[currentMineIndex]) {
         isMine = true;
         currentMineIndex += 1;
       }
       row.push({
         isMine,
         mineTag: false, // 手动添加是否是雷的标识
         isBoom: false, // 是否点击到了雷
         mineNum: 0, // 周围雷数
         showNum: false, // 是否显示雷数
         value: currentNum,
         position: [i, j],
       });
       currentNum += 1;
     }
     gridList.push(row);
   }
   this.setData({
     renderGridList: this.generateMineNum(gridList),
   });
 }

2.2.生成雷

generateMine() {
   this.minePosition = [];
   // 已设置的雷总数
   let hadSetCount = 0;
   // 随机最大值根据网格大小来
   const groundCount = this.groundSize[0] * this.groundSize[1];
   if (this.data.mineCount >= groundCount) {
      return;
    }
    while (hadSetCount < this.data.mineCount) {
      // 生成随机数
      const randomNum = ~~(Math.random() * groundCount);
      // 判断随机数是否存在
      if (!this.minePosition.includes(randomNum)) {
        this.minePosition.push(randomNum);
        hadSetCount += 1;
      }
    }
    // 从小到大排序
    this.minePosition.sort((a, b) => (a > b ? 1 : -1));
  }

根据页面初始数据中的 mineCount 来指定生成的雷数,通过随机值函数来生产随机的雷的 value 值,每生成一个先判断值是否在 minePosition 数组存在,不存在就push到 minePosition 数组中去。最终结果如下:在 initGrid 方法中会根据 minePosition 对应的值和网格的value值作比较,相等即为雷。

minePosition (24) [10, 17, 25, 28, 34, 35, 48, 73, 106, 132, 152, 187, 196, 197, 199, 203, 210, 217, 220, 226, 234, 238, 240, 245]

2.3.生成雷数

generateMineNum(gridList) {
 gridList.forEach(row => {
    row.forEach(col => {
      // 是雷则跳过
      if (col.isMine) {
        return;
      }
      col.mineNum = this.checkMine(gridList, col.position);
    });
  });
  return gridList;
},
checkMine(gridList, position) {
  const [i, j] = position;
  let mineNum = 0;
  // 判断8个方位是否有雷
  // 上 [i - 1][j]
  if (gridList[i - 1] && gridList[i - 1][j].isMine) {
    mineNum += 1;
  }
  // 右上 [i - 1][j + 1]
  if (gridList[i - 1] && gridList[i - 1][j + 1] && gridList[i - 1][j + 1].isMine) {
    mineNum += 1;
  }
  // 右 [i][j + 1]
  if (gridList[i][j + 1] && gridList[i][j + 1].isMine) {
    mineNum += 1;
  }
  // 右下 [i + 1][j + 1]
  if (gridList[i + 1] && gridList[i + 1][j + 1] && gridList[i + 1][j + 1].isMine) {
    mineNum += 1;
  }
  // 下 [i + 1][j]
  if (gridList[i + 1] && gridList[i + 1][j].isMine) {
    mineNum += 1;
  }
  // 左下 [i + 1][j - 1]
  if (gridList[i + 1] && gridList[i + 1][j - 1] && gridList[i + 1][j - 1].isMine) {
    mineNum += 1;
  }
  // 左 [i][j - 1]
  if (gridList[i][j - 1] && gridList[i][j - 1].isMine) {
    mineNum += 1;
  }
  // 左上 [i - 1][j - 1]
  if (gridList[i - 1] && gridList[i - 1][j - 1] && gridList[i - 1][j - 1].isMine) {
    mineNum += 1;
  }
  return mineNum;
}

判断8个方向上是否有雷时我们需要注意那些在边角的网格,这些网格方向少于8个,所以我们在做判断是需先判断其方向上是否有网格才行。

2.4.长按添加雷的标识

setMineTag(e) {
  const {
    currentTarget: {
      dataset: { value },
    },
  } = e;
  const renderGridList = this.data.renderGridList;
  let markMineCount = 0;
  for (const row of renderGridList) {
    for (const col of row) {
      if (col.value === value) {
        col.mineTag = !col.mineTag;
      }
      if (col.mineTag) {
        markMineCount += 1;
      }
    }
  }
  this.setData({
    renderGridList,
    markMineCount,
  });
},

我们在网格上设置 data-value ,这样长按事件就能获取对应的 value 值,通过遍历比较找到对应的网格并对网格的 mineTag 属性取反来达到长按标记或取消的功能,同时 mineTag 为真时需记录下标记数量。

2.5.点击网格事件

clearBox(e) {
  const {
    currentTarget: {
      dataset: { value },
    },
  } = e;
  let renderGridList = this.data.renderGridList;
  out: for (const row of renderGridList) {
    for (const col of row) {
      if (col.value === value) {
        // 判断是否是雷,为雷则输
        col.isBoom = col.isMine;
        if (col.isBoom) {
          wx.showToast({
            icon: 'error',
            title: '踩到雷了',
          });
          break out;
        }
        renderGridList = this.loopClearBox(renderGridList, col);
        break out;
      }
    }
  }
  this.setData({
    renderGridList,
  });
},
loopClearBox(gridList, col) {
  if (col.isMine || col.showNum) {
    return gridList;
  }
  col.showNum = true;
  if (col.mineNum) {
    return gridList;
  }
  // 判断相邻的4个方位是否为空并递归遍历
  const [i, j] = col.position;
  if (gridList[i - 1]) {
  	// 上
    col = gridList[i - 1][j];
    if (col) {
      if (!col.mineNum) {
        gridList = this.loopClearBox(gridList, col);
      } else {
        col.showNum = !col.isMine;
      }
    }
  }
  if (gridList[i + 1]) {
  	// 下
    col = gridList[i + 1][j];
    if (col) {
      if (!col.mineNum) {
        gridList = this.loopClearBox(gridList, col);
      } else {
        col.showNum = !col.isMine;
      }
    }
  }
  // 左
  col = gridList[i][j - 1];
  if (col) {
    if (!col.mineNum) {
      gridList = this.loopClearBox(gridList, col);
    } else {
      col.showNum = !col.isMine;
    }
  }
  // 右
  col = gridList[i][j + 1];
  if (col) {
    if (!col.mineNum) {
      gridList = this.loopClearBox(gridList, col);
    } else {
      col.showNum = !col.isMine;
    }
  }
  return gridList;
}

loopClearBox 是递归遍历方法,当点击的网格的周围雷数为空时我们需要递归其上下左右方向的网格。效果如图所示:
微信小程序实现window经典的扫雷游戏
递归只有遇到有雷数的网格才会停下。

2.6.输赢判断

checkWin() {
  // 当标记数小于总雷数时才判断输赢
  if (this.data.mineCount >= this.data.markMineCount) {
    // 遍历网格判断标记的雷是否正确
    for (let row in this.data.renderGridList) {
      for (let col of row) {
        if (col.isMine !== col.mineTag) {
          return false;
        }
      }
    }
    return true;
  }
  return false;
}

输赢判断是在点击网格事件中执行的,当返回值为true时即为通关。


总结

以上就是整个游戏开发的整体思路讲解,代码量不多,总体js代码只有2百多行,设计思路也比较简单。对于在开发中的收获,或许就是当你玩着自己开发的游戏时,作为程序员的快乐,哈哈哈哈哈。文章来源地址https://www.toymoban.com/news/detail-489619.html

到了这里,关于微信小程序实现window经典的扫雷游戏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言实现扫雷【经典】

    前言 本篇文章要实现的是 扫雷游戏 ,其代码实现与上一篇的三子棋游戏类同,都是在棋盘的基础上,与电脑进行对抗,不同的是,扫雷游戏一开始电脑就已经随机布置好了所有“雷”。 请戳 --- 三子棋 经典玩法: 扫雷就是要把所有非地雷的格子揭开即 胜利 ;踩到地雷格子

    2024年02月16日
    浏览(39)
  • Java课程设计——扫雷游戏程序

    组员 职务 分工 潘鋆祥 组长 顶层格子的代码设计,界面UI设计 覃小杰 组员 扫雷素材的搜集,底层雷的代码设计 以windows 7自带扫雷为例。游戏区包括雷区、地雷计数器和计时器,确定大小的矩形雷区中随机布置一定数量的地雷(初级为9 9个方块10个雷,中级为16 16个方块40个雷

    2024年02月03日
    浏览(50)
  • 微信小程序猜数字小游戏

     我的首页(效果图)使用的是index03 开始游戏使用的是index 游戏规则使用的是index01 关于其他使用的是index02 (创建文件在app.json里面,这是我的app.json创建的文件) (由于我的首页效果图使用的是index03,所以要放在前面) WXML代码 WXSS代码 WXML代码 WXSS代码 index.js代码 WXML代码 WX

    2023年04月10日
    浏览(52)
  • 石头剪刀步微信小程序游戏

    之前接了学弟的一个课程作业,但是因为某些原因,最终换成了一个新的爬虫项目。 这个作业就是一个石头剪刀步的微信小游戏。就是与系统随机的 单机 PK,暂时没有去做联接的,没有那个云服务器,但是可以用轮讯的方式去多人联机玩儿。内容虽小但是传统的基本框架都

    2024年02月07日
    浏览(38)
  • 基于微信小程序的游戏账号交易小程序

    文末联系获取源码 开发语言:Java 框架:ssm JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7/8.0 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 浏览器:谷歌浏览器 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序运行软件:微信开发者 随着网络和计算机

    2024年02月09日
    浏览(47)
  • 全新微信小程序源码|小程序游戏源码|小游戏源码2000套

    Authing小程序SDK(authing-wxapp-sdk)适合在微信小程序环境下使用,基于authing-js-sdk (打开新窗口),对微信小程序环境进行了适配。您可以使用AuthenticationClient中的所有方法authing-js-sdk  (打开新窗口),如获取和修改用户信息、添加用户自定义字段等。同时专门用于小程序环境

    2024年02月05日
    浏览(66)
  • Unity游戏上传到微信小程序

    地址: 微信小程序 补充信息(类目需要选择游戏方面,不然后面调试不了) - 注意AppID 地址:Unity转微信小程序 微信开发者工具 打包好会生成两个项目文件,我们只需要将minigame这个文件导入微信开发者工具即可,并复制好之前的AppID。

    2024年02月12日
    浏览(63)
  • 微信小程序飞机大战游戏步骤及代码

    步骤: 1. 准备游戏资源:准备游戏所需的图片、音效等资源。 2. 创建游戏场景:使用微信小程序的API创建游戏场景,可以使用wx.createCanvasContext()方法创建游戏场景。 3. 加载游戏资源:使用wx.loadImage()方法加载游戏所需的图片资源,使用wx.playBackgroundAudio()方法加载游戏所需的

    2024年02月12日
    浏览(52)
  • 【C语言】实现扫雷游戏

    详细介绍扫雷游戏的思路和实现过程,并用随机数实现埋雷。 • 使用控制台实现经典的扫雷游戏 • 游戏可以通过菜单实现继续玩或者退出游戏 • 扫雷的棋盘是9*9的格⼦ • 默认随机布置10个雷 • 可以排查雷 ◦ 如果位置不是雷,就显示周围有几个雷 ◦ 如果位置是雷,就炸

    2024年02月04日
    浏览(45)
  • 基于JavaFX的扫雷游戏实现(二)——游戏界面

      废话环节:看过上期文章的小伙伴现在可能还是一头雾水,怎么就完成了核心内容,界面呢?哎我说别急让我先急,博主这不夜以继日地肝出了界面部分嘛。还是老规矩,不会把所有地方都照顾到,只挑一些有代表性的内容介绍,您各位多担待🙏。另外博主的JavaFX是跟着

    2024年02月12日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包