| 
 这是我以前玩过的一个智力游戏,那个游戏的名子叫"开窗",实质都是一样的。学过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()新打开一个窗口,并在新窗口中写入游戏规则。 以上就是对本游戏的全部讲解,所有的功能我都调试通过,文章中若有疏漏之处还请高手指点。 |