基于 canvas+uniapp 的 9 宫格拼图游戏

涉及到的 canvas 基础知识

  • 创建画布

    <canvas id="’c1’"></canvas>
    
  • 获取画笔

    let context = uni.createCanvasContext(‘c1’)
    
  • 绘图

    /*** img原图片* x1,y1,w1,w2 从图片指定位置开始截取指定大小的图块* x2,y2,w2,h2 将截取的图片放置到画布指定位置,并设置大小*/
    drawImage(img, x1, y1, w1, h1, x2, y2, w2, h2);
    
  • 清除画布

    /*** x,y 指定开始清除的位置* w,h 清除区域宽高*/
    clearRect(x, y, w, h);
    

其他知识

  • 获取 canvas 画布宽高,用于计算拼图图块大小

    uni.createSelectorQuery().in(this).select('.canvas').boundingClientRect().exec(res => {if (res[0]) {// res[0].width;// res[0].height;}});
    
  • 使用二维数组定义 9 宫格图块位置

    num = [[1, 2, 3],[10, 11, 12],[20, 21, 22],
    ];
    
  • 为保证拼图的随机性,需要将图块位置随机打乱,并定义标号为 22 的图块为空白图块,且始终保持在右下角,即 9 宫格游戏的第 9 个位置

  • 移动滑块

    • 当点击图块为空白图块相邻的图块时,交换两个图块的位置,即交换二维数组中对应的标号
    • 位置更新后,重新绘制图块
  • 判断游戏是否完成

    • 每次交换完图块后,使用双层 for 循环,遍历 num 中数据,判断游戏是否完成
    //判断游戏是否完成(每个图块位置顺序与num初始值相同即为完成拼图)
    checkWin() {let num = this.num;for (var i = 0; i < 3; i++) {for (var j = 0; j < 3; j++) {if (num[i][j] !== Number(i + '' + j)) {return false;}}}return true;
    }
    

整体代码

<template><view style="width: 100%; height: 100%"><canvas class="canvas" canvas-id="canvasId" @touchend="touchend" id="canvasId"></canvas></view>
</template>
<script>
export default {name: 'Jigsaw',props: ['url'],data() {return {context: '',isDone: false, //是否完成拼图canvasWidth: 0, //画布宽度canvasHeight: 0, //画布高度num: [[0, 1, 2], //[00, 01, 02],[10, 11, 12],[20, 21, 22],], //定义方块初始位置 22为空白图块};},mounted() {this.init();},methods: {init() {// 创建绘图对象let context = uni.createCanvasContext('canvasId');this.context = context;//获取画布大小uni.createSelectorQuery().in(this).select('.canvas').boundingClientRect().exec(res => {if (res[0]) {this.canvasWidth = res[0].width;this.canvasHeight = res[0].height;//画布大小获取成功后再画图this.generateNum();this.drawCanvas();}});},//打乱图块位置generateNum() {for (var i = 0; i < 50; i++) {//随机抽取其中一个数据var i1 = Math.round(Math.random() * 2);var j1 = Math.round(Math.random() * 2);//再随机抽取其中一个数据var i2 = Math.round(Math.random() * 2);var j2 = Math.round(Math.random() * 2);//最后一个图块位置不变if ((i1 == 2 && j1 == 2) || (i2 == 2 && j2 == 2)) {continue;}let tempNum = [].concat(this.num);var temp = tempNum[i1][j1];tempNum[i1][j1] = tempNum[i2][j2];tempNum[i2][j2] = temp;this.num = tempNum;}},//根据num图块位置,画图出拼图drawCanvas() {//远程图片需加载至本地uni.getImageInfo({src: this.url,success: img => {//清空画布this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);//画布宽高1/3 用于计算每个图块的位置及宽高let cw = this.canvasWidth / 3;let ch = this.canvasHeight / 3;//图片宽高1/3 用于计算每个图块的位置及宽高let iw = img.width / 3;let ih = img.height / 3;//使用双重for循环绘制3x3的拼图for (var i = 0; i < 3; i++) {for (var j = 0; j < 3; j++) {if (this.num[i][j] != 22) {//获取数值的十位数,即第几行var row = parseInt(this.num[i][j] / 10);//获取数组的个位数,即第几列var col = this.num[i][j] % 10;//在画布的相关位置上绘图this.context.drawImage(img.path,col * iw,row * ih,iw,ih,j * cw,i * ch,cw,ch);}}}this.context.draw(true);},fail(err) {console.log(err);},});},touchend(e) {if (this.isDone) {this.$u.toast('游戏已完成');return;}let x = e.changedTouches[0].x;let y = e.changedTouches[0].y;let w = this.canvasWidth / 3;var row = parseInt(y / w); //将x和y换算成几行几列var col = parseInt(x / w);if (this.num[row][col] != 22) {//如果当前点击的不是空白区域this.detectBox(row, col); //移动点击的方块this.drawCanvas(); //重新绘制画布this.isDone = this.checkWin(); //检查游戏是否成功if (this.isDone) {this.$emit('callback');}}},//判断游戏是否完成(每个图块位置顺序与num初始值相同即为完成拼图)checkWin() {let num = this.num;for (var i = 0; i < 3; i++) {for (var j = 0; j < 3; j++) {if (num[i][j] !== Number(i + '' + j)) {return false;}}}return true;},detectBox(i, j) {//如果点击的方块不在最上面一行if (i > 0) {//检测空白区域是否在当前方块的正上方if (this.num[i - 1][j] == 22) {//交换空白区域与当前方块的位置this.num[i - 1][j] = this.num[i][j];this.num[i][j] = 22;return;}}//如果点击的方块不在最下面一行if (i < 2) {//检测空白区域是否在当前方块的正下方if (this.num[i + 1][j] == 22) {//交换空白区域与当前方块的位置this.num[i + 1][j] = this.num[i][j];this.num[i][j] = 22;return;}}//如果点击的方块不在最左边一列if (j > 0) {//检测空白区域是否在当前方块的左边if (this.num[i][j - 1] == 22) {//交换空白区域与当前方块的位置this.num[i][j - 1] = this.num[i][j];this.num[i][j] = 22;return;}}//如果点击的方块不在最右边一列if (j < 2) {//检测空白区域是否在当前方块的右边if (this.num[i][j + 1] == 22) {//交换空白区域与当前方块的位置this.num[i][j + 1] = this.num[i][j];this.num[i][j] = 22;return;}}},},
};
</script>
<style lang="scss" scoped>
.canvas {height: 100%;width: 100%;
}
</style>

原文:https://blog.csdn.net/qq_38545425/article/details/128221249

基于canvas+uniapp的9宫格拼图游戏组件相关推荐

  1. A*算法实现9宫格拼图游戏最优解

    目标:用A*算法解决拼图的最优路径解 A*算法介绍 ​A* (A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是许多其他问题的常用启发式算法. 在计算机科学中,A*算法作为Dij ...

  2. 基于Canvas的N宫格拼图

    最近使用Canvas实现了一个N宫格拼图的游戏,感觉效果还是很不错的,不过我还是觉得九宫格就好了,太多了反而就复杂了.这里我就主要讲述九宫格的实现过程,其它的只是把数据结构扩大一下了. 实现效果 图片 ...

  3. JavaScript经典进阶:javascript – 9宫格 – 拼图

    项目地址:javascript – 9宫格 – 拼图 总体思路 切图 ==>打乱顺序 ==>拖拽实现数据交换 实现过程中,遇到的问题 数据随机排序方法 Array.sort( functi ...

  4. 飞机大战HTML5游戏源码,基于Canvas制作的网页版飞机大战游戏+飞机大战手机端

    简介: 飞机大战HTML5游戏源码是一款基于Canvas制作的网页版飞机大战游戏,画质精美的飞机大战手机端游戏源码 网盘下载地址: http://kekewangLuo.net/W1S2LQcqAT2 ...

  5. 十六宫格拼图(A*/IDA*)(曼哈顿距离)

    传送门 迭代加深:通过单纯的深度优先搜索无法找出初始状态到最终状态的最短路径,但是重复进行限制最大深度的深度优先搜索(深度受限搜索)却可以.简单来说,就是在循环执行深度受限搜索的过程中逐步增加限制值l ...

  6. 1、迪文屏基于T5L_C51开发手势6宫格解锁

    演示视频 1.概述 基于迪文屏DMG32240C028-03WTC屏的滑动手势6宫格解锁功能,该功能运用了触摸屏状态读取和坐标读取的功能(系统变量接口0x0016),绘图功能,需要配合变量图标显示等基 ...

  7. 使用自动化处理某手游四宫格拼图问题

    今天玩游戏的时候碰到个四宫格的小游戏,想试试能不能通过自动化的方式自动完成. 游戏本身逻辑很简单,就是四个小块拼成一个完整图案,但让它自动点击完成的话,这个思考的过程比较有意思. 游戏图: 初始四个无 ...

  8. IDA*算法解十六宫格拼图问题

    IDA*算法, ID(Iterative Deepening)指的是迭代加深. 它的思想是重复进行限制最大深度的深度优先搜索(此限制从某个最小值遍历到最大值), 也称为深度受限搜索. 一般情况下, 为 ...

  9. 【java】16宫格拼图游戏项目

    这个游戏虽然不是很难,但是从中能帮我巩固很多多东西,比如接口的实现.类的继承等这些java面向对象的特点知识我都在写这个项目的过程中有了更深的理解. 这个游戏的机制就是监听到键盘中的上下左右方向键来对 ...

最新文章

  1. Ubuntu下常用命令
  2. AngularJS学习篇(十九)
  3. MySQL表完整性约束
  4. Spring MVC工作原理
  5. Java LocalDate类| getChronology()方法与示例
  6. 平均薪资29036的Python,零基础初学者如何入门?
  7. 微软符号服务器opencv的符号,Opencv Mat类详解和用法1
  8. PHP生成随机数;订单号唯一
  9. 吴恩达神经网络和深度学习-学习笔记-27-多任务学习
  10. PPT_设计师的十大秘诀
  11. java判断字符串是否是空,java判断字符串是否为空的方法
  12. 夜神模拟器怎么设置android版本号,adb连接夜神模拟器(包括安装adb,夜神模拟器)需要将夜神模拟器的版本号与adb版本一致...
  13. 0123能组成四位数c语言,用0123四个数字能组成多少个不同的三位数
  14. React中的SVG陷阱
  15. 基于asp.net742自驾游旅游服务网站的设计
  16. vue的组件的生命周期
  17. 人月神话 中文版 pdf
  18. 五种企业家,一定不要建自己的网站
  19. 关于宏的bypass学习
  20. MAX40026 280ps高速比较器

热门文章

  1. 中科院信工所考研经验整理(待更新)
  2. 微型机器学习,会是下一代AI革命吗?
  3. Linux系统监控命令整理汇总-掌握CPU,内存,磁盘IO等找出性能瓶颈
  4. 图片加载异常兜底方案
  5. 极具发展潜力的20项油气勘探开发新技术
  6. 福特汉姆大学计算机科学专业,福特汉姆大学计算机研究生
  7. OpenVINO整活(一) 输入分辨率
  8. sencha touch ajax params,sencha touch《实现ajax跨域请求》
  9. Bzoj 2563: 阿狸和桃子的游戏 题解
  10. 什么是局域网监控?是如何监控的...