python實現(xiàn)簡單五子棋小游戲
用python實現(xiàn)五子棋簡單人機模式的練習(xí)過程,供大家參考,具體內(nèi)容如下
最近在初學(xué)python,今天就用自己的一些粗淺理解,來記錄一下這幾天的python簡單人機五子棋游戲的練習(xí),下面是實現(xiàn)過程的理解(是在cmd中運行的):
主要流程:*重點內(nèi)容*
- 首先是模塊及類的劃分
- 棋子類和棋盤類的方法
- 對策略類里的功能進行細分,調(diào)用棋子類和棋盤類
- 寫出判斷輸贏的方法
- 用main函數(shù)進行整個游戲進度的控制
模塊及類的劃分
類的劃分涉及到了面向?qū)ο蟮膬?nèi)容,根據(jù)五子棋游戲的設(shè)定,人和機器依次在一個棋盤里下棋,一方五子連線為贏,初步分為棋子類、棋盤類和策略類,每個類單獨放一個模塊,加上main模塊一共四個模塊。
- 棋子類包含棋子的坐標和棋子顏色(陣營),及相關(guān)get、set方法
- 棋盤類包含了棋盤的大小和棋盤的狀態(tài) ,及相關(guān)get、set方法
- 棋盤類的功能:接收要放入的棋子,清空棋盤,打?。@示)棋盤,給出對應(yīng)位置的狀態(tài)
- 策略類:一個策略類對應(yīng)一個棋盤類,在構(gòu)造器里導(dǎo)入一個棋盤類
- 策略類的功能:人把棋子放入棋盤、機器把棋子放入棋盤、判斷棋局的輸贏
棋子類和棋盤類
棋子類比較簡單,在棋子的角度,只要接收位置和顏色(陣營),傳出位置和顏色(陣營)即可,其中位置用元組打包傳遞
class Chessman(object): ? ? #初始化 ? ? def __init__(self): ? ? ? ? pass ? ? def set_pos(self,pos): ? ? ? ? self.pos = pos ? ? def get_pos(self): ? ? ? ? return self.pos ? ? def set_color(self,color): ? ? ? ? self.color = color ? ? def get_color(self): ? ? ? ? return self.color
棋盤類需要用到棋子類,在這之前,先要進行棋盤的設(shè)定
在這里棋盤是用列表來構(gòu)建,分為兩層,實現(xiàn)x,y的位置,棋盤大小設(shè)為類屬性
#類屬性 ? ? board_size =15 #初始化棋盤 ? ? def __init__(self): ? ? ? ? self.__board = [[0 for i in range(0,Chessboard.board_size+1)] for j in range(0,Chessboard.board_size+1)]
清空棋盤類似
#清空棋盤,‘+'為棋盤的樣子 def init_board(self): ? ? #忽略第0行 ? ? for i in range(1,Chessboard.board_size+1): ? ? ? ? for j in range(1,Chessboard.board_size+1): ? ? ? ? ? ? self.__board[i][j] = '+'
打印也差不多,注意在坐標軸旁放上序列號,這里縱坐標為1-15,橫坐標為a-o
# 打印棋盤 ? ? def print_board(self): ? ? ? ? #打印列號 ? ? ? ? print(' ?', end='') ? ? ? ? for i in range(1,Chessboard.board_size+1): ? ? ? ? ? ? c = chr(ord('a') + i-1) # ord 字母轉(zhuǎn)ASCLL碼 ? ? ? ? ? ? print(c,end='') ? ? ? ? print() ? ? ? ? #棋盤 ? ? ? ? for i in range(1,Chessboard.board_size+1): ? ? ? ? ? ? if 1<= i <=9: ? ? ? ? ? ? ? ? print(' ', end='') ? ? ? ? ? ? print(i, end='') ? ? ? ? ? ? for j in range(1,Chessboard.board_size+1): ? ? ? ? ? ? ? ? print(self.__board[i][j], end='') ? ? ? ? ? ? print()
效果為如下
接下來是棋子的放入:
這個可分為兩個方法,一個根據(jù)傳入的位置放置傳入的顏色;另一個接收一個棋子類的實例對象,獲取該實例的位置和顏色,調(diào)用第一個方法并傳入數(shù)值,一定要注意在傳參的時候驗證
#寫入對應(yīng)位置的顏色 ? ? def set_chess(self,pos, color): ? ? ? ? if not isinstance(pos,tuple): ? ? ? ? ? ? raise RuntimeError('第一個參數(shù)必須為元組') ? ? ? ? if pos[0] <= 0 or pos[0] > Chessboard.board_size: ? ? ? ? ? ? raise RuntimeError('行下標越界') ? ? ? ? if pos[1] <=0 or pos[1] > Chessboard.board_size: ? ? ? ? ? ? raise RuntimeError('縱下標越界') ? ? ? ? self.__board[pos[0]][pos[1]] = color ? ? ? ? ? ? #把棋子對象擺放到棋盤上 ? ? ? ? def set_chessman(self,chessman): ? ? ? ? if not isinstance(chessman, Chessman): ? ? ? ? ? ? raise RuntimeError('類型不對,第一個參數(shù)應(yīng)為ChessMan對象') ? ? ? ? pos = chessman.get_pos() ? ? ? ? color = chessman.get_color() ? ? ? ? self.set_chess(pos,color)
接下來的根據(jù)棋盤位置獲取棋子顏色的方法主要是為了策略類的判定輸贏準備的
#根據(jù)棋盤位置獲取棋子的顏色 ? ? def get_chess(self,pos): ? ? ? ? if pos[0] <= 0 or pos[0] > Chessboard.board_size: ? ? ? ? ? ? raise RuntimeError('行下標越界') ? ? ? ? if pos[1] <=0 or pos[1] > Chessboard.board_size: ? ? ? ? ? ? raise RuntimeError('縱下標越界') ? ? ? ? return self.__board[pos[0]][pos[1]]
策略類
策略類要用到前面兩類,有更多名稱的方法或?qū)傩缘囊?,所以要更仔細一點搞清楚哪個是哪個
首先傳入一個棋盤實例對象
#初始化要把棋盤對象傳入 ? ? def __init__(self,chessboard): ? ? ? ? self.__chessboard = chessboard
人下棋:策略類負責(zé)把人輸入的東西字符串變成x,y坐標,寫入棋子對象
def parse_user_input(self,input,chessman): ? ? ? ? if not isinstance(chessman,Chessman): ? ? ? ? ? ? raise RuntimeError('類型不對,第一個參數(shù)必須為Chessman對象') ? ? ? ? ret = input.split(',') ? ? ? ? value1 = ret[0] ? ? ? ? value2 = ret[1] ? ? ? ? #轉(zhuǎn)換成坐標 ? ? ? ? pos_x = int(value1) ? ? ? ? pos_y = ord(value2) - ord('a') +1 ? ? ? ? chessman.set_pos((pos_x, pos_y)) ? ? ? ? #print(ret)
機器下棋:這里具體策略暫用隨機數(shù)代替了(有空在想,略過略過~)
#電腦下棋的策略 def computer_go(self, chessman): ? ? ? ? if not isinstance(chessman,Chessman): ? ? ? ? ? ? raise RuntimeError('類型不對,第一個參數(shù)必須為Chessman對象') ? ? ? ? while True: ? ? ? ? ? ? # pos_x和pos_y在1~15之間隨機生成一個數(shù) ? ? ? ? ? ? pos_x = math.ceil(random.random()*Chessboard.board_size) ? ? ? ? ? ? pos_y = random.randint(1,15) ? ? ? ? ? ? #判斷是否為空,否則重新生成坐標 ? ? ? ? ? ? if self.__chessboard.get_chess((pos_x,pos_y)) == '+': ? ? ? ? ? ? ? ? print('電腦下棋的位置:%d,%d'%(pos_x,pos_y)) ? ? ? ? ? ? ? ? chessman.set_pos((pos_x,pos_y)) ? ? ? ? ? ? ? ? break
判斷當(dāng)前棋局的勝負:每一方下棋都要判斷一次,因此可根據(jù)當(dāng)前下的一子的范圍來判斷是否在上下左右和兩斜排有連續(xù)五子,如果有則勝利。
斜排主要是x,y的判斷范圍比較難定,其他的差不多。以下是本寶寶絞盡腦汁想到的判斷方法(特別是斜排的),檢查到目前是沒有問題的,或許還有更好的方法:
#判斷勝負 ? ? #當(dāng)擺放一個棋子,判斷是否贏 ? ? def is_won(self,pos,color): ? ? ? ? #垂直方向的范圍 ? ? ? ? start_x = 1 ? ? ? ? end_x = 15 ? ? ? ? if pos[0] -4 >=1: ? ? ? ? ? ? start_x =pos[0] - 4 ? ? ? ? if pos[0] +4 <=15: ? ? ? ? ? ? end_x = pos[0]+4 ? ? ? ? #垂直方向的判斷 ? ? ? ? count = 0 ? ? ? ? for pos_x in range(start_x, end_x+1): ? ? ? ? ? ? if self.__chessboard.get_chess((pos_x, pos[1])) == color: ? ? ? ? ? ? ? ? count +=1 ? ? ? ? ? ? ? ? if count >=5: ? ? ? ? ? ? ? ? ? ? return True ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? # 一旦斷開 統(tǒng)計數(shù)清0 ? ? ? ? ? ? ? ? count = 0 ? ? ? ? #水平方向的范圍 ? ? ? ? ? ? ? ? start_y = 1 ? ? ? ? end_y = 15 ? ? ? ? if pos[1] -4 >=1: ? ? ? ? ? ? start_y =pos[1] - 4 ? ? ? ? if pos[1] +4 <=15: ? ? ? ? ? ? end_y = pos[1]+4 ? ? ? ? #水平方向的判斷 ? ? ? ? count = 0 ? ? ? ? for pos_y in range(start_y, end_y+1): ? ? ? ? ? ? if self.__chessboard.get_chess((pos[0], pos_y)) == color: ? ? ? ? ? ? ? ? count +=1 ? ? ? ? ? ? ? ? if count >=5: ? ? ? ? ? ? ? ? ? ? return True ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? # 一旦斷開 統(tǒng)計數(shù)清0 ? ? ? ? ? ? ? ? count = 0 ? ? ? ? #左上右下方向判斷 ? ? ? ? count = 0 ? ? ? ? s=pos[0] - pos[1] ? ? ? ? start=start_x ? ? ? ? end=end_y+s ? ? ? ? if pos[0]>pos[1]: ? ? ? ? ? ? start=start_y+s ? ? ? ? ? ? end=end_x ? ? ? ? for index in range(start, end+1): ? ? ? ? ? ? if self.__chessboard.get_chess((index, index-s)) == color: ? ? ? ? ? ? ? ? count +=1 ? ? ? ? ? ? ? ? if count >=5: ? ? ? ? ? ? ? ? ? ? return True ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? # 一旦斷開 統(tǒng)計數(shù)清0 ? ? ? ? ? ? ? ? count = 0 ? ? ? ? #左下右上方向判斷 ? ? ? ? count = 0 ? ? ? ? s=pos[0] + pos[1] ? ? ? ? if pos[0]+pos[1]<=16: ? ? ? ? ? ? start=start_x ? ? ? ? ? ? end=s-start_y ? ? ? ? if pos[0]+pos[1]>16: ? ? ? ? ? ? start=s-start_y ? ? ? ? ? ? end=start_x ? ? ? ? if s>=6 and s<=12: ? ? ? ? ? ? for index in range(start, end+1): ? ? ? ? ? ? ? ? if self.__chessboard.get_chess((index, s-index)) == color: ? ? ? ? ? ? ? ? ? ? count +=1 ? ? ? ? ? ? ? ? ? ? if count >=5: ? ? ? ? ? ? ? ? ? ? ? ? return True ? ? ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? ? ? # 一旦斷開 統(tǒng)計數(shù)清0 ? ? ? ? ? ? ? ? ? ? count = 0 ? ? ? ? return False
接下來再用一個判斷勝利方的方法調(diào)用上面的策略
#判斷對象放置后,勝負是否已分 def is_wonman(self,chessman): ? ? ? ? if not isinstance(chessman,Chessman): ? ? ? ? ? ? raise RuntimeError('類型不對,第一個參數(shù)必須為Chessman對象') ? ? ? ? pos = chessman.get_pos() ? ? ? ? color = chessman.get_color() ? ? ? ? #調(diào)用is_won()獲取它的返回值 ? ? ? ? return self.is_won(pos,color)
main模塊
main模塊用來對整個游戲的玩法格局進行控制。
main函數(shù)實現(xiàn)一局的流程,這里用循環(huán)來實現(xiàn)簡單的人機輪流下棋。因為添加了用戶選擇先后的功能,所以代碼暫時被我弄得繁瑣了(捂臉)還可以精簡的,這里就先放這個:
def main(): ? ? chessboard =Chessboard() ? ? chessboard.init_board() ? ? chessboard.print_board() ? ? engine = Engine(chessboard) ? ? count=0 ? ? select = int(input('用戶選擇先后:(先:1,后:2)')) ? ? #先 ? ? while True: ? ? ? ? chessman = Chessman() ? ? ? ? chessman.set_color('x') ? ? ? ? if select==1: ? ? ? ? ? ? i = input('人下棋,請輸入下棋坐標(格式:x,y):') ? ? ? ? ? ? engine.parse_user_input(i, chessman)#轉(zhuǎn)換成坐標 ? ? ? ? else: ? ? ? ? ? ? #電腦下棋 ? ? ? ? ? ? print('電腦下棋:') ? ? ? ? ? ? engine.computer_go(chessman) ? ? ? ? # 把該棋子對象放到棋盤上 ? ? ? ? chessboard.set_chessman(chessman) ? ? ? ? count +=1 ? ? ? ? #打印棋盤 ? ? ? ? chessboard.print_board() ? ? ? ? if engine.is_wonman(chessman): ? ? ? ? ? ? if select==1: ? ? ? ? ? ? ? ? print('人贏了!') ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? print('電腦贏了!') ? ? ? ? ? ? break ? ? ? ? if count == 225: ? ? ? ? ? ? print('平局!') ? ? ? ? ? ? break ? ? ? ? #后 ? ? ? ? ? chessman = Chessman() ? ? ? ? chessman.set_color('o') ? ? ? ? if k==1: ? ? ? ? ? ? #電腦下棋 ? ? ? ? ? ? print('電腦下棋:') ? ? ? ? ? ? #電腦給棋子生成策略(位置) ? ? ? ? ? ? engine.computer_go(chessman) ? ? ? ? else: ? ? ? ? ? ? i = input('人下棋,請輸入下棋坐標(格式:x,y):') ? ? ? ? ? ? engine.parse_user_input(i, chessman)#轉(zhuǎn)換成坐標 ? ? ? ? #下棋 ? ? ? ? chessboard.set_chessman(chessman) ? ? ? ? count +=1 ? ? ? ? chessboard.print_board() ? ? ? ? if engine.is_wonman(chessman): ? ? ? ? ? ? if k==1: ? ? ? ? ? ? ? ? print('電腦贏了!') ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? print('人贏了!') ? ? ? ? ? ? break ? ? ? ? if count == 225: ? ? ? ? ? ? print('平局!') ? ? ? ? ? ? break
主線程作為程序入口操控每個棋局:
if __name__ == '__main__': ? ? while True: ? ? ? ? print('開始一局!') ? ? ? ? #調(diào)用main方法 ? ? ? ? main() ? ? ? ? s=int(input('是否再來一局:(是:1,否:0)')) ? ? ? ? if s!=1: ? ? ? ? ? ? break ? ? print('游戲結(jié)束!') ?
五子棋的簡單人機模式就是綜上所述的了,不過這個代碼中輸入的地方?jīng)]加檢查,所以坐標輸入一定要是數(shù)字加逗號加字母的格式才行,可以加正則表達式進行判斷。放上效果圖:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Selenium獲取登錄Cookies并添加Cookies自動登錄的方法
這篇文章主要介紹了Selenium獲取登錄Cookies并添加Cookies自動登錄的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Python Flask前端自動登錄功能實現(xiàn)詳解
這篇文章主要介紹了Python Flask前端自動登錄功能實現(xiàn),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-10-10python中numpy基礎(chǔ)學(xué)習(xí)及進行數(shù)組和矢量計算
這篇文章主要給大家介紹了python中numpy基礎(chǔ)知識,以及進行數(shù)組和矢量計算的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-02-02python 中的列表生成式、生成器表達式、模塊導(dǎo)入
這篇文章主要介紹了python中的列表生成式、生成器表達式、模塊導(dǎo)入 ,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-06-06Python中實現(xiàn)結(jié)構(gòu)相似的函數(shù)調(diào)用方法
這篇文章主要介紹了Python中實現(xiàn)結(jié)構(gòu)相似的函數(shù)調(diào)用方法,本文講解使用dict和lambda結(jié)合實現(xiàn)結(jié)構(gòu)相似的函數(shù)調(diào)用,給出了不帶參數(shù)和帶參數(shù)的實例,需要的朋友可以參考下2015-03-03python實現(xiàn)提取str字符串/json中多級目錄下的某個值
今天小編就為大家分享一篇python實現(xiàn)提取str字符串/json中多級目錄下的某個值,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02linux上運行python腳本,SyntaxError:?invalid?syntax的解決
這篇文章主要介紹了linux上運行python腳本,SyntaxError:?invalid?syntax的解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12