Тестер языковых навыков с использованием Pygame

Я сделал эту небольшую игру, которая проверяет наши языковые навыки. Он использует один внешний модуль, pinyin, который можно установить с помощью команды командной строки

pip install pinyin

Вот как это происходит:

введите описание изображения здесь

Как вы можете видеть из GIF, игра начинается со случайного выбора символов для верхних ящиков и произношения каждого соответствующего символа для нижних ячеек, разумеется, в случайном порядке.

Каждый раз, когда пользователь вводит символ с правильным произношением, оценка увеличивается на 10, а соответствующие поля отключаются. Каждый раз, когда пользователь вводит символ с неправильным произношением, оценка уменьшается на 5.

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

Вот мой код:

import pygame
from random import sample, shuffle, choice
import pinyin

pygame.init()
pygame.font.init()

wn = pygame.display.set_mode((600, 400))

words="的是不我一有大在人了中到資要可以這個你會好為上來就學交也用能如文時沒說他看提那問生過下請天們所多麼小想得之還"

class Text:
    def __init__(self, text, borders, font):
        self.font = font
        self.color = (255, 255, 0)
        self.text = self.font.render(text, True, self.color)
        width = self.text.get_width()
        height = self.text.get_height()
        x, y, w, h = borders
        self.pos = x + (w - width) / 2, y + (h - height) / 2
    def draw(self):
        wn.blit(self.text, self.pos)

class Score:
    def __init__(self, pos, font=pygame.font.SysFont("Californian FB", 40)):
        self.pos = pos
        self.font = font
        self.value = 0
        self.color = (255, 255, 255)
        self.up = 10
        self.down = 5
        self.potential = 0

    def score_up(self):
        self.value += 10
        
    def score_down(self):
        self.value -= 5
        self.potential += 10

    def draw(self):
        wn.blit(self.font.render(str(self.value), True, self.color), self.pos)

class Box:
    def __init__(self, bottom, x, y, w, h, word, font=pygame.font.SysFont("microsoftyaheimicrosoftyaheiui", 23)):
        self.rect = pygame.Rect(x, y, w, h)
        self.inner_rect = pygame.Rect(x + w * .125, y + h * .125, w * .75, h * .75)
        self.box_color = (100, 0, 0)
        self.port_color = (50, 0, 0)
        self.active_color = (20, 0, 0)
        self.disabled = False
        self.port = pygame.Rect(x + w / 4, y + h, w / 2, h // 8)
        self.word = word
        if bottom:
            self.port.y -= h + h // 8
            word = pinyin.get(word)
        self.text = Text(word, (x, y, w, h), font)

    def over(self, x, y):
        return self.rect.collidepoint(x, y)

    def disable(self):
        self.disabled = True
        self.box_color = (255, 50, 50)

    def draw(self, active):
        if active:
            pygame.draw.rect(wn, self.active_color, self.rect)
            pygame.draw.rect(wn, self.box_color, self.inner_rect)
        else:
            pygame.draw.rect(wn, self.box_color, self.rect)
        self.text.draw()
        if self.disabled:
            return
        pygame.draw.rect(wn, self.port_color, self.port)

class Game:
    def __init__(self, words, x, y):
        self.w = 70
        self.h = 50
        self.box_x_pad = 30
        self.box_y_pad = 120
        self.words = words
        self.in_boxes = list()
        self.out_boxes = list()
        self.active_in_box = None
        self.active_out_box = None
        for i, word in enumerate(words):
            in_box = Box(False, x + i * (self.w + self.box_x_pad), y, self.w, self.h, word)
            self.in_boxes.append(in_box)
        shuffle(words)
        for i, word in enumerate(words):
            out_box = Box(True, x + i * (self.w + self.box_x_pad), y + self.box_y_pad, self.w, self.h, word)
            self.out_boxes.append(out_box)

    def won(self):
        return all(in_box.disabled for in_box in self.in_boxes)

    def draw_lines(self, event):
        if self.active_in_box:
            if self.active_out_box:
                pygame.draw.line(wn, (255, 255, 0), self.active_in_box.port.center, self.active_out_box.port.center, 7)
            else:
                pygame.draw.line(wn, (255, 255, 0), self.active_in_box.port.center, event.pos, 7)
            
    def draw_boxes(self):
        for in_box in self.in_boxes:
            in_box.draw(in_box == self.active_in_box)
        for out_box in self.out_boxes:
            out_box.draw(out_box == self.active_out_box)

bg_color = (200, 0, 0)
game = Game(sample(words, 5), 60, 120)
score = Score((60, 50))
running = True

while running:
    wn.fill(bg_color)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            for in_box in game.in_boxes:
                if in_box.over(*event.pos) and not in_box.disabled:
                    game.active_in_box = in_box
                    break
        elif event.type == pygame.MOUSEMOTION:
            if game.active_in_box:
                for out_box in game.out_boxes:
                    if out_box.over(*event.pos) and not out_box.disabled:
                        game.active_out_box = out_box
                        break
                else:
                    game.active_out_box = None
        elif event.type == pygame.MOUSEBUTTONUP:
            if game.active_in_box and game.active_out_box:
                if game.active_out_box.word == game.active_in_box.word:
                    game.active_out_box.disable()
                    game.active_in_box.disable()
                    score.score_up()
                    if game.won():
                        game = Game(sample(words, 5), 60, 120)
                else:
                    score.score_down()
            game.active_out_box = game.active_in_box = None

    game.draw_lines(event)
    game.draw_boxes()
    score.draw()
    pygame.display.update()

pygame.quit()

Я хочу повысить эффективность своего кода и улучшить концепцию DRY моего кода.

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *