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 相关文章推荐
教你用python3根据关键词爬取百度百科的内容
Aug 18 Python
python爬取淘宝商品详情页数据
Feb 23 Python
python IDLE 背景以及字体大小的修改方法
Jul 12 Python
python 内置函数汇总详解
Sep 16 Python
Python OrderedDict的使用案例解析
Oct 25 Python
python列表生成器迭代器实例解析
Dec 19 Python
tensorflow实现测试时读取任意指定的check point的网络参数
Jan 21 Python
python游戏开发的五个案例分享
Mar 09 Python
python实现TCP文件传输
Mar 20 Python
python 弧度与角度互转实例
Apr 15 Python
python实现定时发送邮件到指定邮箱
Dec 23 Python
Pycharm创建python文件自动添加日期作者等信息(步骤详解)
Feb 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令牌 Token改进版
2008/07/18 PHP
php 进度条实现代码
2009/03/10 PHP
PHP基于GD库的缩略图生成代码(支持jpg,gif,png格式)
2014/06/19 PHP
JSON字符串传到后台PHP处理问题的解决方法
2016/06/05 PHP
PHP观察者模式原理与简单实现方法示例
2017/08/25 PHP
javascript 定义新对象方法
2010/02/20 Javascript
CSS(js)限制页面显示的文本字符长度
2012/12/27 Javascript
Jquery实现图片预加载与延时加载的方法
2014/12/22 Javascript
JS原型链 详解及示例代码
2016/09/06 Javascript
javascript实现一个网页加载进度loading
2017/01/04 Javascript
详解Vue文档中几个易忽视部分的剖析
2018/03/24 Javascript
JS图片懒加载的优点及实现原理
2020/01/10 Javascript
vue项目创建步骤及路由router
2020/01/14 Javascript
详解Python中with语句的用法
2015/04/15 Python
python使用in操作符时元组和数组的区别分析
2015/05/19 Python
python excel使用xlutils类库实现追加写功能的方法
2018/05/02 Python
浅谈Django的缓存机制
2018/08/23 Python
python 运用Django 开发后台接口的实例
2018/12/11 Python
pycharm 安装JPype的教程
2019/08/08 Python
利用python list完成最简单的DB连接池方法
2019/08/09 Python
ubuntu上安装python的实例方法
2019/09/30 Python
Python 实现opencv所使用的图片格式与 base64 转换
2020/01/09 Python
OpenCV+python实现膨胀和腐蚀的示例
2020/12/21 Python
Python datetime模块的使用示例
2021/02/02 Python
使用python实现学生信息管理系统
2021/02/25 Python
HTML5 progress和meter控件_动力节点Java学院整理
2017/07/06 HTML / CSS
澳大利亚在线百货商店:Real Smart
2017/08/13 全球购物
西班牙购买隐形眼镜、眼镜和太阳镜网站:Lentiamo.es
2020/06/11 全球购物
介绍一下.NET构架下remoting和webservice
2014/05/08 面试题
成人高等教育毕业生自我鉴定
2013/10/22 职场文书
大学生安全教育主题班会
2015/08/12 职场文书
2016幼儿园新学期寄语
2015/12/03 职场文书
Python pandas求方差和标准差的方法实例
2021/08/04 Python
一文带你探究MySQL中的NULL
2021/11/11 MySQL
千万级用户系统SQL调优实战分享
2022/03/03 MySQL
python​格式化字符串
2022/04/20 Python