【数独】数独游戏-微信小程序开发流程详解

有没有玩过数独游戏呢,听说,它是一个能训练大脑思维的棋盘类游戏,游戏规则很简单,通过小程序来实现很容易,非常适合对数独游戏逻辑感兴趣的同学,选择它开发入门吧。

准备

  • 会使用微信开发者工具,
  • 有JavaScript编程和Canvas绘制基础,
  • 最好有了解学习过Vue

首先,没有玩过数独的同学,请看一下,数独游戏规则如下

  • 独一无二
    • 一个数独自占用一块地盘,其周边不能再出现这个数,
    • 规定在一个宫格(3x3)内(地盘),不能有两个相同的数,
  • 消除影响
    • 在整个大网格中,横向或纵向方向不能存在两个相同的数,
  • 稳操胜算
    • 把网格留下的空白全部填充完,这样地盘就稳了,算游戏攻关。

创建小程序

打开微信开发者工具,开始创建小程序,最后点确定,如下图
在这里插入图片描述

注意选择

  • 小程序
  • 不使用云服务
  • JavaScript 基础模板

第一页

接下来,开始写第一个页面,文件位置在/pages/index/index.wxml

打开文件续写,加上一个表单组件,选择游戏难度和按钮,布局页面如下图所示
在这里插入图片描述

点击开始游戏按钮,可进入游戏页面,
第一个页面对应的index.js文件逻辑不难写,
相信初学者会自己做出来,这里不做详细说明

第二页

这里再创建一个第二个页面,为游戏页面,文件位置在/pages/game/game.wxml

如下图,要做的页面是这样的
在这里插入图片描述

游戏页面布局,用一个canvas画布,显示元素和一些底部选择按钮

游戏逻辑

先从加载游戏的方法中处理,初始化canvas游戏地图,再实现触摸操作,最后就是处理游戏判断逻辑的

初始化

要知道,小程序页面的生命周期,就是说页面的一些回调函数(方法),

页面打开时,系统调用顺序是先调用onLoad(),再调用onReady()的,

选择在合适的时机,去处理游戏逻辑,实现代码如下

Page({
    
    

  /**
   * 页面的初始数据
   */
  data: {
    
    
    timeNum:0,//计数
    keys:['1','2','3','4','5','6','7','8','9','清除'],//选择的按键
    activeIndex:0,//选中值
    rank:0,//游戏难度
    isEnd:false,//是否结束游戏
    //...
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    
    
    //...处理从第一页传来的参数游戏难度
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    
    
    wx.createSelectorQuery().select('#'+canvasId).fields({
    
    
      size:true, node:true
    },res=>{
    
    
      const {
    
     width, height, node } = res;
      //...省略了
      //初始化网格数据(棋盘)
      this.initGrid();
      //重新绘制方法
      this.redraw();
      //定时更新计数器
      this.data.timer = setInterval(()=>{
    
    
        //...
        this.data.timeNum++
        this.setData({
    
    
          timeNum:this.data.timeNum
        });
      },1000)
    }).exec()
  },
  unLoad(){
    
    
	//...关闭定时器
  }
  //...
}

上面用到了两个方法,这里会讲一下,

初始化网格方法是initGrid(),这里实现绘制游戏地盘,参考如下代码

initGrid(){
    
    
    const {
    
     width, height, context:ctx } = this.data.canvas;
    //...
    let grids = [];
    //获取初始值(地盘)的数据方法
    const cols = 9;//9x9网格
    let nums = this.getInitNumGrids();
    let index = 0;
    for(let r=0; r<cols; r++){
    
    
      for(let c=0; c<cols; c++){
    
    
        let num = nums[index++];
        let g = {
    
    
          //...网格数据
        };
        //...绘制网格
        ctx.rect(g.left,g.top,gs,gs);
        grids.push(g);
      }
    }
    ctx.stroke();
    ctx.beginPath();
    ctx.lineWidth = 3;
    for(let r=0; r<gs; r+=3){
    
    
      //...绘制宫格(3x3)
    }
    ctx.stroke();
    //设置一些值
    Object.assign(this.data.canvas, {
    
     cols, gs, grids });
    //将绘制的棋盘背景缓存,下次会用到
    this.data.bgImg = ctx.getImageData(0,0,width,height);
},

上面还用到了方法getInitNumGrids()是可以自己定义的,相当于游戏的背景数据,包括了初始化的一些数字,可用于增加可选择游戏关卡和难度,这里就不做说明了

重绘方法是redraw(),实现刷新游戏的显示逻辑,参考如下代码,看着很简单

redraw(){
    
    
    const {
    
     gs, grids, context:ctx, width, height } = this.data.canvas;
    //...省略了逻辑,先清除画布
    //绘制前,把之前缓存的背景图画出来
    ctx.putImageData(this.data.bgImg,0,0);
    const r = gs/2;
    //...省略了逻辑,设置画笔大小和颜色,再绘制网格
    grids.forEach(g=>{
    
    
      //...省略了逻辑,判断有数字就绘制出来
      if(g.num) ctx.fillText(g.num,g.left+r,g.top+r*1.3);
    });
},

触摸操作

游戏地盘绘制逻辑写好了后,接下来需要完善触摸操作,

绑定在画布canvas的开始触摸方法是onTouchStart(e),这里处理游戏的交互,实现对用户触摸操作的反馈,代码如下

Page({
    
    
  //...
  onTouchStart(e){
    
    
    if(this.data.isEnd) return;
    const touch = e.touches[0];
    const {
    
     gs, grids } = this.data.canvas;
    //根据触摸位置计算找出位置所在的网格
    let grid = this.findGrid(grids,touch);
    //选择的按键
    let activeBtn = this.data.keys[this.data.activeIndex];
    let isReraw;
    //判断按键
    switch (activeBtn){
    
    
      case '清除':
        //...清除网格中的数字
        break;
      default:
        if (grid.num==undefined) {
    
    
        	//判断规则,返回存在相同的网格(数)
          let scopes = this.scanGridsToScopes(grid,activeBtn);
          if (scopes.length<1){
    
    
            //...省略了,如果不存在相同的数,就继续绘制
            isReraw=true;
          }
          else{
    
    
          	//...省略了,如果存在相同的数,就把数字染成红色,提醒用户
            this.redraw();
            //设一个延迟处理
            this.data.timer2 = setTimeout(()=>{
    
    
              this.data.timer2 = undefined;
              //...到时,将数字恢复原色
              this.redraw();
            },1000);
          }
        }
    }
    if(isReraw) {
    
    
      this.redraw();
      //查找网格是否还存在空位
      let count = this.filterGrids();
      //如果没有了,就判断通关,游戏结束
      if(count<1){
    
    
        this.data.isEnd=true;
        wx.showModal({
    
    
          title:'系统提示',
          content:`游戏结束!耗时:${
      
      this.data.timeNum}s`,
          confirmText:'重新开始',
          success: (res) => {
    
    
            //...
          }
        });
      }
    }
  },
  onClick(e){
    
    
    //...处理用户点击按钮的逻辑
  },
  //...
}

其中方法onClick(e)是处理按钮点击的,
例如打开游戏帮助提示对话框,和点击数字按钮为选中状态,
很简单的,这里就不讲

判断规则

数独的游戏规则上面有开始讲了的,

这个方法是scanGridsToScopes(grid,activeBtn),实现有点儿复杂,大致讲一下

scanGridsToScopes(grid,activeBtn){
    
    
	const {
    
     grids } = this.canvas;
	let scan = function(g,x=0,y=0) {
    
    
		//...省略了判断逻辑
		return false;
	};
	//过滤方法判断
	let scopes = grids.filter(g=>{
    
    
		let exist = false;
		if (g.num==activeBtn) {
    
    
			//...
			if(!exist) exist = scan(g);
			if(!exist) exist = scan(g,3);
			//...
		}
		return exist;
	});
	return scopes;
 }

JavaScript基础必掌握的filter(),是数组(列表)的按条件过滤方法,
主要是多次调用scan()方法来判断,把一个网格周围不同方向的扫描一遍,这样实现对游戏规则的判断

运行测试

讲到这里,整个独数游戏的逻辑就算写完了,看看写得代码不是很多吧,那游戏的实现思路是否清晰了呢,

最后编译运行,运行时游戏效果图如下,
请添加图片描述

显示绿色的数字是填入的数字,
显示红色的数字提示玩家这里有相同数字,是不允许再填入的,
底部的一排数字键是选择键,可以选择填入哪个数字,或清除,
把所有空白填完就算攻关,
看着很像解密游戏,适合一个人玩,这游戏太烧脑,一般人玩不了!

关于项目

这个游戏逻辑实现过程是很简单的,想要学习微信小程序开发的新手同学,可以试试入手,

想看项目源码,请前往点这里找,其中有个名称叫数独游戏,项目源码完整,请放心下载,多谢支持!

若觉得有帮助,请记得点个赞,表示认可,

如有遇到问题请留言,作者有空会回复哦!

猜你喜欢

转载自blog.csdn.net/zs1028/article/details/129442054