本文介绍如何使用JavaScript和Canvas开发连连看游戏小程序。内容涵盖点类Point的设计、地图随机生成、触屏事件处理、图案匹配判断及连接线绘制算法,并包含智能查找提示功能,帮助开发者掌握Canvas游戏开发的核心逻辑。
“连连看”是一款源自台湾的桌面休闲游戏,自传入大陆后广受欢迎,也激发了众多程序员开发不同版本的连连看游戏。该游戏主要考验玩家的眼力与反应速度,要求在限定时间内找出所有可以连接的相同图案。每成功匹配一对,图案便会自动消除,当所有图案全部消除时,玩家即获得胜利。所谓“能够连接”,是指两个图案之间的连线在横向或纵向上转折次数不得超过两次,且连线不能穿过尚未消除的其他图案。
连连看游戏的核心规则可归纳为以下几点:
首先,被选中的两个方块图案必须完全相同。
其次,两个方块之间的连接线折点数量不得超过两个,且连接线必须由平行于x轴和y轴的线段组成。
本篇将详细展示连连看游戏的开发过程,最终实现的游戏效果如图1所示。

图1 连连看运行界面
为了提升用户体验,本游戏还增加了智能查找功能。当玩家无法自行找到可消除的方块时,只需右键单击游戏画面,系统便会自动提示一对可以消除的方块,并以红色边框线高亮显示。
01、程序设计的步骤
1. 设计点类Point
点类Point的设计相对简单,其主要作用是存储方块在棋盘上的坐标位置(x, y)。
//定义坐标点类
function Point(_x, _y) {
this.x = _x;
this.y = _y;
}2. 设计游戏主逻辑
整个游戏逻辑基于Canvas对象实现。在页面加载时,系统会调用create_map()函数,将图标图案随机分布到地图中,地图map数组记录的是图案的数字编号。随后调用print_map()函数,根据map中记录的图案信息,将图2所示的图标绘制在Canvas对象上,从而生成游戏初始界面。同时,系统会绑定Canvas对象的触屏开始事件,以响应玩家的操作。
var map = [];
var Select_first = false; //是否已经选中第一块
var linePointStack = []; //存储连接的折点棋盘坐标
var Height = 12;
var Width = 10;
var p1, p2; //存储选中第一块,第二块方块对象坐标
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
//创建画布上下文
this.init(); //初始化地图, 将地图中所有方块区域位置置为空方块状态
this.create_map() ; //生成随机地图
this.print_map(); //输出map地图
this.ctx = wx.createCanvasContext('myCanvas')
this.ctx.draw();
},
init: function() {
//初始化地图, 将地图中所有方块区域位置置为空方块状态
for (var x = 0; x < Width; x++) {
map[x] = new Array();
for (var y = 0; y < Height; y++) {
map[x][y] = " "; //" "表示空的
}
}
},3. 编写函数代码
print_map()函数依据地图map中记录的图案信息,将图2所示的图标图案渲染至Canvas对象,从而生成游戏初始界面。
**
*按地图map中记录图案信息将图标图案显示在Canvas对象中,生成游戏开始的界面。
*/
print_map: function() { //输出map地图
let ctx = this.ctx
for (var x = 0; x < Width; x++)
for (var y = 0; y < Height; y++)
if (map[x][y] != ' ') {
var img1 = '/images/' + map[x][y] + ".jpg";
//ctx.drawImage('/images/4.jpg', 50 * i, 50, 50, 50)
ctx.drawImage(img1, 25 * x, 25 * y, 25, 25);
}
},当用户在窗口中单击时,系统会根据屏幕像素坐标(e.touches[0].x, e.touches[0].y)计算出被单击方块对应的地图棋盘位置坐标(x, y)。接着判断这是否是第一次选中的方块:如果是,则仅对选定的方块添加红色示意框线;如果是第二次选中的方块,则添加黑色示意框线,并进一步判断两个方块图案是否相同且路径连通。如果满足连通条件,则绘制选中方块之间的连接线。
Canvas对象的触屏事件还会调用智能查找功能find2Block()。
以下是Canvas对象触屏开始事件的相关代码实现。
touchStart: function(e) {
var x = Math.floor(e.touches[0].x / 25);
var y = Math.floor(e.touches[0].y / 25);
let ctx = this.ctx;
var pair=false; //是否配对成功
this.print_map(); //输出map地图
console.log("clicked at" + x + "," + y);
if (map[x][y] == " ")
console.log("提示此处无方块");
else {
if (Select_first == false) {
p1 = new Point(x, y);
//画选定(x1,y1)处的框线
ctx.setStrokeStyle("red");
ctx.strokeRect(x * 25, y * 25, 25, 25);
Select_first = true;
} else {
p2 = new Point(x, y);
//判断第二次单击的方块是否已被第一次单击选取,如果是则返回。
if ((p1.x == p2.x) && (p1.y == p2.y))
return;
//画选定(x2,y2)处的框线
console.log('第二次单击的方块' + x + ', ' + y)
ctx.strokeRect(x * 25, y * 25, 25, 25);
if (this.IsSame(p1, p2) && this.IsLink(p1, p2)) { //判断是否连通
console.log('连通' + x + ', ' + y);
Select_first = false;
//画选中方块之间连接线
this.drawLinkLine(p1, p2);
map[p1.x][p1.y] = ' '; //清空记录地图中第1个方块
map[p2.x][p2.y] = ' '; //清空记录地图中第2个方块
pair=true; //配对成功,定时0.5秒后刷新屏幕
linePointStack=[];
if(this.isWin()) { //游戏结束
console.log("游戏结束,你通关了!!");
}
} else {
//不能连通则取消选定的2个方块
Select_first = false;
}
}
}
ctx.draw();
if (pair) { //配对成功
this.print_map(); //重新输出map地图
//定时0.5秒后刷新屏幕
setTimeout(function () {
ctx.draw();
}, 500); //过半秒
}
},IsSame(p1, p2)函数用于判断p1(x1, y1)与p2(x2, y2)处的方块图案是否相同。
IsSame: function(p1, p2) {
if (map[p1.x][p1.y] == map[p2.x][p2.y]) {
console.log("clicked at IsSame");
return true;
}
return false;
},以下是绘制方块之间连接线的方法实现。
drawLinkLine(p1, p2)函数用于绘制(p1, p2)所在两个方块之间的连接线。该函数通过判断linePointStack数组的长度来确定连接类型:如果长度为0,表示直接连通;如果长度为1,表示一折连通,linePointStack存储该一折连通的折点;如果长度为2,表示两折连通,linePointStack存储这两个折点。
drawLinkLine: function(p1, p2) { //画连接线
console.log("折点数" + linePointStack.length);
if (linePointStack.length == 0) //直线联通
this.drawLine(p1, p2);
if (linePointStack.length == 1) { //一折连通
var z = linePointStack.pop();
console.log("一折连通点z" + z.x + z.y);
this.drawLine(p1, z);
this.drawLine(p2, z);
}
if (linePointStack.length == 2) { //2折连通
var z1 = linePointStack.pop()
//print("2折连通点z1",z1.x,z1.y)
this.drawLine(p2, z1)
var z2 = linePointStack.pop()
//print("2折连通点z2",z2.x,z2.y)
this.drawLine(z1, z2);
this.drawLine(p1, z2);
}
},drawLinkLine(p1, p2)函数还负责绘制(p1, p2)之间的直线部分。
drawLine: function(p1, p2) { //绘制(p1, p2)之间的直线
let ctx = this.ctx;
ctx.beginPath();
ctx.moveTo(p1.x * 25 + 12, p1.y * 25 + 12);
ctx.lineTo(p2.x * 25 + 12, p2.y * 25 + 12);
ctx.stroke();
},IsWin()函数用于检测游戏是否胜利,即检查地图map中是否还有未被消除的方块(元素值非空" ")。如果没有剩余方块,则判定玩家赢得游戏。
/**
*#检测是否已经赢得了游戏
*/
isWin: function() {
//检测是否尚有非未被消除的方块
//(非BLANK_STATE状态)
for (var y = 0; y < Height; y++)
for (var x = 0; x < Width; x++)
if (map[x][y] != " ")
return false;
return true;
}至此,连连看游戏的开发工作全部完成。
到此这篇关于基于JavaScript开发连连看游戏小程序的文章就介绍到这了,更多相关JavaScript连连看小程序内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!