JavaScript寫的一個帶AI的井字棋


       最近有一門課結束了,需要做一個井字棋的游戲,我用JavaScript寫了一個。首先界面應該問題不大,用html稍微寫一下就可以。主要是人機對弈時的ai算法,如何使電腦方聰明起來,是值得思考一下的。開始游戲后,由玩家先行。那么站在計算機的角度,可以對多種情況進行分析,並按照重要程度賦予權值。
情況如下:

1、同一排(行。列。對角線)有且只有兩個棋子,並且都是自己的,只要再進一步就能獲勝,那么剩下的那個位置權值最高,優先級最大。賦予一級權值。

2、同一排(行。列。對角線)有且只有兩個棋子,並且都是對方的(也就是玩家的),只要再進一步,玩家就會成功,所以“我”要堵住,剩下的那個位置賦予二級權值。

3、因為電腦方后行,如果聰明點,需要一直堵玩家方,所以當一排只有一個棋,且是玩家的棋子,那么該排其他位置的權值設為三級。

4、四級權值:一排只有己方(電腦方)的棋子。

5、五級權限:同排沒有棋子,包括對方和己方。

       實現的時候,每個位置的棋子,可以用二維數組full表示,每個位置的權值大小也用一個二維數組val來表示。玩家方下完后,調用AI方的函數,AI方行棋前,先更新一下權值,然后選出權值最大的位置落子(最優解)。無論是ai還是玩家方,每次落子后都要判斷有沒有產生輸贏。用alert()函數輸出結果。

       為了表示權值的大小,規定按照一級到五級順序,依次加  10000、1000、10、5、3

       注:由於可能要提交源碼,我沒有分離出css樣式和js文件,不過最好還是分開寫更規范。如有不足之處,歡迎批評指正。

源碼如下:

<html>
<head>
<meta charset="utf-8">
<title>井字棋</title>
<script>
//定義全局變量
var full=[[0,0,0],[0,0,0],[0,0,0]];//0表示null,1表示我下的,2表示電腦下的
var val=[[1,1,1],[1,1,1],[1,1,1]];//表示每個位置的權值
function judge(){ //檢測是否有人贏
      //
      for(var i=0;i<3;i++){ if(full[i][0]==full[i][1]&&full[i][1]==full[i][2]&&full[i][0]!=0){ if(full[i][0]==1){ window.alert("you win!"); return true; } else { window.alert("you lose"); return true; } } } //
      for(var i=0;i<3;i++){ if(full[0][i]==full[1][i]&&full[1][i]==full[2][i]&&full[0][i]!=0){ if(full[0][i]==1){ window.alert("you win!"); return true; } else { window.alert("you lose"); return true; } } } //主對角線
      if(full[0][0]==full[1][1]&&full[1][1]==full[2][2]&&full[0][0]!=0){ if(full[0][0]==1){ window.alert("you win!"); return true; } else { window.alert("you lose"); return true; } } if(full[0][2]==full[1][1]&&full[2][0]==full[1][1]&&full[0][2]!=0){ if(full[0][2]==1){ window.alert("you win!"); return true; } else { window.alert("you lose"); return true; } } for(var i=0;i<3;i++){ for(var j=0;j<3;j++){ if(full[i][j]==0) return false;//說明還沒結束
             if(i==2&&j==2) {window.alert("平局!"); return true; } } } return false;//無結果
} function bn(i,j){ //如果已經下過,則無效
      if(full[i][j]!=0){ return 0; }else{ //沒下過
 full[i][j]=1; num1=(i*3+j+1)+""; document.getElementById(num1).value="X"; if(judge()==true){ return; } ai();//切換
 } } //重置權值:
function resetValue(){ for(var i=0;i<3;i++){ for(var j=0;j<3;j++){ if(full[i][j]!=0) val[i][j]=0; else{ //看行和列: 
                  //最高權值
                  if(((full[0][j]+full[1][j]+full[2][j])==4)&&(full[0][j]*full[1][j]*full[2][j])==0
                  &&((full[0][j]-1)*(full[1][j]-1)*(full[2][j]-1))==-1) val[i][j]=val[i][j]+10000; if(((full[i][0]+full[i][1]+full[i][2])==4)&&(full[i][0]*full[i][1]*full[i][2])==0
                  &&((full[i][0]-1)*(full[i][1]-1)*(full[i][2]-1))==-1) val[i][j]=val[i][j]+10000; //次級權值
                  if(((full[0][j]+full[1][j]+full[2][j])==2)&&(full[0][j]*full[1][j]*full[2][j])==0
                  &&((full[0][j]-1)*(full[1][j]-1)*(full[2][j]-1))==0) val[i][j]=val[i][j]+1000; if(((full[i][0]+full[i][1]+full[i][2])==2)&&(full[i][0]*full[i][1]*full[i][2])==0
                  &&((full[i][0]-1)*(full[i][1]-1)*(full[i][2]-1))==0) val[i][j]=val[i][j]+1000; //三級權值(一排只有一個X)
                  if(((full[0][j]+full[1][j]+full[2][j])==1)&&(full[0][j]*full[1][j]*full[2][j])==0
                  &&((full[0][j]-1)*(full[1][j]-1)*(full[2][j]-1))==0) val[i][j]=val[i][j]+10; if(((full[i][0]+full[i][1]+full[i][2])==1)&&(full[i][0]*full[i][1]*full[i][2])==0
                  &&((full[i][0]-1)*(full[i][1]-1)*(full[i][2]-1))==0) val[i][j]=val[i][j]+10; //四級權值(一排只有一個O)
                  if(((full[0][j]+full[1][j]+full[2][j])==2)&&(full[0][j]*full[1][j]*full[2][j])==0
                  &&((full[0][j]-1)*(full[1][j]-1)*(full[2][j]-1))==1) val[i][j]=val[i][j]+5; if(((full[i][0]+full[i][1]+full[i][2])==2)&&(full[i][0]*full[i][1]*full[i][2])==0
                  &&((full[i][0]-1)*(full[i][1]-1)*(full[i][2]-1))==1) val[i][j]=val[i][j]+5; //五級權限(該行沒有X或O)
                  if(((full[0][j]+full[1][j]+full[2][j])==0)&&(full[0][j]*full[1][j]*full[2][j])==0
                  &&((full[0][j]-1)*(full[1][j]-1)*(full[2][j]-1))==-1) val[i][j]=val[i][j]+2; if(((full[i][0]+full[i][1]+full[i][2])==0)&&(full[i][0]*full[i][1]*full[i][2])==0
                  &&((full[i][0]-1)*(full[i][1]-1)*(full[i][2]-1))==-1) val[i][j]=val[i][j]+2; //主對角線:同上
                   if((i==0&&j==0)||(i==2&&j==2)||(i==1&&j==1)){ if(((full[0][0]+full[1][1]+full[2][2])==4)&&(full[0][0]*full[1][1]*full[2][2])==0
                        &&((full[0][0]-1)*(full[1][1]-1)*(full[2][2]-1))==-1) val[i][j]=val[i][j]+10000; //次級權值
                  if(((full[0][0]+full[1][1]+full[2][2])==2)&&(full[0][0]*full[1][1]*full[2][2])==0
                  &&((full[0][0]-1)*(full[1][1]-1)*(full[2][2]-1))==0) val[i][j]=val[i][j]+1000; //三級權值(一排只有一個X)
                  if(((full[0][0]+full[1][1]+full[2][2])==1)&&(full[0][0]*full[1][1]*full[2][2])==0
                  &&((full[0][0]-1)*(full[1][1]-1)*(full[2][2]-1))==0) val[i][j]=val[i][j]+10; //四級權值(一排只有一個O)
                  if(((full[0][0]+full[1][1]+full[2][2])==2)&&(full[0][0]*full[1][1]*full[2][2])==0
                  &&((full[0][0]-1)*(full[1][1]-1)*(full[2][2]-1))==1) val[i][j]=val[i][j]+5; //五級權值(該行沒有X或O)
                  if(((full[0][0]+full[1][1]+full[2][2])==0)&&(full[0][0]*full[1][1]*full[2][2])==0
                  &&((full[0][0]-1)*(full[1][1]-1)*(full[2][2]-1))==-1) val[i][j]=val[i][j]+2; } //副對角線(同上)
                if((i==0&&j==2)||(i==2&&j==0)||(i==1&&j==1)){ //一級
                      if(((full[0][2]+full[1][1]+full[2][0])==4)&&(full[0][2]*full[1][1]*full[2][0])==0
                      &&((full[0][2]-1)*(full[1][1]-1)*(full[2][0]-1))==-1) val[i][j]=val[i][j]+10000; //二級
                       if(((full[0][2]+full[1][1]+full[2][0])==2)&&(full[0][2]*full[1][1]*full[2][0])==0
                       &&((full[0][2]-1)*(full[1][1]-1)*(full[2][0]-1))==0) val[i][j]=val[i][j]+1000; //三級權值(一排只有一個X)
                       if(((full[0][2]+full[1][1]+full[2][0])==1)&&(full[0][2]*full[1][1]*full[2][0])==0
                       &&((full[0][2]-1)*(full[1][1]-1)*(full[2][0]-1))==0) val[i][j]=val[i][j]+10; //四級權值(一排只有一個O)
                       if(((full[0][2]+full[1][1]+full[2][0])==2)&&(full[0][2]*full[1][1]*full[2][0])==0
                       &&((full[0][2]-1)*(full[1][1]-1)*(full[2][0]-1))==1) val[i][j]=val[i][j]+5; //五級權值(該行沒有X或O)
                       if(((full[0][2]+full[1][1]+full[2][0])==0)&&(full[0][2]*full[1][1]*full[2][0])==0
                       &&((full[0][2]-1)*(full[1][1]-1)*(full[2][0]-1))==-1) val[i][j]=val[i][j]+2; } } } } } function ai(){ if(judge()==true){ return; } //挑選權值最大的
 resetValue(); var mi=0,mj=0,temp=0; for(var i=0;i<3;i++) for(var j=0;j<3;j++){ if(val[i][j]>temp){ temp=val[i][j]; mi=i; mj=j; } } full[mi][mj]=2; num1=(mi*3+mj+1)+""; document.getElementById(num1).value="O"; if(judge()==true){ return; } } function lose(){ window.alert("you lose"); location.reload(); } </script>
</head>
<body>
<h1 align=center> 井字棋</h1>
<table border=2px bordercolor="blue"width="300"height="300" style="font-size:50 " align=center>
<tr>
<td><input type="button" id="1" Style="width:100px;height:100px;" value=" " onclick="bn(0,0)"/></td>
<td><input type="button" id="2" Style="width:100px;height:100px;" value=" " onclick="bn(0,1)"/></td>
<td><input type="button" id="3" Style="width:100px;height:100px;" value=" " onclick="bn(0,2)"/></td>
</tr>
<tr>
<td><input type="button" id="4" Style="width:100px;height:100px;" value=" " onclick="bn(1,0)"/></td>
<td><input type="button" id="5" Style="width:100px;height:100px;" value=" " onclick="bn(1,1)"/></td>
<td><input type="button" id="6" Style="width:100px;height:100px;" value=" " onclick="bn(1,2)"/></td>
</tr>
<tr >
<td><input type="button" id="7" Style="width:100px;height:100px;" value=" " onclick="bn(2,0)"/></td>
<td><input type="button" id="8" Style="width:100px;height:100px;" value=" " onclick="bn(2,1)"/></td>
<td><input type="button" id="9" Style="width:100px;height:100px;" value=" " onclick="bn(2,2)"/></td>
</tr>
</table>
<div ><input type="button" style="position:relative;left:500px;top:5px;width:100px;height:50px;" value="重新開始" onclick="location.reload() "/>
      <input type="button" style="position:relative;left:550px;top:5px;width:100px;height:50px;" value="認 輸" onclick="lose()"/>
</div>
<body>
</html>

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM