趣味python一迷宫小游戏

  • 读取外部迷宫地图


既然是编写小游戏,那么自然少不了pygame模块,编译环境使用的是pycharm。

迷宫小游戏设计思想是,我们自己绘制迷宫地图文档,然后程序根据我们设计的地图把迷宫绘制到pygame游戏界面当中来。因为本人手残党,所以所有图片素材都来源于网络,如有侵权,我立刻销毁。

首先设计地图,这里一共设计了四个关卡的地图,其中前2关是我自己设计的,第3关地图版权归属了我们家的大哥,三年级逍遥哥。

上地图:

python 迷宫最短路径 python编程一个迷宫_python

这个地图是存放在txt文档中的,所有的“w”都会被程序绘制成墙,“p”是角色出现的位置,“t”是树,“r”是岩石, “g”是目的地,“k”是钥匙的位置,“d”是门的位置。那么第一张图的绘制结果是这样的:

python 迷宫最短路径 python编程一个迷宫_python 迷宫最短路径_02

控制小人走到星星的位置就算游戏成功了,进入下一关。

第二关

python 迷宫最短路径 python编程一个迷宫_小游戏_03


第三关

python 迷宫最短路径 python编程一个迷宫_小游戏_04

由于设计地图能力太有限,也就做了三关的地图,高手可以自己做新地图。

整个游戏的思路就是,首先从地图文档中获取到每一关的地图,然后把地图数据存放到字典变量maze_map_dic中。然后根据关卡取出每一关的地图数据,再根据对应的地图数据再pygame中绘制出对应的图形。

控制方式为上下左右控制角色移动,同时角色移动之前,判断该移动是否合法,如果合法,则交换迷宫对应位置的内容,然后再次绘制地图,造成角色移动的假象。

需要注意的地方是,当地图游玩游戏时,字典变量里的地图数据会根据游玩的不同而发生变化,所以如果将来要选关或者别的情况需要重置地图是,那么我们就需要在使用时深度拷贝地图信息到新的变量中为好。

程序代码:

import random
 import copy
 import pygamefps = 30
 fps_clock = pygame.time.Clock()
 screen_width = 1024
 screen_height = 768display = pygame.display.set_mode((screen_width, screen_height), 0, 32)
 pygame.display.set_caption(‘迷宫小游戏’)tile_width = 30
 tile_height = 30x_margin = 0
 y_margin = 0line_color = ‘white’
level = 0
maze_maps_dic = {}
directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]
 move_direction = (0, 0)maze = []
 player_location = ()
 destination_location = ()keys = []
 doors = []

主函数所有内容先晒出来

if name == ‘main’:

pygame.init()
maze_maps_dic = read_map()

go_to_next_level()
# x_margin = int((screen_width - tile_width * len(maze[0])) / 2)
# y_margin = int((screen_height - tile_height * len(maze)) / 2)
draw_game_board(maze, player_image, destination_image, player_location, destination_location)

while True:
    if player_location == destination_location:
        pygame.time.wait(300)
        level_cartoon()
        go_to_next_level()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
        # 如果按键被按下且抬起,则代表用户按下了某一个按键
        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                move_direction = directions[0]
            elif event.key == pygame.K_RIGHT:
                move_direction = directions[1]
            elif event.key == pygame.K_UP:
                move_direction = directions[2]
            elif event.key == pygame.K_DOWN:
                move_direction = directions[3]
    if is_right_direction(move_direction, player_location):

        # 当移动是被允许的,那么交换当前player坐标内容和player移动到下一步的坐标内容,下一次绘制时,角色位置就发生变化了
        maze[player_location[0]][player_location[1]] = '0'
        player_location = (player_location[0] + move_direction[0], player_location[1] + move_direction[1])
        maze[player_location[0]][player_location[1]] = 'p'
        # 移动完成,重置方向
        move_direction = (0, 0)
    check_player_and_key()
    draw_game_board(maze, player_image, destination_image, player_location, destination_location)
    pygame.display.update()
    fps_clock.tick(fps)

比较重要的一步是读取地图函数,首先需要根据地图的内容读取,定义了一个字典变量来存放地图maze_maps_dic = {}

读取外部迷宫地图

def read_map():
 # maze_maps = []
 maze_level = ‘’
 level_map = []
 with open(‘maze_maps.txt’, ‘r’) as f:
 for line in f:
 line = line.strip(‘\r\n’)
 if ‘#’ in line:
 maze_level = line.strip('# ‘)
 elif line != ‘’:
 line = line.split(’ ')
 level_map.append(line)
 elif line == ‘’ and len(level_map) > 0:
 maze_maps_dic[maze_level] = level_map
 level_map = []
 maze_level = -1

通过读取函数,我们把迷宫地图存放到了字典变量中,格式是:

{‘1’:
 [[‘W’, ‘W’, ‘W’, ‘W’, ‘W’, ‘W’],
 [‘W’, ‘p’, ‘0’, ‘0’, ‘0’, ‘W’],
 [‘W’, ‘0’, ‘T’, ‘0’, ‘0’, ‘W’],
 [‘W’, ‘0’, ‘0’, ‘0’, ‘0’, ‘W’],
 [‘W’, ‘T’, ‘T’, ‘0’, ‘g’, ‘W’],
 [‘W’, ‘W’, ‘W’, ‘W’, ‘W’, ‘W’]],
 ‘2’:
 [[‘p’, ‘0’, ‘0’, ‘w’, ‘0’, ‘w’, ‘0’, ‘0’], [‘w’, ‘w’, ‘0’, ‘r’, ‘0’, ‘0’, ‘t’, ‘0’], [‘k’, ‘r’, ‘0’, ‘t’, ‘0’, ‘0’, ‘0’, ‘0’], [‘0’, ‘0’, ‘0’, ‘r’, ‘0’, ‘0’, ‘t’, ‘0’], [‘w’, ‘t’, ‘0’, ‘r’, ‘0’, ‘t’, ‘0’, ‘0’], [‘w’, ‘r’, ‘d’, ‘0’, ‘0’, ‘r’, ‘r’, ‘r’], [‘0’, ‘r’, ‘t’, ‘r’, ‘0’, ‘g’, ‘t’, ‘0’], [‘w’, ‘r’, ‘r’, ‘r’, ‘t’, ‘t’, ‘t’, ‘t’]],
 ‘3’:
 [[‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’], [‘w’, ‘p’, ‘0’, ‘0’, ‘t’, ‘w’, ‘0’, ‘0’, ‘0’, ‘w’, ‘0’, ‘0’, ‘0’, ‘w’], [‘w’, ‘0’, ‘r’, ‘0’, ‘0’, ‘0’, ‘0’, ‘w’, ‘0’, ‘w’, ‘0’, ‘w’, ‘0’, ‘w’], [‘w’, ‘0’, ‘r’, ‘0’, ‘t’, ‘w’, ‘w’, ‘w’, ‘0’, ‘w’, ‘0’, ‘w’, ‘0’, ‘w’], [‘w’, ‘0’, ‘w’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘w’, ‘t’, ‘w’, ‘0’, ‘w’], [‘w’, ‘0’, ‘t’, ‘r’, ‘r’, ‘r’, ‘r’, ‘r’, ‘t’, ‘t’, ‘0’, ‘g’, ‘0’, ‘w’], [‘w’, ‘0’, ‘r’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘w’, ‘0’, ‘w’], [‘w’, ‘0’, ‘0’, ‘0’, ‘t’, ‘t’, ‘t’, ‘0’, ‘w’, ‘0’, ‘w’, ‘w’, ‘0’, ‘w’], [‘w’, ‘0’, ‘t’, ‘0’, ‘w’, ‘0’, ‘r’, ‘0’, ‘w’, ‘0’, ‘w’, ‘0’, ‘0’, ‘w’], [‘w’, ‘0’, ‘t’, ‘0’, ‘r’, ‘0’, ‘r’, ‘0’, ‘w’, ‘w’, ‘w’, ‘w’, ‘0’, ‘w’], [‘w’, ‘0’, ‘w’, ‘0’, ‘0’, ‘0’, ‘w’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘w’], [‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’, ‘w’]]}

当得到了地图内容后,就可以开始在pygmae中画出地图了。

绘制方格

def go_to_next_level():
 global level, maze, x_margin, y_margin, player_location, destination_location, keys, doors
 level = level % len(maze_maps_dic) + 1
 # 深层拷才不会改变原来的内容,如果增加选关内容,这个深度拷贝就很有用了
 maze = copy.deepcopy(maze_maps_dic[str(level)])
 x_margin = int((screen_width - tile_width * len(maze[0])) / 2)
 y_margin = int((screen_height - tile_height * len(maze)) / 2)
 for i in range(len(maze)):
 for j in range(len(maze[i])):
 if maze[i][j] == ‘p’:
 player_location = (i, j)
 elif maze[i][j] == ‘g’:
 destination_location = (i, j)
 keys.clear()
 doors.clear()

绘制游戏面板所有素材

def draw_game_board(p_maze_map, p_player, p_destination, p_player_location, p_destination_location):
 display.fill(‘sky blue’)
 display_level(level)
 draw_maze_lines(p_maze_map)
 draw_all_maze_wall(p_maze_map)
 draw_role(p_destination, p_destination_location[0], p_destination_location[1])
 draw_role(p_player, p_player_location[0], p_player_location[1])#显示关卡数
 def display_level(level_number):
 level_class = pygame.font.SysFont(‘Chalkboard’, 20, True, False)
 level_class_sur = level_class.render(‘level: %d’ % level_number, True, ‘yellow’)
 level_class_rect = level_class_sur.get_rect()
 level_class_rect.topleft = (20, 20)
 display.blit(level_class_sur, level_class_rect)#加载图片
 def image_load(name):
 image_path = ‘pngs/’ + name
 loaded_image = pygame.image.load(image_path)
 loaded_image = pygame.transform.scale(loaded_image, (25, 25))
 return loaded_imageplayer_image = image_load(‘boy.png’)
 wall_images = [‘Tree.png’, ‘Rock.png’, ‘Wall.png’, ‘Door.png’, ‘Key.png’]
 destination_image = image_load(‘Star.png’)
 tile_image = {‘rock’: image_load(‘Rock.png’),
 ‘tree’: image_load(‘Tree.png’),
 ‘wall’: image_load(‘Wall.png’),
 ‘door’: image_load(‘Door.png’),
 ‘key’: image_load(‘Key.png’)

绘制出所有的墙,树,钥匙,门等等

def draw_all_maze_wall(p_maze):
 for i in range(len(p_maze)):
 for j in range(len(p_maze[0])):
 match maze[i][j].lower():
 case ‘t’:
 tile = tile_image[‘tree’]
 draw_role(tile, i, j)
 case ‘r’:
 tile = tile_image[‘rock’]
 draw_role(tile, i, j)
 case ‘d’:
 tile = tile_image[‘door’]
 draw_role(tile, i, j)
 doors.append((i, j))
 case ‘k’:
 tile = tile_image[‘key’]
 draw_role(tile, i, j)
 keys.append((i, j))
 case ‘w’:
 tile = tile_image[‘wall’]
 draw_role(tile, i, j)剩余函数


目前比较粗暴的方式解密,有多少钥匙就有多少门,每捡到一把钥匙,则按顺序打开门,与钥匙所在地无关

def check_player_and_key():
 global maze
 for i in keys:
 if i == player_location:
 if doors:
 maze[doors[0][0]][doors[0][1]] = ‘0’
 del doors[0]
 keys.remove(i)

过关动画

def level_cartoon():
 for i in range(4):
 display.fill(‘red’)
 pygame.display.update()
 pygame.time.wait(300)
 display.fill(‘sky blue’)
 pygame.display.update()
 pygame.time.wait(300)
 pygame.display.update()

判断是否合法

def is_right_direction(p_direction, p_player_location):

x = p_player_location[0] + p_direction[0]
y = p_player_location[1] + p_direction[1]

# 判断下一步的区域不能是界外
if x < 0 or x >= len(maze) or y < 0 or y >= len(maze[1]):
    return False
# 如果下一步的区域是空格或者是目的地或者是钥匙都可以动
if maze[x][y] == '0' or maze[x][y] == 'g' or maze[x][y] == 'k':
    return True
else:
    return False

然后一个简单的迷宫游戏就完成了,虽然简单,但是它还很简陋,虽然简陋,但是它写的很乱啊。