python实现五子棋游戏(pygame版)


Posted in Python onJanuary 19, 2020

本文实例为大家分享了python五子棋游戏的具体代码,供大家参考,具体内容如下

目录

  • 简介
  • 实现过程
  • 结语

简介

使用python实现pygame版的五子棋游戏;

环境:Windows系统+python3.8.0

游戏规则:

1.分两位棋手对战,默认黑棋先下;当在棋盘点击左键,即在该位置绘制黑棋;

2.自动切换到白棋,当在棋盘点击左键,即在该位置绘制白棋;

3.轮流切换棋手下棋,当那方先形成5子连线者获胜(横、竖、斜、反斜四个方向都可以)。

游戏运行效果如下:

python实现五子棋游戏(pygame版)

实现过程

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 pygame
 
class Checkerboard():
 def __init__(self, ck_settings, screen, position):
 self.ck_settings = ck_settings
 self.screen = screen
 self.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-O
 y_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_settings
 self.screen = screen
 self.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) / 2
 self.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_image
 chess_type = 'black'
 else:
 ck_settings.prompt_info = '当前棋手:黑棋'
 img = cb.white_image
 chess_type = 'white'
 
 """落棋"""
 dropState = check_at(ck_settings, index_coordinates)
 if dropState:
 i, j = index_coordinates
 chess_x = cb.checkerboard[j][i].x - cb.chess_rect.width / 2
 chess_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 False
 return True
 
def check_stats(ck_settings, pos):
 """校验四个方向,是否有了输赢"""
 pos_i, pos_j = pos
 directs = [(1, 0), (0, 1), (1, 1), (1, -1)] # 横、竖、斜、反斜 四个方向检查 
 for direct in directs:
 line_checkerboard = []
 d_x, d_y = direct
 
 last = 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'].x 
 y = ball['coord'].y - last['coord'].y
 if 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 + 4
 if index < len(sorted_line):
  if d_x == 0:
  y1 = item.y
  y2 = 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.x
  x2 = 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].x
 x_last = cb.checkerboard[ck_settings.number - 1][ck_settings.number - 1].x
 y_first = cb.checkerboard[0][0].y
 y_last = cb.checkerboard[ck_settings.number - 1][ck_settings.number - 1].y
 if 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 Infopanel
 
def 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.加上开始游戏按钮,可参考前面python实例;

3.胜负榜单等,可参考前面python实例。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python进程通信之匿名管道实例讲解
Apr 11 Python
Python自动化测试ConfigParser模块读写配置文件
Aug 15 Python
详谈python http长连接客户端
Jun 12 Python
Python实现PS图像调整黑白效果示例
Jan 25 Python
Python Matplotlib库安装与基本作图示例
Jan 09 Python
Python远程视频监控程序的实例代码
May 05 Python
Python实现的服务器示例小结【单进程、多进程、多线程、非阻塞式】
May 23 Python
Django文件上传与下载(FileFlid)
Oct 06 Python
python mysql 字段与关键字冲突的解决方式
Mar 02 Python
浅谈python处理json和redis hash的坑
Jul 16 Python
python通过opencv调用摄像头操作实例分析
Jun 07 Python
python lambda 表达式形式分析
Apr 03 Python
Python turtle画图库&amp;&amp;画姓名实例
Jan 19 #Python
python3连接mysql获取ansible动态inventory脚本
Jan 19 #Python
基于Pycharm加载多个项目过程图解
Jan 19 #Python
使用Python脚本从文件读取数据代码实例
Jan 19 #Python
Python安装tar.gz格式文件方法详解
Jan 19 #Python
Python : turtle色彩控制实例详解
Jan 19 #Python
使用python 的matplotlib 画轨道实例
Jan 19 #Python
You might like
php定时删除文件夹下文件(清理缓存文件)
2013/01/23 PHP
php短网址和数字之间相互转换的方法
2015/03/13 PHP
php相对当前文件include其它文件的方法
2015/03/13 PHP
php使用GD创建保持宽高比缩略图的方法
2015/04/17 PHP
php实现简易聊天室应用代码
2015/09/23 PHP
PHP获取php,mysql,apche的版本信息及更多服务器信息
2021/03/09 PHP
javascript的事件描述
2006/09/08 Javascript
把input初始值不写value的具体实现方法
2013/07/04 Javascript
jquery实现当滑动到一定位置时固定效果
2014/06/17 Javascript
浅析javascript 定时器
2014/12/23 Javascript
jQuery自动完成插件completer附源码下载
2016/01/04 Javascript
动态设置form表单的action属性的值的简单方法
2016/05/25 Javascript
原生js仿淘宝网商品放大镜效果
2017/02/28 Javascript
微信小程序 页面跳转传值实现代码
2017/07/27 Javascript
vue-cli+axios实现文件上传下载功能(下载接收后台返回文件流)
2019/05/10 Javascript
详解vue v-model
2020/08/31 Javascript
原生js实现九宫格拖拽换位
2021/01/26 Javascript
在Python3中初学者应会的一些基本的提升效率的小技巧
2015/03/31 Python
python传递参数方式小结
2015/04/17 Python
Python中返回字典键的值的values()方法使用
2015/05/22 Python
python 用下标截取字符串的实例
2018/12/25 Python
pandas之分组groupby()的使用整理与总结
2020/06/18 Python
Python urllib库如何添加headers过程解析
2020/10/05 Python
Matplotlib配色之Colormap详解
2021/01/05 Python
95%的面试官都会问到的50道Java线程题,附答案
2012/08/03 面试题
体育教师工作总结的自我评价
2013/10/10 职场文书
2014年迎新年活动方案
2014/02/19 职场文书
行政管理毕业生自荐信
2014/02/24 职场文书
升学宴主持词
2014/04/02 职场文书
师德演讲稿范文
2014/05/06 职场文书
三八节活动主持词
2015/07/04 职场文书
大学生社会服务心得体会
2016/01/22 职场文书
MySQL的join buffer原理
2021/04/29 MySQL
详解python字符串驻留技术
2021/05/21 Python
MySQL一些常用高级SQL语句
2021/07/03 MySQL
对讲机的最大通讯距离是多少
2022/02/18 无线电