如何在 pygame 上问 20 道选择题? [英] How to ask 20 multiple choice questions on pygame?

查看:58
本文介绍了如何在 pygame 上问 20 道选择题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 pygame 上为一个项目编写一个非常基本的游戏,游戏的主要功能是根据用户选择玩游戏的操作员和级别提出 20 个问题.

I am coding a very basic game on pygame for a project and the main function of the game is to ask 20 questions based on which operator(s) and level the user has picked to play the game at.

我真的在为两件事而苦苦挣扎:
第一个是我编写的代码确实产生了 20 个问题,并且具有正确的操作符和难度级别,但是我不知道每次用户回答最后一个时如何将这些问题一次一个地显示到屏幕上.目前,该代码仅显示屏幕上的最后一个问题.

I am really struggling with two things:
the first being that the code which I have written does produce 20 questions with the correct operator and level of difficulty however I don't know how to blit these to the screen one at a time each time the user has answered the last one. Currently, the code only shows the last question on the screen.

我遇到的第二个问题是为每个问题制作多项选择按钮.我的游戏中有一个按钮"类,它与您可以在代码中看到的文本"类相同,但是它也会跟踪按钮被点击的时间.
对于每个问题,我需要在屏幕上有 4 个按钮类的实例,其中一个是每个问题的正确答案,另外三个是随机数,我需要代码来随机化哪个按钮是每个问题的答案,所以答案并不总是相同的按钮.

The second problem I am having is making the multiple-choice buttons for each question. I have a 'Button' class in my game which is the same as the 'Text' class which you can see in the code however it also tracks when the button has been clicked on.
For each question, I need to have 4 instances of the button class on the screen one of which is the correct answer for each question and the other three and random numbers and I need the code to randomize which button is the answer for each question so the answer isn't always the same button.

我的游戏中还有一个秒表,这些都不会干扰它.

I also have a stopwatch in my game and none of these can interfere with it.

    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
        gameBG=pygame.image.load('gameBG.bmp').convert()
        screen.blit(gameBG,(0,0))
        questiontxt= Text((325,45),(question), (white), 80)
        questiontxt.draw(screen)
        ticks=pygame.time.get_ticks()
        if timing == False:
            timing=True
            seconds=0
        seconds=int((ticks/1000%60))
        minutes=int((ticks/60000%24))
        out='{minutes:02d}:{seconds:02d}'.format(minutes=minutes, seconds=seconds)
        timefont.render_to(screen,(855,50),out, green)
        pygame.display.update()
        clock.tick(60)

        while j < 38:
            qnum1=int(numlist[j])
            qnum2=int(numlist[j+1])
            if section == 'mixed':
                mixedno=random.randrange(0,4)
                operators=['addition','subtraction','division','multiplication']
                qsection=operators[mixedno]
            else:
                qsection=section

            if qsection == 'addition':
                question=str(qnum1)+ '+'+ str(qnum2)+' = ?'
                answer= qnum1+qnum2
            elif qsection == 'subtraction':
                question=str(qnum1)+ '-'+ str(qnum2)+' = ?'
                answer= qnum1-qnum2
            elif qsection == 'multiplication':
                question=str(qnum1)+ 'x'+ str(qnum2)+' = ?'
                answer= qnum1*qnum2
            else:
                question=str(qnum1)+'÷'+str(qnum2)+' = ?'
                answer= qnum1/qnum2

            print(question)
            questiontxt= Text((325,45),(question), (white), 80)
            questiontxt.draw(screen)
            j=j+2

推荐答案

让我们从一个新的基本 pygame 程序开始.我通常是这样开始的:

Let's start with a new, basic pygame program. I usually start like this:

import pygame

def main():
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    dt = 0
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
        screen.fill(pygame.Color('lightgrey'))
        pygame.display.flip()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

这里没什么可看的.我们创建一个窗口,将其涂成灰色,处理事件并跟踪增量时间(每帧花费的时间).

Not much to see here. We create a window, paint it grey, handle events and keep track of the delta time (the time each frame takes).

让我们思考一下游戏应该如何运作.首先,我们有一个标题画面,然后我们选择一个难度,然后我们显示一些问题,最后我们显示结果.我们将这些部分中的每一个称为场景,然后从一个跳到另一个.

Let's also think a moment of how the game is supposed to work. First, we have a title screen, then we select a difficulty, then we show some questions, and finally, we display the result. We call each of those parts a scene, and we jump from one to another.

我们可以通过以下方式实现这些:

Here's a way we could implement these:

import pygame
import pygame.freetype

class SimpleScene:

    FONT = None

    def __init__(self, text, next_scene):
        self.background = pygame.Surface((640, 480))
        self.background.fill(pygame.Color('lightgrey'))

        if text:
            if SimpleScene.FONT == None:
                SimpleScene.FONT = pygame.freetype.SysFont(None, 32)
            SimpleScene.FONT.render_to(self.background, (120, 180), text, pygame.Color('black'))
            SimpleScene.FONT.render_to(self.background, (119, 179), text, pygame.Color('white'))

        self.next_scene = next_scene

    def start(self):
        pass

    def draw(self, screen):
        screen.blit(self.background, (0, 0))

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    return self.next_scene

def main():
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    dt = 0
    scenes = {
        'TITLE': SimpleScene('PRESS SPACE TO START', 'GAME'),
        'GAME': SimpleScene('Can you press [SPACE]', 'RESULT'),
        'RESULT': SimpleScene('You win! 100 points!', 'TITLE'),
    }
    scene = scenes['TITLE']
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        next_scene = scene.update(events, dt)
        if next_scene:
            scene = scenes[next_scene]
            scene.start()

        scene.draw(screen)

        pygame.display.flip()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

我们现在可以通过按 space 在场景之间进行转换.如您所见,每个场景本身就像一个微型游戏;当然,我们只有SimpleScene,它除了绘制简单的文本之外什么都不做,所以让我们改变它并实现真正的游戏.我们还有一个游戏状态,所以我们也需要跟踪它.

We can now transition between the scenes by pressing space. As you can see, each scene is like a miniature game itself; of course we only have the SimpleScene that does nothing but draw a simple text, so let's change that and implement the real game. We also have a game state, so we need to keep track if it, too.

这是它的样子:

import pygame
import pygame.freetype
import random

class SimpleScene:

    FONT = None

    def __init__(self, next_scene, *text):
        self.background = pygame.Surface((640, 480))
        self.background.fill(pygame.Color('lightgrey'))

        y = 80
        if text:
            if SimpleScene.FONT == None:
                SimpleScene.FONT = pygame.freetype.SysFont(None, 32)
            for line in text:
                SimpleScene.FONT.render_to(self.background, (120, y), line, pygame.Color('black'))
                SimpleScene.FONT.render_to(self.background, (119, y-1), line, pygame.Color('white'))
                y += 50

        self.next_scene = next_scene
        self.additional_text = None

    def start(self, text):
        self.additional_text = text

    def draw(self, screen):
        screen.blit(self.background, (0, 0))
        if self.additional_text:
            y = 180
            for line in self.additional_text:
                SimpleScene.FONT.render_to(screen, (120, y), line, pygame.Color('black'))
                SimpleScene.FONT.render_to(screen, (119, y-1), line, pygame.Color('white'))
                y += 50

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    return (self.next_scene, None)

class GameState:
    def __init__(self, difficulty):
        self.difficulty = difficulty
        self.questions = [
            ('How many legs has a cow?', 4),
            ('How many legs has a bird?', 2),
            ('What is 1 x 1 ?', 1)
        ]
        self.current_question = None
        self.right = 0
        self.wrong = 0

    def pop_question(self):
        q = random.choice(self.questions)
        self.questions.remove(q)
        self.current_question = q
        return q

    def answer(self, answer):
        if answer == self.current_question[1]:
            self.right += 1
        else:
            self.wrong += 1

    def get_result(self):
        return f'{self.right} answers correct', f'{self.wrong} answers wrong', '', 'Good!' if self.right > self.wrong else 'You can do better!'

class SettingScene:

    def __init__(self):
        self.background = pygame.Surface((640, 480))
        self.background.fill(pygame.Color('lightgrey'))

        if SimpleScene.FONT == None:
            SimpleScene.FONT = pygame.freetype.SysFont(None, 32)

        SimpleScene.FONT.render_to(self.background, (120, 50), 'Select your difficulty level', pygame.Color('black'))
        SimpleScene.FONT.render_to(self.background, (119, 49), 'Select your difficulty level', pygame.Color('white'))

        self.rects = []
        x = 120
        y = 120
        for n in range(4):
            rect = pygame.Rect(x, y, 80, 80)
            self.rects.append(rect)
            x += 100

    def start(self, *args):
        pass

    def draw(self, screen):
        screen.blit(self.background, (0, 0))
        n = 1
        for rect in self.rects:
            if rect.collidepoint(pygame.mouse.get_pos()):
                pygame.draw.rect(screen, pygame.Color('darkgrey'), rect)
            pygame.draw.rect(screen, pygame.Color('darkgrey'), rect, 5)                
            SimpleScene.FONT.render_to(screen, (rect.x+30, rect.y+30), str(n), pygame.Color('black'))
            SimpleScene.FONT.render_to(screen, (rect.x+29, rect.y+29), str(n), pygame.Color('white'))
            n+=1

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.MOUSEBUTTONDOWN:
                n = 1
                for rect in self.rects:
                    if rect.collidepoint(event.pos):
                        return ('GAME', GameState(n))
                    n += 1

class GameScene:
    def __init__(self):
        if SimpleScene.FONT == None:
            SimpleScene.FONT = pygame.freetype.SysFont(None, 32)

        self.rects = []
        x = 120
        y = 120
        for n in range(4):
            rect = pygame.Rect(x, y, 80, 80)
            self.rects.append(rect)
            x += 100

    def start(self, gamestate):
        self.background = pygame.Surface((640, 480))
        self.background.fill(pygame.Color('lightgrey'))
        self.gamestate = gamestate
        question, answer = gamestate.pop_question()
        SimpleScene.FONT.render_to(self.background, (120, 50), question, pygame.Color('black'))
        SimpleScene.FONT.render_to(self.background, (119, 49), question, pygame.Color('white'))


    def draw(self, screen):
        screen.blit(self.background, (0, 0))
        n = 1
        for rect in self.rects:
            if rect.collidepoint(pygame.mouse.get_pos()):
                pygame.draw.rect(screen, pygame.Color('darkgrey'), rect)
            pygame.draw.rect(screen, pygame.Color('darkgrey'), rect, 5)
            SimpleScene.FONT.render_to(screen, (rect.x+30, rect.y+30), str(n), pygame.Color('black'))
            SimpleScene.FONT.render_to(screen, (rect.x+29, rect.y+29), str(n), pygame.Color('white'))
            n+=1

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.MOUSEBUTTONDOWN:
                n = 1
                for rect in self.rects:
                    if rect.collidepoint(event.pos):
                        self.gamestate.answer(n)
                        if self.gamestate.questions:
                            return ('GAME', self.gamestate)
                        else:
                            return ('RESULT', self.gamestate.get_result())
                    n += 1

def main():
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    dt = 0
    scenes = {
        'TITLE':    SimpleScene('SETTING', 'Welcome to the quiz', '', '', '', 'press [SPACE] to start'),
        'SETTING':  SettingScene(),
        'GAME':     GameScene(),
        'RESULT':   SimpleScene('TITLE', 'Here is your result:'),
    }
    scene = scenes['TITLE']
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        result = scene.update(events, dt)
        if result:
            next_scene, state = result
            if next_scene:
                scene = scenes[next_scene]
                scene.start(state)

        scene.draw(screen)

        pygame.display.flip()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

当然它不是 100% 完成,但它应该让您了解如何构建您的游戏以获得您想要的东西.

Of course it's not 100% finished, but it should give you an idea on how to structure your game to get what you want.

如您所见,每个场景处理自己的游戏方面,游戏场景在传递游戏状态的同时跳转到自身.要添加计时器,您可以在第一次调用其 start 函数时将当前游戏时间(例如 pygame.time.get_ticks())存储在游戏状态中,并计算剩余时间update 场景功能.如果计时器用完,则跳转到显示结果的场景.

As you can see, each scene handles its own aspect of the game, and the game scene jumps to itself while passing the game state. To add a timer, you can simply store the current game time (e.g. pygame.time.get_ticks()) in the game state the first time its start function is called, and calculate the remaining time in the update function of the scene. If the timer runs out, jump to a scene that displays the result.

这篇关于如何在 pygame 上问 20 道选择题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆