作者 by 超米 / 2024-11-25 / 暂无评论 / 39 个足迹
import simpleguitk as gui
import random
import urllib.request
# 全局变量
has_rising_box = True # 是否有文字块正在上升
canvas_height = 600 # 画布高度,单位为像素
canvas_width = 480 # 画布宽度,单位为像素
box_height = 30 # 文字块高度,单位为像素
box_width = 120 # 文字块宽度,单位为像素,包含3个汉字
rising_speed = -1 # 上升速度,单位为像素
game_over = False # 游戏是否结束
rising_box = None # 正在运动的文字块对象
stopped_box = [] # 停止移动的所有文字块列表
prime_sentence_list = [] # 三字经全文列表,3个字构成1句,每句为一个列表元素
current_section_list = [] # 当前处理的段落文字列表,每句为一个列表元素,4句为一个段落
score = 0 # 游戏得分
def read_from_file(filename):
"""从文本文件读入三字经,存储在列表中,并返回该列表"""
# 三字经文件的格式如下:
'''
# rén zhī chū xìng běn shàn xìng xiāng jìn xí xiāng yuǎn
#人之初 性本善 性相近 习相远
gǒu bú jiào xìng nǎi qiān jiào zhī dào guì yǐ zhuān
苟不教 性乃迁 教之道 贵以专
......
'''
# 奇数行为诗句拼音,偶数行为诗句文本
# 三字经每3个汉字为1句,每1句作为列表的1个元素,四句为一行(一段),句间隔为空格
i = 1
new_list = []
szj_file = urllib.request.urlopen(filename)
for line in szj_file.readlines():
if i % 2 == 0:
line_list = str(line.decode("utf-8")).split()
for sentence in line_list:
new_list.append(sentence)
i += 1
szj_file.close()
return new_list
def text_shuffle(text):
"""打乱文字的次序"""
random_list = list(text)
random.shuffle(random_list)
return ''.join(random_list)
def draw_all_stopped_box(boxes, canvas):
"""绘制所有的停止块"""
for box in boxes:
box.draw(canvas)
def generate_current_section_list():
"""生成当前段落四句诗歌列表"""
global prime_sentence_list
create_list = []
for i in range(4):
create_str = str(i) + prime_sentence_list.pop(0)
create_list.append(create_str)
random.shuffle(create_list)
return create_list
def check_collision(group, moving_box):
"""检查移动块和所有停止块是否发生碰撞"""
for box in group:
if box.collide(moving_box):
return True
return False
def delete_last_four(group):
"""消除最后4个块,字序和句序都正确时调用该函数"""
n = len(group)
group.pop(n - 1)
group.pop(n - 2)
group.pop(n - 3)
group.pop(n - 4)
def last_four_ok(group):
"""判断最后4个块的字序和句序是否都正确"""
n = len(group)
if group[n - 1].proper_order and group[n - 1].sentence == group[n - 1].correct_sentence and \
group[n - 2].proper_order and group[n - 2].sentence == group[n - 2].correct_sentence and \
group[n - 3].proper_order and group[n - 3].sentence == group[n - 3].correct_sentence and \
group[n - 4].proper_order and group[n - 4].sentence == group[n - 4].correct_sentence:
return True
def stop_box(group: object, moving_box: object) -> object:
"""停止移动块"""
global has_rising_box, game_over, score, label, last_four_box, stopped_box
if moving_box.processed:
return
if moving_box.pos[1] == 0 or check_collision(group, moving_box):
moving_box.rising = False
has_rising_box = False
if moving_box.sentence == moving_box.correct_sentence:
score += 5
label_text = "游戏得分 = " + str(score) + "分"
label.set_text(label_text)
if moving_box.pos[0] / box_width != moving_box.order:
moving_box.proper_order = False
moving_box.processed = True
stopped_box.add(moving_box)
last_four_box.append(moving_box)
if len(last_four_box) == 4:
if last_four_ok(last_four_box):
score += 20
label_text = "游戏得分 = " + str(score) + "分"
label.set_text(label_text)
for box in last_four_box:
stopped_box.discard(box)
delete_last_four(last_four_box)
line_index = (moving_box.pos[1] + 15) // box_height
if line_index >= 10:
game_over = True
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')
class Box:
"""Box类的定义"""
def __init__(self, pos, width, height, sentence, correct_sentence, order):
self.pos = [pos[0], pos[1]] # 文字块左上角在画布的坐标位置
self.width = width # 文字块的宽度
self.height = height # 文字块的高度
self.sentence = sentence # 文字块实际显示的句子
self.correct_sentence = correct_sentence # 文字块正确字序的句子
self.rising = True # 文字块是否正在上升
self.processed = False # 反射碰撞后是否处理完毕
self.order = order # 该文字块在一段中的正确句序
self.proper_order = True # 实际句序是否正确
def shuffle_sentence(self):
"""打乱字序"""
self.sentence = text_shuffle(self.sentence)
def collide(self, moving_object):
"""检查是否和移动块发生碰撞"""
if self.pos[1] + self.height == moving_object.pos[1] and self.pos[0] == moving_object.pos[0]:
return True
else:
return False
def draw(self, canvas):
"""绘制自己"""
text_width = frame.get_canvas_textwidth(self.sentence, 22, 'sans-serif')
if self.sentence == self.correct_sentence and self.proper_order:
canvas.draw_polygon([self.pos, [self.pos[0] + self.width, self.pos[1]],
[self.pos[0] + self.width, self.pos[1] + self.height],
[self.pos[0], self.pos[1] + self.height]], 2, 'Green', 'Green')
canvas.draw_text(self.sentence, (self.pos[0] + (self.width - text_width) / 2, self.pos[1] + self.height), 22, 'White', 'sans-serif')
else:
canvas.draw_polygon([self.pos, [self.pos[0] + self.width, self.pos[1]], [self.pos[0] + self.width, self.pos[1] + self.height], [self.pos[0], self.pos[1] + self.height]], 2, 'Red', 'Red')
canvas.draw_text(self.sentence, (self.pos[0] + (self.width - text_width) / 2, self.pos[1] + self.height), 22, 'Yellow','sans-serif')
def update(self):
"""更新垂直位置,使其向上移动"""
if self.rising:
self.pos[1] += rising_speed
def box_spawner():
"""时钟事件处理函数,生产一个上升的方块"""
global has_rising_box, rising_box, current_section_list, game_over
if game_over:
return
if not has_rising_box:
if len(current_section_list) == 0:
current_section_list = generate_current_section_list()
sentence = current_section_list.pop()
random_pos = [random.randrange(4) * box_width, canvas_height]
rising_box = Box(random_pos, box_width, box_height, text_shuffle(sentence[1:]), sentence[1:], int(sentence[0]))
has_rising_box = True
def draw(canvas):
"""屏幕刷新事件处理函数"""
global rising_box
if game_over:
draw_game_over_msg(canvas, '游戏结束!')
else:
rising_box.draw(canvas)
rising_box.update()
draw_all_stopped_box(stopped_box, canvas)
stop_box(stopped_box, rising_box)
def key_down(key):
"""处理键盘按下事件的函数"""
if not game_over:
if key == gui.KEY_MAP["left"]: #向左移动方块
if rising_box.pos[0] - box_width >= 0:
rising_box.pos = [rising_box.pos[0] - box_width, rising_box.pos[1]]
elif key == gui.KEY_MAP["right"]: #向右移动方块
if rising_box.pos[0] + box_width + box_width <= canvas_width:
rising_box.pos = [rising_box.pos[0] + box_width, rising_box.pos[1]]
elif key == gui.KEY_MAP["space"]: #重排文字顺序
rising_box.shuffle_sentence()
def start_game():
"""为游戏开始或重新开始初始化全局变量,也是鼠标点击按钮的事件处理函数"""
global prime_sentence_list, stopped_box, rising_box, current_section_list, has_rising_box, game_over, score, last_four_box
url = 'http://202.201.225.74/video/PythonResoure/ProjectResource/other/szj.txt'
prime_sentence_list = read_from_file(url)
last_four_box = []
score = 0
label.set_text("游戏得分 = 0")
game_over = False
stopped_box = set([])
current_section_list = generate_current_section_list()
rising_sentence = current_section_list.pop()
rising_box = Box([0, canvas_height], box_width, box_height, text_shuffle(rising_sentence[1:]), rising_sentence[1:], int(rising_sentence[0]))
has_rising_box = True
# 创建窗口初始化画布
frame = gui.create_frame("决战《三字经》", canvas_width, canvas_height)
label = frame.add_label("游戏得分 = 0分")
# 注册事件处理函数
frame.set_keydown_handler(key_down) # 按键处理,每次按键会调用key_down函数
frame.set_draw_handler(draw) # 显示处理,每秒调用draw函数60次
timer = gui.create_timer(1000.0, box_spawner) # 每秒调用box_spawner函数1次
button = frame.add_button('重新开始游戏', start_game, 100) # 鼠标每次点击“重新开始游戏”按钮,调用start_game函数1次
# 启动游戏
start_game() # 为游戏开始或重新开始初始化全局变量
timer.start() # 启动定时器
frame.start() # 显示窗口
独特见解