首页  >  文章  >  web前端  >  JS连连看源码完美注释版(推荐)_javascript技巧

JS连连看源码完美注释版(推荐)_javascript技巧

WBOY
WBOY原创
2016-05-16 17:10:141378浏览

闲来无事,也写一个javascript连连看,注释比较完整,想学的朋友可要看了。

连连看最难的部分应该是路径搜索,即鼠标点的两点之间看有无可通的路径。 看过有人写的递归写法,心里痒痒,就捉摸了一下,发现不用递归的情况下难度也不大。

路径搜索由简到难分析,先分析一条直线上是否可直线连通,再分析一条直线上的两点通过拐两个弯是否可通,最后分析不在一条直线上的情况.

在IE6, IE8, firefox3.0.3下测试过.

复制代码 代码如下:




JS连连看源码完美注释版


<script><BR>//以下部分为路径搜索算法部分,与表现层无关 <P>//全局变量<BR>var X = 16;//总行数<BR>var Y = 14;//总列数<BR>var types = 15;//图形种类 <P>//布局矩阵<BR>//为了算法方便,矩阵的第一行,第一列,最后一行,最后一列都标注为0,天然通路。<BR>var arr = new Array(Y);<BR>var tbl;//显示布局的table元素 <P>var p1 = null;//搜索路径用的第1个点的坐标<BR>var p2 = null;//搜索路径用的第2个点的坐标<BR>var e1 = null;//第1个点对应的元素<BR>var e2 = null;//第2个点对应的元素 <P>//路径搜索,给出两个点,搜索出通路<BR>//通路用可连通的点表示<BR>function getPath(p1, p2){<BR> //开始搜索前对p1,p2排序,使p2尽可能的在p1的右下方。<BR> //这样做可以简化算法<BR> if(p1.x>p2.x){<BR> var t = p1; <BR> p1 = p2;<BR> p2 = t; <BR> }<BR> else if(p1.x==p2.x){<BR> if(p1.y>p2.y){<BR> var t = p1; <BR> p1 = p2;<BR> p2 = t; <BR> }<BR> }<BR> //通过分析连连看中两点之间的位置关系,逐步由简到难分析每一种类型<BR> //第一种类型, 两点是否在一条直线上,而且两点之间可直线连通<BR> if((onlineY(p1, p2)||onlineX(p1, p2)) && hasLine(p1, p2)){<BR> status = 'type 1';<BR> return [p1,p2];<BR> }<BR> //第二种类型, 如果两点中任何一个点被全包围,则不通。<BR> if( !isEmpty({x:p1.x, y:p1.y+1}) && !isEmpty({x:p1.x, y:p1.y-1}) && !isEmpty({x:p1.x-1, y:p1.y}) && !isEmpty({x:p1.x+1, y:p1.y}) ){<BR> status = 'type 2';<BR> return null;<BR> }<BR> if( !isEmpty({x:p2.x, y:p2.y+1}) && !isEmpty({x:p2.x, y:p2.y-1}) && !isEmpty({x:p2.x-1, y:p2.y}) && !isEmpty({x:p2.x+1, y:p2.y}) ){<BR> status = 'type 2';<BR> return null;<BR> }<BR> //第三种类型, 两点在一条直线上,但是不能直线连接<BR> var pt0, pt1, pt2, pt3;<BR> //如果都在x轴,则自左至右扫描可能的路径,<BR> //每次构造4个顶点pt0, pt1, pt2, pt3,然后看他们两两之间是否连通<BR> if(onlineX(p1, p2)){<BR> for(var i=0; i<Y; i++){<BR> if(i==p1.y){<BR> continue;<BR> }<BR> pt0 = p1;<BR> pt1 = {x: p1.x, y: i};<BR> pt2 = {x: p2.x, y: i};<BR> pt3 = p2;<BR> //如果顶点不为空,则该路不通。<BR> if(!isEmpty(pt1) || !isEmpty(pt2)){<BR> continue;<BR> }<BR> if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){<BR> status = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')';<BR> return [pt0, pt1, pt2, pt3];<BR> }<BR> }<BR> }<BR> //如果都在y轴,则自上至下扫描可能的路径,<BR> //每次构造4个顶点pt0, pt1, pt2, pt3,然后看他们两两之间是否连通<BR> if(onlineY(p1, p2)){<BR> for(var j=0; j<X; j++){<BR> if(j==p1.x){<BR> continue; <BR> }<BR> pt0 = p1;<BR> pt1 = {x:j, y:p1.y};<BR> pt2 = {x:j, y:p2.y};<BR> pt3 = p2;<BR> //如果顶点不为空,则该路不通。<BR> if(!isEmpty(pt1) || !isEmpty(pt2)){<BR> continue;<BR> }<BR> if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){<BR> status = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')';<BR> return [pt0, pt1, pt2, pt3];<BR> }<BR> }<BR> }<BR> //第四种类型, 两点不在一条直线上。<BR> //先纵向扫描可能的路径<BR> //同样,每次构造4个顶点,看是否可通<BR> for(var k=0; k<Y; k++){<BR> pt0 = p1;<BR> pt1 = {x:p1.x, y:k};<BR> pt2 = {x:p2.x, y:k};<BR> pt3 = p2;<BR> status = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')';<BR> //特殊情况,如果pt0和pt1重合<BR> if(equal(pt0,pt1)){<BR> //如果pt2不为空,则此路不通<BR> if(!isEmpty(pt2)){<BR> continue;<BR> }<BR> if( hasLine(pt1, pt2) && hasLine(pt2, pt3) ){<BR> return [pt1, pt2, pt3];<BR> }<BR> else{<BR> continue;<BR> }<BR> }<BR> //特殊情况,如果pt2和pt3重合<BR> else if(equal(pt2,pt3)){<BR> //如果pt1不为空,则此路不通<BR> if(!isEmpty(pt1)){<BR> continue;<BR> }<BR> if( hasLine(pt0, pt1) && hasLine(pt1, pt2) ){<BR> return [pt0, pt1, pt2];<BR> }<BR> else{<BR> continue;<BR> }<BR> }<BR> //如果pt1, pt2都不为空,则不通<BR> if(!isEmpty(pt1) || !isEmpty(pt2)){<BR> continue;<BR> }<BR> if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){<BR> return [pt0, pt1, pt2, pt3];<BR> }<BR> }<BR> //横向扫描可能的路径<BR> for(var k=0; k<X; k++){<BR> pt0 = p1;<BR> pt1 = {x:k, y:p1.y};<BR> pt2 = {x:k, y:p2.y};<BR> pt3 = p2;<BR> status = '(x:' + pt0.x + ',y:' + pt0.y + ')' + ', (x:' + pt1.x + ',y:' + pt1.y + ')' + ', (x:' + pt2.x + ',y:' + pt2.y + ')' + ', (x:' + pt3.x + ',y:' + pt3.y + ')';<BR> if(equal(pt0,pt1)){<BR> if(!isEmpty(pt2)){<BR> continue;<BR> }<BR> if( hasLine(pt1, pt2) && hasLine(pt2, pt3) ){<BR> return [pt1, pt2, pt3];<BR> }<BR> }<BR> if(equal(pt2,pt3)){<BR> if(!isEmpty(pt1)){<BR> continue;<BR> }<BR> if( hasLine(pt0, pt1) && hasLine(pt1, pt2) ){<BR> return [pt0, pt1, pt2];<BR> }<BR> }<BR> if(!isEmpty(pt1) || !isEmpty(pt2)){<BR> continue;<BR> }<BR> if( hasLine(pt0, pt1) && hasLine(pt1, pt2) && hasLine(pt2, pt3) ){<BR> return [pt0, pt1, pt2, pt3];<BR> }<BR> }<BR> //status='type4';<BR> return null;<BR> /********** end type 4 **************/<BR>} <P>function equal(p1, p2){<BR> return ((p1.x==p2.x)&&(p1.y==p2.y));<BR>} <P>function onlineX(p1, p2){<BR> return p1.y==p2.y;<BR>} <P>function onlineY(p1, p2){<BR> return p1.x==p2.x; <BR>} <P>function isEmpty(p){<BR> return (arr[p.y][p.x]==0); <BR>} <P>function hasLine(p1, p2){<BR> if(p1.x==p2.x&&p1.y==p2.y){<BR> return true; <BR> }<BR> if(onlineY(p1, p2)){<BR> var i = p1.y>p2.y?p2.y:p1.y;<BR> i = i+1;<BR> var max = p1.y>p2.y?p1.y:p2.y;<BR> for(; i<max; i++){<BR> var p = {x: p1.x, y: i};<BR> if(!isEmpty(p)){<BR> break<BR> }<BR> }<BR> if(i==max){<BR> return true;<BR> }<BR> return false;<BR> }<BR> else if(onlineX(p1, p2)){<BR> var j = p1.x>p2.x?p2.x:p1.x;<BR> j = j+1;<BR> var max = p1.x>p2.x?p1.x:p2.x;<BR> for(; j<max; j++){<BR> var p = {x: j, y: p1.y};<BR> if(!isEmpty(p)){<BR> break<BR> }<BR> }<BR> if(j==max){<BR> return true;<BR> }<BR> return false;<BR> }<BR>}<BR>//以下部分为表现层部分,包括绘图, 初始化矩阵, 绑定鼠标事件...<BR>function $(id){return document.getElementById(id)} <P>var t1, t2;//测试用<BR>//图片基路径<BR>var IMG_PATH = 'http://www.jb51.net';<BR>//初始化<BR>function init(){<BR> //构造图片库<BR> var imgs = new Array(30);<BR> for(var i=1; i<=30; i++){<BR> imgs[i] = 'r_' + i + '.gif';<BR> }<BR> tbl = $('tbl');<BR> //构造table<BR> for(var row=0;row<Y-2;row++){<BR> var tr=tbl.insertRow(-1);<BR> for(var col=0;col<X-2;col++) {<BR> var td=tr.insertCell(-1);<BR> }<BR> }<BR> //构造矩阵<BR> for(var i=0; i<Y; i++){<BR> arr[i] = new Array(X);<BR> for(var j=0; j<X; j++){<BR> arr[i][j] = 0;<BR> }<BR> }<BR> var total = (X-2)*(Y-2);<BR> var tmp = new Array(total);//产生随机位置用<BR> for(var i=0; i<total; i++){<BR> tmp[i] = 0;<BR> }<BR> for(var i=0; i<total; i++){<BR> if(tmp[i]==0){<BR> var t = Math.floor(Math.random()*types) + 1;<BR> tmp[i] = t;<BR> while(true){<BR> var c = Math.floor(Math.random()*(total-i)) + i;<BR> if(tmp[c]==0){<BR> tmp[c] = t;<BR> break;<BR> }<BR> }<BR> }<BR> }<BR> var c = 0;<BR> for(var i=1; i<Y-1; i++){<BR> for(var j=1; j<X-1; j++){<BR> arr[i][j] = tmp[c++];<BR> tbl.rows[i-1].cells[j-1].innerHTML = '<img src="' + IMG_PATH + imgs[arr[i][j]] + '" / alt="JS连连看源码完美注释版(推荐)_javascript技巧" >';<BR> } <BR> }<BR> //绑定鼠标事件<BR> var img1, img2;<BR> document.body.onclick = function(e){<BR> var el = document.all?event.srcElement:e.target;<BR> if(el.parentNode.tagName!='TD'){<BR> return;<BR> }<BR> if(!img1){<BR> img1 = el;<BR> }<BR> else{<BR> img2 = el;<BR> }<BR> el.style.border = 'solid #3399FF 3px';<BR> el = el.parentNode;<BR> if(el.innerHTML==''){<BR> p1 = p2 = e1 = e2 = null;<BR> }<BR> var r = el.parentNode.rowIndex +1;<BR> var c = el.cellIndex +1;<BR> if(p1==null){<BR> //el.childNodes[0].style.border = 'solid #ccc 3px';<BR> p1 = {x:c, y:r};<BR> e1 = el;<BR> }<BR> else{<BR> p2 = {x:c, y:r};<BR> e2 = el;<BR> if(!equal(p1, p2)&&e1.innerHTML==el.innerHTML){<BR> var path = getPath(p1, p2);<BR> if(path!=null){<BR> e1.innerHTML = e2.innerHTML = '';<BR> arr[p1.y][p1.x] = arr[p2.y][p2.x] = 0;<BR> }<BR> }<BR> if(t1){t1.style.backgroundColor = '';}<BR> t1 = e1;<BR> if(t2){t2.style.backgroundColor = '';}<BR> t2 = e2;<BR> img1.style.border = 'solid #fff 3px';<BR> img2.style.border = 'solid #fff 3px';<BR> p1 = p2 = e1 = e2 = img1 = img2 = null;<BR> t1.style.backgroundColor = t2.style.backgroundColor = 'lightpink';<BR> }<BR> }<BR>}<BR></script>

 js连连看完美注释版

 
 



声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn