100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > html连连看小游戏论文 JavaScript编写连连看小游戏

html连连看小游戏论文 JavaScript编写连连看小游戏

时间:2018-11-14 17:41:03

相关推荐

html连连看小游戏论文 JavaScript编写连连看小游戏

天天看到别人玩连连看, 表示没有认真玩过, 不就把两个一样的图片连接在一起么, 我自己写一个都可以呢。

使用Javascript写了一个, 托管到github, 在线DEMO地址查看:打开

最终的效果图:

写连连看之前要先考虑哪些呢?

1:如何判断两个元素可以连接呢, 刚刚开始的时候我也纳闷, 可以参考这里:打开;

2:模板引擎怎么选择呢, 我用了底线库的template,因为语法简单。 本来想用Handlebars,但是这个有点大啊, 而且底线库也提供很多常用工具方法( •̀ ω •́ )y;

3:布局如何布局呢, 用table, td加上边框, 边框内部一个div,div就是连连看的棋子, 界面更清爽, 简单, 其实直接用canvas写也行, 没认真研究过canvas;

4:两个元素连接时连线的效果我们要怎么实现呢,如果用dom实现那么需要用到图片,元素连接时候把图片定位到连接的路径。 或者用canvas, 直接用canvas把连接的效果画出来, 我选择后者;

因为我不考虑低浏览器, 使用了zeptoJS库, 基于习惯,把bootstrap也引用了;

使用了三个主要构造函数, 包括Data, View, Score;

View的结构如下, 东西比较少 包括事件绑定, 界面生成, 以及当两个相同元素消失时的 绘图效果:

View

/**

* @desc 根据数据生成map

* */

renderHTML : function

/**

* @desc 界面的主要事件绑定

* @return this;

* */

bindEvents : function

/**

* @desc 工具方法,在canvas上面进行绘图;

* @param [{x:0,y:0},{x:1,y:1},{x:2,y:2},{x:3,y:3}]一个数组, 会自动重绘;

* */

showSparkLine : function

tbody内部元素的模板是这样的:

上面代码的getImg方法会调用全局window的getImg方法,这个方法是根据数据生成图片字符串, 是一个辅助的函数:

window.getImg = function( num ) {

switch(num){

case 1:

return "";

case 2:

return "";

case 3:

return "";

case 4:

return "";

case 5:

return "";

case 6:

return "";

}

};

因为连连看的数据是个二维的数组, 所以模板中必须使用两个for循环, 循环产生HTML字符串, 如果把数据和模板合在一起, 会生成下图的DOM结构:

分数模块构造函数Score, 所有有关得分的代码就这些了 (把元素传进去, 直接调用生成实例的addScore方法, 会自动渲染DOM), 为分数单独写一个构造函数是因为为了解耦:

Score = function(el) {

this.el = $(el);

this.score = 0;

};

$.extend( Score.prototype , {

/**

* @desc 改变元素的HTML,递增分数;

* @param

* */

addScore : function() {

this.el.html(++this.score);

}

});

构造函数Data, 主要的结构如下 , 虽然方法比较少, 实际上Data这块代码占了300行.... 要判断元素是否可以连接用canConnect方法,canConnect方法又会调用dirConnect方法, 计算比较繁琐, 想了解的话最好自己写写:

//新建初始化

newData : function

//工具方法,随机混肴数组;

suffer : function

/**

* @desc set值,把地图中对应的数据清空或者设置,两用接口

* @param x, y

* @return chain

* */

set : function

/**

* @desc 判断两个元素之间是否可以连接

* @param [{x:1,y:1},{x:1,y:1}]

* @return false || []

* */

canConnect : function

/**

* @desc 判断元素是否可以直连

* @param [{x:1,y:1},{x:1,y:1}]

* @return false || true

* */

dirConnect

所有所有代码如下, 作为参考:

link

table{

border-collapse: collapse;

}

td{

border:1px solid #f5f5f5;

text-align: center;

line-height: 40px;

cursor: pointer;

}

td.active{

opacity: 0.7;

}

td div{

width:40px;

height:40px;

}

.bg1{

/*background: #2ECC71;*/

}

.bg2{

/*background: #E67E22;*/

}

.bg3{

/*background: #34495E;*/

}

.bg4{

/*background: #1ABC9C;*/

}

.relative{

position: relative;

}

.absolute{

position: absolute;

left:0;

top:0;

}

得分0

Your browserdoes not support the canvas element.

var el = document.getElementById("tbody");

var elCan = document.getElementById("canvas");

var tpl = document.getElementById("tr-td-tpl");

var cfg = {

width : 8,

height : 8

};

window.getImg = function( num ) {

switch(num){

case 1:

return "";

case 2:

return "";

case 3:

return "";

case 4:

return "";

case 5:

return "";

case 6:

return "";

}

};

var View = function(data, score) {

this.data = data;

this.score = score;

},

Data = function(cfg) {

this.cfg = {

width : cfg.width+2,

height : cfg.height+2

};

this.getRandom = this.getRandom();

},

Score = function(el) {

this.el = $(el);

this.score = 0;

};

$.extend( Data.prototype, {

/**

* @desc 把两个

* @param HTMLELEMENT

* @return true || false

* */

clear : function(obj, target) {

},

/**

* @desc 根据this.cfg新建数据到this.map

* @param void

* @return void

* */

newData : function() {

var result = [];

for(var i=0; i<=this.cfg.height+1; i++ ) {

result[i] = result[i] || [];

for(var j = 0; j<= this.cfg.width+1; j++) {

if(i === 0 || j===0 || (i===this.cfg.height+1) || j === (this.cfg.width+1) ) {

result[i][j] = 0;

}else{

//1-4

result[i][j] = this.getRandom();

}

};

};

this.map = result;

return this;

},

//随机混肴数组;

suffer : function(obj) {

function random(min, max) {

if (max == null) {

max = min;

min = 0;

}

return min + Math.floor(Math.random() * (max - min + 1));

};

var set = obj;

var length = set.length;

var shuffled = Array(length);

for (var index = 0, rand; index < length; index++) {

rand = random(0, index);

if (rand !== index) shuffled[index] = shuffled[rand];

shuffled[rand] = set[index];

}

return shuffled;

},

/**

* @return 返回值必须是成双的, 消除到最后尼玛,发现有一堆不匹配的,玩个球;

* */

getRandom : function() {

//如果消消乐是3*3, 那么你告诉我....最后一个和谁消, 所以要做的就是把所有的元素生成变成一半,然后返回;

var arr = new Array( (this.cfg.height) * (this.cfg.width) / 2 );

var result = [];

for(var i=0; i

arr[i] = (Math.floor( Math.random()*6 ) + 1);

};

result = Array.prototype.concat.call( [] , arr, arr);

result = this.suffer( result );

return function( ) {

return result.pop();

};

},

/**

* @desc set值

* @param x, y

* @return chain

* */

set : function( x, y) {

this.map[y][x] = 0;

return this;

},

/**

* @desc 判断元素是否可以连接

* @param [{x:1,y:1},{x:1,y:1}]

* @return false || true

* */

canConnect : function(obj,target) {

var map = this.map;

//循环obj的y轴相等 , obj.x旁边所有数据为0的元素;;

var getX = function( obj ) {

var result = [];

//循环找出在X附近为0的元素;

for(var i=obj.x+1; i< map[0].length; i++) {

if( map[obj.y][i] == 0 ) {

result.push( {x:i, y:obj.y} );

}else{

break;

};

};

for(var i=obj.x-1; i>=0; i--) {

if( map[obj.y][i] == 0 ) {

result.push( {x:i,y:obj.y} );

}else{

break;

};

};

return result;

};

//循环obj的x轴相等, obj.y旁边所有数据为0的元素;

var getY = function(obj) {

var result = [];

for(var i=obj.y+1; i

if( map[i][obj.x] == 0) {

result.push( { x : obj.x ,y : i} );

}else{

break;

};

};

for(var i=obj.y-1; i>=0; i--) {

if( map[i][obj.x] == 0 ) {

result.push( { x : obj.x ,y : i} );

}else{

break;

};

};

return result;

};

var arr0 = Array.prototype.concat.call( [], getX(obj), obj, getY(obj)).filter(function(obj) {

return !!obj;

});

var arr1 = Array.prototype.concat.call( [], getX(target), target, getY(target) ).filter(function(obj) {

return !!obj;

});

for(i = 0; i

for(var j = 0; j

//只要有一个连接就返回true;

if( this.dirConnect(arr0[i],arr1[j]) ) {

return [obj, arr0[i], arr1[j], target];

};

};

};

return false;

},

/**

* @desc 判断元素是否可以直接连接

* @param [{x:1,y:1},{x:1,y:1}]

* @return false || true

* */

dirConnect : function(obj, target) {

var map = this.map;

//row是x轴 列

//col是y轴 行

var min = 0, max = 0, sum = 0;

if(obj.y === target.y) {

if(obj.x < target.x) {

min = obj.x;

max = target.x;

}else{

min = target.x;

max = obj.x;

};

for(var i=min; i<=max; i++) {

sum += map[obj.y][i];

};

if(sum === (map[obj.y][obj.x] + map[target.y][target.x])) {

return true;

}else{

return false;

};

};

if(obj.x === target.x) {

if(obj.y < target.y) {

min = obj.y;

max = target.y;

}else{

min = target.x;

max = obj.y;

};

for( i=min; i<=max; i++) {

sum += map[i][obj.x];

};

if( sum === (map[obj.y][obj.x] + map[target.y][target.x])) {

return true;

}else{

return false;

};

};

}

});

$.extend( View.prototype, {

/**

* @desc 为view添加视图的主元素

* @return void

* */

setEL : function(el) {

this.el = el;

return this;

},

setTpl : function(tpl) {

this.tpl = _.template( tpl.innerHTML );

return this;

},

/**

* @desc 根据数据生成map

* */

renderHTML : function() {

$(this.el).html( this.tpl( {data : this.data.map} ) );

return this;

},

/**

* @desc 界面的主要事件绑定

* @return this;

* */

bindEvents : function() {

$(this.el).delegate("td", "click", this.click.bind(this));

return this;

},

/**

* @desc click事件, 单独抽出来的;

* */

click : function(ev) {

//修改样式;

$("td.active").removeClass("active");

var target = $(ev.target).closest("td");

target.addClass("active");

//第一次点击我们做的特殊处理;

var prev = this.prev;

if( !prev || target[0] === prev[0]){

this.prev = target;

return;

};

if( prev.attr("data-data") === target.attr("data-data")) {

var xy = JSON.parse( prev.attr("data-info") );

var xxyy = JSON.parse( target.attr("data-info") );

//保存了连接的数组信息

var connectionInfo = [] || false;

if( connectionInfo = this.data.canConnect( xy, xxyy) ) {

this.showSparkLine( connectionInfo );

this.prev = undefined;

this.data.set(xy.x, xy.y);

this.data.set(xxyy.x, xxyy.y);

this.score.addScore();

var _this = this;

setTimeout(function() {

_this.renderHTML();

},2000);

};

prev.attr("data-data", "");

target.attr("data-data","")

}else{

this.prev = target;

};

},

/**

* @desc 工具方法,在canvas上面进行绘图;

* @param [{x:0,y:0},{x:1,y:1},{x:2,y:2},{x:3,y:3}]一个数组, 会自动重绘;

* */

showSparkLine : function( arr ) {

arr = arr.map(function(xy) {

return {

x : (xy.x)*40 + 20,

y : (xy.y)*40 + 20

}

});

var elCan = document.getElementById("canvas");

function spark(ctx) {

function showAndClear(arr, lineWidth) {

ctx.clearRect(0,0,elCan.width,elCan.height);

ctx.beginPath();

ctx.lineJoin = "round";

ctx.lineWidth = lineWidth;

ctx.shadowColor = "rgba(241, 196, 15, 0.41)";

ctx.shadowOffsetX = 1;

ctx.shadowOffsetY = 1;

ctx.shadowBlur = 1;

for(var i=0; i

var xy = arr[i];

var nextXY = arr[i+1]

ctx.moveTo(xy.x, xy.y);

ctx.lineTo(nextXY.x, nextXY.y);

};

ctx.stroke();

};

var ctx = elCan.getContext("2d");

ctx.strokeStyle = "#F1C40F";

var lineWidthArr = [1,2,1,2,1,3,1,0];

var len = lineWidthArr.length;

var times = 400, addTimes = 200;

while(len--) {

(function(len){

setTimeout(function() {

showAndClear(arr, lineWidthArr[len]);

if(len==0) {

ctx.clearRect(0,0,elCan.width,elCan.height);

}

}, times);

times += addTimes;

})(len)

};

};

spark( elCan );

}

});

$.extend( Score.prototype , {

/**

* @desc 改变元素的HTML,递增分数;

* @param

* */

addScore : function() {

this.el.html(++this.score);

}

});

$(function() {

var score = new Score( document.getElementById("score") );

var data = new Data(cfg).newData();

var view = new View(data, score);

view.setEL( el ).setTpl( tpl).renderHTML().bindEvents();

(function init() {

//如果通过style属性添加width或者height,会根据原来的宽和高度自动伸缩的

elCan.width = el.offsetWidth;

elCan.height = el.offsetHeight;

})();

});

在线DEMO地址查看:打开

找到了一个别人写的连连看, 代码极少, 作为参考吧:

连连看

#board{width:508px; height:500px; margin: 30px auto 0px; overflow: hidden; position: relative; background-color: #999999;}

#board span{display: block; position: absolute; width: 30px; height: 30px; }

$(function(){

var cont=$("#board");

var colors=["#ff0000","#00ff00","#0000ff","#ffcc33","#000000","#00ffcc","#ffffff"];

var pos=[];

var click=0;

var firstSpan;

var fx;

var fy;

var arr=[];

arr=[0,0,0,0,0,0,0,0];

pos.push(arr);

for(var i=0;i<8;i++){

new creSpan(i,cont,0,i*40,colors[6],0);

}

for(var i=1;i<=6;i++){

m=new creSpan(i,cont,i*40,0,"#ffffff");

arr=[0];

for(var j=0;j<6;j++){

var color=Math.floor(Math.random()*6);

new creSpan(i,cont,i*40,(j+1)*40,colors[color],(color+1));

arr.push(1);

}

m=new creSpan(i,cont,i*40,(j+1)*40,"#ffffff",0);

arr.push(0);

pos.push(arr);

}

for(var i=0;i<8;i++){

m=new creSpan(i,cont,7*40,i*40,"#ffffff",0);

}

arr=[0,0,0,0,0,0,0,0];

pos.push(arr);

function clear(c1,c2,x,y){

if(c1!=null)c1.style.background="#ffffff";

if(c2!=null){

c2.style.background="#ffffff";

pos[x-1][y-1]=0;

pos[fx-1][fy-1]=0;

}

fx=0;

fy=0;

click=0;

}

$.each($("#board span"),function(index,mSpan){

$(this).click(function(){

var x=Math.floor(index/8);

var y=Math.floor(index%8);

if(click==0){

click=1;

firstSpan=mSpan;

fx=x;

fy=y;

return;

}

if(firstSpan.id!=mSpan.id||(x==fx&&fy==y)){

clear(null,null,0,0);

return;

}

var col=6;

var row=6;

for(var i=0;i

var step=i-x>0?1:-1;

var count=0;

for(var j=x;j!=i;j+=step){

count+=pos[j][y];

}

step=y>fy?-1:1;

for(j=y;j!=fy;j+=step){

count+=pos[i][j];

}

step=i>fx?-1:1;

for(j=i;j!=fx;j+=step){

count+=pos[j][fy];

}

if(count==1){

clear(firstSpan,mSpan,x,y);

return;

}

}

for(i=0;i

step=i-y>0?1:-1;

count=0;

for(j=y;j!=i;j+=step){

count+=pos[x][j];

}

step=x>fx?-1:1;

for(j=x;j!=fx;j+=step){

count+=pos[i][j];

}

step=i

for(j=i;j!=fy;j+=step){

count+=pos[fx][j];

}

if(count==1){

clear(firstSpan,mSpan,x,y);

return;

}

}

clear(null,null,0,0);

});

});

});

function creSpan(n,cont,mtop,mleft,mcolor,idstr){

var mSpan=document.createElement("span");

cont[0].appendChild(mSpan);

mSpan.id=idstr;

with(mSpan.style){

top=mtop+"px";

left=mleft+"px";

background=mcolor;

}

};

以上所述 就是本文的全部内容了,希望大家能够喜欢。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。