5

I have to create a maze game, which receives as an input a command from the user in order to play the game. I have written the code for the maze game. What I want to modify is to only show part of the maze when it is printed to the user (after a move has been made). Here is the maze I have:

level = [
    ["1"," ","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
    ["1"," "," ","1","1","1","1","1","1","1"," "," "," "," "," "," "," "," "," "," ","1","1","1","1","1"],
    ["1"," "," ","1","1","1","1","1","1","1"," "," ","1","1","1","1","1","1"," "," ","1","1","1","1","1"],
    ["1"," "," "," "," "," "," "," ","1","1"," "," ","1","1","1","1","1","1"," "," ","1","1","1","1","1"],
    ["1"," "," "," "," "," "," "," ","1","1"," "," ","1","1","1"," "," "," "," "," "," "," "," ","1","1"],
    ["1"," ","1","1","1","1"," "," ","1","1"," "," ","1","1","1"," "," "," "," "," "," "," "," ","1","1"],
    ["1"," ","1","1","1","1"," "," ","1","1"," "," ","1","1","1","1","1","1"," "," ","1","1","1","1","1"],
    ["1"," ","1","1","1","1"," "," ","1","1"," "," "," "," ","1","1","1","1"," "," ","1","1","1","1","1"],
    ["1"," "," ","1","1","1"," "," "," "," "," "," "," "," ","1","1","1","1"," "," "," "," "," "," ","1"],
    ["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"," ","1"]
]

start_maze = level[0][1]      #start of maze
end_maze = level[9][23]       #end of maze

With an output as such:

The initial configuration of the maze is:
1 X 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1     1 1 1 1 1 1 1                     1 1 1 1 1
1     1 1 1 1 1 1 1     1 1 1 1 1 1     1 1 1 1 1
1               1 1     1 1 1 1 1 1     1 1 1 1 1
1               1 1     1 1 1                 1 1
1   1 1 1 1     1 1     1 1 1                 1 1
1   1 1 1 1     1 1     1 1 1 1 1 1     1 1 1 1 1
1   1 1 1 1     1 1         1 1 1 1     1 1 1 1 1
1     1 1 1                 1 1 1 1             1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1   1

How do I make it so that the player can only see part of the maze as he moves around, rather than being able to see the end (which makes it easy)?

So for example to have a view like this:

    1   1 1 1
    1     1 1 
    1   X 1 1 
    1          
    1               

i.e. so that he can only see 2 other cells in each direction.

I hope I made the question clear. Below is the part of the code that is the main game, if that is needed:

player = {'y': 0, 'x': 1}
level[player['y']][player['x']] = 'X'

# Translate keywords into coordinate changes
move_modifications = {'UP': {'y': -1, 'x': 0},
                      'DOWN': {'y': 1, 'x': 0},
                      'LEFT': {'y':0, 'x': -1},
                      'RIGHT': {'y': 0, 'x': 1}} 

def player_move(maze):

    # Main game loop
    play = True
    while play:
        move = input("Please enter a command (LEFT/RIGHT/UP/DOWN): ")
        move = move.upper()

        coords = move_modifications[move]

        new_y = player['y'] + coords['y']
        new_x = player['x'] + coords['x']

        #Catch them if they try to leave the map
        try:
            maze_position = maze[new_y][new_x]
        except IndexError:
            print("Not on map")
            continue

        if maze_position != '1':
            # Move on the map
            maze[player['y']][player['x']] = ' '
            maze[new_y][new_x] = 'X'

            # Update player coords
            player['y'] = new_y
            player['x'] = new_x

            # Print result
            print_level(maze)

The rest of the code is just moving around, it doesn't include any printing of the maze.

TrebledJ
  • 8,713
  • 7
  • 26
  • 48
MOA
  • 349
  • 1
  • 16
  • Can you share your game? Wanna play it :) – Alderven Mar 14 '19 at 13:18
  • 1
    I added the code here: [link](https://pastebin.com/zEVPg1Ea). I use Jupyter Notebook, so you can copy the code to a new notebook to play. – MOA Mar 14 '19 at 13:32

1 Answers1

4

NumPy arrays make convenient the slicing of 2-dimensional lists. Consider the code and slice below.

# load numpy from its module
import numpy as np

# create a numpy array
np_level = np.array(level)

# slice the map
slice = np_level[max(new_y-2,0) : new_y+3, \    # y slice
                 max(new_x-2,0) : new_x+3]      # x slice

# print the slice
print(slice)
# or print_level(slice), whichever one suits your case

This takes your 2D array level, makes a NumPy array np_level, then prints a slice of it from the range [y-2, y+3) and [x-2, x+3) (using interval notation). This means that it slices the array from y-2 to y+2 and from x-2 to x+2 inclusive.

The max(y-2, 0) is there in case y-2 falls below 0 (i.e. negative). Slicing with a negative begin-index and a positive end-index will return an empty list (e.g. some_array[-1:1] ==> []). The same goes for max(x-2, 0). We could also add min(y+3, <height-of-level>) and min(x+3, <width-of-level>) for the end-indices, but array slicing already handles these edge cases -- so that's all good.

N.B. This requires the NumPy module to be installed. If it isn't already, install it by entering python -m pip install numpy into the command line/terminal.

TrebledJ
  • 8,713
  • 7
  • 26
  • 48
  • Thank you - that is very helpful. However when I try to implement this it gives me only `[ ]` as an output...I replaced `print_level(level)` in my code with what you wrote above. – MOA Mar 14 '19 at 13:05
  • I also edited the code a bit, as I realised `level` is my specific level, whereas in the main game loop we need `maze`. When I call the function then I put in `level`. – MOA Mar 14 '19 at 13:07
  • @MOA "_However when I try to implement this it gives me only [ ] as an output_" -- Hmm... perhaps because the position is at the starting position of (1, 0)? I just added a paragraph on bounds-checking. Try implementing that if you haven't already. – TrebledJ Mar 14 '19 at 13:08
  • I think numpy arrays have less overhead than nested lists in Python, since they have fewer intermediate layers between your script and memory – Ilia Gilmijarow Mar 14 '19 at 13:08
  • @MOA I've made changes to the slice (uses `max` now instead of needing an if-statement). – TrebledJ Mar 14 '19 at 13:11
  • @IliaGilmijarow Ah, that's cool. I wasn't too sure about that paragraph myself, so I removed it. Thanks for the comment. – TrebledJ Mar 14 '19 at 13:11
  • @TrebuchetMS Ok that works partly, it gives me right view, but now the output is like this: `[['1' ' ' '1' '1'] ['1' 'X' ' ' '1'] ['1' ' ' ' ' '1'] ['1' ' ' ' ' ' ']]` So it keeps the list-like look of it, rather than output it as a maze. – MOA Mar 14 '19 at 13:14
  • 1
    Oh i found it, it's `print_level` instead of `print` – MOA Mar 14 '19 at 13:15