python實(shí)現(xiàn)簡(jiǎn)單五子棋小游戲
用python實(shí)現(xiàn)五子棋簡(jiǎn)單人機(jī)模式的練習(xí)過(guò)程,供大家參考,具體內(nèi)容如下
最近在初學(xué)python,今天就用自己的一些粗淺理解,來(lái)記錄一下這幾天的python簡(jiǎn)單人機(jī)五子棋游戲的練習(xí),下面是實(shí)現(xiàn)過(guò)程的理解(是在cmd中運(yùn)行的):
主要流程:*重點(diǎn)內(nèi)容*
- 首先是模塊及類的劃分
- 棋子類和棋盤(pán)類的方法
- 對(duì)策略類里的功能進(jìn)行細(xì)分,調(diào)用棋子類和棋盤(pán)類
- 寫(xiě)出判斷輸贏的方法
- 用main函數(shù)進(jìn)行整個(gè)游戲進(jìn)度的控制
模塊及類的劃分
類的劃分涉及到了面向?qū)ο蟮膬?nèi)容,根據(jù)五子棋游戲的設(shè)定,人和機(jī)器依次在一個(gè)棋盤(pán)里下棋,一方五子連線為贏,初步分為棋子類、棋盤(pán)類和策略類,每個(gè)類單獨(dú)放一個(gè)模塊,加上main模塊一共四個(gè)模塊。
- 棋子類包含棋子的坐標(biāo)和棋子顏色(陣營(yíng)),及相關(guān)get、set方法
- 棋盤(pán)類包含了棋盤(pán)的大小和棋盤(pán)的狀態(tài) ,及相關(guān)get、set方法
- 棋盤(pán)類的功能:接收要放入的棋子,清空棋盤(pán),打印(顯示)棋盤(pán),給出對(duì)應(yīng)位置的狀態(tài)
- 策略類:一個(gè)策略類對(duì)應(yīng)一個(gè)棋盤(pán)類,在構(gòu)造器里導(dǎo)入一個(gè)棋盤(pán)類
- 策略類的功能:人把棋子放入棋盤(pán)、機(jī)器把棋子放入棋盤(pán)、判斷棋局的輸贏
棋子類和棋盤(pán)類
棋子類比較簡(jiǎn)單,在棋子的角度,只要接收位置和顏色(陣營(yíng)),傳出位置和顏色(陣營(yíng))即可,其中位置用元組打包傳遞
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
棋盤(pán)類需要用到棋子類,在這之前,先要進(jìn)行棋盤(pán)的設(shè)定
在這里棋盤(pán)是用列表來(lái)構(gòu)建,分為兩層,實(shí)現(xiàn)x,y的位置,棋盤(pán)大小設(shè)為類屬性
#類屬性 ? ? board_size =15 #初始化棋盤(pán) ? ? def __init__(self): ? ? ? ? self.__board = [[0 for i in range(0,Chessboard.board_size+1)] for j in range(0,Chessboard.board_size+1)]
清空棋盤(pán)類似
#清空棋盤(pán),‘+'為棋盤(pán)的樣子 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] = '+'
打印也差不多,注意在坐標(biāo)軸旁放上序列號(hào),這里縱坐標(biāo)為1-15,橫坐標(biāo)為a-o
# 打印棋盤(pán)
? ? def print_board(self):
? ? ? ? #打印列號(hào)
? ? ? ? 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()
? ? ? ? #棋盤(pán)
? ? ? ? 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()效果為如下

接下來(lái)是棋子的放入:
這個(gè)可分為兩個(gè)方法,一個(gè)根據(jù)傳入的位置放置傳入的顏色;另一個(gè)接收一個(gè)棋子類的實(shí)例對(duì)象,獲取該實(shí)例的位置和顏色,調(diào)用第一個(gè)方法并傳入數(shù)值,一定要注意在傳參的時(shí)候驗(yàn)證
#寫(xiě)入對(duì)應(yīng)位置的顏色
? ? def set_chess(self,pos, color):
? ? ? ? if not isinstance(pos,tuple):
? ? ? ? ? ? raise RuntimeError('第一個(gè)參數(shù)必須為元組')
? ? ? ? if pos[0] <= 0 or pos[0] > Chessboard.board_size:
? ? ? ? ? ? raise RuntimeError('行下標(biāo)越界')
? ? ? ? if pos[1] <=0 or pos[1] > Chessboard.board_size:
? ? ? ? ? ? raise RuntimeError('縱下標(biāo)越界')
? ? ? ? self.__board[pos[0]][pos[1]] = color ? ? ? ?
? ? #把棋子對(duì)象擺放到棋盤(pán)上 ? ?
? ? def set_chessman(self,chessman):
? ? ? ? if not isinstance(chessman, Chessman):
? ? ? ? ? ? raise RuntimeError('類型不對(duì),第一個(gè)參數(shù)應(yīng)為ChessMan對(duì)象')
? ? ? ? pos = chessman.get_pos()
? ? ? ? color = chessman.get_color()
? ? ? ? self.set_chess(pos,color)接下來(lái)的根據(jù)棋盤(pán)位置獲取棋子顏色的方法主要是為了策略類的判定輸贏準(zhǔn)備的
#根據(jù)棋盤(pán)位置獲取棋子的顏色
? ? def get_chess(self,pos):
? ? ? ? if pos[0] <= 0 or pos[0] > Chessboard.board_size:
? ? ? ? ? ? raise RuntimeError('行下標(biāo)越界')
? ? ? ? if pos[1] <=0 or pos[1] > Chessboard.board_size:
? ? ? ? ? ? raise RuntimeError('縱下標(biāo)越界')
? ? ? ? return self.__board[pos[0]][pos[1]]策略類
策略類要用到前面兩類,有更多名稱的方法或?qū)傩缘囊?,所以要更仔?xì)一點(diǎn)搞清楚哪個(gè)是哪個(gè)
首先傳入一個(gè)棋盤(pán)實(shí)例對(duì)象
#初始化要把棋盤(pán)對(duì)象傳入 ? ? def __init__(self,chessboard): ? ? ? ? self.__chessboard = chessboard
人下棋:策略類負(fù)責(zé)把人輸入的東西字符串變成x,y坐標(biāo),寫(xiě)入棋子對(duì)象
def parse_user_input(self,input,chessman):
? ? ? ? if not isinstance(chessman,Chessman):
? ? ? ? ? ? raise RuntimeError('類型不對(duì),第一個(gè)參數(shù)必須為Chessman對(duì)象')
? ? ? ? ret = input.split(',')
? ? ? ? value1 = ret[0]
? ? ? ? value2 = ret[1]
? ? ? ? #轉(zhuǎn)換成坐標(biāo)
? ? ? ? pos_x = int(value1)
? ? ? ? pos_y = ord(value2) - ord('a') +1
? ? ? ? chessman.set_pos((pos_x, pos_y))
? ? ? ? #print(ret)機(jī)器下棋:這里具體策略暫用隨機(jī)數(shù)代替了(有空在想,略過(guò)略過(guò)~)
#電腦下棋的策略
def computer_go(self, chessman):
? ? ? ? if not isinstance(chessman,Chessman):
? ? ? ? ? ? raise RuntimeError('類型不對(duì),第一個(gè)參數(shù)必須為Chessman對(duì)象')
? ? ? ? while True:
? ? ? ? ? ? # pos_x和pos_y在1~15之間隨機(jī)生成一個(gè)數(shù)
? ? ? ? ? ? pos_x = math.ceil(random.random()*Chessboard.board_size)
? ? ? ? ? ? pos_y = random.randint(1,15)
? ? ? ? ? ? #判斷是否為空,否則重新生成坐標(biāo)
? ? ? ? ? ? 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)前棋局的勝負(fù):每一方下棋都要判斷一次,因此可根據(jù)當(dāng)前下的一子的范圍來(lái)判斷是否在上下左右和兩斜排有連續(xù)五子,如果有則勝利。
斜排主要是x,y的判斷范圍比較難定,其他的差不多。以下是本寶寶絞盡腦汁想到的判斷方法(特別是斜排的),檢查到目前是沒(méi)有問(wèn)題的,或許還有更好的方法:
#判斷勝負(fù) ? ? #當(dāng)擺放一個(gè)棋子,判斷是否贏 ? ? 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: ? ? ? ? ? ? ? ? # 一旦斷開(kāi) 統(tǒng)計(jì)數(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: ? ? ? ? ? ? ? ? # 一旦斷開(kāi) 統(tǒng)計(jì)數(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: ? ? ? ? ? ? ? ? # 一旦斷開(kāi) 統(tǒng)計(jì)數(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: ? ? ? ? ? ? ? ? ? ? # 一旦斷開(kāi) 統(tǒng)計(jì)數(shù)清0 ? ? ? ? ? ? ? ? ? ? count = 0 ? ? ? ? return False
接下來(lái)再用一個(gè)判斷勝利方的方法調(diào)用上面的策略
#判斷對(duì)象放置后,勝負(fù)是否已分
def is_wonman(self,chessman):
? ? ? ? if not isinstance(chessman,Chessman):
? ? ? ? ? ? raise RuntimeError('類型不對(duì),第一個(gè)參數(shù)必須為Chessman對(duì)象')
? ? ? ? pos = chessman.get_pos()
? ? ? ? color = chessman.get_color()
? ? ? ? #調(diào)用is_won()獲取它的返回值
? ? ? ? return self.is_won(pos,color)main模塊
main模塊用來(lái)對(duì)整個(gè)游戲的玩法格局進(jìn)行控制。
main函數(shù)實(shí)現(xiàn)一局的流程,這里用循環(huán)來(lái)實(shí)現(xiàn)簡(jiǎn)單的人機(jī)輪流下棋。因?yàn)樘砑恿擞脩暨x擇先后的功能,所以代碼暫時(shí)被我弄得繁瑣了(捂臉)還可以精簡(jiǎn)的,這里就先放這個(gè):
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('人下棋,請(qǐng)輸入下棋坐標(biāo)(格式:x,y):')
? ? ? ? ? ? engine.parse_user_input(i, chessman)#轉(zhuǎn)換成坐標(biāo)
? ? ? ? else:
? ? ? ? ? ? #電腦下棋
? ? ? ? ? ? print('電腦下棋:')
? ? ? ? ? ? engine.computer_go(chessman)
? ? ? ? # 把該棋子對(duì)象放到棋盤(pán)上
? ? ? ? chessboard.set_chessman(chessman)
? ? ? ? count +=1
? ? ? ? #打印棋盤(pán)
? ? ? ? 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('人下棋,請(qǐng)輸入下棋坐標(biāo)(格式:x,y):')
? ? ? ? ? ? engine.parse_user_input(i, chessman)#轉(zhuǎn)換成坐標(biāo)
? ? ? ? #下棋
? ? ? ? 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主線程作為程序入口操控每個(gè)棋局:
if __name__ == '__main__':
? ? while True:
? ? ? ? print('開(kāi)始一局!')
? ? ? ? #調(diào)用main方法
? ? ? ? main()
? ? ? ? s=int(input('是否再來(lái)一局:(是:1,否:0)'))
? ? ? ? if s!=1:
? ? ? ? ? ? break
? ? print('游戲結(jié)束!') ?五子棋的簡(jiǎn)單人機(jī)模式就是綜上所述的了,不過(guò)這個(gè)代碼中輸入的地方?jīng)]加檢查,所以坐標(biāo)輸入一定要是數(shù)字加逗號(hào)加字母的格式才行,可以加正則表達(dá)式進(jìn)行判斷。放上效果圖:



以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python簡(jiǎn)潔優(yōu)雅的推導(dǎo)式示例詳解
這篇文章主要給大家介紹了關(guān)于Python簡(jiǎn)潔優(yōu)雅的推導(dǎo)式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
python的pytest框架之命令行參數(shù)詳解(上)
這篇文章主要介紹了python的pytest框架之命令行參數(shù)詳解,pytest是一款強(qiáng)大的python自動(dòng)化測(cè)試工具,可以勝任各種類型或者級(jí)別的軟件測(cè)試工作。pytest提供了豐富的功能,包括assert重寫(xiě),第三方插件,需要的朋友可以參考下2019-06-06
Python結(jié)巴中文分詞工具使用過(guò)程中遇到的問(wèn)題及解決方法
這篇文章主要介紹了Python結(jié)巴中文分詞工具使用過(guò)程中遇到的問(wèn)題及解決方法,較為詳細(xì)的講述了Python結(jié)巴中文分詞工具的下載、安裝、使用方法及容易出現(xiàn)的問(wèn)題與相應(yīng)解決方法,需要的朋友可以參考下2017-04-04
Python實(shí)現(xiàn)簡(jiǎn)單石頭剪刀布小游戲的示例代碼
石頭剪刀布是一種簡(jiǎn)單而又經(jīng)典的游戲,常常用于決定勝負(fù)或者娛樂(lè)消遣,本文將使用Python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的石頭剪刀布游戲,需要的可以參考一下2023-06-06
python3.7將代碼打包成exe程序并添加圖標(biāo)的方法
這篇文章主要介紹了python3.7將代碼打包成exe程序并添加圖標(biāo)的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-10-10
python 通過(guò) socket 發(fā)送文件的實(shí)例代碼
這篇文章主要介紹了python 通過(guò) socket 發(fā)送文件的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-08-08
使用Pycharm創(chuàng)建一個(gè)Django項(xiàng)目的超詳細(xì)圖文教程
Django是比較經(jīng)典的Python web框架,最近剛好在項(xiàng)目中用到了Django,所以下面這篇文章主要給大家介紹了關(guān)于使用Pycharm創(chuàng)建一個(gè)Django項(xiàng)目的超詳細(xì)圖文教程,文中介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08

