首页 > 嗟来之食 > 前端实现连连看小游戏(1)
2017
09-20

前端实现连连看小游戏(1)

博主玩了这么久的连连看,居然是第一次发现,连连看最多只能有2个转弯。orz…
在网上搜索连连看的连线算法判断,并没有找到很全面的,经过自己摸索之后,做了一些小动画,希望大家可以看一遍都懂啦~)
 
一. 2个物体在同一直线上,可以直接连通 (这个不需要解释啦)

 
二. 2个对象不在同一直线上,一个转弯
【2个物体分别在所在位置进行x,y轴的延伸,如下图则交点为A,B。 只需判断2个交点到2个物体直接是否有障碍物,若没有,则可以连通】
看动画容易理解一点~

 
 
三. 2个物体不在同一直线上,连线有2个转弯 
【如下图,由于有2个转弯,不同于1个转弯的情况,我们需要有2个拐点。这2个拐点必须在同一个轴上(x轴 或者 y轴),那我们只要分别做这2个点的x轴的延伸,或者y轴的延伸,一个一个取点遍历扫描,若都可以连线,则可以连线~】

 
以上就是四种连线算法判断,动画只列举部分情况,每一种按照同样的原理扫描。可覆盖所有连线判断~
说完连线判断的逻辑之后,写一下整体的游戏框架,游戏基本使用原生javascript,使用createjs游戏引擎进行开发。
 
 代码思路:
1. 绘制游戏画图,确定为多少宫图,由于是在移动端的小游戏,根据最小屏幕尺寸(iphone4  320*480),确定为7*9的宫图。
1. 创建一个二维数组,如果某个坐标上有物体,则设为1,否则为0
2.判断该位置是否有物体,只需要判断对应的二维数组上值是否为1,若为1,则有物体,否则没有。
至于画线,消除相同物体,只要会连线逻辑,肯定就会自己绘制线条,消除物体了,所以本篇文章就只讲连线判断啦~
 
在判断能否连线的时候,肯定是从最简单的方法开始判断,如下:
同一直线能否直线连通—>如何一点被包围,则不通—>两点在一条直线上,不能直线连接但是可以连通—> 不在同一直线但是可以连通

getPath: function (p1, p2) {
//开始搜索前对p1,p2排序,使p2尽可能的在p1的右下方。
if (p1.x > p2.x) {
var t = p1;
p1 = p2;
p2 = t;
}
else if (p1.x == p2.x) {
if (p1.y > p2.y) {
var t = p1;
p1 = p2;
p2 = t;
}
}
//2点在同一直线上,可以直线连通
if (this.hasLine(p1, p2).status) {
return true;
}
//如果两点中任何一个点被全包围,则不通。
else if (this.isWrap(p1, p2)) {
return false;
}
//两点在一条直线上,不能直线连接但是可以连通
else if (this.LineLink(p1, p2)) {
return true;
}
//不在同一直线但是可以连通
else if (this.curveLink(p1, p2)) {
return true;
}
}

 

//判断同一条线能否连通,x轴相同或者y轴相同
hasLine: function (p1, p2) {
this.path = [];
//同一点
if (p1.x == p2.x && p1.y == p2.y) {
return {
status: false
};
}
if (this.onlineY(p1, p2)) {
var min = p1.y > p2.y ? p2.y : p1.y;
min = min + 1;
var max = p1.y > p2.y ? p1.y : p2.y;
for (min; min < max; min++) {
var p = {x: p1.x, y: min};
if (!this.isEmpty(p)) {
console.log('有障碍物p点………………');
console.log(p);
this.path = [];
break;
}
this.path.push(p);
}
if (min == max) {
return {
status: true,
data: this.path,
dir: 'y' //y轴
};
}
this.path = [];
return {
status: false
};
}
else if (this.onlineX(p1, p2)) {
var j = p1.x > p2.x ? p2.x : p1.x;
j = j + 1;
var max = p1.x > p2.x ? p1.x : p2.x;
for (j; j < max; j++) {
var p = {x: j, y: p1.y};
if (!this.isEmpty(p)) {
console.log('有障碍物p点………………');
console.log(p);
this.path = [];
break;
}
this.path.push(p);
}

if (j == max) {
return {
status: true,
data: this.path,
dir: 'x' //x轴
};
}
this.path = [];
return {
status: false
};
}
return {
status: false
};
//2点是否有其中一点被全包围,若有,则返回true
isWrap: function (p1, p2) {
//有一点为空,则条件不成立
if (!this.isEmpty({x: p1.x, y: p1.y + 1}) && !this.isEmpty({
x: p1.x,
y: p1.y – 1
}) && !this.isEmpty({
x: p1.x – 1,
y: p1.y
}) && !this.isEmpty({x: p1.x + 1, y: p1.y})) {
return true;
}
if (!this.isEmpty({x: p2.x, y: p2.y + 1}) && !this.isEmpty({
x: p2.x,
y: p2.y – 1
}) && !this.isEmpty({
x: p2.x – 1,
y: p2.y
}) && !this.isEmpty({x: p2.x + 1, y: p2.y})) {
return true;
}
return false;
}
//两点在一条直线上,不能直线连接但是可以连通
LineLink: function (p1, p2) {
var pt0, pt1, pt2, pt3;
//如果都在x轴,则自左至右扫描可能的路径,
//每次构造4个顶点pt0, pt1, pt2, pt3,然后看他们两两之间是否连通
if (this.onlineX(p1, p2)) {
for (var i = 0; i < this.H; i++) {
if (i == p1.y) {
continue;
}
pt0 = p1;
pt1 = {x: p1.x, y: i};
pt2 = {x: p2.x, y: i};
pt3 = p2;
//如果顶点不为空,则该路不通。
if (!this.isEmpty(pt1) || !this.isEmpty(pt2)) {
continue;
}
if (this.hasLine(pt0, pt1).status && this.hasLine(pt1, pt2).status && this.hasLine(pt2, pt3).status) {
this.drawLine(2, [pt0, pt3, pt1, pt2]);
return [pt0, pt1, pt2, pt3];
}
}
}
//如果都在y轴,则自上至下扫描可能的路径,
//每次构造4个顶点pt0, pt1, pt2, pt3,然后看他们两两之间是否连通
if (this.onlineY(p1, p2)) {
for (var j = 0; j < this.W; j++) {
if (j == p1.x) {
continue;
}
pt0 = p1;
pt1 = {x: j, y: p1.y};
pt2 = {x: j, y: p2.y};
pt3 = p2;
//如果顶点不为空,则该路不通。
if (!this.isEmpty(pt1) || !this.isEmpty(pt2)) {
continue;
}
if (this.hasLine(pt0, pt1).status && this.hasLine(pt1, pt2).status && this.hasLine(pt2, pt3).status) {
this.drawLine(2, [pt0, pt3, pt1, pt2]);
return [pt0, pt1, pt2, pt3];
}
}
}
},
//两点不在一条直线上,看是否可通
curveLink: function (p1, p2) {
var pt0, pt1, pt2, pt3;
//特殊情况,先判断是否是一个转弯
var spec1 = {x: p1.x, y: p2.y},
spec2 = {x: p2.x, y: p1.y};
if (this.isEmpty(spec1)) {
if (this.hasLine(p1, spec1).status && this.hasLine(p2, spec1).status) {
console.log('1个转弯');
this.drawLine(1, [p1, p2, spec1]);
return [p1, p2, spec1];
}
}
if (this.isEmpty(spec2)) {
if (this.hasLine(p1, spec2).status && this.hasLine(p2, spec2).status) {
console.log('1个转弯');
// console.table([pt0, spec2, pt3]);
this.drawLine(1, [p1, p2, spec2]);
return [p1, spec2, p2];
}
}
//先纵向扫描可能的路径
//同样,每次构造4个顶点,看是否可通
for (var k = 0; k <= this.H; k++) {
pt0 = p1;
pt1 = {x: p1.x, y: k};
pt2 = {x: p2.x, y: k};
pt3 = p2;

//2个交点都为空
if (this.isEmpty(pt1) && this.isEmpty(pt2)) {
//2个转弯
if (this.hasLine(pt0, pt1).status && this.hasLine(pt1, pt2).status && this.hasLine(pt2, pt3).status) {
console.log('2个转弯');

this.drawLine(2, [pt0, pt3, pt1, pt2]);
return [pt0, pt3, pt1, pt2];
}
}
}

//横向扫描所有可能的路径
for (var k = 0; k <= this.W; k++) {
pt0 = p1;
pt1 = {x: k, y: p1.y};
pt2 = {x: k, y: p2.y};
pt3 = p2;

//2个交点都为空
if (this.isEmpty(pt1) && this.isEmpty(pt2)) {
//2个转弯
if (this.hasLine(pt0, pt1).status && this.hasLine(pt1, pt2).status && this.hasLine(pt2, pt3).status) {
console.log('2个转弯');

this.drawLine(2, [pt0, pt3, pt1, pt2]);
return [pt0, pt3, pt1, pt2];
}
}
}
return false;
}

连线判断
 

最后编辑:
作者:
这个作者貌似有点懒,什么都没有留下。

留下一个回复