Как объединить списки или, альтернативно, создать список списков

У меня есть игра на память, в которой вам нужно найти пары плиток с одинаковыми изображениями. Я хочу модифицировать игру так, чтобы вам приходилось находить пары плитки с изображением и плитки с соответствующим текстом. Например, найдите плитку с изображением кота и плитку с текстом «кошка».

Чтобы понять проблему, вот код, который я считаю наиболее подходящим, показывающий, как я сейчас использую список изображений для создания пар плиток:

class Tile(object):
    def __init__(self, canvas, x, y, image, cardback):
        self.image = image
        more stuff...

class MemGame(tk.Frame):
    def __init__(self, master):
        super(MemGame, self).__init__(master)

        self.images = [
            photoDog,
            more images...
        ]

        selected = []
        for i in range(10):
            randomInd = randint(0, len(self.images) - 1)
            animalImg = self.images[randomInd]
            selected.append(animalImg)
            selected.append(animalImg)
            del self.images[randomInd]
        shuffle(selected)
        self.flippedTiles = []
        NUM_COLS = 5
        NUM_ROWS = 4

        for x in range(0, NUM_COLS):
            for y in range(0, NUM_ROWS):
                self.tiles.append(Tile(self.canvas, x * 108 + 10, y * 108 + 40, selected.pop(), photoCardback))

Я не уверен, должен ли я создать еще один список текстов или изменить список изображений на список списков с изображением и текстом.

Если нужно, вот полный код:

import tkinter as tk
from random import randint
from random import shuffle
import pygame
pygame.init()

class Controller(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        # the container is where we'll stack a bunch of frames
        # on top of each other, then the one we want visible
        # will be raised above the others
        container = tk.Frame(self)
        container.pack(side = "top", fill = "both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        if True:
            self.frames = {}
            for F in (PageMG,):
                page_name = F.__name__
                frame = F(parent=container, controller=self)
                self.frames[page_name] = frame

                # put all of the pages in the same location;
                # the one on the top of the stacking order
                # will be the one that is visible.
                frame.grid(row=0, column=0, sticky = "nsew")

            self.show_frame("PageMG")
        self.geometry("800x480")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()


class PageMG(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        x = MemGame(self)
        x.pack()


class Tile(object):
    def __init__(self, canvas, x, y, image, cardback):
        self.cardback = cardback
        self.canvas = canvas
        self.y = y
        self.x = x
        self.image = image

    def drawFaceDown(self):
        self.canvas.create_rectangle(self.x, self.y, self.x + 100, self.y + 100, fill = "white")
        self.canvas.create_image(self.x + 50, self.y + 50, image=self.cardback)
        self.isFaceUp = False

    def drawFaceUp(self):
        self.canvas.create_rectangle(self.x, self.y, self.x + 100, self.y + 100, fill = "white")
        self.canvas.create_image(self.x + 50, self.y + 50, image=self.image)
        self.isFaceUp = True

    def isUnderMouse(self, event):
        if (event.x > self.x and event.x < self.x + 100):
            if (event.y > self.y and event.y < self.y + 100):
                return True


class MemGame(tk.Frame):
    def __init__(self, master):
        super(MemGame, self).__init__(master)

        photoRestart = tk.PhotoImage(file = "restart.png")
        imgRestart = tk.Label(self, anchor = "s", image=photoRestart)
        imgRestart.image = photoRestart
        buttonRestart = tk.Button(self, activebackground = "white",
                                  image=photoRestart, highlightthickness=0, borderwidth=0,
                                  command=lambda: self.restart())
        buttonRestart.place(x=560, y=200)

        photoDog = tk.PhotoImage(file = "Dyr/dog.png")
        photoElefant = tk.PhotoImage(file = "Dyr/elefant.png")
        photoFlamingo = tk.PhotoImage(file = "Dyr/flamingo.png")
        photoFlodhest = tk.PhotoImage(file = "Dyr/flodhest.png")
        photoKamel = tk.PhotoImage(file = "Dyr/kamel.png")
        photoKatt = tk.PhotoImage(file = "Dyr/katt.png")
        photoKroko = tk.PhotoImage(file = "Dyr/krokodille.png")
        photoNeshorn = tk.PhotoImage(file = "Dyr/neshorn.png")
        photoSkilpadde = tk.PhotoImage(file = "Dyr/skilpadde.png")
        photoStruts = tk.PhotoImage(file = "Dyr/struts.png")
        photoZebra = tk.PhotoImage(file = "Dyr/zebra.png")
        photoLove = tk.PhotoImage(file = "Dyr/love.png")

        photoCardback = tk.PhotoImage(file = "cardback.png")
        self.cardback = photoCardback

        self.riktig_sound = pygame.mixer.Sound("riktig.wav")
        self.click_sound = pygame.mixer.Sound("camerashutter.wav")

        self.configure(width=650, height=480, bg = "white")
        self.canvas = tk.Canvas(self, bg = "white", width=550, height=480, highlightthickness=0, borderwidth=0)
        self.canvas.place(x=0, y=-30)
        self.tiles = []
        self.images = [
            photoDog,
            photoElefant,
            photoFlamingo,
            photoFlodhest,
            photoKamel,
            photoKatt,
            photoKroko,
            photoNeshorn,
            photoSkilpadde,
            photoStruts,
            photoZebra,
            photoLove
        ]

        selected = []
        for i in range(10):
            randomInd = randint(0, len(self.images) - 1)
            animalImg = self.images[randomInd]
            selected.append(animalImg)
            selected.append(animalImg)
            del self.images[randomInd]
        shuffle(selected)
        self.flippedTiles = []
        NUM_COLS = 5
        NUM_ROWS = 4

        for x in range(0, NUM_COLS):
            for y in range(0, NUM_ROWS):
                self.tiles.append(Tile(self.canvas, x * 108 + 10, y * 108 + 40, selected.pop(), photoCardback))

        for i in range(len(self.tiles)):
            self.tiles[i].drawFaceDown()
        self.flippedThisTurn = 0
        self.canvas.bind("<Button-1>", self.mouseClicked)

    def mouseClicked(self, event):
        for tile in self.tiles:
            if tile.isUnderMouse(event) and (self.flippedThisTurn < 2):
                if (not(tile.isFaceUp)):
                    self.clickSound()
                    tile.drawFaceUp()
                    self.flippedTiles.append(tile)
                    self.flippedThisTurn += 1

                if (self.flippedThisTurn == 2):
                    if (self.flippedTiles[-1].image == self.flippedTiles[-2].image): #check last two elements
                        self.riktig()
                    self.after(1000, self.checkTiles)

    def checkTiles(self):
        self.flippedThisTurn = 0

        if not(self.flippedTiles[-1].image == self.flippedTiles[-2].image):
            self.flippedTiles[-1].drawFaceDown()
            self.flippedTiles[-2].drawFaceDown()
            del self.flippedTiles[-2:]

    def restart(self):
        for i in range(len(self.tiles)):
            self.tiles[i].drawFaceDown()

    def riktig(self):
        pygame.mixer.Sound.play(self.riktig_sound)
        pygame.mixer.music.stop()

    def clickSound(self):
        pygame.mixer.Sound.play(self.click_sound)
        pygame.mixer.music.stop()


if __name__ == '__main__':
    c = Controller()
    c.mainloop()

Во-первых, вы не можете создать набор наборов, потому что set нельзя хэшировать. Однако можно создать набор frozensets.

ForceBru 30.05.2019 20:59

Учитывая, что в коде нет set, возможно, OP имеет в виду какую-либо коллекцию.

Jeppe 30.05.2019 22:00

Я имел в виду список, извините. я обновлю пост

Jorgen 30.05.2019 22:22

Почему бы не использовать дикт? photos = {'dog': tk.PhotoImage(file = "Dyr/dog.png"), ... }

wjandrea 30.05.2019 23:02
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
130
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что самый простой подход, который вызывает наименьшие изменения в вашем текущем коде, заключается в следующем:

  • Составьте список изображений (сделано)
  • Составьте список текстовых соответствующих плиток (чтобы сделать)
  • Составьте комбинированный список из двух вышеперечисленных и нарисуйте каждое изображение только один раз вместо двух, как вы делаете сейчас (легко).
  • Создайте словарь, который вы можете использовать для поиска совпадений (см. ниже).
  • Измените функцию «проверить плитки», чтобы увидеть, совпадают ли они с использованием словаря (изменение в одну строку).

Созданный словарь можно использовать двунаправленно, поэтому он найдет соответствие независимо от того, как выполняется сравнение.

In [6]: image_tiles = ['dog_img', 'cat_img', 'hen_img']                         

In [7]: tag_tiles = ['dog', 'cat', 'hen']                                       

In [8]: all_tiles = image_tiles + tag_tiles  # use this to draw tiles                                    

In [9]: matches = { k:v for (k, v) in zip(image_tiles, tag_tiles) }             

In [10]: # add opposite lookup                                                  

In [11]: matches.update([(k, v) for (k, v) in zip(tag_tiles, image_tiles)])     

In [12]: matches                                                                
Out[12]: 
{'dog_img': 'dog',
 'cat_img': 'cat',
 'hen_img': 'hen',
 'dog': 'dog_img',
 'cat': 'cat_img',
 'hen': 'hen_img'}

Большое спасибо за совет. Завтра утром попробую :)

Jorgen 31.05.2019 22:08

У меня проблема с методом drawFaceUp в классе Tile. Прямо сейчас он использует image для рисования плиток, но я думаю, мне нужно каким-то образом передать переменную, такую ​​​​как tile_type, в метод, а затем создать операторы if для рисования разных типов плиток?

Jorgen 02.06.2019 21:50

Я предполагал, что вы будете создавать плитки .png с текстом в них (что не должно быть так сложно), чтобы ВСЕ плитки были одного формата и размера.

AirSquid 02.06.2019 22:22

О да, это имеет смысл, ха-ха, я сделаю это вместо этого

Jorgen 02.06.2019 22:29

Не могли бы вы объяснить, как использовать словарь для создания новой функции «проверить плитки»?

Jorgen 03.06.2019 00:00

Неважно, я понял. Я приму ваш ответ сейчас :) Спасибо за помощь!

Jorgen 04.06.2019 14:16

Другие вопросы по теме