微信小游戏入门案例——拼图游戏

2023-10-27

微信小游戏入门案例——拼图游戏

涉及内容:canvas组件、小程序界面绘图API

目录结构:

 

pages\game\game.js

// pages/game/game.js
// 方块的初始位置
var num = [
  ['00', '01', '02'],
  ['10', '11', '12'],
  ['20', '21', '22']
]

// 方块的宽度
var w = 100

// 图片的初始地址
var url = '/images/pic01.jpg'

Page({

  /**
   * 页面的初始数据
   */
  data: {
    isWin: false

  },

  /**
   * 自定义函数--随机打乱方块顺序
   */
  shuffle: function() {
    // 先令所有方块回归初始位置
    num = [
      ['00', '01', '02'],
      ['10', '11', '12'],
      ['20', '21', '22']
    ]

    // 记录当前空白方块的行和列
    var row = 2
    var col = 2

    // 随机打乱方块顺序100次
    for (var i = 0; i < 100; i++) {
      // 随机生成一个方向:上0,下1,左2,右3
      var direction = Math.round(Math.random() * 3)

      // 上:0
      if (direction == 0) {
        // 空白方块不能在最上面一行
        if (row != 0) {
          // 交换位置
          num[row][col] = num[row - 1][col]
          num[row - 1][col] = '22'

          // 更新空白方块的行
          row -= 1
        }
      }

      // 下:1
      if (direction == 1) {
        // 空白方块不能在最下面一行
        if (row != 2) {
          // 交换位置
          num[row][col] = num[row + 1][col]
          num[row + 1][col] = '22'

          // 更新空白方块的行
          row += 1
        }
      }

      // 左:2
      if (direction == 2) {
        // 空白方块不能在最左边一列
        if (col != 0) {
          // 交换位置
          num[row][col] = num[row][col - 1]
          num[row][col - 1] = '22'

          // 更新空白方块的列
          col -= 1
        }
      }

      // 右:3
      if (direction == 3) {
        // 空白方块不能在最右边一列
        if (col != 2) {
          // 交换位置
          num[row][col] = num[row][col + 1]
          num[row][col + 1] = '22'

          // 更新空白方块的列
          col += 1
        }
      }

    }

  },

  /**
   * 自定义函数--绘制画布内容
   */
  drawCanvas: function() {
    let ctx = this.ctx

    // 清空画布
    ctx.clearRect(0, 0, 300, 300)

    // 使用双重for循环语句绘制3x3拼图
    for (var i = 0; i < 3; i++) {
      for (var j = 0; j < 3; j++) {
        if (num[i][j] != '22') {
          // 获取行和列
          var row = parseInt(num[i][j] / 10)
          var col = num[i][j] % 10

          // 绘制方块
          ctx.drawImage(url, col * w, row * w, w, w, j * w, i * w, w, w)
        }
      }
    }

    ctx.draw()
  },

  /**
   * 自定义函数--监听点击方块事件
   */
  touchBox: function(e) {
    // 如果游戏已经成功,不做任何操作
    if (this.data.isWin) {
      // 终止本函数
      return
    }

    // 获取被点击方块的坐标x和y
    var x = e.changedTouches[0].x
    var y = e.changedTouches[0].y
    // console.log('x:'+x+',y:'+y)

    // 换算成行和列
    var row = parseInt(y / w)
    var col = parseInt(x / w)

    // 如果点击的不是空白位置
    if (num[row][col] != '22') {
      // 尝试移动方块
      this.moveBox(row, col)

      // 重新绘制画布内容
      this.drawCanvas()

      // 判断游戏是否成功
      if (this.isWin()) {
        // 在画面上绘制提示语句
        let ctx = this.ctx

        // 绘制完整图片
        ctx.drawImage(url, 0, 0)

        // 绘制文字
        ctx.setFillStyle('#e64340')
        ctx.setTextAlign('center')
        ctx.setFontSize(60)
        ctx.fillText('游戏成功', 150, 150)
        ctx.draw()
      }
    }
  },

  /**
   * 自定义函数--移动被点击的方块
   */
  moveBox: function(i, j) {
    // 情况1:如果被点击的方块不在最上方,检查可否上移
    if (i > 0) {
      // 如果方块的上方是空白
      if (num[i - 1][j] == '22') {
        // 交换当前被点击的方块和空白的位置
        num[i - 1][j] = num[i][j]
        num[i][j] = '22'
        return
      }
    }

    // 情况2:如果被点击的方块不在最下方,检查可否下移
    if (i < 2) {
      // 如果方块的下方是空白
      if (num[i + 1][j] == '22') {
        // 交换当前被点击的方块和空白的位置
        num[i + 1][j] = num[i][j]
        num[i][j] = '22'
        return
      }
    }

    // 情况3:如果被点击的方块不在最左侧,检查可否左移
    if (j > 0) {
      // 如果方块的左侧是空白
      if (num[i][j - 1] == '22') {
        // 交换当前被点击的方块和空白的位置
        num[i][j - 1] = num[i][j]
        num[i][j] = '22'
        return
      }
    }

    // 情况4:如果被点击的方块不在最右侧,检查可否右移
    if (j < 2) {
      // 如果方块的右侧是空白
      if (num[i][j + 1] == '22') {
        // 交换当前被点击的方块和空白的位置
        num[i][j + 1] = num[i][j]
        num[i][j] = '22'
        return
      }
    }
  },

  /**
   * 自定义函数--判断游戏是否成功
   */
  isWin: function() {
    // 使用双重for循环检查整个数组
    for (var i = 0; i < 3; i++) {
      for (var j = 0; j < 3; j++) {
        // 如果有方块位置不对
        if (num[i][j] != i * 10 + j) {
          // 返回假,游戏尚未成功
          return false
        }
      }
    }

    // 游戏成功,更新状态
    this.setData({
      isWin: true
    })
    // 返回真,游戏成功
    return true
  },

  /**
   * 自定义函数--重新开始游戏
   */
  restartGame: function() {
    // 更新游戏状态
    this.setData({
      isWin: false
    })

    // 打乱方块顺序
    this.shuffle()

    // 绘制画布内容
    this.drawCanvas()
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    // console.log(options.level)

    // 更新图片路径地址
    url = '/images/' + options.level
    // 更新提示图的地址
    this.setData({
      url: url
    })

    // 创建画布上下文
    this.ctx = wx.createCanvasContext("myCanvas")

    // 打乱方块顺序
    this.shuffle()

    // 绘制画布内容
    this.drawCanvas()
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function() {

  }
})

 

pages\game\game.wxml

<view class="container">
  <view class="title">
    提示图
  </view>
  <image src="{{url}}"></image>
  <canvas canvas-id="myCanvas" bindtouchstart="touchBox"></canvas>
  <button type="warn" bindtap="restartGame">重新开始</button>
</view>

 

pages\game\game.wxss

/* pages/game/game.wxss */
/* 提示图 */
image{
  width: 250rpx;
  height: 250rpx;
}

/* 游戏画布区域 */
canvas{
  border: 1rpx solid;
  width: 300px;
  height: 300px;
}

 

pages\index\index.js

Page({

  /**
   * 页面的初始数据
   */
  data: {
    levels:[
      'pic01.jpg',
      'pic02.jpg',
      'pic03.jpg',
      'pic04.jpg',
      'pic05.jpg',
      'pic06.jpg',

    ]
  },
  chooseLevel:function(e){
    let level = e.currentTarget.dataset.level
    wx.navigateTo({
      url: '../game/game?level='+level,
    })
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
    
  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
    
  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
    
  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
    
  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
    
  }
})

 

pages\index\index.wxml

<view class="container">
  <view class="title">
    游戏选关
  </view>

  <view class="levelBox">
    <view class="box" wx:for="{{levels}}" wx:key="levels{{index}}" bindtap="chooseLevel" data-level="{{item}}">
      <image src="/images/{{item}}"></image>
      <text>第{{index+1}}关</text>
    </view>
  </view>
</view>

 

pages\index\index.wxss

/**index.wxss**/
/* 关卡区域列表 */
.levelBox{
  width: 100%;
}

/* 单个关卡区域 */
.box{
  width: 50%;
  float: left;
  margin: 25rpx 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* 选关图片 */
image{
  width: 260rpx;
  height: 260rpx;
}

 

app.json

{
  "pages":[
    "pages/index/index",
    "pages/game/game"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#E64340",
    "navigationBarTitleText": "拼图游戏",
    "navigationBarTextStyle":"black"
  },
  "style": "v2",
  "sitemapLocation": "sitemap.json"
}

app.wxss

/**app.wxss**/
/* 页面容器样式 */
.container{
  height: 100vh;
  color: #e64340;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
}

/* 顶端标题样式 */
.title{
  font-size: 18pt;
}

 

app.js

App({

  /**
   * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
   */
  onLaunch: function () {
    
  },

  /**
   * 当小程序启动,或从后台进入前台显示,会触发 onShow
   */
  onShow: function (options) {
    
  },

  /**
   * 当小程序从前台进入后台,会触发 onHide
   */
  onHide: function () {
    
  },

  /**
   * 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
   */
  onError: function (msg) {
    
  }
})

 

运行截图;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

微信小游戏入门案例——拼图游戏 的相关文章

随机推荐

  • 有趣的telnet站点

    这个都能做电影 不知道他们花了多长的时间 telnet towel blinkenlights nl 下面这个是其他的一些站点 我没有看过 留个链接 http www telnet org htm places htm
  • 记第一次拆机

    两周前的周日 也不知道抽了什么风萌生了拆笔记本电脑的想法 可能是由于从购买之后风扇都没清理过的原因吧 笔记本电脑品牌联想 型号G480 2013年大一暑假购置的机子 也就是普通的上网本吧 玩游戏确实有点卡 比如剑灵 好了 言归正传 下面开始
  • 卡西欧计算机的闹铃怎么取消,卡西欧g-shock怎么关闹钟

    卡西欧g shock怎么关闹钟 连续按mode按键 通常是左下角按键 直至液晶屏幕出现al1 al2 al3等等字样 然后 第二显示屏会显示 on 按 adjust 就可以改为 of 就关闭了 卡西欧g shock闹钟怎么设置 1 按MOD
  • 一文搞定Postman(菜鸟必看)

    什么是Postman Postman是一个可扩展的 API 测试工具 可以快速集成到 CI CD 管道中 它于 2012 年作为 Abhinav Asthana 的一个副项目启动 旨在简化测试和开发中的 API 工作流程 API 代表应用程
  • java高并发多线程架构_java架构师指南 高并发和多线程的区别

    高并发和多线程 总是被一起提起 给人感觉两者好像相等 那它们之间究竟有什么区别呢 1 多线程 多线程是java的特性 也是java架构师必须掌握的一项技术 因为现在cpu都是多核多线程的 可以同时执行多个任务 为了提高JVM的执行效率 Ja
  • 搭建Obsidian+picGo+Lsky Pro图床

    搭建Obsidian picGo Lsky Pro图床 0 前言 去年心血来潮买了个小主机 搭建了家庭服务器 安装了PVE系统 散热拉胯 性能不足目前只创建了个黑群晖系统 搭建一个图床 方便日常笔记工作 1 软件 1 1 Obsidian
  • 浅谈App的性能优化

    浅谈App的性能优化 2018 01 02 说到 Android 系统手机 大部分人的印象是用了一段时间就变得有点卡顿 有些程序在运行期间莫名其妙的出现崩溃 打开系统文件夹一看 发现多了很多文件 然后用手机管家 APP 不断地进行清理优化
  • Git第十讲 Git如何正确使用log快速查找内容/提交

    在Git中 你可以使用不同的命令来快速查找指定内容或指定提交 下面我将介绍两种常用的方法 快速查找指定内容 要快速查找包含特定内容的文件或代码行 可以使用 git grep 命令 它类似于常见的 grep 命令 但是专门用于搜索Git仓库中
  • 以太坊交易确认数如何获取

    以太坊和比特币一样 都有一个最长链的概念 因此也有一个交易确认数的概念 当一个以太坊交易所在区块被新加入区块链时 该交易的确认数为1 之后每增加一个区块 该交易的确认数加1 显然 一个以太坊交易的确认数越多 就意味着该交易在区块链中埋的越深
  • html css js实现抽奖,原生(纯)js+html+css实现移动端抽奖转盘系统

    这是我前个月使用纯javascript html写出的一个抽奖转盘系统 按理来说 我应该在当时做完这个小系统 就应该立即写bike总结才对 但是本人之前没有在网上写博客的习惯 平时总结更加习惯写在纸上 但是现在发现卸载网上可能更好 博客中有
  • 【第26篇】Swin Transformer

    文章目录 摘要 1 简介 2 相关工作 3 方法 3 1 整体架构 3 2 基于移动窗口的自注意力 3 3 架构变体 4 实验 4 1 ImageNet 1K 上的图像分类 4 2 COCO 上的物体检测 4 3 ADE20K 上的语义分割
  • 2. ZK客户端与服务端建立连接的过程(基于NIO)

    ZK客户端与服务端建立连接的过程 引例 1 启动SendThread 2 状态初始化 3 开始连接 4 处理服务端连接响应 5 流程图 在上一篇 客户端启动源码分析 文章中讲到了客户端会使用两个线程 SendThread和EventThre
  • C#知识系列:nameof 运算符

    插眼 总结 获取变量名 避免因为变量名而声明字符串 参考 官方文档 https docs microsoft com zh cn dotnet csharp language reference operators nameof 其他参考
  • Qt 信号与槽 传输自定义结构体跨线程访问程序异常退出问题

    Qt 信号与槽 传输自定义结构体跨线程访问程序异常退出问题 在使用自定义结构体的时候发现在同一个线程里面的信号发送和槽函数访问使用是正常的 当跨线程信号与槽连接访问自定义结构体时发生访问异常程序异常退出 通过尝试找到问题 解决办法如下 自定
  • 基于STM32f103c8t6的测温枪设计过程

    体温枪设计 设计流程 一 开发板和模块的介绍 1 STM32F103C8T6开发板 2 MLX90614测温模块 3 TM1650红外数码管 二 硬件连接 1 STM32F103C8T6引脚图 2 MLX90614测温模块连接原理图 3 T
  • 实训报告:C&C++ 结构实训 - 深入学习与实践

    实训报告 C C 结构实训 深入学习与实践 引言 C和C 是广泛应用于软件开发领域的编程语言 它们为开发人员提供了强大的工具和灵活性 本篇文章将围绕 C C 结构实训展开 深入学习并实践其中的关键概念与技术 一 简介 C C 结构实训是一项
  • Spark内存管理

    概述 spark从1 6 0开始内存管理发生了变化 原来的内存管理由StaticMemoryManager实现 现在被称为Legacy 在1 5 x和1 6 0中运行相同代码的行为是不同的 为了兼容Legacy 可以通过spark memo
  • python综合案例

    综合案例 1 需求分析 2048游戏是一款数字益智游戏 如图所示 具体游戏规则如下 玩家每次可以选择上下左右其中一个方向移动 每移动一次 所有数字方块都会往移动的方向靠拢 相同数字方块在靠拢时会相加 每次移动完成后 系统会在空白的方块中随机
  • QSS的使用

    QSS官方文档 https doc qt io qt 5 stylesheet reference html 图标制作例子 normal hover press disable 图标制作 按钮设计指南 按钮多态的几种方法 一 程序应用qss
  • 微信小游戏入门案例——拼图游戏

    微信小游戏入门案例 拼图游戏 涉及内容 canvas组件 小程序界面绘图API 目录结构 pages game game js pages game game js 方块的初始位置 var num 00 01 02 10 11 12 20