隨筆-57  評論-202  文章-17  trackbacks-0

          用JavaScript做涂格子游戲
          原創(chuàng):oq 2003年7月29日

          這是我以前玩過的一個智力游戲,那個游戲的名子叫"開窗",實質(zhì)都是一樣的。學(xué)過JavaScript后我就試著做了一個,是用JavaScript和HTML及CSS做的一個.htm文檔。

          下面是這個文檔的界面及其源文件的詳細說明,點擊這里可以下載源文件:點擊下載源文件

          首先在源文件的開頭處我引用了一個名為game01.css的樣式表:<link rel="stylesheet" href="game01.css">,用過CSS的朋友應(yīng)該很熟悉了。當把樣式表單獨寫成一個文件時就用<link>標記連接過來。下面我分別介紹游戲中的各個功能:

          游戲一開始會畫出一個10×10的網(wǎng)格,它的大小是可以更改的,只要在"棋盤大小"處輸入你想要的網(wǎng)格大小后再點擊"開始游戲"就可以了。一開始畫出10×10的網(wǎng)格是用drawBoard()函數(shù)完成的,如下:

          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>&nbsp;</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的表格。函數(shù)把一個完整的 <table> 賦給了變量str,最后返回str。兩個for循環(huán)是根據(jù)size的大小賦給str表格的行數(shù)和列數(shù)。第一個for循環(huán)用 str+="<tr>;賦給str 行標記<tr>,每一行中用第二個for循環(huán):

          for(var j=0;j<size;j++)
                   str+="<td>&nbsp;</td>"

          賦給str單元格標記<td>,總共要賦size個,因此循環(huán)條件為:j<size; 。程序運行時在<BODY>的<script>中調(diào)用drawBoard()即:document.write(drawBoard());就畫出了10×10的網(wǎng)格。而對網(wǎng)格的修改則是通過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;
          }

          在單擊"開始游戲"時就觸發(fā)了 onClick="newGame()" 事件,在newGame()函數(shù)中我們對全局變量size的值進行了修改:size=document.all.boardSize.value; 即把玩家在棋盤大小處輸入的值賦給size,再調(diào)用drawBoard()重新畫一遍網(wǎng)格就實現(xiàn)了改變網(wǎng)格的大小。其中

          if(size<2) size=2;
          if(size>14) size=14;

          是為了保證網(wǎng)格的改變在頁面允許的范圍內(nèi),即把size限制在  2<=size<=14 。過大或過小的值都會被 document.all.boardSize.value=size;語句把2或14寫到"棋盤大小"處。newGame()中語句: document.all.gameBoard.outerHTML=drawBoard() 是用THML語言設(shè)置對象內(nèi)容。newGame()中下面的內(nèi)容:

          lightOn=0;
          document.all.LightOn.innerText=lightOn;
           lightOff=Math.pow(size,2);
          document.all.LightOff.innerText=lightOff;
          totalMoves=0;
           document.all.Move.innerText=totalMoves;

          是對記尋游戲狀態(tài)的變量賦初值,就是游戲板左邊的那三個記錄燈亮個數(shù),燈滅個數(shù),以及移動總數(shù)的變量。

          下面我們再來看在鼠標經(jīng)過時如何使網(wǎng)格變色,這就是用了兩個事件:onMouseOver和onMouseOut,都定義在了drawBoard()的那個 <table> 中。當鼠標經(jīng)過時調(diào)用mouseOver():

          function mouseOver()
          {
           currentable=event.srcElement;
           if(currentable.tagName=="TD")
            {
             currentable._background=currentable.style.backgroundColor;
             currentable.style.backgroundColor=
          "#999999";
            }
          }

          其中currentable表示當前發(fā)生事件的對象,用event.srcElement獲得。currentable.tagName表示當前發(fā)生事件對象的標識符名。于是鼠標經(jīng)過時 <table> 時,currentable得到當前發(fā)生事件的 <td> 使得它的_background變?yōu)楫斍暗腷ackgroundColor即: currentable._background=currentable.style.backgroundColor;  把當前的backgroundColor變?yōu)?#999999"即: currentable.style.backgroundColor="#999999"; 。看懂了mouseOver()再看mouseOut()就不難了。以下是mouseOut():

          function mouseOut()
          { 

           if(currentable.tagName=="TD")
            currentable.style.backgroundColor=currentable._background;
          }

          很好理解吧,我在這里就不多廢話了。有了mouseOver()和mouseOut()就可以實現(xiàn)當鼠標經(jīng)過每個單元格時使其改變顏色,而當鼠標移出后又變回原來的顏色。

          源文件中最重要的函數(shù)要屬clicktable()了,它的作用是當鼠標點下時使得當前對象和上下左右的方格都變色,而且要更改燈亮個數(shù),燈滅個數(shù),以及移動總數(shù)的值,還要判斷游戲是否結(jié)束等等很多事情。同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就是記錄總移動次數(shù)的那個變量,totalMoves++就很明白了吧,每當鼠標在某個格子上單擊時就把totalMoves加1,并把totalMoves改變后的值寫在移動總數(shù)的位置:document.all.Move.innerText=totalMoves; 其中innerText用來設(shè)置或得到該對象起始標記到結(jié)束標記之間的內(nèi)容。往下的if語句與另一個函數(shù)setColor(current)有關(guān),setColor(current)通過參數(shù)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.backgroundColo
          r="yellow";
            current._background="yellow";
           }
           else if(current._background=="yellow")
           {
            current.style.backgroundColo
          r="#ccccff";
            current._background="#ccccff";
           }
          }

          代碼不難,我就不細說了。clicktable()中最后的那個light()是判斷游戲是否結(jié)束的函數(shù),因為函數(shù)中要數(shù)一下燈亮和燈滅的個數(shù),所以我就叫它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。接下來就是用一個雙重循環(huán)訪問每一個 <td> 對象的 _background 如果是yellow則lightOn++,如果不是則lightOff++,最后不要忘記把lightOn和lightOff的值賦到LightOn和LightOff的innerText里。然后將lightOff反回并在clicktable()中判斷是否結(jié)束,如果lightOff==0就結(jié)束并在"燈滅"的位置出現(xiàn)"You Win"。

          最后還有一個規(guī)則說明,是一個超鏈接,點擊后調(diào)用newWin():

          function newWin()
          {

           var newin=open("","","height=170,width=250,resizable=0");
           newin.document.write("&nbsp;&nbsp;在'棋盤大小'處輸入數(shù)字 后按'開始游戲'鍵即可得到你想要的棋盤大小。棋盤中黃色表示燈亮, 白色表示燈滅。單擊鼠標后當前方格和上下左右的方格都會變色,把所有的方格都' 點亮'后你就勝利了!");
          }

          newWin()新打開一個窗口,并在新窗口中寫入游戲規(guī)則。

          以上就是對本游戲的全部講解,所有的功能我都調(diào)試通過,文章中若有疏漏之處還請高手指點。

          posted on 2005-07-15 16:46 小米 閱讀(1239) 評論(0)  編輯  收藏 所屬分類: 其它
          主站蜘蛛池模板: 长垣县| 和政县| 大庆市| 集安市| 凭祥市| 黄陵县| 宜兰市| 民乐县| 庄浪县| 渑池县| 榕江县| 琼海市| 卢湾区| 车致| 固始县| 东至县| 高邑县| 杂多县| 南平市| 宁武县| 四川省| 睢宁县| 彝良县| 馆陶县| 萍乡市| 绥江县| 博野县| 渑池县| 惠来县| 洛浦县| 大连市| 灯塔市| 宜丰县| 柳江县| 江安县| 洱源县| 留坝县| 永城市| 庆安县| 壶关县| 贞丰县|