这是我以前玩过的一个智力游戏,那个游戏的名子叫"开窗",实质都是一样的。学过JavaScript后我就试着做了一个,是用JavaScript和HTML及CSS做的一个.htm文档。
下面是这个文档的界面及其源文件的详细说明,点击这里可以下载源文件:点击下载源文件
首先在源文件的开头处我引用了一个名为game01.css的样式表:<link rel="stylesheet" href="game01.css">,用过CSS的朋友应该很熟悉了。当把样式表单独写成一个文件时就用<link>标记连接过来。下面我分别介绍游戏中的各个功能:
游戏一开始会画出一个10×10的网格,它的大小是可以更改的,只要在"棋盘大小"处输入你想要的网格大小后再点击"开始游戏"就可以了。一开始画出10×10的网格是用drawBoard()函数完成的,如下:
function drawBoard() { var str="<table align='center' border='5' cellspacing=' 0' cellpadding='0' id='gameBoard' bordercolor='#0000ff' onMouseOver='mouseOver()' onMouseOut='mouseOut()' onClick='clicktable()'>"; for(var i=0;i<size;i++) { str+="<tr>"; for(var j=0;j<size;j++) str+="<td> </td>"; str+="</tr>"; } str+="</table>"; return str; } |
其中size是在<script></script>标记的一开始定义的全局变量,如下:
var size=10; var totalMoves=0; var lightOn; var lightOff; var currentable; |
它的初值为10,所以游戏一开始先画出一个10×10的表格。函数把一个完整的 <table> 赋给了变量str,最后返回str。两个for循环是根据size的大小赋给str表格的行数和列数。第一个for循环用 str+="<tr>;赋给str 行标记<tr>,每一行中用第二个for循环:
for(var j=0;j<size;j++) str+="<td> </td>"; |
赋给str单元格标记<td>,总共要赋size个,因此循环条件为:j<size; 。程序运行时在<BODY>的<script>中调用drawBoard()即:document.write(drawBoard());就画出了10×10的网格。而对网格的修改则是通过newGame()完成的:
function newGame() { size=document.all.boardSize.value; if(size<2) size=2; if(size>14) size=14; document.all.boardSize.value=size; document.all.gameBoard.outerHTML=drawBoard(); lightOn=0; document.all.LightOn.innerText=lightOn; lightOff=Math.pow(size,2); document.all.LightOff.innerText=lightOff; totalMoves=0; document.all.Move.innerText=totalMoves; } |
在单击"开始游戏"时就触发了 onClick="newGame()" 事件,在newGame()函数中我们对全局变量size的值进行了修改:size=document.all.boardSize.value; 即把玩家在棋盘大小处输入的值赋给size,再调用drawBoard()重新画一遍网格就实现了改变网格的大小。其中
if(size<2) size=2; if(size>14) size=14; |
是为了保证网格的改变在页面允许的范围内,即把size限制在 2<=size<=14 。过大或过小的值都会被 document.all.boardSize.value=size;语句把2或14写到"棋盘大小"处。newGame()中语句: document.all.gameBoard.outerHTML=drawBoard() 是用THML语言设置对象内容。newGame()中下面的内容:
lightOn=0; document.all.LightOn.innerText=lightOn; lightOff=Math.pow(size,2); document.all.LightOff.innerText=lightOff; totalMoves=0; document.all.Move.innerText=totalMoves; |
是对记寻游戏状态的变量赋初值,就是游戏板左边的那三个记录灯亮个数,灯灭个数,以及移动总数的变量。
下面我们再来看在鼠标经过时如何使网格变色,这就是用了两个事件:onMouseOver和onMouseOut,都定义在了drawBoard()的那个 <table> 中。当鼠标经过时调用mouseOver():
function mouseOver() { currentable=event.srcElement; if(currentable.tagName=="TD") { currentable._background=currentable.style.backgroundColor; currentable.style.backgroundColor="#999999"; } } |
其中currentable表示当前发生事件的对象,用event.srcElement获得。currentable.tagName表示当前发生事件对象的标识符名。于是鼠标经过时 <table> 时,currentable得到当前发生事件的 <td> 使得它的_background变为当前的backgroundColor即: currentable._background=currentable.style.backgroundColor; 把当前的backgroundColor变为"#999999"即: currentable.style.backgroundColor="#999999"; 。看懂了mouseOver()再看mouseOut()就不难了。以下是mouseOut():
function mouseOut() { if(currentable.tagName=="TD") currentable.style.backgroundColor=currentable._background; } |
很好理解吧,我在这里就不多废话了。有了mouseOver()和mouseOut()就可以实现当鼠标经过每个单元格时使其改变颜色,而当鼠标移出后又变回原来的颜色。
源文件中最重要的函数要属clicktable()了,它的作用是当鼠标点下时使得当前对象和上下左右的方格都变色,而且要更改灯亮个数,灯灭个数,以及移动总数的值,还要判断游戏是否结束等等很多事情。同onMouseOver和onMouseOut事件一样,在drawBoard()的 <table> 中同样定义了onClick事件。下面是clicktable():
function clicktable() { totalMoves++; document.all.Move.innerText=totalMoves; if(currentable.tagName=="TD") { setColor(currentable); var cell=currentable.cellIndex; var row=currentable.parentElement.rowIndex; if(row>0) setColor(gameBoard.rows[row-1].cells[cell]); if(row<size-1) setColor(gameBoard.rows[row+1].cells[cell]); if(cell>0) setColor(gameBoard.rows[row].cells[cell-1]); if(cell<size-1) setColor(gameBoard.rows[row].cells[cell+1]); } var over=light(); if(!over) document.all.LightOff.innerText="You Win!"; } |
totalMoves就是记录总移动次数的那个变量,totalMoves++就很明白了吧,每当鼠标在某个格子上单击时就把totalMoves加1,并把totalMoves改变后的值写在移动总数的位置:document.all.Move.innerText=totalMoves; 其中innerText用来设置或得到该对象起始标记到结束标记之间的内容。往下的if语句与另一个函数setColor(current)有关,setColor(current)通过参数current得到当前对象,然后将当前对象的颜色改为黄色(灯亮)。这样通过
cell=currentable.cellIndex; row=currentable.parentElement.rowIndex; |
取得当前对象所在表格的行、列,从而gameBoard.rows[row-1].cells[cell]就可以访问到与该对象在同列但比它靠前一行的那个对象,也用 setColor(gameBoard.rows[row-1].cells[cell] 把它的颜色改变,同理在该对象右、下、左的对象也都可以访问到,使它们的颜色都得以改变。下面是setColor():
function setColor(current) { if(current._background==""||current._background==null||current._background=="#ccccff") { current.style.backgroundColor="yellow"; current._background="yellow"; } else if(current._background=="yellow") { current.style.backgroundColor="#ccccff"; current._background="#ccccff"; } } |
代码不难,我就不细说了。clicktable()中最后的那个light()是判断游戏是否结束的函数,因为函数中要数一下灯亮和灯灭的个数,所以我就叫它light()了,如下:
function light() { lightOn=0; lightOff=0; for(var i=0;i<size;i++) for(var j=0;j<size;j++) if(gameBoard.rows[i].cells[j]._background=="yellow") lightOn++; else lightOff++; document.all.LightOn.innerText=lightOn; document.all.LightOff.innerText=lightOff; return lightOff; } |
lightOn和lightOff还是在一开始定义的全局变量,因为鼠标每次单击后都要检查一遍,所以要先给它们赋0。接下来就是用一个双重循环访问每一个 <td> 对象的 _background 如果是yellow则lightOn++,如果不是则lightOff++,最后不要忘记把lightOn和lightOff的值赋到LightOn和LightOff的innerText里。然后将lightOff反回并在clicktable()中判断是否结束,如果lightOff==0就结束并在"灯灭"的位置出现"You Win"。
最后还有一个规则说明,是一个超链接,点击后调用newWin():
function newWin() { var newin=open("","","height=170,width=250,resizable=0"); newin.document.write(" 在'棋盘大小'处输入数字 后按'开始游戏'键即可得到你想要的棋盘大小。棋盘中黄色表示灯亮, 白色表示灯灭。单击鼠标后当前方格和上下左右的方格都会变色,把所有的方格都' 点亮'后你就胜利了!"); } |
newWin()新打开一个窗口,并在新窗口中写入游戏规则。
以上就是对本游戏的全部讲解,所有的功能我都调试通过,文章中若有疏漏之处还请高手指点。 |