摘要:javascript 連連看小遊戲(附上參考來源)
為了SV的姐姐,
終於完成這個小遊戲了~
不過中間隔這麼久是因為SV之前過的焦頭爛額,
快要永無止境的加班的緣故。
感謝網友臨風小築:
http://www.shirne.com/?cid=30&id=25
然後SV的姐姐喜歡玩無止境的遊戲,於是就製作成這樣了:
http://mail2.tmue.edu.tw/~9716025/Link/
想要參考的網友,希望能附上臨風小築當參考資料(而不是SV喔)!
圖片是SV之前畫給巴友們的圖,因此不建議使用><
(畢竟是別人的勇造)
然後如果需要教學,就開始吧(咦)!
自己建設的方法為:
準備檔案空間,新增兩個資料夾:img、source
img裡面放圖片(檔名皆數字+.png,如1.png,從1開始。SV是用16張圖)
接著source資料夾要放五個外部連結檔案(js和css的),
SV一一介紹:
block.js:
function block(obj,x,y){
var _=this;
_.ele=obj;
_.x=x;
_.y=y;
_.type=shapes.Rnd();
_.ele.style.left=(_.x-1)*size[0]+'px';
_.ele.style.top=(_.y-1)*size[1]+'px';
_.setStyle();
_.ele.onclick=function(){
if(prev && prev.ele!==_.ele){
_.link(prev);
}else{
_.active();
}
}
}
block.prototype.setStyle=function(){
this.ele.style.background='url('+imgfolder+this.type+'.png) center center no-repeat';
}
block.prototype.move=function(t){
var op=[this.x,this.y];
map[(op[1]-1)*level.x+op[0]]=0;
switch(t){
case 1:
if(this.y>1 && !map[(this.y-2)*level.x+this.x]){
this.y=this.y-1;
this.ele.style.top=(this.y-1)*size[1]+'px';
}
break;
case 2:
if(this.y<map.length-1 && !map[this.y*level.x+this.x]){
this.y=this.y+1;
this.ele.style.top=(this.y-1)*size[1]+'px';
}
break;
case 3:
if(this.x>1 && !map[(this.y-1)*level.x+this.x-1]){
this.x=this.x-1;
this.ele.style.left=(this.x-1)*size[0]+'px';
}
break;
case 4:
if(this.x<map.length-1 && !map[(this.y-1)*level.x+this.x+1]){
this.x=this.x+1;
this.ele.style.left=(this.x-1)*size[0]+'px';
}
break;
}
map[(this.y-1)*level.x+this.x]=this;
};
block.prototype.active=function( b){
if(prev===this){
prev=null;if( !b)removeClass.call(this.ele,'active');
}else{
if( !b)prev=this;
addClass.call(this.ele,'active');
}
};
block.prototype.link=function(o){
var _=this;
if(_.type==o.type){
way.init([_.x,_.y],[o.x,o.y]);
if(way.finded){
way.show(function(){
_.hide();
o.hide();
prev=null;
});
return;
}
}
o.active();
_.active();
};
block.prototype.hide=function(){
box.removeChild(this.ele);
map[(this.y-1)*level.x+this.x]=0;
counter--;
link.move([this.x,this.y],level.type);
if(counter<=0){
link.start();
}
};
config.js:
Array.prototype.pushItem=function(Item){
this.push(Item);
return this;
};
function $(id){return document.getElementById(id)}
function ce(tag,prop,inner){
var d=document.createElement(tag);
if(prop){
for(var i in prop)
if(i=='class') d.className=prop[i];
else if(i=='style') d.style.cssText=prop[i];
else d.setAttribute(i, prop[i]);
}
if(inner) d.innerHTML=inner;
return d;
}
function addClass(cls){
if(!this.className.match(new RegExp('\\b'+cls+'\\b','g'))){
this.className=this.className
.split(/\s+/g).pushItem(cls).join(' ');
}
}
function removeClass(cls){
this.className=this.className
.replace(new RegExp('(^|\\s+)'+cls+'\\b','g'),'');
}
document.onselectstart=function(){return false};
var map=[],
size=[42,42],
prev=null,
imgfolder='img/',
imgnumber=53,
shapes=[],
counter,
box=document.getElementById('box'),
level=null,
levels=[
{x:8,y:8,shapes:Math.ceil(.3*imgnumber),type:0},
];
for(var i=1;i<imgnumber;i++){
document.createElement('img').src=imgfolder+i+'.png';
}
shapes.Rnd=function(){
var index=Math.ceil(Math.random()*(this.length-1));
return this.splice(index,1)[0];
};
link.start();
way.js:
var way={
finded:false,
init:function(p1,p2){
var _=this, i, j, k, line;
if(_.point && _.finded && _.path.length){
if((_.point[0]==p1 && _.point[1]==p2)||
(_.point[1]==p1 && _.point[0]==p2)){
_.path.pop();
}
}
_.path=[];
_.finded=false;
_.point=[p1,p2];
var stepX = p1[0] > p2[0] ? -1 : 1,
stepY = p1[1] > p2[1] ? -1 : 1;
if(p1[1] == p2[1]){
for( k = p1[0]; k*stepX < p2[0]*stepX; k += stepX)
_.path.push([k, p1[1]]);
if( this.check() )
return this;
}else if(p1[0] != p2[0]){
for( i = p1[1]; i*stepY <= p2[1]*stepY; i += stepY){
for( j = p1[1]; j*stepY < i*stepY; j += stepY)
_.path.push([p1[0],j]);
for( k = p1[0]; k*stepX < p2[0]*stepX; k += stepX)
_.path.push([k, j]);
for( ; j*stepY < p2[1]*stepY; j += stepY)
_.path.push([p2[0],j]);
if( this.check() )
return this;
}
}
if(p1[0] == p2[0]){
for( k = p1[1]; k*stepY < p2[1]*stepY; k += stepY)
_.path.push([p1[0], k]);
if( this.check() )
return this;
}else if(p1[1] != p2[1]){
for( i=p1[0]; i*stepX <= p2[0]*stepX; i += stepX){
for( j = p1[0]; j*stepX < i*stepX; j += stepX)
_.path.push([j, p1[1]]);
for( k = p1[1]; k*stepY < p2[1]*stepY; k += stepY)
_.path.push([j, k]);
for( ; j*stepX < p2[0]*stepX; j += stepX)
_.path.push([j, p2[1]]);
if( this.check() )
return this;
}
}
if(p1[0]>p2[0])maxSide=Math.max(p2[0],level.x-p1[0]+1);
else maxSide=Math.max(p1[0],level.x-p2[0]+1);
if(p1[1]>p2[1])maxSide=Math.max(p2[1],level.y-p1[1]+1,maxSide);
else maxSide=Math.max(p1[1],level.y-p2[1]+1,maxSide);
for( var i=1; i <= maxSide; i++){
line = Math.min(p1[1],p2[1])-i;
if(line >= 0){
for( j = p1[1]; j > line; j--)
_.path.push([p1[0], j]);
for( k = p1[0]; k*stepX < p2[0]*stepX; k += stepX)
_.path.push([k, j]);
for( ; j < p2[1]; j++)
_.path.push([p2[0], j]);
if( this.check() )
return this;
}
line = Math.max(p1[1],p2[1])+i;
if(line <= level.y+1){
for( j = p1[1]; j < line; j++)
_.path.push([p1[0], j]);
for( k = p1[0]; k*stepX < p2[0]*stepX; k += stepX)
_.path.push([k, j]);
for( ; j > p2[1]; j--)
_.path.push([p2[0], j]);
if( this.check() )
return this;
}
line = Math.min(p1[0],p2[0])-i;
if(line >= 0){
for( j = p1[0]; j > line; j--)
_.path.push([j, p1[1]]);
for( k = p1[1]; k*stepY < p2[1]*stepY; k += stepY)
_.path.push([j, k]);
for( ; j < p2[0]; j++)
_.path.push([j, p2[1]]);
if( this.check() )
return this;
}
line = Math.max(p1[0],p2[0])+i;
if(line <= level.x+1){
for( j = p1[0]; j < line; j++)
_.path.push([j, p1[1]]);
for( k = p1[1]; k*stepY < p2[1]*stepY; k += stepY)
_.path.push([j, k]);
for( ; j > p2[0]; j--)
_.path.push([j, p2[1]]);
if( this.check() )
return this;
}
}
return this;
},
check:function (){
var _=this;
for ( var i = 1; i < _.path.length; i++ ){
if(_.path[i][0]<1 || _.path[i][1]<1 ||
_.path[i][0]>level.x || _.path[i][1]>level.y){
continue;
}else if(map[(_.path[i][1]-1)*level.x+_.path[i][0]] ){
_.path=[];
return false;
}
}
_.path.push(_.point[1]);
_.finded=true;
return true;
},
show:function( fn){
var path=ce('div'),pathWord=['─','│','┌','┐','└','┘'];
path.appendChild(ce('div',{'class':'line','style':'left:'+
(this.path[0][0]-1)*size[0]
+'px;top:'+ (this.path[0][1]-1)*size[1] +'px'},eptype(this.path[0],this.path[1])));
for(var i=1;i<this.path.length-1; i++){
path.appendChild(ce('div',{'class':'line','style':'left:'+ (this.path[i][0]-1)*size[0] +'px;top:'+ (this.path[i][1]-1)*size[1] +'px'},pathWord[type(this.path[i],this.path[i-1],this.path[i+1])]));
}
path.appendChild(ce( 'div',{'class':'line','style':'left:'+ (this.path[i][0]-1)*size[0] +'px;top:'+ (this.path[i][1]-1)*size[1] +'px'},eptype(this.path[i],this.path[i-1]) ));
box.appendChild(path);
fn();
this.find();
setTimeout(function(){box.removeChild(path);},300);
function eptype(p, p1){
switch(p[0]-p1[0]){
case -1:
return '<p class="b2">'+ pathWord[0] +'</p>';
case 1:
return '<p class="b1">'+ pathWord[0] +'</p>';
default:
switch(p[1]-p1[1]){
case -1:
return '<p class="b4">'+ pathWord[1] +'</p>';
case 1:
return '<p class="b3">'+ pathWord[1] +'</p>';
}
}
}
function type(p, p1, p2){
switch(p[0]-p1[0]){
case -1:
switch(p2[1]-p[1]){
case -1:
return 4;
case 1:
return 2;
default:
return 0;
}
case 1:
switch(p2[1]-p[1]){
case -1:
return 5;
case 1:
return 3;
default:
return 0;
}
default:
if(p[1]>p1[1]){
switch(p2[0]-p[0]){
case -1:
return 5;
case 1:
return 4;
default:
return 1;
}
}else{
switch(p2[0]-p[0]){
case -1:
return 3;
case 1:
return 2;
default:
return 1;
}
}
}
}
},
find:function(){
for(var i=1;i<map.length;i++){
if(map[i]){
for(var j=i+1;j<map.length;j++){
if(map[j] && map[i].type==map[j].type){
this.init([map[i].x,map[i].y],[map[j].x,map[j].y]);
if(this.finded){
window.tip=false;
window.finded=[map[i],map[j]];
return;
}
}
}
}
}
window.finded=null;
}
};
main.js:
var link={
start : function(){
this.enter();
},
resort:function (){
for(var i=1; i < map.length; i++){
if(map[i]){
shapes.push(map[i].type);
}
}
for(var i=1; i < map.length; i++){
if(map[i]){
map[i].type=shapes.Rnd();
map[i].setStyle();
}
}
way.find();
},
show:function (){
if(window.finded){
window.finded[0].active(true);
window.finded[1].active(true);
window.tip=true;
}else{
alert('');
}
},
enter:function(){
var temp;
level = levels[0];
box.style.width = (level.x*size[0])+'px';
box.style.height= (level.y*size[1])+'px';
for(var i=1;i<level.x*level.y;i+=2){
shapes[i]=shapes[i+1]=Math.ceil(Math.random()*level.shapes);
}
for(var j=1;j<=level.y;j++){
for(var i=1;i<=level.x;i++){
map[(j-1)*level.x+i]=new block(temp=ce('p',{'class':'block'}),i,j);
box.appendChild(temp);
}
}
box.style.display= 'block';
counter = level.x*level.y;
way.find();
},
move:function( p, t, k){
if(t===0)return;
var index;
if(k===undefined)k=1;
switch(t){
case 1:
for(var i=p[1];i<level.y*k;i++)
if(map[index=i*level.x+p[0]])map[index].move(t);
break;
case 2:
for(var i=p[1]; i>level.y*(1-k); i--)
if(map[index=(i-1)*level.x+p[0]])map[index].move(t);
break;
case 3:
for(var i=p[0]+1; i<=level.x*k; i++)
if(map[index=(p[1]-1)*level.x+i])map[index].move(t);
break;
case 4:
for(var i=p[0]-1; i>level.x*(1-k); i--)
if(map[index=(p[1]-1)*level.x+i])map[index].move(t);
break;
case 5:
if(p[0]/p[1] >= level.x/level.y){
if((level.x-p[0])/p[1] >= level.x/level.y)
this.move( p, 2);
else
this.move( p, 3);
}else{
if((level.y-p[1])/p[0] >= level.y/level.x)
this.move( p, 4);
else
this.move( p, 1);
}
return;
case 6:
if(p[0]/p[1] >= level.x/level.y){
if((level.x-p[0])/p[1] >= level.x/level.y)
this.move( p, 1, .5);
else
this.move( p, 4, .5);
}else{
if((level.y-p[1])/p[0] >= level.y/level.x)
this.move( p, 3, .5);
else
this.move( p, 2, .5);
}
return;
case 7:
if(p[1]<=level.y*.5)
this.move(p, 1, .5);
else
this.move(p, 2, .5);
return;
case 8:
if(p[0]<=level.x*.5)
this.move(p, 3, .5);
else
this.move(p, 4, .5);
return;
case 9:
if(p[1]<=level.y*.5)
this.move(p, 3);
else
this.move(p, 4);
return;
case 10:
if(p[0]<=level.x*.5)
this.move(p, 1);
else
this.move(p, 2);
return;
case 11:
this.move( p, Math.ceil(Math.random()*4));
default:
return;
}
}
}
master.css:
* { margin:0; padding:0 }
body { padding-top:40px }
#head { width:900px; margin:0 auto; font-size:12px; line-height:2em}
#head a{color:#363;text-decoration:none}
#head .button{width:60px;height:24px;text-align:center;}
#box { border:1px #ccc solid; position:relative; margin:50px auto; display:none }
#box .block { border:1px #ddf solid; background:#666; width:40px; height:40px; color:#fff; text-align:center; line-height:40px; font-family:"Arial"; position:absolute; cursor:pointer }
#box .line { width:42px; height:42px; color:#fa0; font-size:42px; line-height:42px; position:absolute; z-index:99}
#box .line .b1{width:21px;overflow:hidden;float:left}
#box .line .b2{width:21px;overflow:hidden;float:right}
#box .line .b3{height:21px;overflow:hidden;}
#box .line .b4{height:21px;overflow:hidden;margin-top:21px;}
#box .active { width:38px;height:38px; border:2px solid #fa0; color:#fa0 }
接著主要網頁index.html是:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="source/master.css" />
<title>Linkers</title>
</head>
<body>
參考來源:http://www.shirne.com/?cid=30&id=25
(臨風小築)
<div id="head">
</div>
<div id="box"></div>
<script type="text/javascript" src="source/block.js"></script>
<script type="text/javascript" src="source/way.js"></script>
<script type="text/javascript" src="source/main.js"></script>
<script type="text/javascript" src="source/config.js"></script>
</body>
</html>
SV不得不佩服原作的程式很有條理~而且還用了很多SV沒學過的技巧,真的很厲害喔!
如果要修改圖片的大小,是修改config.js的size=(42,42)
修改畫面大小是修改config.js的levels陣列裡的8x8
順帶一提因為原作的消掉模式很多,config.js裡的levels的type:0可以改成0~6等等(原本是配合不同關卡)!
然後因為連連看的線是用文字表示的,檔案必須是utf-8比較好喔~
嗯嗯,大概就是這樣了!
真的再次佩服原作,
然後真的很謝謝原作!
因為還有很多方法SV也是一知半解,不一定能幫大家解答,
就分享到這囉~