首页 > 解决方案 > 计算图像数量并比较相似度

问题描述

我正在编写一个名为“Memory”的游戏,其中包含随机顺序的 8 对图像(16 个图像)。游戏开始时,其中 16 个必须显示相同的背景图像。玩家单击任何图块后,图块会从背景图像翻转到前景图像。如果两个前景图像相同,则它们保持不变。如果两个前景图像不同,它们会在几秒钟内消失。目前,我不知道如何检查它们的相似性。我尝试使用 self.count 来计算翻转图像的数量,但无法正常工作。请帮我。非常非常感谢你!

import pygame
import random
import time

screen = pygame.display.set_mode((525, 435))

def main():
   pygame.init()
   pygame.display.set_mode((535, 435))
   pygame.display.set_caption('Memory')
   w_surface = pygame.display.get_surface() 
   game = Game(w_surface)
   game.play()
   pygame.quit()

class Game:

   def __init__(self, surface):
      self.surface = surface
      self.bg_color = pygame.Color('black')
      self.FPS = 10
      self.game_Clock = pygame.time.Clock()
      self.close_clicked = False
      self.continue_game = True
      Tile.set_surface(self.surface)
      self.grid_size = 4
      self.grid = []
      self.score = 0
      imgnames = ['./images/' + str(i) + '.jpg' for i in range(1,9)]
      self.images = [pygame.image.load(name) for name in imgnames]
      self.shuffle = self.images + self.images
      random.shuffle(self.shuffle)
      self.create_grid(self.grid_size)

   def create_grid(self, grid_size):
      for row_num in range(grid_size):
         new_row = self.create_row(row_num, grid_size)
         self.grid.append(new_row)     

   def create_row(self, row_num, size):
      tile_height = self.surface.get_height() // size
      tile_width = self.surface.get_width() // (size+1)
      one_row = [ ]
      for col_num in range(size):
         y = row_num * tile_height + 5
         x = col_num * tile_width + 5
         i = col_num*size + row_num
         one_tile = Tile(x, y, tile_width, tile_height, self.shuffle[i], self.surface)
         one_row.append(one_tile)
      return one_row

   def play(self):
      while not self.close_clicked:
         self.handle_events()
         self.draw()
         if self.continue_game:
            self.update()
            self.decide_continue()
         self.game_Clock.tick(self.FPS)

   def handle_events(self):
         events = pygame.event.get()
         for event in events:
            if event.type == pygame.QUIT:
               self.close_clicked = True
            elif event.type == pygame.MOUSEBUTTONUP:
               position = event.pos
               for row in self.grid:
                  for tile in row:
                     if tile.rect.collidepoint(position):
                        tile.flip = True

   def draw(self):
      self.surface.fill(self.bg_color)
      self.draw_score()
      for row in self.grid:
         for tile in row:
            tile.draw()
      pygame.display.update()

   def update(self):
      self.score = pygame.time.get_ticks() // 1000

   def decide_continue(self):
      pass

   def draw_score(self):
      score_string = str(self.score)    
      score_font = pygame.font.SysFont('', 48)
      score_fg_color = pygame.Color('white')
      score_image = score_font.render(score_string, True, score_fg_color)
      self.surface.blit(score_image, (430,10))

class Tile:
   def __init__(self, pos_x, pos_y, tile_numx, tile_numy, image, surface):
      self.pos_x = pos_x
      self.pos_y = pos_y
      self.numx = tile_numx
      self.numy = tile_numy
      self.image = image
      self.surface = surface
      self.flip = False
      self.count = 0
      self.rect = self.image.get_rect(topleft = (self.pos_x,self.pos_y))

   @classmethod
   def set_surface(cls, surface):
      cls.surface = surface   

   def draw(self):
      x = 0
      y = 0
      i = 0
      if self.flip == False:
         screen.blit(pygame.image.load('./images/bg.jpg'),(self.pos_x,self.pos_y))
      elif self.flip == True:
         while self.count < 2:
            screen.blit(self.image,(self.pos_x,self.pos_y))
            self.count + 1



main()

标签: pythonpython-3.xpygame

解决方案


self.count从类中删除属性Tile。不需要:

class Tile:
  # [...]

  def draw(self):
      x, y, i = 0, 0, 0
      if self.flip == False:
         screen.blit(pygame.image.load('./images/bg.jpg'),(self.pos_x,self.pos_y))
      elif self.flip == True:
         screen.blit(self.image,(self.pos_x,self.pos_y))

如果两个图块具有相同的图像,则它们是相等的。在您的代码中,2 个相等的图块共享相同的图像对象。比较.image瓷砖的属性。例如,如果有 atileA和 a tileB,那么它们相等 if tileA.image == tileB.image

将翻转的瓷砖列表添加到类Game

class Game:

   def __init__(self, surface):
      # [...]

      self.flipped = []

如果按下鼠标按钮,则找到被“单击”的图块并将其添加到翻转的图块中:

elif event.type == pygame.MOUSEBUTTONUP:

    for row in self.grid:
        for tile in row:
            if tile.rect.collidepoint(event.pos) and not tile.flip:
                tile.flip = True
                self.flipped.append(tile)

如果其中的瓦片数self.flipped为偶数(len(self.flipped) % 2 == 0),则比较列表中的最后 2 个瓦片(self.flipped[-1], self.flipped[-2])。保持相同的瓷砖。如果瓷砖不相等 ( tileA.image != tileB.image),则将它们从中删除self.flipped并翻转回来:

if len(self.flipped) > 0 and len(self.flipped) % 2 == 0:
    tileA = self.flipped[-1]
    tileB = self.flipped[-2] 
    if tileA.image != tileB.image:
        tileA.flip = False
        tileB.flip = False
        self.flipped = self.flipped[:-2]

这一切都可以应用于handle_events

class Game:

   def __init__(self, surface):
      # [...]

      self.flipped = []


  # [...]

  def handle_events(self):
         events = pygame.event.get()
         for event in events:
            if event.type == pygame.QUIT:
               self.close_clicked = True

            elif event.type == pygame.MOUSEBUTTONUP:

               if len(self.flipped) > 0 and len(self.flipped) % 2 == 0:
                  tileA = self.flipped[-1]
                  tileB = self.flipped[-2] 
                  if tileA.image != tileB.image:
                     tileA.flip = False
                     tileB.flip = False
                     self.flipped = self.flipped[:-2]

               for row in self.grid:
                  for tile in row:
                     if tile.rect.collidepoint(event.pos) and not tile.flip:
                        tile.flip = True
                        self.flipped.append(tile)

请注意,瓷砖不会在一段时间后翻转,但在单击新瓷砖时会翻转。


如果您希望瓷砖在一段时间(例如 2 秒)后自动翻转,那么我建议使用计时器事件
计时器可以由 启动pygame.time.set_timer()。它可以通过时间 0 到 停止pygame.time.set_timer()

class Game:
   def __init__(self, surface):
      # [...]
      self.flipped = []

   def handle_events(self):
         timer_id = pygame.USEREVENT + 1

         events = pygame.event.get()
         for event in events:
            if event.type == pygame.QUIT:
               self.close_clicked = True
            elif event.type == timer_id:
               pygame.time.set_timer(timer_id, 0)
               if len(self.flipped) > 0 and len(self.flipped) % 2 == 0:
                  tileA, tileB = self.flipped[-1], self.flipped[-2] 
                  if tileA.image != tileB.image:
                     tileA.flip, tileB.flip = False, False
                     self.flipped = self.flipped[:-2]

            elif event.type == pygame.MOUSEBUTTONUP:
               if len(self.flipped) > 0 and len(self.flipped) % 2 == 0:
                  tileA, tileB = self.flipped[-1], self.flipped[-2] 
                  if tileA.image != tileB.image:
                     tileA.flip, tileB.flip = False, False
                     self.flipped = self.flipped[:-2]           
               for row in self.grid:
                  for tile in row:
                     if tile.rect.collidepoint(event.pos) and not tile.flip:
                        tile.flip = True
                        self.flipped.append(tile)

               if len(self.flipped) > 0 and len(self.flipped) % 2 == 0:
                  pygame.time.set_timer(timer_id, 2000) # 2 seconds
               else:
                  pygame.time.set_timer(timer_id, 0)


推荐阅读