本文实例为大家分享了python五子棋游戏的具体代码,供大家参考,具体内容如下
目录
- 简介
- 实现过程
- 结语
简介
使用python实现pygame版的五子棋游戏;
环境:Windows系统+python3.8.0
游戏规则:
1.分两位棋手对战,默认黑棋先下;当在棋盘点击左键,即在该位置绘制黑棋;
2.自动切换到白棋,当在棋盘点击左键,即在该位置绘制白棋;
3.轮流切换棋手下棋,当那方先形成5子连线者获胜(横、竖、斜、反斜四个方向都可以)。
游戏运行效果如下:
实现过程
1.新建文件settings.py,用来定义一些必须的基本属性和初始值;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
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,主要用来绘制背景图和棋格线;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
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,主要用来绘制棋盘右边提示信息(暂时只有显示下棋方和获胜信息);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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”,存放跟游戏有关的所有业务逻辑函数;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
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,主函数用来初始化程序,并同步更新程序的信息;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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实例。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/king0964/article/details/104015047