用pygame做一个背单词小游戏~

最终功能:显示问题和选项在页面上,根据玩家的选择作出回应,正确的选项变绿,错误的选项变红,并记录玩家的得分
先上效果图~
(1)回答正确的页面,右上角可以积分
在这里插入图片描述
(2)回答错误的页面
在这里插入图片描述
为了实现上述功能,需要考虑以下几个点:

  1. 用什么样的方式将题目和选项显示在屏幕上
  2. 如何根据玩家的回答变选项的颜色

首先,关于第一点的思路如下
因为题目和选项的内容在不断变化,给每一个问题和选项都设置一个输出语句不现实
在这种情况下,用文件就比较合适
用readlines方法读出来的文件会存到一个列表中,文件中的每一行都是列表中的一项,但是用print语句输出这个列表后发现,列表中的每一项后面都会带一个换行符
为了删除这个换行符,使用了如下方法
此处还要注意,因为文件中有中文,所以打开文件时必须加上编码方式(应该就是这个原因,我加了才对了)

   f=open(textname,encoding='utf-8')  #transfer gbk(the way of chinese text) to utf-8
        question_data=f.readlines()
        f.close()
        for question_line in question_data:
            self.data.append(question_line.strip()) #load in data[] in lines without any strip
            self.total+=1

也就是逐行读入,再逐项删除换行字符
将数据存入文件还需要一定的格式:
第一行是问题,第2-5行是选项,第6行是答案
就像这样:

接近,方法,通路
access
acess
acces
eccess
1

好了,题库的问题解决了,接下来我们考虑显示的问题
将文字显示在窗口有3步:
(1)new一个Font对象(java的术语习惯了哈哈)
(2)将字体转换为位图
(3)贴图
这里需要特别注意的是,Font没有中文,我用了这个方法显示中文:
自己下载一个中文字体的包,与py文件保存在一起,把Font构造方法中的None改成字体文件的文件名
另外,整个窗口有多处需要显示文字,为了方便,直接把上述操作打包成一个函数,代码如下:

def print_text(font,x,y,text,color=(255,255,255),shadow=True):
    #font conversion
    if shadow:
        #create 2D font
        img_text=font.render(text,True,(0,0,0))
        screen.blit(img_text,(x-2,y-2))

    img_text=font.render(text,True,color)
    screen.blit(img_text,(x,y))

这里设置了shadow参数,决定是否显示2D字体(就是普通字体后面带一块阴影哈哈)

接下来,我们来解决如何根据用户的输入来改变选项颜色的问题:
逻辑很简单:接收用户输入->判断是否正确->改变相应选项的颜色
接收用户输入+判断正误:

 #handdle player's answer
    def handdle_answer(self,player_input):
        if not self.scored and not self.failed:
            #in case to when the player have answered question without pressing enter to next
            if player_input==self.correct:
                self.scored=True
                self.score+=1
            else:
                self.wronganswer=player_input
                self.failed=True

每一题的正确答案都保存在“第六行”(题库文件把答案序号放在了每一题的最后),用correct来保存
与用户输入作对比,正确就置scored属性(下面会讲为啥定义这个变量)为True,反之把用户输入保存在wronganswer变量中,因为错误的选项需要变成红色,并置failed属性(下面会讲)为True
在近期的学习中,我觉得在某些情况下很有必要定义“flag”类型变量,就是标记,它只有两个值,可以放在if语句中做相应操作
这个某些情况,我觉得就是当你的程序需要根据某些结果做出某些反应
这里的scored和failed就是
用户输入正确时,需要将正确选项变成绿色,输入错误时,需要将用户的选择变红,正确的选项变绿

变换颜色:
我觉得这个程序的神奇之处之一就是变颜色这个操作
我们知道,颜色就在将文本贴在窗口上的函数中的一个参数
四个选项的颜色参数每一题都在变化
我们现在能利用的就是已经知道了用户的选择的选项和正确选项,而且它们都是1,2,3,4这种类型
此时就应该想到列表的下标
我们设置一个放四个选项颜色的列表,通过判断用户输入的结果来改变列表的对应项
最后直接取出列表中的对应项来做文本的颜色参数就ok

 #handdle player's answer
          #respond to correct answer
        if self.scored:
            self.colors=[white,white,white,white]  #Is this line  restless?
            self.colors[self.correct-1]=green
            print_text(font1,210,380,"CORRECT!",green)
            print_text(font2,130,420,"Press Enter For Next Question",green)
        elif self.failed:
            self.colors=[white,white,white,white]
            self.colors[self.correct-1]=green
            self.colors[self.wronganswer-1]=red
            print_text(font1,220,380,"INCORRECT!",red)
            print_text(font2,170,420,"Press Enter For Next Question",green) #former is x,latter is y

        #display answers
        print_text(font1,5,170,"ANSWERS")
        print_text(font2,20,210,"1-"+self.data[self.current+1],self.colors[0])
        print_text(font2,20,240,"2-"+self.data[self.current+2],self.colors[1])
        print_text(font2,20,270,"3-"+self.data[self.current+3],self.colors[2])
        print_text(font2,20,300,"4-"+self.data[self.current+4],self.colors[3])

好了,我觉得这个程序的精华大概就是这些
哦对,游戏的主逻辑都放在了类里,前面说的什么failed,scored 都是类的属性
其实我本来还想说一下游戏的循环,但是我一直没有把while循环理解透,下次再来吧~
另外还需说明的是,这个程序并不完全是我想出来的,我参照了Jonathan S.Harbour编写的Trivia游戏

接下来是源代码,字体文件和题库大家可以自行下载和编写,题库用记事本写就OK

import pygame
import sys
from pygame.locals import *
import time

#main logic
class Recite():
    def __init__(self,textname):
        self.data=[] #file list
        self.current=0 #data current index
        self.correct=0 #true answer
        self.score=0 #player's socre
        self.scored=False #flag
        self.failed=False #flag
        self.wronganswer=0 #player's wronganswer
        self.total=0 #total of the file's lines
        self.colors=[white,white,white,white] #options'color
        self.question_number=1 #record question number
        #load file to data list
        f=open(textname,encoding='utf-8')  #transfer gbk(the way of chinese text) to utf-8
        question_data=f.readlines()
        f.close()
        for question_line in question_data:
            self.data.append(question_line.strip()) #load in data[] in lines without any strip
            self.total+=1

    #show_question
    def show_question(self):
        print_text(font1,160,5,"CET4 WORDS TEST")
        print_text(font2,150,500-30,"Press keys (1-4) To Answer",purple)
        print_text(font2,530,5,"SCORE",purple)
        print_text(font2,550,25,str(self.score),purple)

        #get correct answer from data[]
        self.correct=int(self.data[self.current+5]) #the lines are string

        #display question
        print_text(font1,5,80,"QUESTION "+str(self.question_number))
        print_text(font2,20,120,self.data[self.current],yellow)

        #respond to correct answer
        if self.scored:
            self.colors=[white,white,white,white]  #Is this line  restless? Yes
            self.colors[self.correct-1]=green
            print_text(font1,210,380,"CORRECT!",green)
            print_text(font2,130,420,"Press Enter For Next Question",green)
        elif self.failed:
            self.colors=[white,white,white,white]
            self.colors[self.correct-1]=green
            self.colors[self.wronganswer-1]=red
            print_text(font1,220,380,"INCORRECT!",red)
            print_text(font2,170,420,"Press Enter For Next Question",green) #former is x,latter is y

        #display answers
        print_text(font1,5,170,"ANSWERS")
        print_text(font2,20,210,"1-"+self.data[self.current+1],self.colors[0])
        print_text(font2,20,240,"2-"+self.data[self.current+2],self.colors[1])
        print_text(font2,20,270,"3-"+self.data[self.current+3],self.colors[2])
        print_text(font2,20,300,"4-"+self.data[self.current+4],self.colors[3])



    #next_question
    def next_question(self):
        self.scored=False
        self.failed=False
        self.current+=6
        self.colors=[white,white,white,white]
        self.correct=0   #reset  arributes
        if self.current>self.total:
            self.current=0
        self.question_number+=1

    #handdle player's answer
    def handdle_answer(self,player_input):
        if not self.scored and not self.failed:
            #in case to when the player have answered question without pressing enter to next
            if player_input==self.correct:
                self.scored=True
                self.score+=1
            else:
                self.wronganswer=player_input
                self.failed=True


def print_text(font,x,y,text,color=(255,255,255),shadow=True):
    #font conversion
    if shadow:
        #create 2D font
        img_text=font.render(text,True,(0,0,0))
        screen.blit(img_text,(x-2,y-2))

    img_text=font.render(text,True,color)
    screen.blit(img_text,(x,y))

#program initialized
#create pygame windows,and make preparations to the game
pygame.init()
screen=pygame.display.set_mode((600,500))
pygame.display.set_caption("Cet-4 words dictation")
font1=pygame.font.Font('mnjyx.ttf',40)  #Chinese font or it can't be identified
font2=pygame.font.Font('mnjyx.ttf',24)
white=255,255,255
purple=255,0,255
yellow=255,255,0
green=0,255,0
red=255,0,0


#new a object
recite=Recite("CET4 words.txt")

#game loop
while True:
    for event in pygame.event.get():
        if event.type== QUIT:
            sys.exit()
        elif event.type==KEYUP:
            if event.key==pygame.K_ESCAPE:
                sys.exit()
            elif event.key==pygame.K_1:
                recite.handdle_answer(1)
            elif event.key==pygame.K_2:
                recite.handdle_answer(2)
            elif event.key==pygame.K_3:
                recite.handdle_answer(3)
            elif event.key==pygame.K_4:
                recite.handdle_answer(4)
            elif event.key==pygame.K_RETURN:
                recite.next_question()
        #clear screen
        screen.fill((0,0,200))

        #show_question
        recite.show_question()

        time.sleep(0.0005)

        #update
        pygame.display.update()

如果我的代码还有可以优化改进的部分,欢迎各路大神指出

自认为今后功能优化可以有:
1.题库存放到数据库里,通过数据库来调
2.将玩家答错的题提取出来,定期发送到他的微信上,提醒他背诵
(因为前两天看到一个文章说可以用python写一个微信提醒备忘录,觉得hen6)
3. 联机玩儿法,在规定的时间,看谁答对的最多,并设置排行榜

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个pygame制作的简单小游戏示例: ```python import pygame import random # 初始化pygame pygame.init() # 设置游戏窗口的大小 screen_width = 400 screen_height = 400 screen = pygame.display.set_mode((screen_width, screen_height)) # 设置游戏标题 pygame.display.set_caption("小游戏") # 设置游戏背景颜色 background_color = (255, 255, 255) # 设置游戏结束的标志 game_over = False # 设置游戏时钟 clock = pygame.time.Clock() # 定义玩家的位置和大小 player_size = 50 player_x = screen_width / 2 - player_size / 2 player_y = screen_height - player_size - 10 # 定义敌人的位置和大小 enemy_size = 50 enemy_x = random.randint(0, screen_width - enemy_size) enemy_y = 0 enemy_speed = 10 # 定义得分 score = 0 font = pygame.font.SysFont(None, 25) # 游戏循环 while not game_over: # 处理游戏事件 for event in pygame.event.get(): if event.type == pygame.QUIT: game_over = True # 获取键盘按键状态 keys = pygame.key.get_pressed() if keys[pygame.K_LEFT] and player_x > 0: player_x -= 5 elif keys[pygame.K_RIGHT] and player_x < screen_width - player_size: player_x += 5 # 移动敌人 enemy_y += enemy_speed if enemy_y > screen_height: enemy_x = random.randint(0, screen_width - enemy_size) enemy_y = 0 score += 10 enemy_speed += 1 # 判断是否碰撞 if (enemy_x >= player_x and enemy_x < player_x + player_size) or (player_x >= enemy_x and player_x < enemy_x + enemy_size): if (enemy_y >= player_y and enemy_y < player_y + player_size) or (player_y >= enemy_y and player_y < enemy_y + enemy_size): game_over = True # 绘制游戏界面 screen.fill(background_color) pygame.draw.rect(screen, (255, 0, 0), (enemy_x, enemy_y, enemy_size, enemy_size)) pygame.draw.rect(screen, (0, 0, 255), (player_x, player_y, player_size, player_size)) # 绘制得分 text = font.render("得分: " + str(score), True, (0, 0, 0)) screen.blit(text, (10, 10)) # 更新游戏显示 pygame.display.update() # 控制游戏帧率 clock.tick(30) # 退出游戏 pygame.quit() ``` 这个小游戏的规则很简单,玩家需要控制一个方块躲避从屏幕上方下落的另一个方块,同时获得尽可能高的得分。玩家可以使用左右箭头键来移动自己的方块。如果玩家的方块与下落的方块相撞,游戏结束。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值