這是我以前玩過的一個智力游戲,那個游戲的名子叫"開窗",實質都是一樣的。學過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"; ??炊薽ouseOver()再看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()新打開一個窗口,并在新窗口中寫入游戲規則。
以上就是對本游戲的全部講解,所有的功能我都調試通過,文章中若有疏漏之處還請高手指點。 |