连连看小游戏前端实现

上周五突然接到一个重磅消息:公司决定开发首款手机小游戏,运行平台是淘宝app上的微淘平台。这个微淘平台从技术上讲是一个能运行html5的平台,跟微信比较类似。接到这样的任务,我自然很高兴呀,因为这也是我的第一款手机游戏了。经过一个周末的奋战,算是初步把这个游戏跑起来了。在写之前我也是查看了不少算法和实际线上代码,因为这都是个被写烂了的游戏了,那么你只要百度一下‘连连看算法’的话你基本都不用自己写了,算法也有好几种,一开始我也比较迷惑,不知道从何下手,经过几番比较,我还是选择了自己的一种简单算法,如果跟你或者跟你看到的算法有雷同,那么只能说我看到过的连连看算法还是太少了。不过我这个算法并没有确保开局的科学性,也就是没有对开局有深度计算确保这个连连看是可玩的,但是因为在7*7=49个方格子上只有20个图片,按照这个疏密程度来看的话,开局不可解的情况是相当少的,我自己测了过百次也没有遇到这样的情况。好了我们开始吧!!!

先看一下游戏的界面:一点击开始,游戏就开始计时,顶部的折扣会飞速上升,如果玩家玩的速度太慢的话那么只能拿到一个他都不想要的折扣了,呵呵


<img src="png0.jpg" id="png0"/><img src="png1.jpg" id="png1"/><img src="png2.jpg" id="png2"/><img src="png3.jpg" id="png3"/><img src="png4.jpg" id="png4"/>
<img src="png5.jpg" id="png5"/><img src="png6.jpg" id="png6"/><img src="png7.jpg" id="png7"/><img src="png8.jpg" id="png8"/><img src="png9.jpg" id="png9"/>
<img src="head.jpg" id="head"/>
<div id="main">
<canvas id="gameHead"></canvas>
<canvas id="gameBody"></canvas>
<div id="startGame"><span>开始</span></div>
</div>

  这段算是最主要的html代码。你看到的顶部的那10张图片是display:none掉的,我之所以放是因为,在js里面,我需要在一个数组里面存放这十个图片的原生对象,那么为了早点下载这个图片呢,我希望他们随着html一起下载,而不是到时候通过var
img = new
Image();img.src=‘png0.png‘这种形式来加载,方便加快游戏加载速度。这个#main是游戏的主题,里面存放了两个canvas,第一个canvas用于写当前折扣,下面一个canvas才是玩游戏的主场。下面我们着重讲javascript部分:


var gridW = document.width / 7;//每一个格子的宽度,根据屏幕的宽度来定,做到自适应
var gridH = document.width / 7;
var get = function(str){
return document.getElementById(str);
};
var pngs;
var leftPair = 10;
var nums = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10];//此数组用于随机的布局20张图片,图片只有10种,每种2张,到时候逐一取出数字来,再从pngs这个数组上取出图片对象
var Darray = [];//这个太重要了,这个是一个7*7的二维数组,通过这个数组,我能够知道在某一点上有没有物体,以及两个物体是不是同一个物体,这样才能判断我需不需要对两个物体进行消除计算,他的初始化在下方
var gameStart = false;//游戏有没有开始的标记,false表示不能开始,点击无效
var canvas = document.getElementById("gameBody");
var canvas_x = canvas.offsetLeft;//游戏canvas距离屏幕左边的距离
var canvas_y = canvas.offsetTop;
var cxt = canvas.getContext(‘2d‘);
window.onload = function(){
pngs = [get(‘png0‘), get(‘png1‘), get(‘png2‘), get(‘png3‘), get(‘png4‘), get(‘png5‘), get(‘png6‘), get(‘png7‘), get(‘png8‘), get(‘png9‘)];//图片都加载好以后我就把图片对象保存到这个pngs对象上
pngs = pngs.concat(pngs);//需要20张图片,那么我就再通过concat方法复制一遍这个pngs
timing(‘0.0折‘);//游戏未开始时先设置为0.0折
layout();//做好布局,此时还不能玩,只是布局好看看
get(‘startGame‘).addEventListener(‘click‘,function(e){//点击开始这个大按钮开始计时,gameStart也变为true
timing();
gameStart = true;
this.style.display = ‘none‘;
e.stopPropagation();
});
}
function layout(){//layout这个函数呢,就是首先生成一个7*7的二维数组,再进行图片的随机布局,我们接着看
for(var i = 0 ; i < 7 ; i ++){
Darray[i] = [0, 0, 0, 0, 0, 0, 0];
}
while(nums.length){//只要nums这个数组还有长度,就说明还没有布局好,nums这个数组是布局一张图片减少一个数组项的
var _ = Math.floor(Math.random() * 7 + 0);//这两部随机生成一个横坐标和纵坐标来随机决定在哪个坑上放图片
var $ = Math.floor(Math.random() * 7 + 0);
if(! Darray[_][$]){//如果这个坑上还没有图片,那就放上去,并且把nums shift掉一个
Darray[_][$] = nums.shift();
cxt.drawImage(pngs[Darray[_][$] - 1] , $ * gridW , _ * gridH , gridW , gridH);
}
}
}
window.coor_1 = null;//这两个玩意重要了,他们是当前被点击的两张图片的经纪人,到时候就根据他两来决定要不要进一步的消除算法
window.coor_2 = null;
/*下面这段要好好讲一下,这里存在一个兼容性问题,就在昨天下班前,document.body这个位置还是canvas,在不太老的安卓机器上跑得很顺畅,但是在安卓2.3或者更老的机器上,出现这样一个问题:点击canvas就会出现一个透明框,一个不太敢确定的原///因是,安卓2.3上的html5 canvas一旦监听click事件,一点击就出现这个透明框,用其他的比如touchstart之类的事件是没有问题的,找来找去没找到方案,最好主管提示我可以把事件绑定在全局上,那么稍作修改,也能跑,并且老安卓也ok了。*/
document.body.addEventListener(‘click‘ , function(e){
if(!gameStart){
return;
}
var coor_x = Math.floor((e.pageY-canvas.offsetTop) / gridW);
var coor_y = Math.floor(e.pageX / gridW);
if(! Darray[coor_x][coor_y]){
return;
}
if(! window.coor_1){
window.coor_1 = [coor_x, coor_y];
drawRect(window.coor_1);
}else{
window.coor_2 = [coor_x, coor_y];
if(Darray[window.coor_1[0]][window.coor_1[1]] != Darray[window.coor_2[0]][window.coor_2[1]] || window.coor_1.join(‘;‘) == window.coor_2.join(‘;‘)){
cleanRect(window.coor_1);
window.coor_1 = null;
window.coor_2 = null;
return;
}else if(window.coor_1 && window.coor_2){
zeroCorner(window.coor_1 , window.coor_2 , true);
}
}
e.stopPropagation();
} , false);

function zeroCorner(coor_1 , coor_2 , next){
if(coor_1[0] != coor_2[0] && coor_1[1] != coor_2[1]){
oneCorner(coor_1 , coor_2 , true);
return;
}
if(coor_1[0] == coor_2[0]){
var start = Math.min(coor_1[1] , coor_2[1]) + 1;
var end = Math.max(coor_1[1] , coor_2[1]);
var arr = Darray[coor_1[0]].slice(start , end);
if(! Math.max.apply(null , arr) || ! arr.length){
if(next){
clear(coor_1 , coor_2);
}else{
return true;
}
}else if(next){
oneCorner(coor_1 , coor_2 , true);
}
}else if(coor_1[1] == coor_2[1]){
var satrt = Math.min(coor_1[0] , coor_2[0]) + 1;
var end = Math.max(coor_1[0] , coor_2[0]);
var arr = [];
for(var i = satrt ; i < end ; i ++){
arr.push(Darray[i][coor_1[1]]);
}
if(! Math.max.apply(null , arr) || ! arr.length){//如果最大值是0或者两者是隔壁,说明此路可走
if(next){
clear(coor_1 , coor_2);
}else{
return true;
}
}else if(next){
oneCorner(coor_1 , coor_2 , true);
}
}
}
function oneCorner(coor_1 , coor_2 , next){
var Diagonal_1 = [coor_2[0], coor_1[1]];
var Diagonal_2 = [coor_1[0], coor_2[1]];
if(! Darray[Diagonal_1[0]][Diagonal_1[1]] && zeroCorner(Diagonal_1 , coor_1 , false) && zeroCorner(Diagonal_1 , coor_2 , false)){/*如果行得通*/
if(next){
clear(coor_1 , coor_2);
}else{
return true;
}
}else if(! Darray[Diagonal_2[0]][Diagonal_2[1]] && zeroCorner(Diagonal_2 , coor_1 , false) && zeroCorner(Diagonal_2 , coor_2 , false)){
if(next){
clear(coor_1 , coor_2);
}else{
return true;
}
}else if(next){
twoCorner(coor_1 , coor_2);
}
}
function twoCorner(coor_1 , coor_2){
var coor_1_y = coor_1[0];
var coor_1_x = coor_1[1];
var coor_2_y = coor_2[0];
var coor_2_x = coor_2[1];
var coor_1_arr = [
[coor_1_y, 0],
[coor_1_y, 1],
[coor_1_y, 2],
[coor_1_y, 3],
[coor_1_y, 4],
[coor_1_y, 5],
[coor_1_y, 6],
[0, coor_1_x],
[1, coor_1_x],
[2, coor_1_x],
[3, coor_1_x],
[4, coor_1_x],
[5, coor_1_x],
[6, coor_1_x]
];
var coor_2_arr = [
[coor_2_y, 0],
[coor_2_y, 1],
[coor_2_y, 2],
[coor_2_y, 3],
[coor_2_y, 4],
[coor_2_y, 5],
[coor_2_y, 6],
[0, coor_2_x],
[1, coor_2_x],
[2, coor_2_x],
[3, coor_2_x],
[4, coor_2_x],
[5, coor_2_x],
[6, coor_2_x]
];
for(var i = 0 , len = coor_1_arr.length ; i < len ; i ++){
if(Darray[coor_1_arr[i][0]][coor_1_arr[i][1]]){
continue;
}
if(oneCorner(coor_1_arr[i] , coor_2 , false) && zeroCorner(coor_1_arr[i] , coor_1 , false)){
clear(coor_1 , coor_2);
return;
}
}
for(var i = 0 ; i < coor_2_arr.length ; i ++){
if(Darray[coor_2_arr[i][0]][coor_2_arr[i][1]]){
continue;
}
if(oneCorner(coor_2_arr[i] , coor_1 , false) && zeroCorner(coor_2_arr[i] , coor_2 , false)){
clear(coor_1 , coor_2);
return;
}
}
cleanRect(window.coor_1);
window.coor_1 = null;
window.coor_2 = null;
}
function clear(coor_1 , coor_2){
cxt.clearRect(coor_1[1] * gridW , coor_1[0] * gridH , gridW , gridH);
cxt.clearRect(coor_2[1] * gridW , coor_2[0] * gridH , gridW , gridH);
Darray[coor_1[0]][coor_1[1]] = 0;
Darray[coor_2[0]][coor_2[1]] = 0;
window.coor_1 = null;
window.coor_2 = null;
leftPair --;
if(! leftPair){
clearInterval(window.timingInterval);
gameStart = false;
document.getElementById(‘finish‘).style.display = ‘block‘;
}
}
function drawRect(coor){
cxt.save();
cxt.lineWidth = 4;
cxt.strokeStyle = ‘#f27b04‘;
cxt.lineJoin = ‘round‘;
cxt.strokeRect(coor[1] * gridW + 3 , coor[0] * gridH + 3 , gridW - 6 , gridH - 6);
cxt.restore();
}
function cleanRect(coor_1){
cxt.drawImage(pngs[Darray[coor_1[0]][coor_1[1]] - 1] , coor_1[1] * gridW , coor_1[0] * gridH , gridW , gridH);
}
var canvas_timing = get(‘gameHead‘);
var cxt_timing = canvas_timing.getContext(‘2d‘);
function timing(str){
cxt_timing.clearRect(0 , 0 , canvas_timing.width , canvas_timing.height);
cxt_timing.font = ‘40px impact‘;
cxt_timing.fillStyle = ‘red‘;
cxt_timing.textAlign = ‘center‘;
cxt_timing.textBaseline="middle";
if(str){
cxt_timing.fillText(str,canvas_timing.width/2,canvas_timing.height/2);
return;
}
var step = 0.05;
var discount = 0;
window.timingInterval = setInterval(function(){
cxt_timing.clearRect(0 , 0 , canvas_timing.width , canvas_timing.height);
cxt_timing.fillText(discount.toFixed(2) + ‘折‘,canvas_timing.width/2,canvas_timing.height/2);
discount = discount + step;
if(discount >= 10){
discount = 10;
clearInterval(window.timingInterval);
}
} , 80);
}

get(‘playAgain‘).addEventListener(‘click‘, function () {
window.coor_1 = null;
window.coor_2 = null;
nums = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10];
leftPair = 10;
layout();
get(‘startGame‘).style.display = ‘block‘;
document.getElementById(‘finish‘).style.display = ‘none‘;
});

  

时间: 2024-08-26 09:31:18

连连看小游戏前端实现的相关文章

利用Python制作一个连连看小游戏,边学边玩!

导语 今天我们将制作一个连连看小游戏,让我们愉快地开始吧~ 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Python自带的模块 环境搭建 安装Python并添加到环境变量,pip安装需要的相关模块即可. 先睹为快 在cmd窗口运行"Game15.py"文件即可. 效果如下: 原理简介 游戏规则: 玩家通过鼠标交换相邻的拼图,若交换后水平/竖直方向存在连续三个相同的拼图,则这些拼图消失,玩家得分,同时生成新的拼图以补充消失的部分,否则,交换失败,玩家不

软件设计之基于Java的连连看小游戏(一)——开题及游戏首页的制作

原本计划紧张忙碌的考试月在图书馆和实验室度过,结果突如其来为期两周的软件设计把课余时间几乎捆绑在了机房.软设没有太多知识上的要求,只要成品简洁美观.实用准确即可.考虑了很久决定要用Java swing做一个完善的连连看小游戏. (一)工作计划安排: 1.16周完成游戏界面的制作以及图形消除功能的实现. 2.17周完成连线的显示以及菜单功能的实现(退出.再来一局等功能),并进行界面及性能的优化. 今天第一天确定了具体的实施方案,决定了游戏界面要达到的效果,并开始着手制作游戏首页的界面. (二)目前

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

博主玩了这么久的连连看,居然是第一次发现,连连看最多只能有2个转弯.orz- 在网上搜索连连看的连线算法判断,并没有找到很全面的,经过自己摸索之后,画了下面的图(图有点丑--) 一. 2个物体在同一直线上,可以直接连通 (这个不需要解释啦) 二.2个物体在同一直线上,中间有障碍物,不能直接连通 (2个转弯) [循环遍历黄线中的交点,比如A,B点,再判断蓝线有没有障碍物,若没有,则可以连通,若有,则继续循环查找新的A,B点] 三. 2个对象不在同一直线上,一个转弯 [2个物体分别在所在位置进行x,

结对项目——连连看小游戏

实验报告 一.题目简介: 游戏主要是鼠标两次点击的图片能否消去的问题.当前,前提是点击两张相同的图片,若点击的是同一张图片或者两张不同的图片,则不予处理.该游戏由多张不同的图片组成,游戏开始将会出现多张随机组合的图片,在规则下点击两张相同的图片后图片将会消失.图片全部消完为游戏成功. 二.结对分工及过程: 此次项目中:王庆祥负责设计图片及编写代码, 郝佳伟负责运行并测试程序是否正确运行. 完成连连看基本功能是:看图和判断. 为实现课程设计需求,需要实现的各个类.每个类需要负责实现的功能. 定义了

原生js实现一个连连看小游戏(二)-----------生成随机不重复数字

直接贴代码: <!DOCTYPE html> <html> <head> <title>生成随机不重复数</title> </head> <body> <script type="text/javascript"> var arr=new Array(); for(var i=0;i<10;i++){ arr.push(i); } // console.log(arr) var get

原生js实现一个连连看小游戏(三)-----------点击列表获取索引

需求:当点击一个列表时,我们要知道它在列表的第几项,即索引,代码实现如下: <!DOCTYPE html> <html> <head> <title></title> </head> <body> <ul id="myUl"> <li>第1个li</li> <li>第1个li</li> <li>第1个li</li> &l

结对项目-小游戏连连看

我与我的结对同学作的是连连看小游戏,由王庆祥同学进行编码,我来检查以及运行监测,最后得结果如下图: 最后附上我的GitHub地址:https://github.com/jiaweihao/Test.git

javascrpit开发连连看记录-小游戏

工作之余,总想做点什么有意思的东西.但是苦于不知道做什么,也就一直没有什么动作.在一个午饭后,跟@jedmeng和@墨尘聊天过程中,发现可以写一些小东西来练练手,有以下几点好处: 1. 加强巩固前端相关知识 2. 可以用一些平时项目中想用但没用的新东西 3. 一块儿做相同的东西,可以分享各自不同的想法 先来一张效果图,也可以来这里玩玩~      接下来就介绍一下做这个小游戏,自己的一些步骤和思路: 首先就是熟悉连连看的规则,为此还专门下载了一个app感受了一下,规则简单的说就是:找到两个相同的

从头开始构建web前端应用——字符炸弹小游戏(二)

接上篇.欢迎指正. 现在,需要考虑如何拆分文件. 拆分文件的目的,是为了方便代码管理.很显然,样式表,网页源文件,js代码需要放在不同的地方.另外,对于前端开发来说,主要的逻辑控制流程,都在js文件里面,所以,还需要拆分js文件.我个人习惯上按功能模块来拆分.在拆分前,你需要仔细思考一下,每一个函数和其他函数之间的关联度,尽量做到相关功能函数在一个文件里. ok,开工.在html所在文件目录下创建2个新文件夹,分别命名为css,js. 1.拆分css. css样式表写的不多,直接在css文件夹下