【Python游戏开发】拼图小游戏demo

使用mu编辑器 + pgzero编写拼图小游戏

import random

SIZE = 96           # 设置每张图块的大小
WIDTH = SIZE * 3    # 根据土块大小设置窗口
HEIGHT = SIZE * 3
pics = []           # 存放图块
finished  = False   # 游戏结束标识

# 将前八张图块存放在pics列表中
for i in range(8):
    # 使用Actor()方法创建图块
    pic = Actor("puzzle_pic" + str(i))
    # 给每张图块设置索引值
    pic.index = i
    pics.append(pic)

# 将图块列表pics的顺序打乱
random.shuffle(pics)

# 设立每块图块的初始位置
for i in range(8):
    # 使用余数确认x坐标,如0、3、6余数为0,所以都在第一列
    pics[i].left = i % 3 * SIZE
    # 使用除数确认y坐标,如0、1、2除以3整数部分都为0,所以在第一行
    pics[i].top = i // 3 * SIZE
# 创建最后一张图块,固定放置在最后一个位置
lastpic = Actor("puzzle_pic8")
lastpic.left = 2 * SIZE
lastpic.top = 2 * SIZE

def draw():
    # 设置游戏背景色
    screen.fill((255,255,255))
    # 绘制图块
    for pic in pics:
        pic.draw()
    # 如果游戏结束,则将最后一张图块绘制进游戏中
    if finished:
        lastpic.draw()
        # 显示结束语
        screen.draw.text("victory!",center = (WIDTH // 2, HEIGHT // 2),
                            fontsize = 50, color = "red")

# 鼠标点击处理
def on_mouse_down(pos):
    if finished:
        return
    # 获取被点击位置的坐标
    grid_x = pos[0] // SIZE
    grid_y = pos[1] // SIZE
    # 检测是否存在图块
    thispic = get_pic(grid_x,grid_y)
    # 不存在,则return,不执行任何存在
    if thispic == None:
        return
    # 存在,则判断其相邻位置是否为空,如为空,则移动图块至空位
    if grid_y> 0 and get_pic(grid_x,grid_y - 1) == None:
        thispic.y -= SIZE
        return
    if grid_y< 2 and get_pic(grid_x,grid_y + 1 ) == None:
        thispic.y += SIZE
        return
    if grid_x> 0 and get_pic(grid_x - 1,grid_y) == None:
        thispic.x -= SIZE
        return
    if grid_x< 2 and get_pic(grid_x + 1,grid_y) == None:
        thispic.x += SIZE
        return

# 通过坐标获取图块信息
def get_pic(grid_x,grid_y):
    # 循环遍历图块判断是否有图块在对应坐标中
    for pic in pics:
        if pic.x // SIZE == grid_x and pic.y // SIZE == grid_y:
           return pic
    return None

def update():
    global finished
    if finished:
        return
    # 遍历前八个坐标位置,判断位置上的图块是否符合需求
    for i in range(8):
        # 获取坐标位置上的图块信息
        pic = get_pic(i % 3 ,i// 3)
        # 如果不存在图块或者图块索引值不对,则return
        if (pic == None or pic.index != i):
            return
    # 游戏结束
    finished = True
    # 设置胜利
    sounds.win.play()

代码执行,便会生成3x3拼图小游戏
在这里插入图片描述

完成拼图后
在这里插入图片描述

但是,因为是使用随机数Random无规则的打乱顺序,所以会导致游戏存在无解的情况
在这里插入图片描述

所以放弃采用random.shuffle(pics)打乱图块的方法,改为程序多次自动随机点击空图块相邻的图块,实现打乱图块效果

# 将图块列表pics的顺序打乱
# random.shuffle(pics)
blank_pic = [2,2]   # 初始空白图块的坐标
# 逆向打乱拼图顺序
def init_pics():
    global blank_pic
    move_list = []
    # 将空白图块相邻的图块位置插入列表中
    if blank_pic[0] > 0:
        move_list.append([blank_pic[0] - 1,blank_pic[1]])
    if blank_pic[0] < 2:
        move_list.append([blank_pic[0] + 1,blank_pic[1]])
    if blank_pic[1] > 0:
        move_list.append([blank_pic[0],blank_pic[1] - 1])
    if blank_pic[1] < 2:
        move_list.append([blank_pic[0],blank_pic[1] + 1])
    # 从列表中随机一个图块进行点击
    blank_pic = random.choice(move_list)
    on_mouse_down([blank_pic[0] * SIZE,blank_pic[1] * SIZE])

最后,根据自己的设定,循环调用init_pics方法,实现打乱效果

for i in range(50):
    init_pics()

运行结果如图,也是实现了随机打乱图块的效果,且不会出现无解的情况
在这里插入图片描述
调整优化:

  1. SUM_XSUM_Y:可设置拼图难度,生成m*n拼图
  2. random_num:设置系统打乱方块的步数
# 在这里写上你的代码
import random
SUM_X = 4               # 设置每行存放图块的数量
SUM_Y = 3               # 设置每列存放图块的数量
random_num = 100        # 打乱方块次数
SIZE = 96               # 设置每张图块的大小

SUM_I = SUM_X * SUM_Y   # 图块总数
WIDTH = SIZE * SUM_X    # 根据土块大小设置窗口
HEIGHT = SIZE * SUM_Y
pics = []               # 存放图块
finished  = False       # 游戏结束标识

blank_pic = [SUM_X - 1,SUM_Y - 1]   # 空白图块坐标

# 将显示图块存放在pics列表中
for i in range(SUM_I - 1):
    # 使用Actor()方法创建图块
    pic = Actor("puzzle_pic" + str(i))
    # 给每张图块设置索引值
    pic.index = i
    pics.append(pic)

# 设立每块图块的初始位置
for i in range(SUM_I - 1):
    # 使用余数确认x坐标
    pics[i].left = i % SUM_Y * SIZE
    # 使用除数确认y坐标
    pics[i].top = i // SUM_X * SIZE
    
# 创建最后一张图块,固定放置在最后一个位置
lastpic = Actor("puzzle_pic8")
lastpic.left = SUM_X * SIZE
lastpic.top = SUM_Y * SIZE

def draw():
    # 设置游戏背景色
    screen.fill((255,255,255))
    # 绘制图块
    for pic in pics:
        pic.draw()
    # 如果游戏结束,则将最后一张图块绘制进游戏中
    if finished:
        lastpic.draw()
        # 显示结束语
        screen.draw.text("victory!",center = (WIDTH // 2, HEIGHT // 2),
                            fontsize = 50, color = "red")

# 鼠标点击处理
def on_mouse_down(pos):
    if finished:
        return
    # 获取被点击位置的坐标
    grid_x = pos[0] // SIZE
    grid_y = pos[1] // SIZE
    # 检测是否存在图块
    thispic = get_pic(grid_x,grid_y)
    # 不存在,则return,不执行任何存在
    if thispic == None:
        return
    # 存在,则判断其相邻位置是否为空,如为空,则移动图块至空位
    if grid_y> 0 and get_pic(grid_x,grid_y - 1) == None:
        thispic.y -= SIZE
        return
    if grid_y< (SUM_Y - 1) and get_pic(grid_x,grid_y + 1 ) == None:
        thispic.y += SIZE
        return
    if grid_x> 0 and get_pic(grid_x - 1,grid_y) == None:
        thispic.x -= SIZE
        return
    if grid_x< (SUM_X - 1) and get_pic(grid_x + 1,grid_y) == None:
        thispic.x += SIZE
        return

# 通过坐标获取图块信息
def get_pic(grid_x,grid_y):
    # 循环遍历图块判断是否有图块在对应坐标中
    for pic in pics:
        if pic.x // SIZE == grid_x and pic.y // SIZE == grid_y:
           return pic
    return None

def update():
    global finished
    if finished:
        return
    # 遍历前八个坐标位置,判断位置上的图块是否符合需求
    for i in range(SUM_I - 1):
        # 获取坐标位置上的图块信息
        pic = get_pic(i % SUM_X ,i// SUM_Y)
        # 如果不存在图块或者图块索引值不对,则return
        if (pic == None or pic.index != i):
            return
    # 游戏结束
    finished = True
    # 设置胜利
    sounds.win.play()
    
# 逆向打乱拼图顺序
def init_pics():
    global blank_pic
    move_list = []
    if blank_pic[0] > 0:
        move_list.append([blank_pic[0] - 1,blank_pic[1]])
    if blank_pic[0] < SUM_X - 1:
        move_list.append([blank_pic[0] + 1,blank_pic[1]])
    if blank_pic[1] > 0:
        move_list.append([blank_pic[0],blank_pic[1] - 1])
    if blank_pic[1] < SUM_Y - 1:
        move_list.append([blank_pic[0],blank_pic[1] + 1])
    # 从列表中随机一个移动方法
    blank_pic = random.choice(move_list)
    on_mouse_down([blank_pic[0] * SIZE,blank_pic[1] * SIZE])
    
for i in range(random_num):
    init_pics()

因为图块是随机打乱的,我们无法确认随机出来的图块会不会跟没打乱的图块一致,出现一进游戏就获胜的情况,但这我们可以加代码去判定,比较简单,所以就不阐述了

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值