Maze Runner 2D

Tags: large, game, maze

This two-dimensional maze runner shows the player a top-down, bird’s-eye view of a maze file you create in a text editor, such as the IDE you use to write your .py files. Using the WASD keys, the player can move up, left, down, and right, respectively, to navigate the @ symbol toward the exit marked by the X character.

To make a maze file, open a text editor and create the following pattern. Don’t type the numbers along the top and left side; they are only there for reference:

  123456789
1 #########
2 #S# # # #
3 #########
4 # # # # #
5 #########
6 # # # # #
7 #########
8 # # # #E#
9 #########

The # characters represent walls, the S marks the start, and the E marks the exit. The # characters in bold represent walls that you can remove to form your maze. Don’t remove the walls at odd-numbered columns and odd-numbered rows, and don’t remove the borders of the maze. When you’re done, save the maze as a .txt (text) file. It could look something like this:

#########
#S    # #
# ### # #
# #   # #
# ##### #
#   #   #
### # # #
#     #E#
#########

Of course, this is a simple maze. You can make maze files of any size as long as they have an odd number of rows and columns. Be sure it’ll still fit on the screen, though! You can also download maze files from https://invpy.com/mazes/.

maze_runner_2d.py
  1"""Maze Runner 2D, by Al Sweigart al@inventwithpython.com
  2Move around a maze and try to escape. Maze files are generated by
  3mazemakerrec.py.
  4This code is available at https://nostarch.com/big-book-small-python-programming
  5Tags: large, game, maze"""
  6
  7import sys, os
  8
  9# Maze file constants:
 10WALL = '#'
 11EMPTY = ' '
 12START = 'S'
 13EXIT = 'E'
 14
 15PLAYER = '@'  # (!) Try changing this to '+' or 'o'.
 16BLOCK = chr(9617)  # Character 9617 is '░'
 17
 18
 19def displayMaze(maze):
 20    # Display the maze:
 21    for y in range(HEIGHT):
 22        for x in range(WIDTH):
 23            if (x, y) == (playerx, playery):
 24                print(PLAYER, end='')
 25            elif (x, y) == (exitx, exity):
 26                print('X', end='')
 27            elif maze[(x, y)] == WALL:
 28                print(BLOCK, end='')
 29            else:
 30                print(maze[(x, y)], end='')
 31        print()  # Print a newline after printing the row.
 32
 33
 34print('''Maze Runner 2D, by Al Sweigart al@inventwithpython.com
 35
 36(Maze files are generated by mazemakerrec.py)''')
 37
 38# Get the maze file's filename from the user:
 39while True:
 40    print('Enter the filename of the maze (or LIST or QUIT):')
 41    filename = input('> ')
 42
 43    # List all the maze files in the current folder:
 44    if filename.upper() == 'LIST':
 45        print('Maze files found in', os.getcwd())
 46        for fileInCurrentFolder in os.listdir():
 47            if (fileInCurrentFolder.startswith('maze') and
 48            fileInCurrentFolder.endswith('.txt')):
 49                print('  ', fileInCurrentFolder)
 50        continue
 51
 52    if filename.upper() == 'QUIT':
 53        sys.exit()
 54
 55    if os.path.exists(filename):
 56        break
 57    print('There is no file named', filename)
 58
 59# Load the maze from a file:
 60mazeFile = open(filename)
 61maze = {}
 62lines = mazeFile.readlines()
 63playerx = None
 64playery = None
 65exitx = None
 66exity = None
 67y = 0
 68for line in lines:
 69    WIDTH = len(line.rstrip())
 70    for x, character in enumerate(line.rstrip()):
 71        assert character in (WALL, EMPTY, START, EXIT), 'Invalid character at column {}, line {}'.format(x + 1, y + 1)
 72        if character in (WALL, EMPTY):
 73            maze[(x, y)] = character
 74        elif character == START:
 75            playerx, playery = x, y
 76            maze[(x, y)] = EMPTY
 77        elif character == EXIT:
 78            exitx, exity = x, y
 79            maze[(x, y)] = EMPTY
 80    y += 1
 81HEIGHT = y
 82
 83assert playerx != None and playery != None, 'No start in maze file.'
 84assert exitx != None and exity != None, 'No exit in maze file.'
 85
 86while True:  # Main game loop.
 87    displayMaze(maze)
 88
 89    while True:  # Get user move.
 90        print('                           W')
 91        print('Enter direction, or QUIT: ASD')
 92        move = input('> ').upper()
 93
 94        if move == 'QUIT':
 95            print('Thanks for playing!')
 96            sys.exit()
 97
 98        if move not in ['W', 'A', 'S', 'D']:
 99            print('Invalid direction. Enter one of W, A, S, or D.')
100            continue
101
102        # Check if the player can move in that direction:
103        if move == 'W' and maze[(playerx, playery - 1)] == EMPTY:
104            break
105        elif move == 'S' and maze[(playerx, playery + 1)] == EMPTY:
106            break
107        elif move == 'A' and maze[(playerx - 1, playery)] == EMPTY:
108            break
109        elif move == 'D' and maze[(playerx + 1, playery)] == EMPTY:
110            break
111
112        print('You cannot move in that direction.')
113
114    # Keep moving in this direction until you encounter a branch point.
115    if move == 'W':
116        while True:
117            playery -= 1
118            if (playerx, playery) == (exitx, exity):
119                break
120            if maze[(playerx, playery - 1)] == WALL:
121                break  # Break if we've hit a wall.
122            if (maze[(playerx - 1, playery)] == EMPTY
123                or maze[(playerx + 1, playery)] == EMPTY):
124                break  # Break if we've reached a branch point.
125    elif move == 'S':
126        while True:
127            playery += 1
128            if (playerx, playery) == (exitx, exity):
129                break
130            if maze[(playerx, playery + 1)] == WALL:
131                break  # Break if we've hit a wall.
132            if (maze[(playerx - 1, playery)] == EMPTY
133                or maze[(playerx + 1, playery)] == EMPTY):
134                break  # Break if we've reached a branch point.
135    elif move == 'A':
136        while True:
137            playerx -= 1
138            if (playerx, playery) == (exitx, exity):
139                break
140            if maze[(playerx - 1, playery)] == WALL:
141                break  # Break if we've hit a wall.
142            if (maze[(playerx, playery - 1)] == EMPTY
143                or maze[(playerx, playery + 1)] == EMPTY):
144                break  # Break if we've reached a branch point.
145    elif move == 'D':
146        while True:
147            playerx += 1
148            if (playerx, playery) == (exitx, exity):
149                break
150            if maze[(playerx + 1, playery)] == WALL:
151                break  # Break if we've hit a wall.
152            if (maze[(playerx, playery - 1)] == EMPTY
153                or maze[(playerx, playery + 1)] == EMPTY):
154                break  # Break if we've reached a branch point.
155
156    if (playerx, playery) == (exitx, exity):
157        displayMaze(maze)
158        print('You have reached the exit! Good job!')
159        print('Thanks for playing!')
160        sys.exit()

https://inventwithpython.com/bigbookpython/project44.html