如何在Pygame记忆配对游戏中显示玩家最终用时?
解决记忆配对游戏的计时器持续运行与最终用时显示问题
我帮你排查了代码,发现两个核心问题导致计时器停不下来,而且没法正确获取最终用时:一是时间计算的公式写错了,二是游戏结束后没有冻结计时并保存最终时间值。下面一步步给你修正:
问题1:时间计算逻辑错误
你当前的时间计算是:
time = 0 + int((pygame.time.get_ticks() + start_time) / 1000)
这里应该用当前时间减去初始时间,因为pygame.time.get_ticks()返回的是从pygame初始化到现在的毫秒数,所以正确的公式是:
time = int((pygame.time.get_ticks() - start_time) / 1000)
问题2:游戏结束后未停止计时并保存最终用时
当matches达到15(也就是全部配对完成)时,你设置了game_over = True,但后续的循环里依然会调用draw_backgrounds()更新时间,而且end_time变量完全没定义,导致显示时会报错。
修改方案:
- 在游戏结束时,立即保存当前的
time作为end_time,之后不再更新time变量。 - 修复
draw_backgrounds()里的时间更新逻辑,只有在game_over为False时才计算时间。 - 确保游戏结束界面显示的是正确的
end_time。
修改后的关键代码部分
1. 修正draw_backgrounds()函数:
def draw_backgrounds(): global start_time, time, end_time top_menu = pygame.draw.rect(screen, orange, [0, 0, screen_width, 75]) score_text = small_font.render(f'Player 1 score : {score}', True, white) screen.blit(score_text, (20, 20)) board_space = pygame.draw.rect(screen, turquoise, [0, 100, screen_width, screen_height - 200], 0) bottom_menu = pygame.draw.rect(screen, orange, [0, screen_height - 100, screen_width, 100], 0) # 只有游戏未结束时才更新时间 if not game_over: time = int((pygame.time.get_ticks() - start_time) / 1000) time_text = small_font.render(f'Your time: {time}', True, white) screen.blit(time_text, (20, 550)) else: # 游戏结束后显示最终用时 time_text = small_font.render(f'Final Time: {end_time}', True, white) screen.blit(time_text, (20, 550))
2. 修正游戏结束的判断逻辑:
#Checks for game over if matches == rows * cols // 2 and not game_over: game_over = True end_time = time # 保存最终用时 winner = pygame.draw.rect(screen, turquoise,[0, 0, 600, 600]) winner_text = large_font.render(f'YOUR TIME WAS {end_time} !!', True, orange) screen.blit(winner_text, (70, screen_height - 350))
这里加了and not game_over的判断,避免每次循环都重复创建结束界面和赋值end_time。
3. 初始化end_time变量
在游戏变量定义部分添加:
end_time = 0
完整修改后的代码(关键部分已修正)
# build a guessing game! import random import pygame global options_list, spaces, used, new_board, first_guess, second_guess, first_guess_num, second_guess_num, score, matches, game_over, rows, cols, correct, time, end_time pygame.init() # game variables and constants screen_width = 600 screen_height = 600 white = (255, 255, 255) black = (0, 0, 0) orange = (255,97,3) turquoise = (0, 206, 209) green = (0, 255, 0) fps = 60 timer = pygame.time.Clock() rows = 5 cols = 6 correct = [[0, 0, 0, 0, 0, 0,], [0, 0, 0, 0, 0, 0,], [0, 0, 0, 0, 0, 0,], [0, 0, 0, 0, 0, 0,], [0, 0, 0, 0, 0, 0]] options_list = [] spaces = [] used = [] new_board = True first_guess = False second_guess = False #Guess is assigned an index value. Checks what number is clicked first_guess_num = 0 second_guess_num = 0 score = 0 matches = 0 game_over = False cards_left_covered = 0 #timer start time start_time = pygame.time.get_ticks() time = 0 end_time = 0 # 新增最终用时变量 # create screen screen = pygame.display.set_mode([screen_width, screen_height]) pygame.display.set_caption('Memory Game!') #sets fonts large_font = pygame.font.Font('freesansbold.ttf', 56) small_font = pygame.font.Font('freesansbold.ttf', 26) def generate_board(): global options_list, spaces, used for item in range(rows * cols // 2): options_list.append(item) # goes through list of options between 1-24. Guarantees that only 2 cards can be selected for item in range(rows * cols): card = options_list[random.randint(0, len(options_list) - 1)] spaces.append(card) if card in used: used.remove(card) options_list.remove(card) else: used.append(card) #Sets background colours and shapes def draw_backgrounds(): global start_time, time, end_time top_menu = pygame.draw.rect(screen, orange, [0, 0, screen_width, 75]) score_text = small_font.render(f'Player 1 score : {score}', True, white) screen.blit(score_text, (20, 20)) board_space = pygame.draw.rect(screen, turquoise, [0, 100, screen_width, screen_height - 200], 0) bottom_menu = pygame.draw.rect(screen, orange, [0, screen_height - 100, screen_width, 100], 0) # 游戏未结束时才更新时间 if not game_over: time = int((pygame.time.get_ticks() - start_time) / 1000) time_text = small_font.render(f'Your time: {time}', True, white) screen.blit(time_text, (20, 550)) else: # 游戏结束后显示最终用时 time_text = small_font.render(f'Final Time: {end_time}', True, white) screen.blit(time_text, (20, 550)) def draw_cards(): global rows, columns, correct card_list = [] for i in range(cols): for j in range(rows): #draws the cards and sets their size and position card = pygame.draw.rect(screen, orange,[i * 85 + 48, j *78 + 110, 61, 65], 0, 4) card_list.append(card) ## randomly adds numbers onto the cards. to make sure that the black numbers dont populate instantly when game is created '''card_text = small_font.render(f'{spaces[i * rows + j]}', True, black) screen.blit(card_text, (i * 75 + 18, j * 65 + 120))''' for r in range(rows): for c in range(cols): if correct[r][c] == 1: #creates green border around cards when match is made pygame.draw.rect(screen, green, [c * 85 + 48, r * 78 + 110, 61, 65], 3, 4) card_text = small_font.render(f'{spaces[c * rows + r]}', True, black) screen.blit(card_text, (c * 85 + 55, r * 78 + 125)) return card_list def check_guesses(first, second): global spaces, correct, score, matches if spaces[first] == spaces[second]: #floor division col1 = first // rows col2 = second // rows row1 = first - (first // rows * rows) row2 = second - (second // rows * rows) #checks for match and score incremented by 1 if correct[row1][col1] == 0 and correct[row2][col2] == 0: correct[row1][col1] = 1 correct[row2][col2] = 1 score += 1 matches += 1 running = True while running: timer.tick(fps) screen.fill(turquoise) if new_board: generate_board() new_board = False draw_backgrounds() board = draw_cards() if first_guess and second_guess: check_guesses(first_guess_num, second_guess_num) ##delays code for miliseconds to see second guess pygame.time.delay(1000) first_guess = False second_guess = False for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.MOUSEBUTTONDOWN: for i in range(len(board)): button = board[i] #can guess as long as it's not game over if not game_over: if button.collidepoint(event.pos) and not first_guess: first_guess = True first_guess_num = i ##ensures that the same card cannot be clicked twice if button.collidepoint(event.pos) and not second_guess and first_guess and i != first_guess_num: second_guess = True second_guess_num = i #Checks for game over if matches == rows * cols // 2 and not game_over: game_over = True end_time = time # 保存最终用时 winner = pygame.draw.rect(screen, turquoise,[0, 0, 600, 600]) winner_text = large_font.render(f'YOUR TIME WAS {end_time} !!', True, orange) screen.blit(winner_text, (70, screen_height - 350)) #allows card to be flipped to show number if first_guess: card_text = small_font.render(f'{spaces[first_guess_num]}', True, black) location = (first_guess_num // rows * 85 + 55, (first_guess_num - (first_guess_num // rows * rows)) * 78 + 125) screen.blit(card_text, (location)) if second_guess: card_text = small_font.render(f'{spaces[second_guess_num]}', True, black) location = (second_guess_num // rows * 85 + 55, (second_guess_num - (second_guess_num // rows * rows)) * 78 + 125) screen.blit(card_text, (location)) pygame.display.flip() pygame.quit()
现在这样修改后,游戏结束时计时器会停止,并且正确显示最终用时了。核心就是在游戏结束时冻结时间,并且修正时间计算的公式。
内容的提问来源于stack exchange,提问作者Adil
相关产品推荐
相关产品推荐

