之前用pygame完成了刮刮乐的游戏,也就是一个:4×4的方格,16只动物图片随机排序,点击后显示随机数字。如下图。
具体内容见:pygame设计一个刮刮乐加分小游戏小程序,教师加分奖,翻牌游戏
完成后想到可以利用这种方法,设计一个舒尔特方格的游戏,也可以设计一个记忆力训练翻牌游戏。先来尝试舒尔特方格游戏。
初步设想思路如下:
3*3方格,9个数字。数字位置随机。点击正确的数字时,该数字变色。点击错误的数字时,发出错误的提示音,该数字不变色。开始按钮和重新开始按钮的设计~~显示计时时间,且玩家全部完成后要结束计时,并显示总用时。~封装成exe文件。ok,边做边琢磨。
STEP1前期准备。
安装python。win+R,输入cmd,进入命令提示符。。安装pygame:pip install pygame
安装python转exe的工具PyInstaller:pip install PyInstaller
安装numpy:pip install numpy
准备图片,我是用ppt设计了图片,并另存为图片。
然后利用画图软件修改图片像素为200×200。完成后如下图:
其中,白色数字为未点击状态,蓝色数字为点击后数字。文件吗分别为pic什么和qic什么。
STEP2. 9幅数字图片显示
import pygameimport sysimport randomimport numpy as npimport itertoolspygame.init() # 初始化pygamesize = width, height = 600, 600 # 设置窗口大小screen = pygame.display.set_mode(size) # 显示窗口Xpts=[0, 200, 400]Ypts=[0, 200, 400]map = np.array(list(itertools.product(Xpts, Ypts))) #9幅图片坐标status = [0 for i in range(9)] #是否被翻开的状态位list1 = [[i] for i in range(9)]random.shuffle(list1)#将图片打乱顺序,并载入图片print(list1) #注意该句,下面要用到它输出的数组。for i in range(9): #这里必须 9screen.blit(pygame.image.load("pic/pic" + str(*list1[i-1]) + ".jpg"), map[i])while True: # 死循环确保窗口一直显示for event in pygame.event.get(): # 遍历所有事件if event.type == pygame.QUIT: sys.exit()pygame.display.flip() # 更新全部显示pygame.quit() # 退出pygame
上面的代码和之前刮刮乐游戏的代码是一样的,只不过图片数量变为9幅,去掉了点击后图片变化效果(之前刮刮乐程序是点击图片呕随机出现一张分数图片,这里不能随机出现了,只能出现和点击的一样的蓝色图片)。
STEP3 设计点击后图片变色效果
要注意程序中这句代码:
print(list1) #注意该句,下面要用到它输出的数组。
为了确定点开的到底是哪幅图片以便显示点击后的图片,要去研究pygame的界面和输出的数组对应的关系。
对上图的说明:数组中的数字是显示图片时打乱的顺序,也就是将0-8这9个数字随机排序,然后系统依次显示这9个数字对应的图片,第1个数字“7”对应的图片为8号图片(第1幅图),但它显示在了第一列第2个;第2个数字“1”对应图片为2号图片,显示在了第一列第3(第2幅图),所以图片的显示顺序为:
而上面图片中的坐标则为每一幅图片的左上角的坐标。(不用管)
添加点击效果,进行测试:
代码如下:
for i in range(9):if event.type == pygame.MOUSEBUTTONDOWN and map[i][0]<=event.pos[0]<=map[i][0] + 200 and map[i][1]<=event.pos[1]<=map[i][1] + 200 and status[i] != 1: #判断鼠标位置以及是否摁了下去。:print(i)
发现变量i的分布如图:
for i in range(9):if event.type == pygame.MOUSEBUTTONDOWN and map[i][0]<=event.pos[0]<=map[i][0] + 200 and map[i][1]<=event.pos[1]<=map[i][1] + 200 and status[i] != 1: #判断鼠标位置以及是否摁了下去。:print(i)screen.blit(pygame.image.load("pic/qic" + str(*list1[i-1])+ ".jpg"), map[i])
上面的代码:当点击一个图片后,获取变量i值,如果i=2,说明点击了第1列第3幅图,对应随机图片list1数组里的图片顺序为第2张图片。注意代码list1[]前面的星号。
screen.blit(pygame.image.load("pic/qic" + str(*list1[i-1])+ ".jpg"), map[i])
运行后效果如下:
STEP4 设计顺序点击才变色的效果。
增加了zero的变量,初始值为0,根据确定的i值,找到list1列表中的翻开的数字图片,判断是否是最小的图片。添加了音效,如果按的数字不是小的播放音效。音效提前放到了sound文件夹下。
import pygameimport sysimport randomimport numpy as npimport itertoolspygame.init() # 初始化pygamesize = width, height = 600, 600 # 设置窗口大小screen = pygame.display.set_mode(size) # 显示窗口Xpts=[0, 200, 400]Ypts=[0, 200, 400]map = np.array(list(itertools.product(Xpts, Ypts))) #9幅图片坐标zero = 0 #此处添加了一个变量用来确保从最小的数字开始变。list1 = [[i] for i in range(9)]random.shuffle(list1)#将动物图片打乱顺序,并载入图片print(list1)for i in range(9): #这里必须 9screen.blit(pygame.image.load("pic/pic" + str(*list1[i-1]) + ".jpg"), map[i])wavFileName = 'sound/sound1.wav'#载入音效sndTrack = pygame.mixer.music.load(wavFileName)while True: # 死循环确保窗口一直显示for event in pygame.event.get(): # 遍历所有事件if event.type == pygame.QUIT: # 如果单击关闭窗口,则退出sys.exit()for i in range(9):if event.type == pygame.MOUSEBUTTONDOWN and map[i][0]<=event.pos[0]<=map[i][0] + 200 and map[i][1]<=event.pos[1]<=map[i][1] + 200: #判断鼠标位置以及是否摁了下去。:print(i)if int(*list1[i-1]) <= zero:screen.blit(pygame.image.load("pic/qic" + str(*list1[i-1])+ ".jpg"), map[i])zero = zero + 1else:pygame.mixer.music.play() #错误时播放音乐pygame.display.flip() # 更新全部显示pygame.quit() # 退出pygame
运行效果见下图:
STEP5 添加开始界面。
import pygameimport sysimport randomimport numpy as npimport itertoolspygame.init() # 初始化pygamesize = width, height = 600, 600 # 设置窗口大小screen = pygame.display.set_mode(size) # 显示窗口pygame.display.set_caption("舒尔特方格") # 给窗口取个名#clock = pygame.time.Clock()# 游戏刷新速度#图片准备Xpts=[0, 200, 400]Ypts=[0, 200, 400]map = np.array(list(itertools.product(Xpts, Ypts))) #9幅图片坐标zero = 0 #此处添加了一个变量用来确保从最小的数字开始变。pic_zreo = 1list1 = [[i] for i in range(9)]random.shuffle(list1)#将动物图片打乱顺序wavFileName = 'sound/sound1.wav' # 载入音效sndTrack = pygame.mixer.music.load(wavFileName)# 开始界面start_page = Truewhile start_page:for event in pygame.event.get(): # 遍历所有事件if event.type == pygame.QUIT: # 如果单击关闭窗口,则退出sys.exit()screen.blit(pygame.image.load("pic/start0.jpg"), (200, 200))t_x, t_y = pygame.mouse.get_pos()if 200 <= t_x <= 500 and 200 <= t_y <= 290:screen.blit(pygame.image.load("pic/start1.jpg"), (200, 200))if event.type == pygame.MOUSEBUTTONDOWN and 200 <= t_x <= 500 and 200 <= t_y <= 290:start_page = Falsegame_page = Truepygame.display.flip()#游戏界面while game_page:while pic_zreo:for i in range(9): # 这里必须 9screen.blit(pygame.image.load("pic/pic" + str(*list1[i - 1]) + ".jpg"), map[i])print("hahaha")pic_zreo = 0for event in pygame.event.get(): # 遍历所有事件if event.type == pygame.QUIT: # 如果单击关闭窗口,则退出sys.exit()for i in range(9):if event.type == pygame.MOUSEBUTTONDOWN and map[i][0]<=event.pos[0]<=map[i][0] + 200 and map[i][1]<=event.pos[1]<=map[i][1] + 200: #判断鼠标位置以及是否摁了下去。:print(i)if int(*list1[i-1]) <= zero:screen.blit(pygame.image.load("pic/qic" + str(*list1[i-1])+ ".jpg"), map[i])zero = zero + 1else:pygame.mixer.music.play() #错误时播放音乐pygame.display.flip() # 更新全部显示pygame.quit() # 退出pygame
在游戏界面开始的时候设置的pic_zero状态位是为了防止题目一直刷新,点击后变色又变了回来。它怎么会一直运行呢,奇怪。说明我对里面的循环还不清楚。
添加了两张图片“开始游戏”。
运行效果如图:
鼠标放上去变色。
点击后进入游戏界面。
STEP6 添加计时器、重新开始的按钮和主循环
import pygameimport sysimport randomimport numpy as npimport itertoolsimport timepygame.init() # 初始化pygamesize = width, height = 600, 600 # 设置窗口大小screen = pygame.display.set_mode(size) # 显示窗口pygame.display.set_caption("舒尔特方格") # 给窗口取个名#图片准备Xpts=[0, 200, 400]Ypts=[0, 200, 400]map = np.array(list(itertools.product(Xpts, Ypts))) #9幅图片坐标# 载入音效wavFileName = 'sound/sound1.wav'sndTrack = pygame.mixer.music.load(wavFileName)## 计时器文本准备myfont=pygame.font.Font(None,60)col=0,0,255#定义全局变量#准备题目def zhunbei1():global list1list1 = [[i] for i in range(9)]random.shuffle(list1)#开始界面def kaishi(start_page):while start_page:for event in pygame.event.get(): # 遍历所有事件if event.type == pygame.QUIT: # 如果单击关闭窗口,则退出sys.exit()screen.blit(pygame.image.load("pic/start0.jpg"), (200, 200))global t_x,t_yt_x, t_y = pygame.mouse.get_pos()if 200 <= t_x <= 500 and 200 <= t_y <= 290:screen.blit(pygame.image.load("pic/start1.jpg"), (200, 200)) #获取鼠标位置,移动到某位置时变色if event.type == pygame.MOUSEBUTTONDOWN and 200 <= t_x <= 500 and 200 <= t_y <= 290:start_page = Falsegame_page = Trueglobal time_starttime_start = time.time()pygame.display.flip()#游戏界面def youxijiemian(game_page):zero = 0 # 此处添加了一个变量用来确保从最小的数字开始变。pic_zreo = 1 # 出题界面状态,保证只刷出一次题目。while game_page:while pic_zreo:for i in range(9): # 这里必须 9screen.blit(pygame.image.load("pic/pic" + str(*list1[i - 1]) + ".jpg"), map[i])pic_zreo = 0for event in pygame.event.get(): # 遍历所有事件if event.type == pygame.QUIT: # 如果单击关闭窗口,则退出sys.exit()for i in range(9):if event.type == pygame.MOUSEBUTTONDOWN and map[i][0]<=event.pos[0]<=map[i][0] + 200 and map[i][1]<=event.pos[1]<=map[i][1] + 200: #判断鼠标位置以及是否摁了下去。:#print(i)if int(*list1[i-1]) <= zero:screen.blit(pygame.image.load("pic/qic" + str(*list1[i-1])+ ".jpg"), map[i])zero = zero + 1print(zero)if zero == 9:time_end = time.time() # 结束计时time_c = time_end - time_start # 运行所花时间print('time cost', time_c, 's')textImage = myfont.render(str(time_c), True, col)screen.blit(textImage, (100, 100))screen.blit(pygame.image.load("pic/start0.jpg"), (200, 200))if event.type == pygame.MOUSEBUTTONDOWN and 200 <= t_x <= 500 and 200 <= t_y <= 290:start_page = Truegame_page = Falsepygame.display.flip() # 更新全部显示else:pygame.mixer.music.play() #错误时播放音乐pygame.display.flip() # 更新全部显示#主循环start_page = Truegame_page = Truewhile True:zhunbei1()kaishi(start_page)youxijiemian(game_page)#pygame.quit() # 退出pygame
程序改动较大,主要有:
添加了结束时显示时间。在按下开始按钮时开始计时器,在完成题目后结束计时。设置了全局变量,如global time_start
、global list1
设置了程序循环,将程序分为3大块,分别是准备题目、开始界面、游戏界面。通过while设置死循环。
STEP7 导出生成exe件。
参看pygame设计一个刮刮乐加分小游戏小程序,教师加分奖,翻牌游戏
1.win+r打开运行,输入cmd,进入命令提示符。
2. 进入到py文件目录下。
cd D:\pylearn\shuertefangge
d:
3.输入:pyinstaller -F shuerte3.py
4. 将图片和音效放入exe文件夹下。
5.运行exe文件
程序错误。呃呃。
看样子是字体的原因。估计是分数的字体,修改一下。
myfont=pygame.font.SysFont('Comic Sans MS', 60)
命令提示符下重新打包
pyinstaller -w -F shuerte3.py
成功。
完结撒花。最后再附上完整代码:
import pygameimport sysimport randomimport numpy as npimport itertoolsimport timepygame.init() # 初始化pygamesize = width, height = 600, 600 # 设置窗口大小screen = pygame.display.set_mode(size) # 显示窗口pygame.display.set_caption("舒尔特方格") # 给窗口取个名#图片准备Xpts=[0, 200, 400]Ypts=[0, 200, 400]map = np.array(list(itertools.product(Xpts, Ypts))) #9幅图片坐标# 载入音效wavFileName = 'sound/sound1.wav'sndTrack = pygame.mixer.music.load(wavFileName)## 计时器文本准备myfont=pygame.font.SysFont('Comic Sans MS', 60)GREEN = (0,255,0)BLUE = (0,0,128)#定义全局变量#准备题目def zhunbei1():global list1list1 = [[i] for i in range(9)]random.shuffle(list1)#开始界面def kaishi(start_page):while start_page:for event in pygame.event.get(): # 遍历所有事件if event.type == pygame.QUIT: # 如果单击关闭窗口,则退出sys.exit()screen.blit(pygame.image.load("pic/start0.jpg"), (200, 200))global t_x,t_yt_x, t_y = pygame.mouse.get_pos()if 200 <= t_x <= 500 and 200 <= t_y <= 290:screen.blit(pygame.image.load("pic/start1.jpg"), (200, 200)) #获取鼠标位置,移动到某位置时变色if event.type == pygame.MOUSEBUTTONDOWN and 200 <= t_x <= 500 and 200 <= t_y <= 290:start_page = Falsegame_page = Trueglobal time_starttime_start = time.time()pygame.display.flip()#游戏界面def youxijiemian(game_page):zero = 0 # 此处添加了一个变量用来确保从最小的数字开始变。pic_zreo = 1 # 出题界面状态,保证只刷出一次题目。while game_page:while pic_zreo:for i in range(9): # 这里必须 9screen.blit(pygame.image.load("pic/pic" + str(*list1[i - 1]) + ".jpg"), map[i])pic_zreo = 0for event in pygame.event.get(): # 遍历所有事件if event.type == pygame.QUIT: # 如果单击关闭窗口,则退出sys.exit()for i in range(9):if event.type == pygame.MOUSEBUTTONDOWN and map[i][0]<=event.pos[0]<=map[i][0] + 200 and map[i][1]<=event.pos[1]<=map[i][1] + 200: #判断鼠标位置以及是否摁了下去。:#print(i)if int(*list1[i-1]) <= zero:screen.blit(pygame.image.load("pic/qic" + str(*list1[i-1])+ ".jpg"), map[i])zero = zero + 1print(zero)if zero == 9:time_end = time.time() # 结束计时time_c = time_end - time_start # 运行所花时间print('time cost', time_c, 's')textImage = myfont.render(str(time_c), True, GREEN,BLUE)screen.blit(textImage, (100, 100))screen.blit(pygame.image.load("pic/start0.jpg"), (200, 200))if event.type == pygame.MOUSEBUTTONDOWN and 200 <= t_x <= 500 and 200 <= t_y <= 290:start_page = Truegame_page = Falsepygame.display.flip() # 更新全部显示else:pygame.mixer.music.play() #错误时播放音乐pygame.display.flip() # 更新全部显示#主循环start_page = Truegame_page = Truewhile True:zhunbei1()kaishi(start_page)youxijiemian(game_page)#pygame.quit() # 退出pygame
程序越写越长,程序员不易~加油!