Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python Python Collections (2016, retired 2019) Dungeon Game Movement

Jerimiah Willhite
Jerimiah Willhite
12,014 Points

Using shorthand for moves?

So I've set up the moves for the dungeon game to be "NORTH", "EAST", "SOUTH", and "WEST", and they all work fine, but I've tried using every way I can think of to set up a shorthand and nothing works. Ideally what I want is for the player to only have to type "N" or "E", etc. and be able to move that way. I've even tested it this way to check, but it seems that breaks the game and doesn't let the player move at all:

    if move == "W":
        x -= 1
    if move == "E":
        x += 1
    if move == "N":
        y -= 1
    if move == "S":
        y += 1  

I've also tried:

if move == "WEST" or move == "W":
    x -= 1

But then only "WEST" does anything, while "W" gets the hard walls message (because it goes to the else block). Is there some sort of inherent limitation in Python for not being able to accept one letter inputs or what am I not getting?

Here's the full code. It works fine it just won't do shorthand for some reason I can't figure out:

import random
import os


CELLS = [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0),
         (0, 1), (1, 1), (2, 1), (3, 1), (4, 1),
         (0, 2), (1, 2), (2, 2), (3, 2), (4, 2),
         (0, 3), (1, 3), (2, 3), (3, 3), (4, 3),
         (0, 4), (1, 4), (2, 4), (3, 4), (4, 4),]


def clear_screen():
    os.system('cls' if os.name == 'nt' else 'clear')

def get_locations():
    return random.sample(CELLS, 3)


def move_player(player, move):

    x, y = player
    if move == "WEST" or move == "W": ##Trying to do shorthand here but isn't working properly
        x -= 1
    if move == "EAST":
        x += 1
    if move == "NORTH":
        y -= 1
    if move == "SOUTH":
        y += 1              


    return x, y

def get_moves(player):
    moves = ["NORTH", "SOUTH", "EAST", "WEST"]
    x, y = player
    if x == 0:
        moves.remove("WEST")
    if x == 4:
        moves.remove("EAST")
    if y == 0:
        moves.remove('NORTH')
    if y == 4:
        moves.remove('SOUTH')       

    return moves

def draw_map(player):
    print(" _"*5)
    tile = "|{}"

    for cell in CELLS:
        x, y = cell
        if x < 4:
            line_end = ""
            if cell == player:
                output = tile.format("@")
            else:
                output = tile.format("_")
        else: 
            line_end = "\n"
            if cell == player:
                output = tile.format("X|")
            else:
                output = tile.format("_|")
        print(output, end=line_end)


def game_loop():
    monster, door, player = get_locations()
    playing = True
    while playing:
        clear_screen()
        draw_map(player)
        valid_moves = get_moves(player)

        print("You're currently in room {}.".format(player)) 
        print("You can move {}.".format(", ".join(valid_moves)))
        print("Enter QUIT to quit")

        move = input("> ").upper()

        if move == 'QUIT':
            print("\n ** See you next time! **\n")
            break
        if move in valid_moves:
            player = move_player(player, move)

            if player == monster:
                print("\n Oh no! The monster got you! Better luck next time! **\n")
                playing = False

            if player == door: 
                print("\n You escaped! Congratulations!")
                playing = False
        else:
            input("\n ** Walls are hard! Don't run into them! ** \n")   

    else:
        if input("Play again? Y/n").upper != "N":
            game_loop()         





clear_screen()
print("Welcome to the dungeon!")
input("Press return to start!")
clear_screen()
game_loop()

1 Answer

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 67,989 Points

You'll have to change more than just the move_player() function to achieve your goal.

The function get_moves() is restricting the valid moves to the full words.

One way to move forward would be adding the single character options to the valid moves list. Be sure to remove both the full word and single character when a move is restricted.

Another way would be to convert all code to use the single letter representation, then only use the first character of user input (move[0]). A side-effect is "STOP" would be seen as "S"outh.

Jerimiah Willhite
Jerimiah Willhite
12,014 Points

Thanks for the answer! That helps with what I'm looking for! I've updated it, but was wondering if there's any way to possibly hide the extra choices of NESW? I've updated the string to explain that they're shortcuts, but they are slightly unsightly. Your second method works, but like you said would have side effects.

Chris Freeman
Chris Freeman
Treehouse Moderator 67,989 Points

This is one of those trade offs where keeping the code simple is at odds with looking for elegant solutions to problems. Sometimes you have to punt and just pick anything that works. Later you can refactor to improve it if it turns out to be needing improvement.

In this code valid_moves is being used to hold the possible moves and used directly as the out put to the user. One solution is have get_moves create return two lists: one of full words and one of shortcut keys. Still removing the illegal directions from both lists.

valid_moves_long, valid_moves_short = get_moves(player)

Use both list to check if move is valid:

 If move in valid_moves_long or move in valid_moves_short:

Then you could use formatting to create the user message from the two lists:

print("You can move ", end="")
for short, long in zip(valid_moves_short, valid_moves_long):
    # print short and ending of long
    print("[{}]{} ".format(short, long[1:]), end="")
print("")

This is the fun part of programming: playing with various solutions to find what works best. It helps fill your "snippet bank" with style ideas you've learned along the way.

Good luck and have fun!!

Jerimiah Willhite
Jerimiah Willhite
12,014 Points

That's a great idea! Thanks for the follow-up. Python has taught me more about thinking like a programmer than any of the front-end languages, but obviously there's still a long way to go.