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 相关文章推荐
使用cx_freeze把python打包exe示例
Jan 24 Python
使用python 爬虫抓站的一些技巧总结
Jan 10 Python
十分钟利用Python制作属于你自己的个性logo
May 07 Python
解决pandas使用read_csv()读取文件遇到的问题
Jun 15 Python
Python WEB应用部署的实现方法
Jan 02 Python
Python爬虫实战之12306抢票开源
Jan 24 Python
python3 字符串/列表/元组(str/list/tuple)相互转换方法及join()函数的使用
Apr 03 Python
ubuntu 安装pyqt5和卸载pyQt5的方法
Mar 24 Python
python 写函数在一定条件下需要调用自身时的写法说明
Jun 01 Python
k-means 聚类算法与Python实现代码
Jun 01 Python
python中的垃圾回收(GC)机制
Sep 21 Python
python遍历路径破解表单的示例
Nov 21 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
如何在symfony中导出为CSV文件中的数据
2011/10/06 PHP
对于PHP 5.4 你必须要知道的
2013/08/07 PHP
jquery不支持toggle()高(新)版本的问题解决
2016/09/24 PHP
php数组遍历类与用法示例
2019/05/24 PHP
静态的动态续篇之来点XML
2006/08/15 Javascript
ext 代码生成器
2009/08/07 Javascript
javascript下对于事件、事件流、事件触发的顺序随便说说
2010/07/17 Javascript
jquery offset函数应用实例
2012/11/14 Javascript
jQuery 网易相册鼠标移动显示隐藏效果实现代码
2013/03/31 Javascript
使用js判断数组中是否包含某一元素(类似于php中的in_array())
2013/12/12 Javascript
javascript省市级联功能实现方法实例详解
2015/10/20 Javascript
javascript中call apply 与 bind方法详解
2016/03/10 Javascript
JavaScript的React Web库的理念剖析及基础上手指南
2016/05/10 Javascript
JavaScript 基础函数_深入剖析变量和作用域
2016/05/18 Javascript
如何检测JavaScript的各种类型
2016/07/30 Javascript
jQuery基于BootStrap样式实现无限极地区联动
2016/08/26 Javascript
js与jQuery实现的用户注册协议倒计时功能实例【三种方法】
2017/11/09 jQuery
jquery中ajax请求后台数据成功后既不执行success也不执行error的完美解决方法
2017/12/24 jQuery
JQuery通过键盘控制键盘按下与松开触发事件
2020/08/07 jQuery
Python入门篇之正则表达式
2014/10/20 Python
利用Python绘制MySQL数据图实现数据可视化
2015/03/30 Python
Python如何生成树形图案
2018/01/03 Python
Python使用matplotlib绘图无法显示中文问题的解决方法
2018/03/14 Python
python多线程之事件Event的使用详解
2018/04/27 Python
python实现计算器功能
2019/10/31 Python
python 上下文管理器及自定义原理解析
2019/11/19 Python
用pytorch的nn.Module构造简单全链接层实例
2020/01/14 Python
python 通过邮件控制实现远程控制电脑操作
2020/03/16 Python
mac安装python3后使用pip和pip3的区别说明
2020/09/01 Python
xxx同志考察材料
2014/02/07 职场文书
医药营销个人求职信
2014/04/12 职场文书
2014年资料员工作总结
2014/11/18 职场文书
具结保证书范本
2015/05/11 职场文书
2016学习全国教书育人楷模先进事迹心得体会
2016/01/21 职场文书
创业计划书之冷饮店
2019/09/27 职场文书
Nginx报404错误的详细解决方法
2022/07/23 Servers