Python游戏开发,pygame模块,Python实现拼图小游戏

前言:

本期我们将制作一个拼图小游戏。让我们愉快地开始吧~~~

先来看看效果是这样子的:

Python游戏开发,pygame模块,Python实现拼图小游戏

开发工具

Python版本:3.6.4

相关模块:

pygame模块;

以及一些Python自带的模块

环境搭建

安装Python并添加到环境变量,pip安装需要的相关模块即可。

原理介绍

游戏简介:

将图像分为m×n个矩形块,并将图像右下角的矩形块替换为空白块后,将这些矩形块随机摆放成原图像的形状。游戏目标为通过移动非空白块将随机摆放获得的图像恢复成原图像的模样,且规定移动操作仅存在于非空白块移动到空白块。

例如下图所示:

Python游戏开发,pygame模块,Python实现拼图小游戏

逐步实现:

Step1:游戏初始界面

既然是游戏,总得有个初始界面吧?

OK,我们先写一个游戏初始界面:

'''显示游戏开始界面'''
def ShowStartInterface(screen, width, height):
	screen.fill(cfg.BACKGROUNDCOLOR)
	tfont = pygame.font.Font(cfg.FONTPATH, width//4)
	cfont = pygame.font.Font(cfg.FONTPATH, width//20)
	title = tfont.render('拼图游戏', True, cfg.RED)
	content1 = cfont.render('按H或M或L键开始游戏', True, cfg.BLUE)
	content2 = cfont.render('H为5*5模式, M为4*4模式, L为3*3模式', True, cfg.BLUE)
	trect = title.get_rect()
	trect.midtop = (width/2, height/10)
	crect1 = content1.get_rect()
	crect1.midtop = (width/2, height/2.2)
	crect2 = content2.get_rect()
	crect2.midtop = (width/2, height/1.8)
	screen.blit(title, trect)
	screen.blit(content1, crect1)
	screen.blit(content2, crect2)
	while True:
		for event in pygame.event.get():
			if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
				pygame.quit()
				sys.exit()
		elif event.type == pygame.KEYDOWN:
		if event.key == ord('l'): return 3
		elif event.key == ord('m'): return 4
		elif event.key == ord('h'): return 5
		pygame.display.update()

根据玩家自身水平,可以选择不同难度的拼图游戏。

Step2:定义移动操作

定义移动操作的目的是为了移动拼图(好像是废话T_T),具体实现起来十分简单:

'''将空白Cell左边的Cell右移到空白Cell位置'''
def moveR(board, blank_cell_idx, num_cols):
	if blank_cell_idx % num_cols == 0: return blank_cell_idx
	board[blank_cell_idx-1], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx-1]
	return blank_cell_idx - 1


'''将空白Cell右边的Cell左移到空白Cell位置'''
def moveL(board, blank_cell_idx, num_cols):
	if (blank_cell_idx+1) % num_cols == 0: return blank_cell_idx
	board[blank_cell_idx+1], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx+1]
	return blank_cell_idx + 1


'''将空白Cell上边的Cell下移到空白Cell位置'''
def moveD(board, blank_cell_idx, num_cols):
	if blank_cell_idx < num_cols: return blank_cell_idx
	board[blank_cell_idx-num_cols], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx-num_cols]
	return blank_cell_idx - num_cols


'''将空白Cell下边的Cell上移到空白Cell位置'''
def moveU(board, blank_cell_idx, num_rows, num_cols):
	if blank_cell_idx >= (num_rows-1) * num_cols: return blank_cell_idx
	board[blank_cell_idx+num_cols], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx+num_cols]
	return blank_cell_idx + num_cols

Step3:游戏主界面

OK,有了前面的铺垫,我们可以开始实现我们的游戏主界面了。

首先,我们需要打乱拼图,但是随机打乱很可能导致拼图无解,因此我们通过随机移动拼图来实现打乱拼图的效果,这也是我们先定义拼图的移动操作的主要原因:

'''获得打乱的拼图'''
def CreateBoard(num_rows, num_cols, num_cells):
	board = []
	for i in range(num_cells): board.append(i)
	# 去掉右下角那块
	blank_cell_idx = num_cells - 1
	board[blank_cell_idx] = -1
	for i in range(cfg.NUMRANDOM):
		# 0: left, 1: right, 2: up, 3: down
		direction = random.randint(0, 3)
		if direction == 0: blank_cell_idx = moveL(board, blank_cell_idx, num_cols)
		elif direction == 1: blank_cell_idx = moveR(board, blank_cell_idx, num_cols)
		elif direction == 2: blank_cell_idx = moveU(board, blank_cell_idx, num_rows, num_cols)
		elif direction == 3: blank_cell_idx = moveD(board, blank_cell_idx, num_cols)
	return board, blank_cell_idx

游戏主界面初始化:

Python游戏开发,pygame模块,Python实现拼图小游戏

最后实现主界面的显示刷新以及事件响应等功能:

while True:
		game_board, blank_cell_idx = CreateBoard(num_rows, num_cols, num_cells)
		if not isGameOver(game_board, size):
			break
	# 游戏主循环
	is_running = True
	while is_running:
		# --事件捕获
		for event in pygame.event.get():
			# ----退出游戏
			if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
				pygame.quit()
				sys.exit()
			# ----键盘操作
			elif event.type == pygame.KEYDOWN:
				if event.key == pygame.K_LEFT or event.key == ord('a'):
					blank_cell_idx = moveL(game_board, blank_cell_idx, num_cols)
				elif event.key == pygame.K_RIGHT or event.key == ord('d'):
					blank_cell_idx = moveR(game_board, blank_cell_idx, num_cols)
				elif event.key == pygame.K_UP or event.key == ord('w'):
					blank_cell_idx = moveU(game_board, blank_cell_idx, num_rows, num_cols)
				elif event.key == pygame.K_DOWN or event.key == ord('s'):
					blank_cell_idx = moveD(game_board, blank_cell_idx, num_cols)
			# ----鼠标操作
			elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
				x, y = pygame.mouse.get_pos()
				x_pos = x // cell_width
				y_pos = y // cell_height
				idx = x_pos + y_pos * num_cols
				if idx == blank_cell_idx-1:
					blank_cell_idx = moveR(game_board, blank_cell_idx, num_cols)
				elif idx == blank_cell_idx+1:
					blank_cell_idx = moveL(game_board, blank_cell_idx, num_cols)
				elif idx == blank_cell_idx+num_cols:
					blank_cell_idx = moveU(game_board, blank_cell_idx, num_rows, num_cols)
				elif idx == blank_cell_idx-num_cols:
					blank_cell_idx = moveD(game_board, blank_cell_idx, num_cols)
		# --判断游戏是否结束
		if isGameOver(game_board, size):
			game_board[blank_cell_idx] = num_cells - 1
			is_running = False
		# --更新屏幕
		screen.fill(cfg.BACKGROUNDCOLOR)
		for i in range(num_cells):
			if game_board[i] == -1:
				continue
			x_pos = i // num_cols
			y_pos = i % num_cols
			rect = pygame.Rect(y_pos*cell_width, x_pos*cell_height, cell_width, cell_height)
			img_area = pygame.Rect((game_board[i]%num_cols)*cell_width, (game_board[i]//num_cols)*cell_height, cell_width, cell_height)
			screen.blit(game_img_used, rect, img_area)
		for i in range(num_cols+1):
			pygame.draw.line(screen, cfg.BLACK, (i*cell_width, 0), (i*cell_width, game_img_used_rect.height))
		for i in range(num_rows+1):
			pygame.draw.line(screen, cfg.BLACK, (0, i*cell_height), (game_img_used_rect.width, i*cell_height))
		pygame.display.update()
		clock.tick(cfg.FPS)

Step4:游戏结束界面

当玩家完成拼图后,需要显示游戏结束界面,和游戏初始界面类似,实现起来都比较简单:

'''显示游戏结束界面'''
def ShowEndInterface(screen, width, height):
	screen.fill(cfg.BACKGROUNDCOLOR)
	font = pygame.font.Font(cfg.FONTPATH, width//15)
	title = font.render('恭喜! 你成功完成了拼图!', True, (233, 150, 122))
	rect = title.get_rect()
	rect.midtop = (width/2, height/2.5)
	screen.blit(title, rect)
	pygame.display.update()
	while True:
		for event in pygame.event.get():
			if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
				pygame.quit()
				sys.exit()
		pygame.display.update()

文章到这里就结束了,感谢你的观看,Python24个小游戏系列,下篇文章分享滑雪小游戏

为了感谢读者们,我想把我最近收藏的一些编程干货分享给大家,回馈每一个读者,希望能帮到你们。

干货主要有:

① 2000多本Python电子书(主流和经典的书籍应该都有了)

② Python标准库资料(最全中文版)

③ 项目源码(四五十个有趣且经典的练手项目及源码)

④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)

⑤ Python学习路线图(告别不入流的学习)

⑥ 两天的Python爬虫训练营直播权限

Python游戏开发,pygame模块,Python实现拼图小游戏

All done~点赞+评论~详见个人简介或者私信获取完整源代码。。

往期回顾

Python实现“小兔子和Bun”游戏

Python实现八音符小游戏

上一篇:vue路由跳转总是跳转到首页,路由匹配不上


下一篇:几种常见Ruby on Rails内置方法介绍