阿瑟 發表
這篇文章會講解如何利用一些Javascript中的文件物件操作和邏輯判斷來撰寫一個簡易的井字遊戲.
雖然現在用網頁 Script 語言去寫小遊戲已經有點落伍了 (現在多半的網頁小遊戲都是用 Java 和 Flash 完成的), 但其簡單的文件物件 (Document Object) 結構 與 事件處理 (Event Handling), 拿來作為程式設計入門或是促進邏輯設計的思維都是不錯的選擇.
井字遊戲大家應該都有玩過吧? 只要將三個自己的符號 (圈圈或是叉叉) 連成一條線就可以了, 規則非常的簡單.
做跟玩井字遊戲都是一樣的, 一開始當然要先畫出一個大井字.
小弟是選擇使用表格, 畫出九個方塊, 每個方塊都是一個物件, 一開始每個方塊都是空的 (含有一個空白字元):
<table border=1 style="border-collapse:collapse;width:150px;height:150px" bordercolor="#000000"> <tr> <td width=50 align="center" id="ttt00"> </td> <td width=50 align="center" id="ttt01"> </td> <td width=50 align="center" id="ttt02"> </td> </tr> <tr> <td width=50 align="center" id="ttt10"> </td> <td width=510 align="center" id="ttt11"> </td> <td width=50 align="center" id="ttt12"> </td> </tr> <tr> <td width=50 align="center" id="ttt20"> </td> <td width=50 align="center" id="ttt21"> </td> <td width=50 align="center" id="ttt22"> </td> </tr> </table> |
接下來就要開始寫一些 Script.
先寫一個可以把圈和叉畫在方塊內的函式:
var turn = 0; function playRound(objDest) { if(turn == 0) { objDest.innerText = "O"; turn = 1; } else { objDest.innerText = "X"; turn = 0; } } |
接著我們要把這個函式應用到剛剛的物件上:
<table border=1 style="border-collapse:collapse;width:150px;height:150px" bordercolor="#000000"> <tr> <td width=50 align="center" id="ttt00" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt01" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt02" onClick="playRound(this);"> </td> </tr> <tr> <td width=50 align="center" id="ttt10" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt11" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt12" onClick="playRound(this);"> </td> </tr> <tr> <td width=50 align="center" id="ttt20" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt21" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt22" onClick="playRound(this);"> </td> </tr> </table> |
這樣其實井字遊戲可以算是完成了, 但是先別急著把網頁關掉唷! 試想, 如果有使用者在已經有圈圈叉叉的方塊上點了一下, 那符號不就被覆蓋過了, 整個遊戲就亂掉了.
我們必須修改一下 playRound() 函式, 來更正這個錯誤 (當然, 這就是 bug 囉):
function playRound(objDest) { if(objDest.innerText == " " && turn == 0) { objDest.innerText = "O"; turn = 1; } else if(objDest.innerText == " " && turn == 1) { objDest.innerText = "X"; turn = 0; } else { confirm("方塊已經被佔用了!"); } } |
這樣一來就不會錯亂了. 接著要給井字遊戲加上勝負機制. 這樣玩起來才有意思嘛!
這時候就要腦力激盪一下, 仔細想想井字遊戲的規則...
我們可以再一次修改 playRound() 函式, 讓他加入其他的功能:
function playRound(objDest) { if(objDest.innerText == " " && turn == 0) { objDest.innerText = "O"; turn = 1; } else if(objDest.innerText == " " && turn == 1) { objDest.innerText = "X"; turn = 0; } else { confirm("方塊已經被佔用了!"); } if(checkRow()) { if(turn == 0) { if(confirm("玩家2贏了!\n\n要再玩一場嗎?")) clearTable(); } else if(turn == 1) { if(confirm("玩家1贏了!\n\n要再玩一場嗎?")) clearTable(); } } else if(tableIsFull()) { if(confirm("平手\n\n要再玩一場嗎?")) clearTable(); } } |
現在我們要來一一完成這些函式, 先從 checkRow() 開始:
function checkRow() { for(i=0; i<=2; i++) { // 列 if(eval("compare("+"ttt"+i+"0"+","+"ttt"+i+"1"+","+"ttt"+i+"2"+")")) return true; // 對角線 if(eval("compare("+"ttt"+"0"+i+","+"ttt"+"1"+"1"+","+"ttt"+"2"+(2-i)+")")) return true; // 欄 if(eval("compare("+"ttt"+"0"+i+","+"ttt"+"1"+i+","+"ttt"+"2"+i+")")) return true; } return false; } |
在這裡最好先完成 compare() 函式以免忘記:
function compare(obj0, obj1, obj2) { if(obj0.innerText != " " && obj1.innerText != " " && obj2.innerText != " ") if(obj0.innerText == obj1.innerText && obj1.innerText == obj2.innerText) return true; return false; } |
接著要寫 tableIsFull() 函式:
function tableIsFull() { for(i=0; i<=2; i++) for(j=0; j<=2; j++) if(eval("ttt" + i + j).innerText == " ") return false; return true; } |
最後的 clearTable() 函式最簡單了:
function clearTable() { for(i=0; i<=2; i++) { eval("ttt" + i + "0" + ".innerHTML = ' ';") eval("ttt" + i + "1" + ".innerHTML = ' ';") eval("ttt" + i + "2" + ".innerHTML = ' ';") } } |
這樣就大功告成囉!
現在我們來組合之前寫的函式:
<script language="Javascript"> <!-- var turn = 0; function playRound(objDest) { if(objDest.innerText == " " && turn == 0) { objDest.innerText = "O"; turn = 1; } else if(objDest.innerText == " " && turn == 1) { objDest.innerText = "X"; turn = 0; } else { confirm("方塊已經被佔用了!"); } if(checkRow()) { if(turn == 0) { if(confirm("玩家2贏了!\n\n要再玩一場嗎?")) clearTable(); } else if(turn == 1) { if(confirm("玩家1贏了!\n\n要再玩一場嗎?")) clearTable(); } } else if(tableIsFull()) { if(confirm("平手\n\n要再玩一場嗎?")) clearTable(); } } function clearTable() { for(i=0; i<=2; i++) { eval("ttt" + i + "0" + ".innerHTML = ' ';") eval("ttt" + i + "1" + ".innerHTML = ' ';") eval("ttt" + i + "2" + ".innerHTML = ' ';") } } function checkRow() { for(i=0; i<=2; i++) { // 列 if(eval("compare("+"ttt"+i+"0"+","+"ttt"+i+"1"+","+"ttt"+i+"2"+")")) return true; // 對角線 if(eval("compare("+"ttt"+"0"+i+","+"ttt"+"1"+"1"+","+"ttt"+"2"+(2-i)+")")) return true; // 欄 if(eval("compare("+"ttt"+"0"+i+","+"ttt"+"1"+i+","+"ttt"+"2"+i+")")) return true; } return false; } function tableIsFull() { for(i=0; i<=2; i++) for(j=0; j<=2; j++) if(eval("ttt" + i + j).innerText == " ") return false; return true; } function compare(obj0, obj1, obj2) { if(obj0.innerText != " " && obj1.innerText != " " && obj2.innerText != " ") if(obj0.innerText == obj1.innerText && obj1.innerText == obj2.innerText) return true; return false; } --> </script> <h3>井字遊戲</h3> 玩家1: O<br> 玩家2: X<br><br> <table border=1 style="border-collapse:collapse;width:150px;height:150px" bordercolor="#000000"> <tr> <td width=50 align="center" id="ttt00" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt01" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt02" onClick="playRound(this);"> </td> </tr> <tr> <td width=50 align="center" id="ttt10" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt11" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt12" onClick="playRound(this);"> </td> </tr> <tr> <td width=50 align="center" id="ttt20" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt21" onClick="playRound(this);"> </td> <td width=50 align="center" id="ttt22" onClick="playRound(this);"> </td> </tr> </table> |
這個井字遊戲雖然不難寫, 但是卻可以激發一些基礎的程式邏輯和演算法的思考, 也是一個挺好玩的小程式.
小弟寫到這邊先停筆了, 希望這篇教學對您有所幫助.