python实现五子棋游戏(控制台版)
程序员文章站
2024-03-18 14:50:04
...
一、简介
使用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。