小学生python游戏编程5----拼图游戏继
- 前言
- 应用知识点
- 1、python知识点
- 1.1 通过点击图块的次数,交换图块
- 1.2 输赢确定
- 1.3 对方块进行描边及选中的方块显红框
- 1.4 读取文件及写入成绩
- 2、pygamezero知识点
- 2.1 点击图块,互换位置
- 2.2 判断输赢
- 2.3 改进,点击图片时进行划红框,每块显示绿框
- 2.4 增加底框
- 总结
- 源码获取
前言
接前两篇文章,小学生python游戏编程3----拼图游戏-准备,小学生python游戏编程4----拼图游戏今天此主拼图游戏做完整 ,上次写到可以打乱图片,拼成游戏界面,今天主要写要如何通过点击图块互换位置,如何全局判断输赢,显示用时间及历史最高记录。
应用知识点
1、python知识点
1.1 通过点击图块的次数,交换图块
if clickTime % 2 == 0: # 点击偶数次
clickId1 = k # 第一个要交换的小拼图块序号
clickTime += 1 # 点击次数加1
elif clickTime % 2 == 1: # 点击奇数次
clickId2 = k # 第二个要交换的小拼图块序号
clickTime += 1 # 点击次数加1
jiaohuanFk(clickId1, clickId2) # 交换两个小拼图块位置
1.2 输赢确定
通过全局变量 allRight 进行设置,通过浏览每个小方块的位置与最初的方块集(打乱顺序前的)位置进行比对,如都一致则拼对了。
allRight = True # 假设全拼对了
for i in range(3):
for j in range(3):
tile = grid[i*3+j]
# 遍历,只要有一个小拼图的位置不对,就没有全拼对
# print(‘第’,i,j,tile.left,tile.top)
# print(tile.left,j * TILE_SIZE_w,‘后’,tile.top,i * TILE_SIZE_h)
if tile.left != j * TILE_SIZE_w or tile.top != i * TILE_SIZE_h:
allRight = False # 拼错了
break
# 如果上面的if语句都不执行,则表示全拼对了
1.3 对方块进行描边及选中的方块显红框
for i in range(x): # 画两条横线、两条竖线
screen.draw.line((0, i * TILE_SIZE_h), (WIDTH, i * TILE_SIZE_h), 'green')
screen.draw.line((i * TILE_SIZE_w, 0), (i * TILE_SIZE_w, y * TILE_SIZE_h), 'green')
if clickId1 != -1: # 为选中的第一个小拼图块画一个红色框
screen.draw.rect(Rect((grid[clickId1].left, grid[clickId1].top), (TILE_SIZE_w, TILE_SIZE_h)), 'red')
1.4 读取文件及写入成绩
读取文件,设置变量
txtFile = open(‘dangan.txt’, ‘r’) # 打开最佳时间记录存档文件
line = txtFile.readline() # 读取一行字符串
oldTime = int(line) # 将记录的秒数转换为整型存储
txtFile.close() # 关闭文件
start = datetime.datetime.now() # 程序运行开始计时
newTime = 0 # 这次游戏花了多长时间
游戏结束时,对比成绩,如有新战绩把新绩写入文档
if allRight:
if newTime < oldTime: # 看看是否更新最短时间记录
txtFile = open(‘rank.txt’, ‘w’)
txtFile.write(str(newTime))
txtFile.close()
具体细节多看下面的原码,想试试效果的可直接复制下来运行,还是希望你按自己的想法录一篇,会体会更深。
2、pygamezero知识点
2.1 点击图块,互换位置
效果:
代码:
import pgzrun # 导入游戏库
from pgzero.actor import Actor
from pgzero.screen import Screen
screen: Screen # 类型标注
TILE_SIZE_w = 132 # 根据小图块的宽设置
TILE_SIZE_h = 118 # 根据小图块的高设置
x = 5 # 横向方块数
y = 5 # 纵向方块数
WIDTH = x*TILE_SIZE_w # 设置窗口的宽度
HEIGHT = y*TILE_SIZE_h # 设置窗口的高度
TITLE = '拼图小游戏'
clickTime = 0 # 记录鼠标点击了多少次
clickId1 = clickId2 = -1 # 两次点击的小拼图块的序号
fk_list =[]
for i in range(1,x*y+1):
fk_list.append(Actor('fenge\\df-'+str(i)))
grid = [] # 列表,用来存放最终所有拼图信息
for i in range(x): # 对行循环
for j in range(y): # 对列循环
# print(i*x+j)
fangkuai = fk_list[i*x+j] # 导入拼图方块图片
fangkuai.left = j * TILE_SIZE_w # 拼图方块图片最左边的x坐标
fangkuai.top = i * TILE_SIZE_h # 拼图方块图片最顶部的y坐标
grid.append(fangkuai) # 将当前拼图加入到列表中
# 以下函数实现两个小拼图块位置的交换
def jiaohuanFk(a, b):
# i,j为要交换的两个小拼图块的序号
# 以下利用tempPos中间变量,实现两个小拼图块位置的交换
tempPos = grid[a].pos
grid[a].pos = grid[b].pos
grid[b].pos = tempPos
import random
# 重复随机交换多次小拼图的位置
for k in range(x*y-1):
i = random.randint(0, x*y-1) # 第一个小拼图块的序号
j = random.randint(0, x*y-1) # 第二个小拼图块的序号
jiaohuanFk(i, j) # 调用函数交换两个小拼图块的位置
print('ok')
def draw(): # 绘制模块,每帧重复执行
screen.clear() # 每帧清除屏幕,便于重新绘制
for fk in grid:
fk.draw() # 绘制小拼图块
def on_mouse_down(pos, button): # 当鼠标按键时执行
global clickTime, clickId1, clickId2
for k in range(x*y): # 对所有grid中的小拼图块遍历
if grid[k].collidepoint(pos): # 如果小拼图与鼠标位置碰撞
print(k) # 输出拼图块序号
break # 跳出当前循环
if clickTime % 2 == 0: # 点击偶数次
clickId1 = k # 第一个要交换的小拼图块序号
clickTime += 1 # 点击次数加1
elif clickTime % 2 == 1: # 点击奇数次
clickId2 = k # 第二个要交换的小拼图块序号
clickTime += 1 # 点击次数加1
jiaohuanFk(clickId1, clickId2) # 交换两个小拼图块位置
pgzrun.go() # 开始执行游戏
2.2 判断输赢
效果:
代码:
import pgzrun # 导入游戏库
from pgzero.actor import Actor
from pgzero.screen import Screen
screen: Screen # 类型标注
TILE_SIZE_w = 132 # 根据小图块的宽设置
TILE_SIZE_h = 118 # 根据小图块的高设置
x = 5 # 横向方块数
y = 5 # 纵向方块数
WIDTH = x*TILE_SIZE_w # 设置窗口的宽度
HEIGHT = y*TILE_SIZE_h # 设置窗口的高度
TITLE = '拼图小游戏'
clickTime = 0 # 记录鼠标点击了多少次
clickId1 = clickId2 = -1 # 两次点击的小拼图块的序号
allRight = False # 是否小拼图的位置全对了
fk_list =[]
for i in range(1,x*y+1):
fk_list.append(Actor('fenge\\df-'+str(i)))
grid = [] # 列表,用来存放最终所有拼图信息
for i in range(x): # 对行循环
for j in range(y): # 对列循环
# print(i*x+j)
fangkuai = fk_list[i*x+j] # 导入拼图方块图片
fangkuai.left = j * TILE_SIZE_w # 拼图方块图片最左边的x坐标
fangkuai.top = i * TILE_SIZE_h # 拼图方块图片最顶部的y坐标
grid.append(fangkuai) # 将当前拼图加入到列表中
# 以下函数实现两个小拼图块位置的交换
def jiaohuanFk(a, b):
# i,j为要交换的两个小拼图块的序号
# 以下利用tempPos中间变量,实现两个小拼图块位置的交换
tempPos = grid[a].pos
grid[a].pos = grid[b].pos
grid[b].pos = tempPos
import random
# 重复随机交换多次小拼图的位置
for k in range(x*y-1):
i = random.randint(0, x*y-1) # 第一个小拼图块的序号
j = random.randint(0, x*y-1) # 第二个小拼图块的序号
jiaohuanFk(i, j) # 调用函数交换两个小拼图块的位置
# print('ok')
def draw(): # 绘制模块,每帧重复执行
screen.clear() # 每帧清除屏幕,便于重新绘制
for fk in grid:
fk.draw() # 绘制小拼图块
def on_mouse_down(pos, button): # 当鼠标按键时执行
global clickTime, clickId1, clickId2, allright
for k in range(x*y): # 对所有grid中的小拼图块遍历
if grid[k].collidepoint(pos): # 如果小拼图与鼠标位置碰撞
print(k) # 输出拼图块序号
break # 跳出当前循环
if clickTime % 2 == 0: # 点击偶数次
clickId1 = k # 第一个要交换的小拼图块序号
clickTime += 1 # 点击次数加1
elif clickTime % 2 == 1: # 点击奇数次
clickId2 = k # 第二个要交换的小拼图块序号
clickTime += 1 # 点击次数加1
jiaohuanFk(clickId1, clickId2) # 交换两个小拼图块位置
allRight = True # 假设全拼对了
for i in range(3):
for j in range(3):
tile = grid[i*3+j]
# 遍历,只要有一个小拼图的位置不对,就没有全拼对
# print('第',i,j,tile.left,tile.top)
# print(tile.left,j * TILE_SIZE_w,'后',tile.top,i * TILE_SIZE_h)
if tile.left != j * TILE_SIZE_w or tile.top != i * TILE_SIZE_h:
allRight = False # 拼错了
break
# 如果上面的if语句都不执行,则表示全拼对了
pgzrun.go() # 开始执行游戏
2.3 改进,点击图片时进行划红框,每块显示绿框
效果:
代码:
import pgzrun # 导入游戏库
from pgzero.actor import Actor
from pgzero.screen import Screen
import random
screen: Screen # 类型标注
TILE_SIZE_w = 132 # 根据小图块的宽设置
TILE_SIZE_h = 118 # 根据小图块的高设置
x = 5 # 横向方块数
y = 5 # 纵向方块数
WIDTH = x*TILE_SIZE_w # 设置窗口的宽度
HEIGHT = y*TILE_SIZE_h # 设置窗口的高度
TITLE = '拼图小游戏'
clickTime = 0 # 记录鼠标点击了多少次
clickId1 = clickId2 = -1 # 两次点击的小拼图块的序号
allRight = False # 是否小拼图的位置全对了
fk_list =[]
for i in range(1,x*y+1):
fk_list.append(Actor('fenge\\df-'+str(i)))
grid = [] # 列表,用来存放最终所有拼图信息
for i in range(x): # 对行循环
for j in range(y): # 对列循环
# print(i*x+j)
fangkuai = fk_list[i*x+j] # 导入拼图方块图片
fangkuai.left = j * TILE_SIZE_w # 拼图方块图片最左边的x坐标
fangkuai.top = i * TILE_SIZE_h # 拼图方块图片最顶部的y坐标
grid.append(fangkuai) # 将当前拼图加入到列表中
# 以下函数实现两个小拼图块位置的交换
def jiaohuanFk(a, b):
# i,j为要交换的两个小拼图块的序号
# 以下利用tempPos中间变量,实现两个小拼图块位置的交换
tempPos = grid[a].pos
grid[a].pos = grid[b].pos
grid[b].pos = tempPos
# 重复随机交换多次小拼图的位置
for k in range(x*y-1):
i = random.randint(0, x*y-1) # 第一个小拼图块的序号
j = random.randint(0, x*y-1) # 第二个小拼图块的序号
jiaohuanFk(i, j) # 调用函数交换两个小拼图块的位置
# print('ok')
def draw(): # 绘制模块,每帧重复执行
screen.clear() # 每帧清除屏幕,便于重新绘制
for fk in grid:
fk.draw() # 绘制小拼图块
if allRight: # 输出游戏胜利信息
screen.draw.text("游戏胜利!", (40, 10),
fontsize=50, fontname='simhei', color='blue')
else: # 如果没有成功,可以画几条提示线
for i in range(x): # 画两条横线、两条竖线
screen.draw.line((0, i*TILE_SIZE_h), (WIDTH, i*TILE_SIZE_h), 'green')
screen.draw.line((i*TILE_SIZE_w, 0), (i*TILE_SIZE_w, y*TILE_SIZE_h), 'green')
if clickId1 != -1: # 为选中的第一个小拼图块画一个红色框
screen.draw.rect(Rect((grid[clickId1].left, grid[clickId1].top), (TILE_SIZE_w, TILE_SIZE_h)), 'red')
def on_mouse_down(pos, button): # 当鼠标按键时执行
global clickTime, clickId1, clickId2, allRight
for k in range(x*y): # 对所有grid中的小拼图块遍历
if grid[k].collidepoint(pos): # 如果小拼图与鼠标位置碰撞
print(k) # 输出拼图块序号
break # 跳出当前循环
if clickTime % 2 == 0: # 点击偶数次
clickId1 = k # 第一个要交换的小拼图块序号
clickTime += 1 # 点击次数加1
elif clickTime % 2 == 1: # 点击奇数次
clickId2 = k # 第二个要交换的小拼图块序号
clickTime += 1 # 点击次数加1
jiaohuanFk(clickId1, clickId2) # 交换两个小拼图块位置
allRight = True # 假设全拼对了
for i in range(x):
for j in range(y):
tile = grid[i*x+j]
# 遍历,只要有一个小拼图的位置不对,就没有全拼对
# print('第',i,j,tile.left,tile.top)
# print(tile.left,j * TILE_SIZE_w,'后',tile.top,i * TILE_SIZE_h)
if tile.left != j * TILE_SIZE_w or tile.top != i * TILE_SIZE_h:
allRight = False # 拼错了
break
# 如果上面的if语句都不执行,则表示全拼对了
pgzrun.go() # 开始执行游戏
2.4 增加底框
效果:
代码:
import pgzrun # 导入游戏库
from pgzero.actor import Actor
from pgzero.screen import Screen
import datetime # 导入日期和时间库
from pgzero.rect import Rect # Rect类引入
import random
screen:Screen # 类型标注
TILE_SIZE_w = 132 # 根据小图块的宽设置
TILE_SIZE_h = 118 # 根据小图块的高设置
x = 5 # 横向方块数
y = 5 # 纵向方块数
WIDTH = x * TILE_SIZE_w # 设置窗口的宽度
HEIGHT = y * TILE_SIZE_h + 60 # 设置窗口的高度,增加下框
TITLE = '拼图小游戏'
clickTime = 0 # 记录鼠标点击了多少次
clickId1 = clickId2 = -1 # 两次点击的小拼图块的序号
allRight = False # 是否小拼图的位置全对了
txtFile = open('dangan.txt') # 打开最佳时间记录存档文件
line = txtFile.readline() # 读取一行字符串
oldTime = int(line) # 将记录的秒数转换为整型存储
txtFile.close() # 关闭文件
start = datetime.datetime.now() # 程序运行开始计时
newTime = 0 # 这次游戏花了多长时间
fk_list = []
for i in range(1, x * y + 1):
fk_list.append(Actor('fenge\\df-' + str(i)))
grid = [] # 列表,用来存放最终所有拼图信息
for i in range(x): # 对行循环
for j in range(y): # 对列循环
# print(i*x+j)
fangkuai = fk_list[i * x + j] # 导入拼图方块图片
fangkuai.left = j * TILE_SIZE_w # 拼图方块图片最左边的x坐标
fangkuai.top = i * TILE_SIZE_h # 拼图方块图片最顶部的y坐标
grid.append(fangkuai) # 将当前拼图加入到列表中
# 以下函数实现两个小拼图块位置的交换
def jiaohuanFk(a, b):
# i,j为要交换的两个小拼图块的序号
# 以下利用tempPos中间变量,实现两个小拼图块位置的交换
tempPos = grid[a].pos
grid[a].pos = grid[b].pos
grid[b].pos = tempPos
# 重复随机交换多次小拼图的位置
for k in range(x * y - 1):
i = random.randint(0, x * y - 1) # 第一个小拼图块的序号
j = random.randint(0, x * y - 1) # 第二个小拼图块的序号
jiaohuanFk(i, j) # 调用函数交换两个小拼图块的位置
# print('ok')
def draw(): # 绘制模块,每帧重复执行
screen.clear() # 每帧清除屏幕,便于重新绘制
for fk in grid:
fk.draw() # 绘制小拼图块
if allRight: # 输出游戏胜利信息
screen.draw.text("游戏胜利!", (WIDTH/3-60, HEIGHT - 60),
fontsize=50, fontname='simhei', color='blue')
else: # 如果没有成功,可以画几条提示线
for i in range(x): # 画两条横线、两条竖线
screen.draw.line((0, i * TILE_SIZE_h), (WIDTH, i * TILE_SIZE_h), 'green')
screen.draw.line((i * TILE_SIZE_w, 0), (i * TILE_SIZE_w, y * TILE_SIZE_h), 'green')
if clickId1 != -1: # 为选中的第一个小拼图块画一个红色框
screen.draw.rect(Rect((grid[clickId1].left, grid[clickId1].top), (TILE_SIZE_w, TILE_SIZE_h)), 'red')
screen.draw.text("最佳记录:" + str(oldTime) + '秒', (WIDTH/2-60, HEIGHT - 60), fontsize=25,
fontname='simhei', color='red')
screen.draw.text("游戏运行:" + str(newTime) + '秒', (WIDTH/2-60, HEIGHT - 30), fontsize=25,
fontname='simhei', color='red')
def on_mouse_down(pos, button): # 当鼠标按键时执行
global clickTime, clickId1, clickId2, allRight
for k in range(x * y): # 对所有grid中的小拼图块遍历
if grid[k].collidepoint(pos): # 如果小拼图与鼠标位置碰撞
# print(k) # 输出拼图块序号
break # 跳出当前循环
if clickTime % 2 == 0: # 点击偶数次
clickId1 = k # 第一个要交换的小拼图块序号
clickTime += 1 # 点击次数加1
elif clickTime % 2 == 1: # 点击奇数次
clickId2 = k # 第二个要交换的小拼图块序号
clickTime += 1 # 点击次数加1
jiaohuanFk(clickId1, clickId2) # 交换两个小拼图块位置
allRight = True # 假设全拼对了
for i in range(x):
for j in range(y):
tile = grid[i * x + j]
# 遍历,只要有一个小拼图的位置不对,就没有全拼对
# print('第',i,j,tile.left,tile.top)
# print(tile.left,j * TILE_SIZE_w,'后',tile.top,i * TILE_SIZE_h)
if tile.left != j * TILE_SIZE_w or tile.top != i * TILE_SIZE_h:
allRight = False # 拼错了
break
# 如果上面的if语句都不执行,则表示全拼对了
if allRight:
if newTime < oldTime: # 看看是否更新最短时间记录
txtFile = open('dangan.txt', 'w')
txtFile.write(str(newTime))
txtFile.close()
def update(): # 更新模块,每帧重复操作
global newTime
if not allRight:
end = datetime.datetime.now()
newTime = (end - start).seconds # 程序运行了多少秒
pgzrun.go() # 开始执行游戏
总结
通过此次的《拼图游戏》游戏三连发实现,让我对python的相关知识有了进一步的了解,对拼图游戏有了一些想法,如何更进一步的设计实现新功能,用于学习。