最近有一門課結束了,需要做一個井字棋的游戲,我用JavaScript寫了一個。首先界面應該問題不大,用html稍微寫一下就可以。主要是人機對弈時的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]+