初学Javascript,多动手,做了个拼图游戏,支持键盘和鼠标操作。运行效果如下图: js文件: function init() { window.stepNode=document.getElementById("step"); window.timeNode=document.getElementById("time"); window.selectNode=document.getElementById("select"); window.startNode=document.getElementById("start"); window.resetNode=document.getElementById("reset"); window.selectNode=document.getElementById("select"); window.imgNode=document.getElementById("source"); window.rootNode=document.getElementById("root"); window.urlNode=document.getElementById("urlImg"); window.applyNode=document.getElementById("apply"); size=selectNode.value; game=new GameArea(size,size,360,360); game.appendEvent(); } function ImageSource(width,height)//图片数据 { function clipRect(a,b) { return "rect("+a*ylen+","+(b+1)*xlen+","+(a+1)*ylen+","+b*xlen+")"; } this.cutOut=function (row,col)//按指定行列创建剪裁图片数组并重置原点于剪裁左上角 { xlen=width/col; ylen=height/row; arr=new Array(); for(i=0;i<row;i++) { arr[i]=new Array(); for(j=0;j<col;j++) { unit=document.createElement("img"); unit.src=imgNode.src;// unit.style.clip=clipRect(i,j); unit.title=[i,j]; unit.style.pixelTop=-i*ylen; unit.style.pixelLeft=-j*xlen; arr[i][j]=unit; } } return arr; } } function GameArea(row,col,imgWidth,imgHeight)//拼图游戏区 { var imgSrc=new ImageSource(imgWidth,imgHeight); var width;//每行高和每列宽 var height; var arrImg;//小图片数组 var step; var time; var started; var timerId; var curPos; var curImg; var blankPos;//空位 this.appendEvent=function() { document.οnkeydοwn=keyDown; selectNode.οnchange=changeArea; startNode.οnclick=startGame; resetNode.οnclick=resetGame; applyNode.οnclick=applyImage; appendInnerEvent(); } function appendInnerEvent() { for(i=0;i<arrImg.length;i++) for(j=0;j<arrImg[i].length;j++) arrImg[i][j].οnclick=clickImg; } function Pos(vx,vy) { this.x=vx;this.y=vy; } Pos.prototype.getLeft=function() { return new Pos(this.x,this.y-1); } Pos.prototype.getDown=function() { return new Pos(this.x+1,this.y); } Pos.prototype.getUp=function() { return new Pos(this.x-1,this.y); } Pos.prototype.getRight=function() { return new Pos(this.x,this.y+1); } Pos.prototype.reset=function(pos) { this.x=pos.x; this.y=pos.y; } Pos.prototype.isSame=function(pos) { return (this.x==pos.x&&this.y==pos.y); } function getTime() { var res=new String(); var h=Math.floor(time/3600); var s=time%60; var m=((time-s)/60)%60; if(h<10) res="0"; res+=h+":"; if(m<10)res+="0"; res+=m+":"; if(s<10)res+="0"; res+=s; return res; } function applyImage() { imgNode.src=urlNode.value; for(var i=0;i<arrImg.length;i++) for(var j=0;j<arrImg[i].length;j++) arrImg[i][j].src=imgNode.src; } function changeArea() { row=col=selectNode.value; initArea(); appendInnerEvent(); } function resetGame()//重置游戏信息 { started=false; clearInterval(timerId); step=time=0; stepNode.innerHTML=0; timeNode.innerHTML=getTime(); selectCur(blankPos); var toPos=new Pos(row-1,col-1); moveImg(toPos); blankPos.reset(toPos); randomOrder(); showBlank(true); } function createArea() { rootNode.innerHTML=""; var ul=document.createElement("ul"); rootNode.appendChild(ul); var li, lili,unit; for(i=0;i<row;i++) { li=document.createElement("li"); ul.appendChild(li); for(j=0;j<col;j++) { unit=arrImg[i][j]; lili=document.createElement("div"); lili.style.width=width; lili.style.height=height; li.appendChild(lili); lili.appendChild(unit); } li.style.width=width*col; li.style.height=height; } resetGame(); } function initArea() { width=imgWidth/col+1;//每行高和每列宽 height=imgHeight/row+1; arrImg=imgSrc.cutOut(row,col); curPos=new Pos(0,0); blankPos=new Pos(row-1,col-1); createArea(); } function randomOrder()//将图片数组除右下角外随机排列 { var order=getRandomOrder(row*col-2); var pos;//当前随机数所在位 var toPos; var crow=0;var ccol=0; var orow=0;var ocol=0;//被置数的 for(var i=0;i<order.length;i++) { crow=Math.floor(order[i]/col); ccol=order[i]%col; if(crow!=orow||ccol!=ocol) { pos=new Pos(crow,ccol); selectCur(pos); moveImg(new Pos(orow,ocol)); } ocol++; if(ocol==col) { orow++;ocol=0; } } } function getRandomOrder(num)//获取0-num的随机排列,如num=3时,2,1,3,0 { var sarr,arr,n,e,i,j; sarr=new Array();//待选数组 arr=new Array(); for(i=0;i<=num;i++) { sarr[i]=i; } for(n=num+1,i=0;n>0;n--,i++)//n剩余序列的个数 { e=Math.ceil(Math.random()*n); //从剩余序列中选第e个,0<e<n+1; while(sarr[e-1]==-1)e++; arr[i]=sarr[e-1];sarr[e-1]=-1;//选中后置-1 } return arr; } function startGame() { if(started)return; started=true; showBlank(false); timerId=setInterval(countIt,1000); timeNode.innerHTML=getTime(); time++; } function countIt() { timeNode.innerHTML=getTime(); time++; } function keyDown() { if(!checkKeyValid(event.keyCode))return ; switch(event.keyCode) { case 37://左 if(blankPos.y==col-1)return ; moveLeft(); break; case 38://上 if(blankPos.x==row-1)return ; moveUp(); break; case 39://右 if(blankPos.y==0)return ; moveRight(); break; case 40://下 if(blankPos.x==0)return; moveDown(); break; default: break; } return false; } function clickImg() { for(i=0;i<arrImg.length;i++) for(j=0;j<arrImg[i].length;j++) if(event.srcElement==arrImg[i][j]) { if(Math.abs(i-blankPos.x)+Math.abs(j-blankPos.y)==1) { selectCur(new Pos(i,j)); stepImgToBlank(); } return; } } function selectCur(pos)//选取pos作为cur { curPos.reset(pos); curImg=getImg(pos); } function moveLeft() { selectCur(blankPos.getRight());//选右元素 stepImgToBlank(); } function moveRight() { selectCur(blankPos.getLeft());// stepImgToBlank(); } function moveUp() { selectCur(blankPos.getDown());//选下行元素 stepImgToBlank(); } function moveDown() { selectCur(blankPos.getUp());//选上行元素 stepImgToBlank(); } function stepImgToBlank()//将cur走到blank { moveImg(blankPos); blankPos.reset(curPos); step++; stepNode.innerHTML=step; } function moveImg(toPos)//将cur与toPos对移 { var vx=toPos.y-curPos.y; var vy=toPos.x-curPos.x; if(vx!=0) { curImg.style.pixelLeft+=vx*width; getImg(toPos).style.pixelLeft-=vx*width; } if(vy!=0) { curImg.style.pixelTop+=vy*height; getImg(toPos).style.pixelTop-=vy*height; } exchangeImg(curPos,toPos); } function exchangeImg(fromPos,toPos)// { if(fromPos.isSame(toPos))return; var img=getImg(fromPos); arrImg[fromPos.x][fromPos.y]=getImg(toPos); arrImg[toPos.x][toPos.y]=img; } function checkKeyValid(code) { if(code<37|code>40)return false; return true; } function getImg(pos) { return arrImg[pos.x][pos.y]; } function showBlank(bshow) { var img=getImg(blankPos); if(!bshow)img.style.visibility="hidden"; else img.style.visibility="visible"; } initArea(); } html: <html> <head> <title></title> <link href="StyleSheet.css" mce_href="StyleSheet.css" rel="stylesheet" type="text/css" /> <mce:script src="JScript.js" mce_src="JScript.js" type="text/javascript"></mce:script> </head> <body οnlοad="init()"> <div id="mid"> <div id="info"> <span>难度选择</span> <select id="select" size="1" > <option value="3">初级</option> <option selected="selected" value="4">中级</option> <option value="5">高级</option> <option value="6">超高</option> <option value="10">狂人</option> </select> <br /> <input id="start" value="开始" type="button"/> <input id="reset" value="重置" type="button" /> <div>用时:<span id="time">00:00:00</span></div> <div>步数:<span id="step">0</span></div> </div> <div id="root"></div> <div id="imgfile"> <img id="source" src="http://www.pcgames.com.cn/netgames/xwkx/gnww/0605/pic/pcwmsj06051505_1_thumb.jpg" mce_src="http://www.pcgames.com.cn/netgames/xwkx/gnww/0605/pic/pcwmsj06051505_1_thumb.jpg" alt="Image" /> <span> <input id="urlImg" title="输入图片地址" name="box" type="text" style="width:150; vertical-align:bottom" /> <span style="width:22;overflow:hidden" > <select οnchange="box.value=value;" style="width:172;margin-left:-152"> <option value="http://www.pcgames.com.cn/netgames/xwkx/gnww/0605/pic/pcwmsj06051505_1_thumb.jpg">默认</option> <option value="http://www.sznews.com/news/content/images/site3/20071102/001558d8bd730894a6c406.jpg">图一</option> <option value="http://www.yacou.net/jianfei/nangeshou/liudehua/%E5%88%98%E5%BE%B7%E5%8D%8E2.jpg">图二</option> </select></span></span> <input id="apply" type="button" value="应用背景" /> </div> </div> </body> </html> css: * { padding: 0px; margin: 0px; } body { width: 700; height: 500; background-color: #666699; color: #FFFFFF; } #mid { border-style: solid; border-width: 1px; position: absolute; width: 700; left: 50%; margin-left: -350; height: 400; top: 50%; margin-top: -200; border-top-color: #FFFF00; } #root { top:0; right: 10%; position: absolute; } #root ul { border: thick ridge #FFFF00; list-style-type: none; background-color: #FFCC00; position: relative; } #root ul li { position:relative; height:121; vertical-align:bottom; width:363; } #root ul li div { position:relative; width:121; height:121; float:left; } #root img { position: absolute; width: 360; height: 360; cursor:hand; } select { background-color: #FFCC00; } #info { margin: 5px; position: relative; clear: both; } #imgfile { margin: 5px; clear:both; width:200; height:200; } #source { margin: 5px; position: relative; width:150; height:150; }