上回講過:
python+pygame實現五子棋人機對戰之一
python+pygame實現五子棋人機對戰之二
界面已經有了,并且可以支持鼠標操作選擇菜單和人機對戰開始下棋了,那電腦是如何應手落子呢?以下內容是通用的類,全部放在utils.py中
四、
最常見的基本棋型大體有以下幾種:連五,活四,沖四,活三,眠三,活二,眠二了,下面簡要講解一下:
4.1 連五:五顆同色棋子連在一起
4.2 活四:由4枚同色棋子形成的兩端沒有對方棋子的四枚棋子
4.3 沖四一(連四):由4枚同色棋子形成的一端有對方棋子的四枚棋子
4.4 沖四二(跳四):由4枚同色棋子形成的中間沒有對方棋子的四枚棋子。
4.5 眠四:由4枚同色棋子形成的兩端有對方棋子的4枚棋子。? 不能成五的四連。
相對比活四來說,沖四的威脅性就小了很多,此時,防守方只要跟著防守在那個唯一的連五點上,沖四就沒法形成連五。
4.6 活三一(連三):由3枚同色棋子形成連三、跳三。? 再走一著可以形成活四的三。 兩端都是威脅的活三。簡稱“連三”。
4.7 活三二(跳三):由3枚同色棋子形成的中間沒有對方棋子的三枚棋子。中間夾有一個威脅的活三。簡稱“跳三”。
4.8 眠三:由3枚同色棋子形成的兩端有對方棋子的3枚棋子。? 即再走一著可以形成沖四的三。眠三的形狀是很豐富的。眠三的棋型與活三的棋型相比,危險系數下降不少,因為眠三棋型即使不去防守,下一手它也只能形成沖四,而對于單純的沖四棋型,我們是可以防守住的。
活三可以形成眠三,但也能夠形成活四。眠三只能夠形成沖四。
4.9 活二 :由2枚同色棋子形成的連二(由2枚同色棋子連在一起形成的兩頭沒有對方棋子的2枚棋子。)、跳二(由2枚同色棋子形成的中間沒有對方棋子的2枚棋子。)、大跳二(中間有兩個空白位置的跳二)。
4.10 眠二 :由2枚同色棋子形成的兩端有對方棋子的2枚棋子。是能夠形成眠三的二。
? ? ?
??????
???
對于棋盤上每一個交叉點,會有8個方向連成五子的可能性,那么我們就利用算法算出所有的可能性,并根據它成五的概率給它打分,這樣,得分最高的就是最好的落子點。
如何去實現呢?首先我們在8個方向上將其抽象成坐標的加減,例如水平向右,那么x+1,y不變,向右上,則x+1,y+1 .按正下方開始,逆時針8個方向就形成下面的數據結構:
directions = [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]
?獲取當前坐標的各個方向上棋子屬性,返回1代表白棋,返回2代表黑棋,返回0代表沒有棋,返回5表示在棋盤外。
from params import Paramsrows = int(Params.get('ROWS'))
blocksize = int(Params.get('blockSize'))
width = int(Params.get('WIDTH'))
height = int(Params.get('HEIGHT'))# 獲取當前坐標的各個方向上棋子屬性,返回1代表白棋,返回2代表黑棋,返回0代表沒有棋,返回5表示在棋盤外
def getpointpiece(_mapchess,pos, src, offset):# 8個方向directions = [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]x1, y1 = posx1 = x1 + directions[src - 1][0] * offset * blocksizey1 = y1 + directions[src - 1][1] * offset * blocksizeif x1 > 588 or y1 > 588 or x1 < 28 or y1 < 28:return 5else:return _mapchess[str(x1) + ',' + str(y1)]
再加上剛才分析的五子棋的基本棋型,可以設計出一個打分算法:
from params import Paramsrows = int(Params.get('ROWS'))
blocksize = int(Params.get('blockSize'))
width = int(Params.get('WIDTH'))
height = int(Params.get('HEIGHT'))# 判斷每個點的value,用來排序該點下棋的可行性
def pointvalue(_mapchess, pos, flag1, flag2):value = 0 #加權值for i in range(1, 9): #8個方向# 11111 連五if getpointpiece(_mapchess,pos, i, 1) == flag1 and \getpointpiece(_mapchess,pos, i, 2) == flag1 and \getpointpiece(_mapchess,pos, i, 3) == flag1 and \getpointpiece(_mapchess,pos, i, 4) == flag1 and \getpointpiece(_mapchess,pos, i, 5) == flag1:value += 1000000# *1111_ 活四if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == flag1 and \getpointpiece(_mapchess, pos, i, 3) == flag1 and \getpointpiece(_mapchess, pos, i, 4) == flag1 and \getpointpiece(_mapchess, pos, i, 5) == 0:value += 50000# *11112 沖四1,沖四指加一個點就是連五,比活四威力小得多if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == flag1 and \getpointpiece(_mapchess, pos, i, 3) == flag1 and \getpointpiece(_mapchess, pos, i, 4) == flag1 and \getpointpiece(_mapchess, pos, i, 5) == flag2:value += 30000# 1*111 沖四2if getpointpiece(_mapchess, pos, i, -1) == flag1 and \getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == flag1 and \getpointpiece(_mapchess, pos, i, 3) == flag1:value += 30000# 11*11 沖四3if getpointpiece(_mapchess, pos, i, -2) == flag1 and \getpointpiece(_mapchess, pos, i, -1) == flag1 and \getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == flag1:value += 30000# *111_ 活三1,活三可以形成活四的三if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == flag1 and \getpointpiece(_mapchess, pos, i, 3) == flag1 and \getpointpiece(_mapchess, pos, i, 4) == 0:value += 20000# *1_11_ 活三2if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == 0 and \getpointpiece(_mapchess, pos, i, 3) == flag1 and \getpointpiece(_mapchess, pos, i, 4) == flag1 and \getpointpiece(_mapchess, pos, i, 5) == 0:value += 20000# *1112 眠三1 眠三是只能形成沖四的三if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == flag1 and \getpointpiece(_mapchess, pos, i, 3) == flag1 and \getpointpiece(_mapchess, pos, i, 4) == flag2:value += 15000# _1_112 眠三2if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == 0 and \getpointpiece(_mapchess, pos, i, 3) == flag1 and \getpointpiece(_mapchess, pos, i, 4) == flag1 and \getpointpiece(_mapchess, pos, i, 5) == flag2:value += 15000# _11_12 眠三3if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == flag1 and \getpointpiece(_mapchess, pos, i, 3) == 0 and \getpointpiece(_mapchess, pos, i, 4) == flag1 and \getpointpiece(_mapchess, pos, i, 5) == flag2:value += 15000# 1__11 眠三4if getpointpiece(_mapchess, pos, i, -1) == flag1 and \getpointpiece(_mapchess, pos, i, 1) == 0 and \getpointpiece(_mapchess, pos, i, 2) == flag1 and \getpointpiece(_mapchess, pos, i, 3) == flag1:value += 15000# 1_1_1 眠三5if getpointpiece(_mapchess, pos, i, -1) == flag1 and \getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == 0 and \getpointpiece(_mapchess, pos, i, 3) == flag1:value += 15000# 2_111_2 眠三6if getpointpiece(_mapchess, pos, i, -1) == flag2 and \getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == flag1 and \getpointpiece(_mapchess, pos, i, 3) == flag1 and \getpointpiece(_mapchess, pos, i, 4) == 0 and \getpointpiece(_mapchess, pos, i, 5) == flag2:value += 15000# __11__ 活二1 活二能夠形成活三的二if getpointpiece(_mapchess, pos, i, -1) == 0 and \getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == flag1 and \getpointpiece(_mapchess, pos, i, 3) == 0 and \getpointpiece(_mapchess, pos, i, 4) == 0:value += 10000# _1_1_ 活二2if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == 0 and \getpointpiece(_mapchess, pos, i, 3) == flag1 and \getpointpiece(_mapchess, pos, i, 4) == 0:value += 10000# 211__ 眠二1 ,能夠形成眠三的二if getpointpiece(_mapchess, pos, i, -1) == flag2 and \getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == flag1 and \getpointpiece(_mapchess, pos, i, 3) == 0 and \getpointpiece(_mapchess, pos, i, 4) == 0 and \getpointpiece(_mapchess, pos, i, 5) == 0:value += 1000#21_1__ 眠二2if getpointpiece(_mapchess, pos, i, -1) == flag2 and \getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == 0 and \getpointpiece(_mapchess, pos, i, 3) == flag1 and \getpointpiece(_mapchess, pos, i, 4) == 0 and \getpointpiece(_mapchess, pos, i, 5) == 0:value += 1000#21__1_ 眠二3if getpointpiece(_mapchess, pos, i, -1) == flag2 and \getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == 0 and \getpointpiece(_mapchess, pos, i, 3) == 0 and \getpointpiece(_mapchess, pos, i, 4) == flag1 and \getpointpiece(_mapchess, pos, i, 5) == 0:value += 1000#*1___1 眠二4if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == 0 and \getpointpiece(_mapchess, pos, i, 3) == 0 and \getpointpiece(_mapchess, pos, i, 4) == 0 and \getpointpiece(_mapchess, pos, i, 5) == flag1:value += 1000# *1__if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == 0 and \getpointpiece(_mapchess, pos, i, 3) == 0:value += 30# *1_if getpointpiece(_mapchess, pos, i, 1) == flag1 and \getpointpiece(_mapchess, pos, i, 2) == 0:value += 20# *1if getpointpiece(_mapchess, pos, i, 1) == flag1:value += 10return value# 獲取當前坐標的各個方向上棋子屬性,返回1代表白棋,返回2代表黑棋,返回0代表沒有棋,返回5表示在棋盤外
def getpointpiece(_mapchess,pos, src, offset):# 8個方向directions = [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]x1, y1 = posx1 = x1 + directions[src - 1][0] * offset * blocksizey1 = y1 + directions[src - 1][1] * offset * blocksizeif x1 > 588 or y1 > 588 or x1 < 28 or y1 < 28:return 5else:return _mapchess[str(x1) + ',' + str(y1)]
這樣就可以實現:當人下了棋后,電腦通過這個算法找出最有利的落子點,然后就在那里下棋。
注:本程序只是提供一個思路而已,并不是最優解。代碼中value值可以自行修改,算法可以自己再設計,例如可以假如雙活三之類的必須防御的應手。
如何判斷勝負呢?待續。。。
python+pygame實現五子棋人機對戰之四