五子棋的AI構想 有句話叫“當局者迷,旁觀者清?!保@句話在由AI所控制的計算機玩家上是不成立的,因為計算機必須知道有那些獲勝方式,并計算出每下一步棋到棋盤上任一格子的獲勝幾率,也就是說,一個完整的五子棋的AI構想必須:
1、能夠知道所有的獲勝組合; 2、建立和使用獲勝表; 3、設定獲勝的分數(shù); 4、使電腦具有攻擊和防守的能力; 一、求五子棋的獲勝組合 在一場五子棋的游戲中,計算機必須要知道有那些的獲勝組合,因此我們必須求得獲勝組合的總數(shù)。我們假定當前的棋盤為10*10?! 。?)計算水平方向的獲勝組合數(shù),每一列的獲勝組合是:6,共10列,所以水平方向的獲勝組合數(shù)為:6*10=60 ?。?)計算垂直方向的獲勝組合總數(shù),每一行的獲勝組合是:6,共10行,則垂直方向的獲勝組合數(shù)為:6*10=60 (3)計算正對角線方向的獲勝組合總數(shù),正對角線上的獲勝組合總數(shù)為6+(5+4+3+2+1)*2=36 (4)計算反對角線方向的獲勝組合總數(shù),反對角線上的獲勝組合總數(shù)為6+(5+4+3+2+1)*2=36,這樣所有的獲勝組合數(shù)為:60+60+36+36=192 二、建立和使用獲勝表 我們已經(jīng)計算出了一個10*10的五子棋盤會有192種獲勝方式,這樣我們可以利用數(shù)組建立獲勝表,獲勝表的主要作用是:1,判斷當前的獲勝方式是否有效;2,判斷當前的獲勝方式中到底有多少子落入該獲勝組合中。詳細的使用您將在后面的程序中可以看出。 三,分數(shù)的設定 在游戲中為了讓計算機能夠決定下一步最佳的走法,必須先計算出計算機下到棋盤上任一空格的分數(shù),而其中最高分數(shù)便是計算機下一步的最佳走法?! ≡恚何覀兣卸ó斍坝懻摰目崭衽c當前討論的點有幾種獲勝的方式,有幾種該空格就加幾分。這種原理初聽起來似乎是無法入手,沒關系,當您了解我們后面的程序后您就會明白這種決策原理了?! ∵@種決策有一些缺陷,因為如果只根據(jù)這個模型設計,就有可能出現(xiàn)電腦或玩家有三個子連成一線的時候,計算機卻判斷不出,它認為其他某些空格是當前的獲勝的最佳位置而不去攻擊或防守。沒關系我們完全可以通過一個加強算法來改變當前的分值情況,也就是說當電腦或玩家有三個子或四個子連成一線時,我們通過加強算法將當前與三個子或四個子有關的空格的分值提高,從而可以彌補這一缺憾?! ∷?、攻擊與防守 以上的方式,事實上計算機只是計算出了最佳的攻擊位置,為了防守我們還應計算當前玩家的最佳的攻擊位置。這樣有什么用呢?道理很簡單,如果玩家最佳攻擊位置的分數(shù)大于計算機最佳攻擊位置上的分數(shù),那么計算機就將下一步的棋子擺在玩家的最佳攻擊位上以阻止玩家的進攻,否則計算機便將棋子下在自己的最佳攻擊位置上進行攻擊。 事實上,這個AI構想是很強大的如果你不是很厲害的五子棋高手的話,可能很快會被計算機打敗。我在聯(lián)眾上可是中級棋手啊,跟這種構想打的時候勝率也不是很高。使用vb.net編寫五子棋 一、編寫前的準備: 1、用計算機的思想描述整個下棋的過程 考慮步驟: ?。?)為了簡便我們可以先讓電腦先走第一步棋,電腦每走一步就會封掉許多玩家的獲勝可能情況?! 。?)當玩家走棋的時候我們首先應該考慮玩家走棋的合法性。 ?。?)如果合法,那么玩家也會封掉許多電腦的獲勝的可能情況?! 。?)電腦的思考路徑:首先判斷當前玩家和電腦的所有獲勝組合是否需要進行加強賦值,
是進行加強賦值,否則進行普通的賦值?! 。?)比較當前玩家和電腦誰的分值最大。將分值最大的點作為電腦的下一步走法?! ?、利用vb.net窗體和圖形工具建立五子棋的棋盤界面 (1)添加一個picturebox控件 作用:使用picturebox控件繪制棋子和棋盤 ?。?)添加一個label控件 作用:顯示當前的獲勝標志,也就是當某一方獲勝或和棋時顯示此標簽。 ?。?)添加一個mainmenu控件 作用:控制游戲的開始或結束 ?。?)添加一個mediaplay組件 作用:使程序可以播放音樂?! ?、設置整體框價 我們采取10*10的棋盤,為主要的平臺。利用數(shù)組定義整個棋盤桌面,利用數(shù)組定義獲勝組合以及獲勝標志等?! 《暶魅謹?shù)組和變量 定義虛擬桌面:Dimtable(9,9)AsInteger 定義當前玩家桌面空格的分數(shù):Dimpscore(9,9)AsInteger 定義當前電腦桌面空格的分數(shù):Dimcscore(9,9)AsInteger 定義玩家的獲勝組合:Dimpwin(9,9,191)AsBoolean 定義電腦的獲勝組合:Dimcwin(9,9,191)AsBoolean 定義玩家的獲勝組合標志:Dimpflag(191)AsBoolean 定義電腦的獲勝組合標志:
Dimcflag(191)AsBoolean 定義游戲有效標志:DimtheplayflagAsBoolean三、初始化游戲'*****************************************************************************
'**模塊名稱:initplayenvironment
'**
'**描述:此函數(shù)主要功能如下:
'**1.設置背景音樂。
'**2.設置游戲狀態(tài)有效。
'**3.初始化游戲狀態(tài)標簽。
'**4.直接指定電腦的第一步走法。
'**5.初始化基本得分桌面。
'**6.電腦和玩家獲勝標志初始化。
'**7.初始化所有獲勝組合。
'**8.重新設定玩家的獲勝標志。
'**
'*****************************************************************************
Subinitplayenvironment()
player.FileName=.\music\zhyu01.mid
player.Play()
theplayflag=True
'游戲有效
Label1.Visible=False
'游戲狀態(tài)標簽不顯示
PictureBox1.Refresh()
'清空picturebox1的內(nèi)容
yuandian(130,130)
'調(diào)用繪圖函數(shù)繪制當前電腦先走的位置
Dimi,j,m,nAsInteger
Fori=0To9
Forj=0To9
table(i,j)=0
Next
Next
'桌面初始化
Fori=0To191
pflag(i)=True
cflag(i)=True
Next
'獲勝標志初始化
table(4,4)=1
'由于我們設定電腦先手,并下了4,4位所以將其值設為1
'''********初始化獲勝組合********
n=0
Fori=0To9
Forj=0To5
Form=0To4
pwin(j+m,i,n)=True
cwin(j+m,i,n)=True
Next
n=n+1
Next
Next
Fori=0To9
Forj=0To5
Form=0To4
pwin(i,j+m,n)=True
cwin(i,j+m,n)=True
Next
n=n+1
Next
Next
Fori=0To5
Forj=0To5
Form=0To4
pwin(j+m,i+m,n)=True
cwin(j+m,i+m,n)=True
Next
n=n+1
Next
Next
Fori=0To5
Forj=9To4Step-1
Form=0To4
pwin(j-m,i+m,n)=True
cwin(j-m,i+m,n)=True
Next
n=n+1
Next
Next
'''********初始化獲勝組合結束********
Fori=0To191
Ifpwin(4,4,i)=TrueThen
pflag(i)=False
EndIf
Next
'由于電腦已下了4,4位所以我們需要重新設定玩家的獲勝標志
EndSub
四,處理鼠標事件'*****************************************************************************
'**模塊名稱:themousedown
'**
'**描述:此函數(shù)主要實行以下功能:
'**1.判定當前游戲標志是否有效。
'**2.將實際坐標轉化成虛擬坐標。
'**3.繪制玩家的棋子。
'**4.執(zhí)行檢查獲勝函數(shù)。
'**5.執(zhí)行電腦算法函數(shù)。
'**
'*****************************************************************************
Subthemousedown(ByValxAsInteger,ByValyAsInteger)
Iftheplayflag=FalseThen
ExitSub
EndIf
'檢查游戲狀態(tài)是否有效
Dimi,jAsInteger
Dimzhx,zhyAsInteger
zhx=Int((x-10)/30)
zhy=Int((y-10)/30)
Fori=0To9
Forj=0To9
Iftable(zhx,zhy)>0Then
ExitSub
EndIf
Next
Next
'檢查當前鼠標點擊的格子是否有效
DimmycolorAsColor
DimgAsSystem.Drawing.Graphics
g=PictureBox1.CreateGraphics
mycolor=Color.White
Dimbrush1AsSystem.Drawing.Brush=NewSolidBrush(mycolor)
g.FillEllipse(brush1,zhx*30+10,zhy*30+10,30,30)
'繪制玩家的棋子
table(zhx,zhy)=2
Fori=0To191
Ifcwin(zhx,zhy,i)=TrueThen
cflag(i)=False
EndIf
Next
'重設電腦的獲勝標志
checkwin()
'檢查當前玩家是否獲勝
diannao()
'調(diào)用電腦算法
EndSub 五、獲勝檢查算法。'*****************************************************************************
'**模塊名稱:checkwin
'**
'**描述:此模塊執(zhí)行以下功能:
'**1.檢查是否和棋。
'**2.檢查電腦是否獲勝。
'**3.檢查玩家是否獲勝。
'**
'*****************************************************************************
Subcheckwin()
Dimi,j,k,m,nAsInteger
DimcaAsInteger
DimpaAsInteger
DimcnormalAsInteger=0
Fori=0To191
Ifcflag(i)=FalseThen
cnormal=cnormal+1
EndIf
Next
Ifcnormal=190Then
Label1.Visible=True
Label1.Text=和棋,請重新開始!
PictureBox1.Refresh()
theplayflag=False
ExitSub
EndIf
'設定和棋規(guī)則
Fori=0To191
Ifcflag(i)=TrueThen
ca=0
Forj=0To9
Fork=0To9
Iftable(j,k)=1Then
Ifcwin(j,k,i)=TrueThen
ca=ca+1
EndIf
EndIf
Next
Next
Ifca=5Then
Label1.Visible=True
Label1.Text=電腦獲勝,請重新開始
PictureBox1.Refresh()
theplayflag=False
ExitSub
EndIf
EndIf
Next
'檢查電腦是否獲勝
Fori=0To191
Ifpflag(i)=TrueThen
pa=0
Forj=0To9
Fork=0To9
Iftable(j,k)=2Then
Ifpwin(j,k,i)=TrueThen
pa=pa+1
EndIf
EndIf
Next
Next
Ifpa=5Then
Label1.Visible=True
Label1.Text=玩家獲勝,請重新開始
PictureBox1.Refresh()
theplayflag=False
ExitSub
EndIf
EndIf
Next
'檢查玩家是否獲勝
EndSub 六、電腦算法'*****************************************************************************
'**模塊名稱:diannao
'**
'**描述:此程序主要執(zhí)行以下功能:
'**1.初始化賦值系統(tǒng)。
'**2.賦值加強算法。
'**3.計算電腦和玩家的最佳攻擊位。
'**4.比較電腦和玩家的最佳攻擊位并決定電腦的最佳策略。
'**5.執(zhí)行檢查獲勝函數(shù)。
'**
'*****************************************************************************Subdiannao()
Dimi,j,k,m,nAsInteger
DimdcAsInteger
DimcabAsInteger
DimpabAsInteger
Fori=0To9
Forj=0To9
pscore(i,j)=0
cscore(i,j)=0
Next
Next
'初始化賦值數(shù)組
'''********電腦加強算法********
Fori=0To191
Ifcflag(i)=TrueThen
cab=0
Forj=0To9
Fork=0To9
Iftable(j,k)=1Then
Ifcwin(j,k,i)=TrueThen
cab=cab+1
EndIf
EndIf
Next
Next
SelectCasecab
Case3
Form=0To9
Forn=0To9
Iftable(m,n)=0Then
Ifcwin(m,n,i)=TrueThen
cscore(m,n)=cscore(m,n)+5
EndIf
EndIf
Next
Next
Case4
Form=0To9
Forn=0To9
Iftable(m,n)=0Then
Ifcwin(m,n,i)=TrueThen
yuandian(m*30+10,n*30+10)
table(m,n)=1
Fordc=0To191
Ifpwin(m,n,dc)=TrueThen
pflag(dc)=False
checkwin()
ExitSub
EndIf
Next
EndIf
EndIf
Next
Next
EndSelect
EndIf
Next
Fori=0To191
Ifpflag(i)=TrueThen
pab=0
Forj=0To9
Fork=0To9
Iftable(j,k)=2Then
Ifpwin(j,k,i)=TrueThen
pab=pab+1
EndIf
EndIf
Next
Next
SelectCasepab
Case3
Form=0To9
Forn=0To9
Iftable(m,n)=0Then
Ifpwin(m,n,i)=TrueThen
pscore(m,n)=pscore(m,n)+30
EndIf
EndIf
Next
Next
Case4
Form=0To9
Forn=0To9
Iftable(m,n)=0Then
Ifpwin(m,n,i)=TrueThen
yuandian(m*30+10,n*30+10)
table(m,n)=1
Fordc=0To191
Ifpwin(m,n,dc)=TrueThen
pflag(dc)=False
checkwin()
ExitSub
EndIf
Next
EndIf
EndIf
Next
Next
EndSelect
EndIf
Next
'''********電腦加強算法結束********'********賦值系統(tǒng)********
Fori=0To191
Ifcflag(i)=TrueThen
Forj=0To9
Fork=0To9
Iftable(j,k)=0Then
Ifcwin(j,k,i)=TrueThen
Form=0To9
Forn=0To9
Iftable(m,n)=1Then
Ifcwin(m,n,i)=TrueThen
cscore(j,k)=cscore(j,k)+1
EndIf
EndIf
Next
Next
EndIf
EndIf
Next
Next
EndIf
Next
Fori=0To191
Ifpflag(i)=TrueThen
Forj=0To9
Fork=0To9
Iftable(j,k)=0Then
Ifpwin(j,k,i)=TrueThen
Form=0To9
Forn=0To9
Iftable(m,n)=2Then
Ifpwin(m,n,i)=TrueThen
pscore(j,k)=pscore(j,k)+1
EndIf
EndIf
Next
Next
EndIf
EndIf
Next
Next
EndIf
Next
'''********賦值系統(tǒng)結束********
'''********分值比較算法********
Dima,b,c,dAsInteger
DimcsAsInteger=0
DimpsAsInteger=0
Fori=0To9
Forj=0To9
Ifcscore(i,j)>csThen
cs=cscore(i,j)
a=i
b=j
EndIf
Next
Next
Fori=0To9
Forj=0To9
Ifpscore(i,j)>psThen
ps=pscore(i,j)
c=i
d=j
EndIf
Next
Next
Ifcs>psThen
yuandian(a*30+10,b*30+10)
table(a,b)=1
Fori=0To191
Ifpwin(a,b,i)=TrueThen
pflag(i)=False
EndIf
Next
Else
yuandian(c*30+10,d*30+10)
table(c,d)=1
Fori=0To191
Ifpwin(c,d,i)=TrueThen
pflag(i)=False
EndIf
Next
EndIf
'''********分值比較算法結束********
checkwin()
EndSub 七、繪制棋子'*****************************************************************************
'**模塊名稱:yuandian
'**
'**描述:此函數(shù)主要進行電腦棋子的繪制。
'**
'*****************************************************************************Subyuandian(ByValxAsInteger,ByValyAsInteger)
DimmycolorAsColor
DimgAsSystem.Drawing.Graphics
g=PictureBox1.CreateGraphics
Dimzhx,zhyAsInteger
zhx=Int((x-10)/30)
zhy=Int((y-10)/30)
mycolor=Color.Black
Dimbrush1AsSystem.Drawing.Brush=NewSolidBrush(mycolor)
g.FillEllipse(brush1,zhx*30+10,zhy*30+10,30,30)
EndSub