项目介绍
华容道是一种古老的中国益智游戏,其目标是通过移动方块,将特定的方块移动到指定位置以完成布局。这个项目是一个基于Python的华容道游戏,通过图形界面展现游戏画面,并提供交互式操作。
安装要求
在运行本项目前,需要确保已安装Python编程语言以及simpleguitk库。如果尚未安装simpleguitk库,可以通过以下命令进行安装:
#pip install simpleguitk
如何运行
- 下载并保存华容道游戏的Python脚本文件(.py)。
- 在合适的Python开发环境中打开该文件。
- 运行程序即可启动华容道游戏的图形界面。
游戏规则
华容道游戏规则如下:
- 通过点击方块或使用键盘上的方向键来移动空格位置,从而移动其他方块。
- 将指定的方块移动至特定位置以完成游戏。
代码结构
本项目的代码结构分为以下几个部分:
- 游戏初始化:对游戏进行初始化设置,包括界面布局、方块位置等。
- 事件处理:处理用户操作,包括鼠标点击事件和键盘事件。
- 游戏逻辑:根据用户操作更新游戏状态,判断游戏是否完成等。
- 图形界面:使用simpleguitk库创建游戏的图形界面。
示例运行结果
示例代码
import simpleguitk as gui
# 全局变量
canvas_height = 500 # 画布高度,单位为像素
canvas_width = 400 # 画布宽度,单位为像素
game_over = False # 游戏是否结束
figure_moving = False # 是否有运动的人物
figures = {} # 所有人物
steps = 0 # 移动步数
current_figure = None # 鼠标点中的人物
current_center = [] # 鼠标点中人物的中心坐标
original_point = [] # 鼠标点击的初始位置坐标,用来计算鼠标拖动的方向
speed = 5 # 人物移动的速度
machao_image = gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project6/machao.png')
zhangfei_image = gui.load_image(
'http://202.201.225.74/video/PythonResoure/ProjectResource/images/project6/zhangfei.png')
zhaoyun_image = gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project6/zhaoyun.png')
huangzhong_image = gui.load_image(
'http://202.201.225.74/video/PythonResoure/ProjectResource/images/project6/huangzhong.png')
guanyu_image = gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project6/guanyu.png')
caocao_image = gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project6/caocao.png')
soldier_image = gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project6/shibing.png')
TEST = 0
# Figure类(棋子类)
class Figure:
def __init__(self, image, src_center, src_size, des_center, des_size, name, move_direction=None):
self.image = image # 棋子图像
self.src_center = src_center # 源图像中心坐标
self.src_size = src_size # 源图像大小
self.des_center = des_center # 画布显示图像中心坐标
self.des_size = des_size # 画布显示图像大小
self.name = name # 棋子名称,如“曹操”
self.move_direction = move_direction # 移动方向
def get_des_center(self):
return self.des_center
def get_des_size(self):
return self.des_size
def get_name(self):
return self.name
def set_move_direction(self, direction):
self.move_direction = direction
def draw(self, canvas):
canvas.draw_image(self.image, self.src_center, self.src_size, self.des_center, self.des_size)
def update(self):
if self.move_direction == 'left':
self.des_center[0] = self.des_center[0] - speed
elif self.move_direction == 'right':
self.des_center[0] = self.des_center[0] + speed
elif self.move_direction == 'up':
self.des_center[1] = self.des_center[1] - speed
elif self.move_direction == 'down':
self.des_center[1] = self.des_center[1] + speed
def collide(self, other):
global figure_moving, steps, TEST
# 判断鼠标拖动的方向
# 如果向左拖动,
if self.move_direction == 'left':
self_left = self.des_center[0] - self.des_size[0] / 2
other_right = other.get_des_center()[0] + other.get_des_size()[0] / 2
self_top = self.des_center[1] - self.des_size[1] / 2
self_bottom = self.des_center[1] + self.des_size[1] / 2
other_top = other.get_des_center()[1] - other.get_des_size()[1] / 2
other_bottom = other.get_des_center()[1] + other.get_des_size()[1] / 2
TEST += 1
if (self_left == other_right and self_bottom > other_top
and self_top < other_bottom) or self_left == 0:
if TEST < 10:
self.move_direction = None
figure_moving = False
TEST = 0
else:
steps += 1
self.move_direction = None
figure_moving = False
TEST = 0
elif self.move_direction == 'right':
self_right = self.des_center[0] + self.des_size[0] / 2
other_left = other.get_des_center()[0] - other.get_des_size()[0] / 2
self_top = self.des_center[1] - self.des_size[1] / 2
self_bottom = self.des_center[1] + self.des_size[1] / 2
other_top = other.get_des_center()[1] - other.get_des_size()[1] / 2
other_bottom = other.get_des_center()[1] + other.get_des_size()[1] / 2
TEST += 1
if (
self_right == other_left and self_bottom > other_top and self_top < other_bottom) or self_right == canvas_width:
if TEST < 10:
self.move_direction = None
figure_moving = False
TEST = 0
else:
steps += 1
self.move_direction = None
figure_moving = False
TEST = 0
elif self.move_direction == 'up':
self_top = self.des_center[1] - self.des_size[1] / 2
other_bottom = other.get_des_center()[1] + other.get_des_size()[1] / 2
self_left = self.des_center[0] - self.des_size[0] / 2
self_right = self.des_center[0] + self.des_size[0] / 2
other_left = other.get_des_center()[0] - other.get_des_size()[0] / 2
other_right = other.get_des_center()[0] + other.get_des_size()[0] / 2
TEST += 1
if (self_top == other_bottom and self_right > other_left and self_left < other_right) or self_top == 0:
if TEST < 10:
self.move_direction = None
figure_moving = False
TEST = 0
else:
steps += 1
self.move_direction = None
figure_moving = False
TEST = 0
elif self.move_direction == 'down':
self_bottom = self.des_center[1] + self.des_size[1] / 2
other_top = other.get_des_center()[1] - other.get_des_size()[1] / 2
self_left = self.des_center[0] - self.des_size[0] / 2
self_right = self.des_center[0] + self.des_size[0] / 2
other_left = other.get_des_center()[0] - other.get_des_size()[0] / 2
other_right = other.get_des_center()[0] + other.get_des_size()[0] / 2
TEST += 1
if figure_moving:
if (
self_bottom == other_top and self_right > other_left and self_left < other_right) or self_bottom == canvas_height:
if TEST < 10:
self.move_direction = None
figure_moving = False
TEST = 0
else:
steps += 1
self.move_direction = None
figure_moving = False
TEST = 0
# # 检查移动与其它静止棋子及边界的碰撞
def check_collide():
global game_over, steps, figure_moving, TEST
# 当前鼠标点中的图像的大小[200,200]和中心坐标[200,400]时,曹操已经到达出逃位置,向下移动,步数加一
# 否则 遍历figures,检测图像和当前鼠标点中的图像是否发生碰撞
# 如果当前图像中心位置的纵坐标大于600,说明棋子曹操已经消失,游戏结束,gameover设置True
if current_figure.get_des_center()[1] > 600: # 曹操已经消失
game_over = True
if current_figure.get_des_size()[0] == 200 and current_figure.get_des_size()[1] == 200 \
and current_figure.get_des_center()[0] == 200 \
and current_figure.get_des_center()[1] == 400: # 曹操到达逃出位置
current_figure.set_move_direction("down")
steps += 1
else:
for figure in figures.values():
if figure != current_figure:
current_figure.collide(figure)
# 绘制全部棋子
def draw_figures(figures, canvas):
for figure in figures.values():
figure.draw(canvas)
# 绘制游戏结束信息
def draw_game_over_msg(canvas, msg):
msgwidth = frame.get_canvas_textwidth(msg, 48, 'sans-serif')
canvas.draw_text(msg, ((canvas_width - msgwidth) / 2, canvas_height / 2), 48, 'Red', 'sans-serif')
# 鼠标点击事件的处理函数
def mouse_click(pos):
global current_figure, current_center, original_point, original_center
if not figure_moving:
current_figure = None
for key, figure in figures.items():
center = figure.get_des_center()
size = figure.get_des_size()
if pos[0] >= center[0] - size[0] / 2 and pos[0] <= center[0] + size[0] / 2 and pos[1] >= center[1] - size[
1] / 2 and pos[1] <= center[1] + size[1] / 2:
current_figure = figure
current_center = figure.get_des_center()
original_point = pos
original_center = [figure.get_des_center(), 0]
break
# 鼠标拖动事件的处理函数
def mouse_drag(pos):
global current_figure, current_center, original_point, figure_moving
if current_figure != None:
horizontal_move = pos[0] - original_point[0]
vertical_move = pos[1] - original_point[1]
figure_moving = True
if abs(horizontal_move) > abs(vertical_move):
if horizontal_move > 0:
current_figure.set_move_direction("right")
else:
current_figure.set_move_direction("left")
else:
if vertical_move > 0:
current_figure.set_move_direction("down")
else:
current_figure.set_move_direction("up")
# 屏幕刷新事件处理函数
def draw(canvas):
global steps
if game_over:
draw_game_over_msg(canvas, '通关成功')
else:
draw_figures(figures, canvas)
if current_figure != None:
check_collide()
current_figure.update()
label_text = "移动次数 = " + str(steps) + " 步"
label.set_text(label_text)
# 为游戏开始或重新开始初始化全局变量,也是鼠标点击按钮的事件处理函数
def start_game():
global steps, figures, game_over, current_figure, figure_moving
figure_moving = False
steps = 0
figures = {}
figures['马超'] = Figure(machao_image, [50, 100], [100, 200], [50, 100], [100, 200], '马超')
figures['曹操'] = Figure(caocao_image, [100, 100], [200, 200], [200, 100], [200, 200], '曹操')
figures['张飞'] = Figure(zhangfei_image, [50, 100], [100, 200], [350, 100], [100, 200], '张飞')
figures['赵云'] = Figure(zhaoyun_image, [50, 100], [100, 200], [50, 300], [100, 200], '赵云')
figures['关羽'] = Figure(guanyu_image, [100, 50], [200, 100], [200, 250], [200, 100], '关羽')
figures['黄忠'] = Figure(huangzhong_image, [50, 100], [100, 200], [350, 300], [100, 200], '黄忠')
figures['卒一'] = Figure(soldier_image, [50, 50], [100, 100], [150, 350], [100, 100], '卒一')
figures['卒二'] = Figure(soldier_image, [50, 50], [100, 100], [250, 350], [100, 100], '卒二')
figures['卒三'] = Figure(soldier_image, [50, 50], [100, 100], [50, 450], [100, 100], '卒三')
figures['卒四'] = Figure(soldier_image, [50, 50], [100, 100], [350, 450], [100, 100], '卒四')
game_over = False
label.set_text("移动次数 = 0 步")
# 创建窗口初始化画布
frame = gui.create_frame("华容道之横刀立马", canvas_width, canvas_height)
label = frame.add_label("移动次数 = 0 步")
# 注册事件处理函数
frame.set_draw_handler(draw) # 显示处理,每秒调用draw函数60次
button = frame.add_button('重新开始游戏', start_game, 50) # 鼠标每次点击“重新开始游戏”按钮,调用start_game函数1次
frame.set_mouseclick_handler(mouse_click) #
frame.set_mousedrag_handler(mouse_drag)
start_game()
frame.start()