使用python实现pygame版的五子棋游戏;
环境:Windows系统+python3.8.0 (文末送读者福利)
1、分两位棋手对战,默认黑棋先下;当在棋盘点击左键,即在该位置绘制黑棋;
2、自动切换到白棋,当在棋盘点击左键,即在该位置绘制白棋;
3、轮流切换棋手下棋,当那方先形成5子连线者获胜(横、竖、斜、反斜四个方向都可以)。

1、新建文件settings.py,用来定义一些必须的基本属性和初始值; (文末送读者福利)
class Settings():
def __init__(self):
"""初始化的游戏配置"""
# 屏幕宽高
self.width = 700
self.height = 554
# 文字颜色和大小
self.fontsize = 14
self.fonttype = 'simsunnsimsun'
# 棋盘格数
self.number = 15
# 棋盘左边距、上边距和间隔
self.bd_left = 30
self.bd_top = 30
self.bd_space = 36
# 判断游戏是否结束(默认开始)
self.game_active = True
# 判断哪方下棋(默认黑子先写)
self.chess_player = 1
self.prompt_info = '当前棋手:黑棋'
# 开始校验输赢(两边合计9,因为已经有一边5步)
self.win_number = 0
# 设置背景图、黑棋图片、白棋图片路径
self.checkerboard_bg = 'images/checkerboard_bg.png'
self.black_chess = 'images/black_chess.png'
self.white_chess = 'images/white_chess.png'
# 存储落子数据
self.move_chess = []
2、新建文件checkerboard.py,主要用来绘制背景图和网格线;
import sys
import pygameclass Checkerboard():def __init__(self, ck_settings, screen, position):self.ck_settings = ck_settingsself.screen = screenself.position = position# 颜色和坐标大小self.text_color = (0, 0, 0)self.font = pygame.font.SysFont(ck_settings.fonttype, ck_settings.fontsize)# 存储棋子坐标self.checkerboard = []# 加载背景图、黑棋和白棋(当有图片不存在时,打印错误并退出游戏)try:self.bg_image = pygame.image.load(ck_settings.checkerboard_bg) self.black_image = pygame.image.load(ck_settings.black_chess).convert_alpha() # convert_alpha背景透明self.white_image = pygame.image.load(ck_settings.white_chess).convert_alpha()self.chess_rect = self.black_image.get_rect()except Exception as e:print('error:', e)sys.exit()def draw_board(self): # 存储棋子坐标 for i in range(self.ck_settings.number):self.checkerboard.append([])for j in range(self.ck_settings.number):self.checkerboard[i].append(self.position(self.ck_settings.bd_left + i * self.ck_settings.bd_space, self.ck_settings.bd_top + j * self.ck_settings.bd_space))# 绘制棋盘坐标for i in range(0, self.ck_settings.number):# ord返回字符的ASCII数值,chr再返回字符x_text = self.font.render(chr(ord('A') + i), True, self.text_color) # A-Oy_text = self.font.render(str(i + 1), True, self.text_color) # 1-15# 绘制xy轴坐标(在棋盘背景图绘制)self.bg_image.blit(x_text, (self.checkerboard[i][0].x - x_text.get_width() / 2, self.checkerboard[i][0].y - 20))self.bg_image.blit(y_text, (self.checkerboard[0][i].x - 20, self.checkerboard[0][i].y - y_text.get_height() / 2))# 绘制横竖线(在棋盘背景图绘制)pygame.draw.line(self.bg_image, self.text_color, self.checkerboard[0][i], self.checkerboard[self.ck_settings.number-1][i])pygame.draw.line(self.bg_image, self.text_color, self.checkerboard[i][0], self.checkerboard[i][self.ck_settings.number-1])# 绘制棋盘背景图self.screen.blit(self.bg_image, (0, 0))
3、新建文件infopanel.py,主要用来绘制棋盘右边提示信息(暂时只有显示下棋方和获胜信息);
import pygame.font
class Infopanel():def __init__(self, ck_settings, screen):"""初始化属性"""self.settings = ck_settingsself.screen = screenself.screen_rect = screen.get_rect()# 设置文字颜色和字体大小self.info_color = (217, 8, 10)self.font = pygame.font.SysFont(ck_settings.fonttype, 16)def draw_info(self, info):"""将文字渲染为图像,并定位到右边水平居中"""self.info_image = self.font.render(info, True, self.info_color)self.info_image_rect = self.info_image.get_rect()self.info_image_rect.right = self.screen_rect.right - (self.screen_rect.width - 536 - self.info_image_rect.width) / 2self.info_image_rect.top = 50# 绘制到屏幕self.screen.blit(self.info_image, self.info_image_rect)
4.新建文件“game_functions.py”,存放跟游戏有关的所有业务逻辑函数;
import sys
import pygame# 棋
def update_board(ck_settings, cb, index_coordinates, position):"""更新棋盘信息"""# 判断棋手(黑棋或白棋)if ck_settings.chess_player == 1:ck_settings.prompt_info = '当前棋手:白棋'img = cb.black_imagechess_type = 'black'else:ck_settings.prompt_info = '当前棋手:黑棋'img = cb.white_imagechess_type = 'white'"""落棋"""dropState = check_at(ck_settings, index_coordinates)if dropState:i, j = index_coordinateschess_x = cb.checkerboard[j][i].x - cb.chess_rect.width / 2chess_y = cb.checkerboard[j][i].y - cb.chess_rect.height / 2# 累计步数(两边合计)ck_settings.win_number += 1# 落子并转换棋手ck_settings.move_chess.append({'type': chess_type, 'coord': position(i, j)})cb.bg_image.blit(img, (chess_x, chess_y))ck_settings.chess_player *= -1# 合计9步开始校验输赢if ck_settings.win_number >= 9:check_stats(ck_settings, (i, j)) else:ck_settings.prompt_info = '已经有其他棋子'# 检查(i,j)位置是否已占用
def check_at(ck_settings, index_coordinates):for item in ck_settings.move_chess:if index_coordinates == item['coord']:return Falsereturn Truedef check_stats(ck_settings, pos):"""校验四个方向,是否有了输赢"""pos_i, pos_j = posdirects = [(1, 0), (0, 1), (1, 1), (1, -1)] # 横、竖、斜、反斜 四个方向检查 for direct in directs:line_checkerboard = []d_x, d_y = directlast = ck_settings.move_chess[-1]line_ball = [] # 存放在一条线上的棋子for ball in ck_settings.move_chess:# 跟最后落子判断if ball['type'] == last['type']:x = ball['coord'].x - last['coord'].xy = ball['coord'].y - last['coord'].yif d_x == 0:if x == 0:line_ball.append(ball['coord'])if d_y == 0:if y == 0:line_ball.append(ball['coord'])if x * d_y == y * d_x:line_ball.append(ball['coord'])if len(line_ball) >= 5: # 只有5子及以上才继续判断sorted_line = sorted(line_ball)for i, item in enumerate(sorted_line):index = i + 4if index < len(sorted_line):if d_x == 0:y1 = item.yy2 = sorted_line[index].y# 此点和第5个点比较y值,如相差为4则连成5子if abs(y1 - y2) == 4:ck_settings.prompt_info = '黑棋获胜' if last['type'] == 'black' else '白棋获胜'else:x1 = item.xx2 = sorted_line[index].x# 此点和第5个点比较x值,如相差为4则连成5子if abs(x1 - x2) == 4:ck_settings.prompt_info = '黑棋获胜' if last['type'] == 'black' else '白棋获胜'else:break# 事件
def check_events(ck_settings, cb, position):"""监听事件"""for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()elif event.type == pygame.MOUSEBUTTONDOWN:# 点击左键if event.button == 1:pos = pygame.mouse.get_pos() # 获取点击实际坐标# 判断是否溢出x_first = cb.checkerboard[0][0].xx_last = cb.checkerboard[ck_settings.number - 1][ck_settings.number - 1].xy_first = cb.checkerboard[0][0].yy_last = cb.checkerboard[ck_settings.number - 1][ck_settings.number - 1].yif pos[0] < x_first or pos[0] > x_last or pos[1] < y_first or pos[1] > y_last:ck_settings.prompt_info = '落子位置不正确!'else:index_coordinates = to_index(ck_settings, pos)update_board(ck_settings, cb, index_coordinates, position)def to_index(ck_settings, pos):"""实际坐标转换为棋盘下标"""i = round((pos[1] - ck_settings.bd_top) / ck_settings.bd_space)j = round((pos[0] - ck_settings.bd_left) / ck_settings.bd_space)return (i, j)
5、新建文件gobang.py,主函数用来初始化程序,并同步更新程序的信息;
import pygame
from settings import Settings
from checkerboard import Checkerboard
from collections import namedtuple
import game_functions as gf
from infopanel import Infopaneldef run_game():"""运行游戏"""# 初始化游戏屏幕pygame.init()# 创建时钟对象 (可以控制游戏循环频率)clock = pygame.time.Clock()# 配置实例化ck_settings = Settings() screen = pygame.display.set_mode((ck_settings.width, ck_settings.height))pygame.display.set_caption('五子棋游戏')# namedtuple创建类似于元组的数据类型,除了可以用索引访问,能够迭代,还能用属性名访问数据position = namedtuple('Position', ['x', 'y'])# 创建实例cb = Checkerboard(ck_settings, screen, position)# 实例化面板信息infopanel = Infopanel(ck_settings, screen)while ck_settings.game_active:# 绘制棋盘cb.draw_board()# 绘制面板信息infopanel.draw_info(ck_settings.prompt_info)# 检查玩家事件并更新棋盘gf.check_events(ck_settings, cb, position)# 让最近绘制的屏幕可见pygame.display.flip()# 通过时钟对象指定循环频率clock.tick(60) # 每秒循环60次run_game()
6、在文件gobang.py目录路径下,执行命令“python gobang.py”弹出窗口,即可对其操作游玩。
该游戏只是实现了基础功能,还有很多可优化的功能:
1、根据实际情况加上更详细的面板信息(比如倒计时等);
2、加上开始游戏按钮,
3、胜负榜单等,
读者福利:知道你对Python感兴趣,便准备了这套python学习资料,
对于0基础小白入门:
如果你是零基础小白,想快速入门Python是可以考虑的。
一方面是学习时间相对较短,学习内容更全面更集中。
二方面是可以找到适合自己的学习方案
包括:Python web开发,Python爬虫,Python数据分析,人工智能、机器学习等教程。带你从零基础系统性的学好Python!
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。(学习教程文末领取哈)


温馨提示:篇幅有限,已打包文件夹,获取方式在:文末
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

检查学习结果。



这份完整版的Python全套学习资料已为大家备好,朋友们如果需要可以微信扫描下方二维码添加,输入"领取资料" 可免费领取全套资料【有什么需要协作的还可以随时联系我】朋友圈也会不定时的更新最前言python知识。

了解python的前景: https://blog.csdn.net/weixin_49892805/article/details/127196159
python有什么用: https://blog.csdn.net/weixin_49892805/article/details/127214402
上一篇:dumi 2,它来了它来了它来了
下一篇:有关夜幕降临得非常非常好的句子