一、簡介
使用python實現控制檯版的五子棋遊戲;
環境:Windows系統+python3.8.0
遊戲規則:
1.分兩位棋手對戰,默認*棋手先下;當按照提示輸入座標(A1),並按回車鍵<Enter>即可在棋盤上顯示下的棋(*);
2.自動切換到o棋手下棋,當按照提示輸入座標(C1),並按回車鍵<Enter>即可在棋盤上顯示下的棋(o);
3.輪流切換棋手下棋,當那方先形成5子連線者獲勝(橫、豎、斜、反斜四個方向都可以)。
遊戲運行界面如下(如果運行後,中文部分顯示亂碼,可右鍵定位到options--Text,修改“Locale”爲“zh_CN”、“Character set”爲“GBK”):
二、實現過程
- 新建文件settings.py,用來定義一些必須的基本屬性和初始值:
class Settings(): def __init__(self): """初始化的遊戲配置""" # 棋盤格數 self.number = 10 # 判斷遊戲是否結束(默認開始) self.game_active = True # 判斷哪方下棋 self.chess_player = 1 # 開始校驗輸贏(兩邊合計9,因爲已經有一邊5步) self.win_number = 0
- 新建文件checkerboard.py,主要是利用二維列表(數組)存放棋盤數據,棋子位置都用“-”表示;
class Checkerboard(): def __init__(self, ck_settings): self.number = ck_settings.number def draw(self): # 繪製棋盤 checkerboard = [] for i in range(self.number): checkerboard.append([]) for j in range(self.number): checkerboard[i].append('-') return checkerboard
- 新建文件“game_functions.py”,存放跟遊戲有關的所有業務邏輯函數:
def printed_board(checkerboard): """打印棋盤(黃底黑色字體)""" # 設置字體和背景色格式:\033[顯示方式;前景色;背景色m;而後面的\033[0m用來關閉屬性,不加會影響後面 print('\033[1;41m--------------簡易五子棋遊戲(控制檯版)---------------\033[0m') print('\033[1;30;43m-------------------------------------------------------') print(' 1 2 3 4 5 6 7 8 9 10 ') for i in range(len(checkerboard)): # ord返回字符的ASCII數值,chr再返回字符;end=''設置不換行 print(chr(ord('A') + i) + ' ', end='') for j in range(len(checkerboard[i])): print(checkerboard[i][j] + ' ', end='') print() print('-------------------------------------------------------\033[0m') def update_board(ck_settings, checkerboard, position): """更新棋盤信息""" if ck_settings.chess_player == 1: print('請棋手*輸入棋子座標(例如A1,輸入exit可退出程序):', end='') check_input(ck_settings, checkerboard, '*', position) else: print('請棋手o輸入棋子座標(例如C1,輸入exit可退出程序):', end='') check_input(ck_settings, checkerboard, 'o', position) def check_input(ck_settings, checkerboard, char, position): """校驗輸入數據,正確則把座標打印到棋盤""" inputStr = input() # 獲取輸入數據 if len(inputStr) == 0: # 判斷空情況 print('\033[1;31m***請輸入座標(例如A1)!***\033[0m') elif inputStr == 'exit': # 退出程序 exit() elif not inputStr[1].isdigit(): # 第二位不爲數字情況 print('\033[1;31m***您輸入的座標不正確,請重新輸入(例如A1)!***\033[0m') else: # 獲取棋盤下標 ch = inputStr[0].upper() # 獲取第一個字符並轉換爲大寫 i = ord(ch) - 65 # A的ASCII是65 j = int(inputStr[1:3]) - 1 # 最大允許10,所以必須獲取兩位 # 判斷是否輸入溢出 if (i < 0 or i > 9 or j < 0 or j > 9): print('\033[1;31m***您輸入的座標不正確,請重新輸入(例如A1)!***\033[0m') # 判斷輸入的是否已經有棋子 else: if checkerboard[i][j] == '-': # 累計步數(兩邊合計) ck_settings.win_number += 1 # 未落子則替換棋手符號,並轉換棋手 checkerboard[i][j] = char ck_settings.chess_player *= -1 # 合計9步開始校驗輸贏 if ck_settings.win_number >= 9: check_stats(ck_settings, checkerboard, (i, j), char, position) else: print('\033[1;31m***您輸入的座標已經有其他棋子,請重新輸入(例如A1)!***\033[0m') def check_stats(ck_settings, checkerboard, pos, char, position): """校驗四個方向,是否有了輸贏""" pos_i, pos_j = pos directs = [(1, 0), (0, 1), (1, 1), (1, -1)] # 橫、豎、斜、反斜 四個方向檢查 for direct in directs: line_checkerboard = [] d_i, d_j = direct # 橫排 if d_j == 0: # 橫排成數組 for j in range(ck_settings.number): # 判斷是“*”或“o”才添加 if checkerboard[pos_i][j] == char: line_checkerboard.append(position(pos_i, j)) # print('橫排', line_checkerboard) win_condition(ck_settings, checkerboard, line_checkerboard, d_j, char) elif d_i == 0: # 豎排成數組 for i in range(ck_settings.number): # 判斷是“*”或“o”才添加 if checkerboard[i][pos_j] == char: line_checkerboard.append(position(i, pos_j)) # print('豎排', line_checkerboard) win_condition(ck_settings, checkerboard, line_checkerboard, d_j, char) elif d_i == 1 and d_j == 1: # 斜線成數組 # 左部分 minValue = min(pos_i, pos_j) # 獲取較小值 for i in range(minValue): # 判斷是“*”或“o”才添加 if checkerboard[pos_i - minValue + i][pos_j - minValue + i] == char: line_checkerboard.append(position(pos_i - minValue + i, pos_j - minValue + i)) # 右部分 maxValue = max(pos_i, pos_j) maxValue = ck_settings.number - maxValue # 獲取可疊加的最大數值 for i in range(maxValue): # 判斷是“*”或“o”才添加 if checkerboard[pos_i + i][pos_j + i] == char: line_checkerboard.append(position(pos_i + i, pos_j + i)) # print('斜線', line_checkerboard) win_condition(ck_settings, checkerboard, line_checkerboard, d_j, char) else: # 反斜線成數組 # 左部分 minValue = min(ck_settings.number - pos_i, pos_j) # 獲取較小值 for i in range(minValue): # 判斷是“*”或“o”才添加 if checkerboard[pos_i + minValue - 1 - i][pos_j - minValue + i] == char: line_checkerboard.append(position(pos_i + minValue - 1 - i, pos_j - minValue + i)) # 右部分 maxValue = min(pos_i, ck_settings.number - pos_j) # 獲取可疊加的最大數值 for i in range(maxValue): # 判斷是“*”或“o”才添加 if checkerboard[pos_i - i][pos_j + i] == char: line_checkerboard.append(position(pos_i - i, pos_j + i)) # print('反斜線', line_checkerboard) win_condition(ck_settings, checkerboard, line_checkerboard, d_j, char) def win_condition(ck_settings, checkerboard, line_checkerboard, d_j, char): """判斷是否連續5個一樣""" if len(line_checkerboard) >= 5: for i, item in enumerate(line_checkerboard): index = i + 4 if index < len(line_checkerboard): # 橫排情況 if d_j == 0: j1 = item.y j2 = line_checkerboard[index].y if (j2 - j1) == 4: printed_board(checkerboard) print('\033[1;32m' + char + '選手獲勝!\033[0m') ck_settings.game_active = False break # 豎排、斜、反斜情況 else: i1 = item.x i2 = line_checkerboard[index].x # 取絕對值,因爲反斜線是負數 if abs(i2 - i1) == 4: printed_board(checkerboard) print('\033[1;32m' + char + '選手獲勝!\033[0m') ck_settings.game_active = False break
- 新建文件gobang.py,主函數用來初始化程序,並同步更新程序的信息;
from settings import Settings from checkerboard import Checkerboard from collections import namedtuple import game_functions as gf def run_game(): """運行遊戲""" # 配置實例化 ck_settings = Settings() # 棋盤實例化並調用繪製方法 ck = Checkerboard(ck_settings) checkerboard = ck.draw() # namedtuple創建類似於元組的數據類型,除了可以用索引訪問,能夠迭代,還能用屬性名訪問數據 position = namedtuple('Position', ['x', 'y']) while ck_settings.game_active: # 打印棋盤 gf.printed_board(checkerboard) # 更新棋盤 gf.update_board(ck_settings, checkerboard, position) run_game()
- 在文件gobang.py目錄路徑下,執行命令“python gobang.py”打印棋盤,並可對其操作遊玩。
-
總結:代碼都有詳盡的備註說明,如果還有不明白,可參考網址https://jingyan.baidu.com/article/5225f26b328388a6fb09084e.html。