记忆游戏不匹配瓷砖 [英] Memory game not matching tiles
问题描述
我正在制作一个记忆游戏,我无法让程序检查瓷砖是否匹配,如果它们匹配,则让瓷砖保持暴露状态,如果瓷砖不匹配,则保持瓷砖暴露一秒钟.第 116-122 行我认为程序的一部分应该检查但它永远不会为 is_matching() 返回 true.我觉得我应该检查实际的瓷砖本身是否彼此相等,但对我来说,这似乎适得其反,因为瓷砖只是网格上的一个位置,而图像是在瓷砖上绘制的?提前致谢
# 代码示例 2#导入pygame随机导入导入时间# 用户自定义函数定义主():# 初始化所有pygame模块(有些需要初始化)pygame.init()# 创建一个pygame显示窗口pygame.display.set_mode((500, 400))# 设置显示窗口的标题pygame.display.set_caption('井字游戏')# 获取显示面w_surface = pygame.display.get_surface()# 创建一个游戏对象游戏 = 游戏(w_surface)# 通过调用游戏对象上的 play 方法开始主游戏循环游戏.play()# 退出pygame并清理pygame窗口pygame.quit()# 用户定义的类课堂游戏:# 这个类中的一个对象代表一个完整的游戏.def __init__(self,surface):# 初始化游戏.# - self 是要初始化的游戏# - 表面是显示窗口表面对象# === 对象是我们将讨论的每个游戏的一部分self.surface = 表面self.bg_color = pygame.Color('黑色')self.FPS = 60self.game_Clock = pygame.time.Clock()self.close_clicked = Falseself.continue_game = True# === 游戏特定对象self.board = []self.score = [0]self.board_size = 4self.create_board()self.click = 0自我暴露 = 0self.first_image= 无self.second_image= 无self.tile1 = 无self.tile2 = 无self.match = 无def create_board(self):Tile.set_surface(self.surface)# width = self.surface.get_width()//self.board_size# height = self.surface.get_height()//self.board_size# 图像是表面类型self.images = []new_image =['image1.bmp','image2.bmp','image3.bmp','image4.bmp','image5.bmp','image6.bmp','image7.bmp','image8.bmp','image1.bmp','image2.bmp','image3.bmp','image4.bmp','image5.bmp','image6.bmp','image7.bmp','image8.bmp']对于 new_image 中的 file_name:图像 = pygame.image.load(file_name)self.images.append(image)# random.shuffle(self.images)cover = pygame.image.load('image0.bmp')#image1 = pygame.image.load(images_list)宽度 = image.get_width()高度 = image.get_height()对于范围内的 row_index(0,self.board_size):行 = []对于范围内的 col_index(0,self.board_size):x = 宽度 * col_indexy = 高度 * row_indeximageindex = row_index * self.board_size + col_index图像 = self.images[图像索引]瓷砖 = 瓷砖(x,y,图像,封面)row.append(tile)self.board.append(row)定义播放(自我):# 玩游戏直到玩家按下关闭框.# - self 是应该继续与否的游戏.while not self.close_clicked: # 直到玩家点击关闭框# 播放帧self.handle_events()self.draw()如果 self.continue_game:自我更新()self.decide_continue()self.game_Clock.tick(self.FPS) # 最多以每秒 FPS 帧数运行def handle_events(self):# 通过适当地改变游戏状态来处理每个用户事件.# - self 是将处理其事件的游戏事件 = pygame.event.get()对于事件中的事件:如果 event.type == pygame.QUIT:self.close_clicked = True如果 event.type == pygame.MOUSEBUTTONUP 和 self.continue_game == True:self.handle_mouse_up(事件)定义更新(自我):# 更新下一帧的游戏对象.# - self 是要更新的游戏self.score[0] = pygame.time.get_ticks()//1000如果 self.first_image != None 和 self.match:打印(self.check_matching())self.first_image = 无self.tile1 = 无self.second_image = 无self.tile2 = 无自我暴露 += 1打印(自我曝光)如果 self.first_image != 无:如果 self.second_image != None 而不是 self.match:# time.sleep(1)打印(self.check_matching())self.tile1.hide_tile()self.tile2.hide_tile()self.second_image = 无self.tile2 = 无self.first_image = 无self.tile1 = 无def handle_mouse_up(self,event):对于 self.board 中的行:对于行中的瓷砖:valid_click = tile.select(event.pos)如果 valid_click == True:# self.number_exposed += 1# time.sleep(1)tile.expose_tile()打印(self.click)如果 self.click == 0:self.first_image = tile.imageself.tile1 = 瓷砖elif self.click == 1:self.second_image = tile.imageself.tile2 = 瓷砖self.click += 1打印(self.first_image)打印(self.second_image)如果 self.click >1:self.click = 0定义绘制(自我):# 绘制所有游戏对象.# - self 是要绘制的游戏# 绘制瓷砖self.surface.fill(self.bg_color) # 先清空显示面对于 self.board 中的 each_row:对于 each_row 中的 each_tile:each_tile.draw()self.draw_score()pygame.display.update() # 使更新的表面出现在显示器上def draw_score(self):# 1.设置颜色大小 = self.surface.get_width()fg_color = pygame.Color('白色')# 2.创建字体对象font = pygame.font.SysFont('', 70)# 3 通过渲染字体创建一个文本框text_string = '' + str(self.score[0])text_box = font.render(text_string, True, fg_color, self.bg_color)surface_height = self.surface.get_width()text_box_height = text_box.get_width()位置 = (surface_height - text_box_height, 0)# 4 计算文本框的位置#location = (430, 0)# 5 Blit 或 pin 文本框在表面上self.surface.blit(text_box, location)定义决定_继续(自我):如果 self.exposed >= 1:self.continue_game = Falsedef check_matching(self):self.match = self.first_image == self.second_image返回 self.match# 检查并记住游戏是否应该继续# - self 是要检查的游戏类瓷砖:表面 = 无边框尺寸 = 3border_color = pygame.Color('黑色')# 这个类中的一个对象代表一个会移动的点@类方法def set_surface(cls,game_surface):cls.surface = game_surface# 实例方法def __init__(self,x, y, image, cover):self.image = 图像self.cover = 封面self.covered = 真宽度 = self.image.get_width()高度 = self.image.get_height()self.rect = pygame.Rect(x, y, 宽度, 高度)定义绘制(自我):pygame.draw.rect(Tile.surface,Tile.border_color,self.rect,Tile.border_size)Tile.surface.blit(self.image,self.rect)如果自我覆盖:Tile.surface.blit(self.cover, self.rect)别的:Tile.surface.blit(self.image, self.rect)# 在曲面上画点# - self 是点定义选择(自我,位置):valid_click = 假如果 self.rect.collidepoint(position):如果自我覆盖:valid_click = 真self.expose_tile()别的:valid_click = 假返回 valid_clickdefexpose_tile(self):# 如果一个图块被点击,这个方法将显示该图块下面的图片self.covered = 假def hide_tile(self):self.covered = 真def __eq__(self, other_tile):如果 self.first_image == other_tile.image:返回真别的:返回错误主要的()
tiles 不匹配,因为你实际上做的是比较图像对象:
<块引用>self.match = self.first_image == self.second_image
但每个图像都加载了两次.因为每张图片都是针对不同的对象生成的,所以它们永远不会匹配.
加载每个图像一次并将其用于 2 个匹配的图块:
# 定义唯一的图像名称new_image =['image1.bmp','image2.bmp','image3.bmp','image4.bmp','image5.bmp','image6.bmp','image7.bmp','image8.bmp']# 加载每个唯一的图像对于 new_image 中的 file_name:图像 = pygame.image.load(file_name)self.images.append(image)# 创建一个列表,其中每个加载的图像对象被使用两次self.images = self.images + self.images
此外,由于图像名称只是数量不同,可以简化名称列表的定义:
new_image = ['image' + str(i) + '.bmp' for i in range(1,9)]
<小时>
根据推荐扩展
<块引用>延时怎么样
完全删除self.first_image
和self.second_image
.适应 Tile
:
class Tile:# [...]def __eq__(self, other_tile):返回 self.image == other_tile.image
点击磁贴后,将它们保留在 self.tile1
和 self.tile2
中.当第一次点击发生时,隐藏暴露的瓷砖,如果它们不匹配:
if self.click == 0:如果 self.tile1 != self.tile2:如果 self.tile1:self.tile1.hide_tile()如果 self.tile2:self.tile2.hide_tile()
当第二次点击发生时,设置它们必须被自动覆盖的时间(例如 pygame.time.get_ticks() + 2000
):
elif self.click == 1:self.tile2 = 瓷砖self.hide_time = pygame.time.get_ticks() + 2000
评估是否必须在 update
中覆盖图块:
ticks = pygame.time.get_ticks()如果 self.tile1 和 self.tile2:if self.tile1 != self.tile2 and self.hide_time >0 和刻度 >self.hide_time:self.tile1.hide_tile()self.tile2.hide_tile()
对代码的更改:
class 游戏:def __init__(self,surface):# [...]self.hide_time = 0# [...]定义更新(自我):滴答 = pygame.time.get_ticks()self.score[0] = ticks//1000如果 self.tile1 和 self.tile2:if self.tile1 != self.tile2 and self.hide_time >0 和刻度 >self.hide_time:self.tile1.hide_tile()self.tile2.hide_tile()def handle_mouse_up(self,event):self.hide_time = 0如果 self.click == 0:如果 self.tile1 != self.tile2:如果 self.tile1:self.tile1.hide_tile()如果 self.tile2:self.tile2.hide_tile()瓷砖 = [t for row in self.board for t in row if t.select(event.pos) and not t.covered]如果有(瓷砖):瓷砖 = 瓷砖 [0]如果 self.click == 0:self.tile1 = 瓷砖elif self.click == 1:self.tile2 = 瓷砖self.hide_time = pygame.time.get_ticks() + 2000tile.expose_tile()self.click += 1如果 self.click >1:self.click = 0# [...]def check_matching(self):self.match = self.tile1.image == self.tile2.image返回 self.match
I am making a memory game and I can't get the program to check if the tiles match and if they do match get the tiles to stay exposed, and keep the tiles exposed for one second if the tiles don't match. lines 116-122 I think that part of the program is supposed to check but it never returns true for is_matching(). I feel like I am supposed to check if the actual tiles themselves are equal to each other but to me, that seems counterproductive because the tile is just a location on the grid and the image is what's drawn on the tile?? thanks in advance
# Code Example 2
#
import pygame
import random
import time
# User-defined functions
def main():
# initialize all pygame modules (some need initialization)
pygame.init()
# create a pygame display window
pygame.display.set_mode((500, 400))
# set the title of the display window
pygame.display.set_caption('Tic Tac Toe')
# get the display surface
w_surface = pygame.display.get_surface()
# create a game object
game = Game(w_surface)
# start the main game loop by calling the play method on the game object
game.play()
# quit pygame and clean up the pygame window
pygame.quit()
# User-defined classes
class Game:
# An object in this class represents a complete game.
def __init__(self, surface):
# Initialize a Game.
# - self is the Game to initialize
# - surface is the display window surface object
# === objects that are part of every game that we will discuss
self.surface = surface
self.bg_color = pygame.Color('black')
self.FPS = 60
self.game_Clock = pygame.time.Clock()
self.close_clicked = False
self.continue_game = True
# === game specific objects
self.board = []
self.score = [0]
self.board_size = 4
self.create_board()
self.click = 0
self.exposed = 0
self.first_image= None
self.second_image= None
self.tile1 = None
self.tile2 = None
self.match = None
def create_board(self):
Tile.set_surface(self.surface)
# width = self.surface.get_width()//self.board_size
# height = self.surface.get_height() // self.board_size
# image is of type surface
self.images = []
new_image =['image1.bmp','image2.bmp','image3.bmp','image4.bmp', 'image5.bmp','image6.bmp','image7.bmp',
'image8.bmp','image1.bmp','image2.bmp','image3.bmp','image4.bmp', 'image5.bmp','image6.bmp',
'image7.bmp','image8.bmp']
for file_name in new_image:
image = pygame.image.load(file_name)
self.images.append(image)
# random.shuffle(self.images)
cover = pygame.image.load('image0.bmp')
#image1 = pygame.image.load(images_list)
width = image.get_width()
height = image.get_height()
for row_index in range(0, self.board_size):
row = []
for col_index in range(0, self.board_size):
x = width * col_index
y = height * row_index
imageindex = row_index * self.board_size + col_index
image = self.images[imageindex]
tile = Tile(x,y,image,cover)
row.append(tile)
self.board.append(row)
def play(self):
# Play the game until the player presses the close box.
# - self is the Game that should be continued or not.
while not self.close_clicked: # until player clicks close box
# play frame
self.handle_events()
self.draw()
if self.continue_game:
self.update()
self.decide_continue()
self.game_Clock.tick(self.FPS) # run at most with FPS Frames Per Second
def handle_events(self):
# Handle each user event by changing the game state appropriately.
# - self is the Game whose events will be handled
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
self.close_clicked = True
if event.type == pygame.MOUSEBUTTONUP and self.continue_game == True:
self.handle_mouse_up(event)
def update(self):
# Update the game objects for the next frame.
# - self is the Game to update
self.score[0] = pygame.time.get_ticks() // 1000
if self.first_image != None and self.match:
print(self.check_matching())
self.first_image = None
self.tile1 = None
self.second_image = None
self.tile2 = None
self.exposed += 1
print(self.exposed)
if self.first_image != None:
if self.second_image != None and not self.match:
# time.sleep(1)
print(self.check_matching())
self.tile1.hide_tile()
self.tile2.hide_tile()
self.second_image = None
self.tile2 = None
self.first_image = None
self.tile1 = None
def handle_mouse_up(self,event):
for row in self.board:
for tile in row:
valid_click = tile.select(event.pos)
if valid_click == True:
# self.number_exposed += 1
# time.sleep(1)
tile.expose_tile()
print(self.click)
if self.click == 0:
self.first_image = tile.image
self.tile1 = tile
elif self.click == 1:
self.second_image = tile.image
self.tile2 = tile
self.click += 1
print(self.first_image)
print(self.second_image)
if self.click > 1:
self.click = 0
def draw(self):
# Draw all game objects.
# - self is thae Game to draw
# draw tiles
self.surface.fill(self.bg_color) # clear the display surface first
for each_row in self.board:
for each_tile in each_row:
each_tile.draw()
self.draw_score()
pygame.display.update() # make the updated surface appear on the display
def draw_score(self):
# 1. Set the color
size = self.surface.get_width()
fg_color = pygame.Color('white')
# 2.create the font object
font = pygame.font.SysFont('', 70)
# 3 Create a text box by rendering the font
text_string = '' + str(self.score[0])
text_box = font.render(text_string, True, fg_color, self.bg_color)
surface_height = self.surface.get_width()
text_box_height = text_box.get_width()
location = (surface_height - text_box_height, 0)
# 4 Compute the location of the text box
#location = (430, 0)
# 5 Blit or pin the text box on the surface
self.surface.blit(text_box, location)
def decide_continue(self):
if self.exposed >= 1:
self.continue_game = False
def check_matching(self):
self.match = self.first_image == self.second_image
return self.match
# Check and remember if the game should continue
# - self is the Game to check
class Tile:
surface = None
border_size = 3
border_color = pygame.Color('black')
# An object in this class represents a Dot that moves
@classmethod
def set_surface(cls,game_surface):
cls.surface = game_surface
# instance method
def __init__(self,x , y, image, cover):
self.image = image
self.cover = cover
self.covered = True
width = self.image.get_width()
height = self.image.get_height()
self.rect = pygame.Rect(x, y, width, height)
def draw(self):
pygame.draw.rect(Tile.surface,Tile.border_color,self.rect,Tile.border_size)
Tile.surface.blit(self.image,self.rect)
if self.covered:
Tile.surface.blit(self.cover, self.rect)
else:
Tile.surface.blit(self.image, self.rect)
# Draw the dot on the surface
# - self is the Dot
def select(self, position):
valid_click = False
if self.rect.collidepoint(position):
if self.covered:
valid_click = True
self.expose_tile()
else:
valid_click = False
return valid_click
def expose_tile(self):
# if a tile is clicked this method will show the picture underneath that tile
self.covered = False
def hide_tile(self):
self.covered = True
def __eq__(self, other_tile):
if self.first_image == other_tile.image:
return True
else:
return False
main()
The tiles do not match, because what you actually do is to compare image objects:
self.match = self.first_image == self.second_image
but each image is loaded twice. For each image are generated to different objects, so they will never match.
Load each image once and use it for 2 matching tiles:
# define unique image names
new_image =['image1.bmp','image2.bmp','image3.bmp','image4.bmp',
'image5.bmp','image6.bmp','image7.bmp','image8.bmp']
# load each unique image
for file_name in new_image:
image = pygame.image.load(file_name)
self.images.append(image)
# create a list where each loaded image object is used twice
self.images = self.images + self.images
Furthermore, since the image names just differ in the number, the definition of the name list can be simplified:
new_image = ['image' + str(i) + '.bmp' for i in range(1,9)]
Extension according to the commend
what about the time delay
Completely remove self.first_image
and self.second_image
. Adapt Tile
:
class Tile:
# [...]
def __eq__(self, other_tile):
return self.image == other_tile.image
Once tiles have been clicked then keep them stated in self.tile1
and self.tile2
. When the 1st click occurs, then hide the exposed tiles, if they do not match:
if self.click == 0:
if self.tile1 != self.tile2:
if self.tile1:
self.tile1.hide_tile()
if self.tile2:
self.tile2.hide_tile()
When the 2nd click occurs then set the time (e.g. pygame.time.get_ticks() + 2000
) when they have to be covered automatically:
elif self.click == 1:
self.tile2 = tile
self.hide_time = pygame.time.get_ticks() + 2000
Evaluate if the tiles have to be covered in update
:
ticks = pygame.time.get_ticks()
if self.tile1 and self.tile2:
if self.tile1 != self.tile2 and self.hide_time > 0 and ticks > self.hide_time:
self.tile1.hide_tile()
self.tile2.hide_tile()
Changes to your code:
class Game:
def __init__(self, surface):
# [...]
self.hide_time = 0
# [...]
def update(self):
ticks = pygame.time.get_ticks()
self.score[0] = ticks // 1000
if self.tile1 and self.tile2:
if self.tile1 != self.tile2 and self.hide_time > 0 and ticks > self.hide_time:
self.tile1.hide_tile()
self.tile2.hide_tile()
def handle_mouse_up(self,event):
self.hide_time = 0
if self.click == 0:
if self.tile1 != self.tile2:
if self.tile1:
self.tile1.hide_tile()
if self.tile2:
self.tile2.hide_tile()
tiles = [t for row in self.board for t in row if t.select(event.pos) and not t.covered]
if any(tiles):
tile = tiles[0]
if self.click == 0:
self.tile1 = tile
elif self.click == 1:
self.tile2 = tile
self.hide_time = pygame.time.get_ticks() + 2000
tile.expose_tile()
self.click += 1
if self.click > 1:
self.click = 0
# [...]
def check_matching(self):
self.match = self.tile1.image == self.tile2.image
return self.match
这篇关于记忆游戏不匹配瓷砖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!