在600*600的屏幕上,进行拼图划分。(可以是N * M不一定是N * N)
利用鼠标来操作拼图移动
制作一个类:PartPicture用来保存分块图片的信息(分块图像,位置x,y,以及每个图片的id)
class PartPicture:
# 初始化一个图片分块,保存图像和图像的位置, id代表原图第几块的位置
def __init__(self, img, x, y, id):
self.img = img
self.x = x
self.y = y
self.id = id
# get和set方法
def getX(self):
return self.x;
def getY(self):
return self.y
# 获取图片坐标
def getXY(self):
return self.x, self.y
# 修改图片坐标
def setXY(self,x, y):
self.x = x
self.y = y
# 获取id
def getId(self):
return self.id
现在这个类还没有完善,等下我们再完善它
设置默认的游戏屏幕大小,拼图划分的数量,以及每块拼图的大小,firstClickCell用来记录以后第一次点击的图片,successFlag用来保存是否游戏成功
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600
ROW = 0
COL = 0
CELL_WIDTH = 0#SCREEN_WIDTH / COL
CELL_HEIGHT = 0#SCREEN_HEIGHT / ROW
firstClickCell = None
successFlag = False
设置pygame的初始参数
pygame.init() # 初始化pygame
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # 创建了一个窗口 大小是(宽,高)
pygame.display.set_caption('交换式拼图') # 设置窗口标题
设置颜色RGB以及设置相关字体
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
myfont = pygame.font.Font(None, 70)
textImage1 = myfont.render("simple", True , GREEN)
textImage2 = myfont.render("difficult", True , BLUE)
textImage3 = myfont.render("bow!!!", True , RED)
setInit = False
开始界面选择拼图难度,setInit用来保存是否初始化设置,点击相关难度,然后开始进行初始化设置(拼图的各个大小块,可以是N*M比如3 * 4或者4 * 3)也就是ROW和COL的值
setInit = False
while True:
if setInit:
break
for event in pygame.event.get():
if event.type == QUIT:
exit() # 接收到退出事件后退出程序
elif event.type == MOUSEBUTTONDOWN:
b1, b2, b3 = pygame.mouse.get_pressed()
if b1 == 1:
point_x, point_y = pygame.mouse.get_pos() # 返回鼠标当前坐标
if 100 < point_y < 250:
ROW = 4
COL = 4
setInit = True
elif 250 < point_y < 400:
ROW = 10
COL = 10
setInit = True
elif 400 < point_y < 550:
ROW = 100
COL = 100
setInit = True
screen.fill((0,0,0))
screen.blit(textImage1, (200, 100))
screen.blit(textImage2, (200, 250))
screen.blit(textImage3, (200, 400))
pygame.display.update()
CELL_WIDTH = SCREEN_WIDTH / COL
CELL_HEIGHT = SCREEN_HEIGHT / ROW
imgSrc = pygame.image.load('src.jpg').convert() # 原图 提高 blit 的速度 convert_alpha相对于convert,保留了图像的Alpha 通道信息,可以认为是保留了透明的部分,实现了透明转换
PictureList = devide(imgSrc)
# 图片分块的方法
def devide(imgSrc):
# 切割原来的图片
pictures = []
ScPictures = []
id = 0 # 给每个分块的图片设置下标
for i in range(ROW):
for j in range(COL):
# 提取部分图片
partOfPicutre = imgSrc.subsurface(j * CELL_WIDTH, i * CELL_HEIGHT, CELL_WIDTH, CELL_HEIGHT)
# 保存第一组图片
tempPicture = PartPicture(partOfPicutre, j * CELL_WIDTH, i * CELL_HEIGHT, id)
pictures.append(tempPicture)
# 保存第二组图片
tempPicture = PartPicture(partOfPicutre, j * CELL_WIDTH, i * CELL_HEIGHT, id)
ScPictures.append(tempPicture)
id += 1
random.shuffle(pictures)
# 开始利用第二组图片来打乱原来的图片
for i in range(len(pictures)):
pictures[i].setXY(ScPictures[i].getX(), ScPictures[i].getY())
return pictures # 把打乱的图片返回
我们让这个类来操作图片的移动,isPressed()我们需要判断鼠标点击的第一个图片,并且利用isOver()方法来锁定我们选择的图片。保存好第一个图片以后,firstClickCell就有值了,当我们再次点击的时候,我们就把第一个图片和第二次选择的图片交换(可以是自己),交换完毕后我们再把firstClickCell复原。其中每次操作我们都需要判断是否完成拼图,完成拼图判断是否拼图在原来的位置,我们可以利用id属性获取行和列的块的位置,然后计算出相关坐标,如果有一个不符合拼图就没有完成
class PartPicture:
# 初始化一个图片分块,保存图像和图像的位置, id代表原图第几块的位置
def __init__(self, img, x, y, id):
self.img = img
self.x = x
self.y = y
self.id = id
# 判断是否在图片内
def isOver(self):
w, h = self.img.get_size()
point_x, point_y = pygame.mouse.get_pos() # 返回鼠标当前坐标
in_x = self.x < point_x < self.x + w
in_y = self.y < point_y < self.y + h
#('id,x,y', self.id,':' ,self.getX(), ',',self.getY())
#print('id', self.id, in_x, in_y)
return in_x and in_y
# 检测移动
def isPressed(self, pictureList):
# print('is_pressed')
if self.isOver():
b1, b2, b3 = pygame.mouse.get_pressed()
if b1 == 1:
global firstClickCell
global successFlag
if firstClickCell is None:
firstClickCell = self
print('id为{}的块被点击'.format(firstClickCell.getId()))
else:
print('交换{}与{}的坐标'.format(firstClickCell.getId(), self.getId()))
self.pictureSwitch(firstClickCell, self)
if self.isFinish(pictureList):
print('成功!')
successFlag = True
else:
successFlag = False
firstClickCell = None
return True
return False
# 判断拼图完成
def isFinish(self, pictureList):
for cell in pictureList:
nowp_x, nowp_y = cell.getXY()
p_x = cell.getId() % COL * CELL_WIDTH
p_y = (cell.getId() // COL) * CELL_HEIGHT
print("id{} nowx{}与nowy{}的坐标 本来的坐标x{}y{}".format(cell.getId(), nowp_x, nowp_y, p_x, p_y))
if nowp_x != p_x or nowp_y != p_y:
return False
return True
def pictureSwitch(self, cell1, cell2):
tempX = cell1.getX()
tempY = cell1.getY()
cell1.setXY(cell2.getX(), cell2.getY())
cell2.setXY(tempX, tempY)
def render(self, screen):
screen.blit(self.img, (self.x, self.y))
while True: # 游戏主循环
for event in pygame.event.get():
if event.type == QUIT:
exit() # 接收到退出事件后退出程序
elif event.type == MOUSEBUTTONDOWN:
for cell in PictureList:
# 检测按键按下,并且交换图片位置
if cell.isPressed(PictureList):
break
for partPicture in PictureList:
partPicture.render(screen)
if not successFlag:
# # Sta 绘制分割线
for i in range(1, COL):
pygame.draw.lines(screen, GREEN, 0, [(i * SCREEN_WIDTH // COL, 0), (i * SCREEN_WIDTH // COL, SCREEN_HEIGHT)], 1)
for i in range(1, ROW):
pygame.draw.lines(screen, GREEN, 0, [(0, i * SCREEN_HEIGHT // ROW), (SCREEN_WIDTH, i * SCREEN_HEIGHT // ROW)], 1)
# End 绘制分割线
pygame.display.update() # 刷新一下画面
图像为src,600*600大小
import random
from sys import exit # 使用sys模块的exit函数来退出游戏
import pygame
from pygame.locals import * # 导入一些常用的函数和常量
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600
ROW = 100
COL = 100
CELL_WIDTH = 0#SCREEN_WIDTH / COL
CELL_HEIGHT = 0#SCREEN_HEIGHT / ROW
firstClickCell = None
class PartPicture:
# 初始化一个图片分块,保存图像和图像的位置, id代表原图第几块的位置
def __init__(self, img, x, y, id):
self.img = img
self.x = x
self.y = y
self.id = id
# 判断是否在图片内
def isOver(self):
w, h = self.img.get_size()
point_x, point_y = pygame.mouse.get_pos() # 返回鼠标当前坐标
in_x = self.x < point_x < self.x + w
in_y = self.y < point_y < self.y + h
#('id,x,y', self.id,':' ,self.getX(), ',',self.getY())
#print('id', self.id, in_x, in_y)
return in_x and in_y
# 检测移动
def isPressed(self, pictureList):
# print('is_pressed')
if self.isOver():
b1, b2, b3 = pygame.mouse.get_pressed()
if b1 == 1:
global firstClickCell
global successFlag
if firstClickCell is None:
firstClickCell = self
print('id为{}的块被点击'.format(firstClickCell.getId()))
else:
print('交换{}与{}的坐标'.format(firstClickCell.getId(), self.getId()))
self.pictureSwitch(firstClickCell, self)
if self.isFinish(pictureList):
print('成功!')
successFlag = True
else:
successFlag = False
firstClickCell = None
return True
return False
# 判断拼图完成
def isFinish(self, pictureList):
for cell in pictureList:
nowp_x, nowp_y = cell.getXY()
p_x = cell.getId() % COL * CELL_WIDTH
p_y = (cell.getId() // COL) * CELL_HEIGHT
print("id{} nowx{}与nowy{}的坐标 本来的坐标x{}y{}".format(cell.getId(), nowp_x, nowp_y, p_x, p_y))
if nowp_x != p_x or nowp_y != p_y:
return False
return True
def pictureSwitch(self, cell1, cell2):
tempX = cell1.getX()
tempY = cell1.getY()
cell1.setXY(cell2.getX(), cell2.getY())
cell2.setXY(tempX, tempY)
def render(self, screen):
screen.blit(self.img, (self.x, self.y))
# get和set方法
def getX(self):
return self.x;
def getY(self):
return self.y
# 获取图片坐标
def getXY(self):
return self.x, self.y
# 修改图片坐标
def setXY(self,x, y):
self.x = x
self.y = y
# 获取id
def getId(self):
return self.id
# 图片分块的方法
def devide(imgSrc):
# 切割原来的图片
pictures = []
ScPictures = []
id = 0 # 给每个分块的图片设置下标
for i in range(ROW):
for j in range(COL):
# 提取部分图片
partOfPicutre = imgSrc.subsurface(j * CELL_WIDTH, i * CELL_HEIGHT, CELL_WIDTH, CELL_HEIGHT)
# 保存第一组图片
tempPicture = PartPicture(partOfPicutre, j * CELL_WIDTH, i * CELL_HEIGHT, id)
pictures.append(tempPicture)
# 保存第二组图片
tempPicture = PartPicture(partOfPicutre, j * CELL_WIDTH, i * CELL_HEIGHT, id)
ScPictures.append(tempPicture)
id += 1
random.shuffle(pictures)
# 开始利用第二组图片来打乱原来的图片
for i in range(len(pictures)):
pictures[i].setXY(ScPictures[i].getX(), ScPictures[i].getY())
return pictures # 把打乱的图片返回
pygame.init() # 初始化pygame
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # 创建了一个窗口 大小是(宽,高)
pygame.display.set_caption('交换式拼图') # 设置窗口标题
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
myfont = pygame.font.Font(None, 70)
textImage1 = myfont.render("simple", True , GREEN)
textImage2 = myfont.render("difficult", True , BLUE)
textImage3 = myfont.render("bow!!!", True , RED)
setInit = False
while True:
if setInit:
break
for event in pygame.event.get():
if event.type == QUIT:
exit() # 接收到退出事件后退出程序
elif event.type == MOUSEBUTTONDOWN:
b1, b2, b3 = pygame.mouse.get_pressed()
if b1 == 1:
point_x, point_y = pygame.mouse.get_pos() # 返回鼠标当前坐标
if 100 < point_y < 250:
ROW = 4
COL = 4
setInit = True
elif 250 < point_y < 400:
ROW = 10
COL = 10
setInit = True
elif 400 < point_y < 550:
ROW = 100
COL = 100
setInit = True
screen.fill((0,0,0))
screen.blit(textImage1, (200, 100))
screen.blit(textImage2, (200, 250))
screen.blit(textImage3, (200, 400))
pygame.display.update()
CELL_WIDTH = SCREEN_WIDTH / COL
CELL_HEIGHT = SCREEN_HEIGHT / ROW
imgSrc = pygame.image.load('src.jpg').convert() # 原图 提高 blit 的速度 convert_alpha相对于convert,保留了图像的Alpha 通道信息,可以认为是保留了透明的部分,实现了透明转换
PictureList = devide(imgSrc)
# 标记是否游戏成功
successFlag = False
while True: # 游戏主循环
for event in pygame.event.get():
if event.type == QUIT:
exit() # 接收到退出事件后退出程序
elif event.type == MOUSEBUTTONDOWN:
for cell in PictureList:
# 检测按键按下,并且交换图片位置
if cell.isPressed(PictureList):
break
for partPicture in PictureList:
partPicture.render(screen)
if not successFlag:
# # Sta 绘制分割线
for i in range(1, COL):
pygame.draw.lines(screen, GREEN, 0, [(i * SCREEN_WIDTH // COL, 0), (i * SCREEN_WIDTH // COL, SCREEN_HEIGHT)], 1)
for i in range(1, ROW):
pygame.draw.lines(screen, GREEN, 0, [(0, i * SCREEN_HEIGHT // ROW), (SCREEN_WIDTH, i * SCREEN_HEIGHT // ROW)], 1)
# End 绘制分割线
pygame.display.update() # 刷新一下画面