简体   繁体   中英

Can I call an instance of a class using its instance attribute?

New to python, so the question might not mean what I think it means, apologies if that is the case.

I wrote an adventure game and ran it in a GUI, I have gotten a lot of feedback (including on a deleted question here) that I was using too many global variables and my code could be better organised using classes. So, reading followed, now I am attempting to do what I have read.

I have a class:

class room:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.location = (self.x, self.y)
    
    #this displays in a GUI window
    def prompt(self):
        write('Another, identical, wood-panelled, four-doored room. What now?')
    
    #this updates a dictionary which maintains current location
    def where(self):
        locale['place'] = self.location
        
    
room1 = room(0, 0)
room2 = room(0, 1)
room3 = room(0, 2)
room4 = room(1, 0)
room5 = room(1, 1)
room6 = room(1, 2)

Now I am using a roomfinder function, to produce prompts and update location based on user input in a GUI. Exerpt:

def roomfinder():
   #if and nested if statements for every room location  
   elif locale['place'] == room3.location:
        if user_input.lower() == 'n':
            messagebox.showinfo(title='Game Over', message='You fall to your doom. There was no room here! \n \n')
            clear_console()
            startroom()
        elif user_input.lower() == 's':
            clear_console()
            room6.where()
            room6.prompt()
        elif user_input.lower() == 'e':
            messagebox.showinfo(title='Game Over', message='You fall to your doom. There was no room here! \n \n')
            clear_console()
            startroom()
        elif user_input.lower() == 'w':
            clear_console()
            room2.where()
            room2.prompt()
        else:
            write('Please enter a valid response')

Now with nested elif statements for 6 rooms, and a similar function for performing a search in each location, this is big and untidy (feedback agreed with my feelings on this). I am looking for some code that will do something like (obv this is not real code)

if user_input.lower() == 'n'
    locale['place'] = ( current +1, current)
    roomX.prompt where roomX = room where location is locale['place']

does such a syntax exist? Is this possible? Does my question make sense?

I don't know if I understood your question correctly, but you could write your code like so:


def write(msg):
    """Fake write function implementation, that only prints message to console."""
    print(msg)


def clear_console(): pass


class messagebox:
    """Fake Messagebox implementation."""
    def showinfo(
        self,
        title='Game Over',
        message='You fall to your doom. There are no rooms here!\n\n',
    ):
        print(title)
        print(message)


class Room:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.location = (self.x, self.y)
    
    def prompt(self):
        """Display message in GUI window."""
        write('Another, identical, wood-panelled, four-doored room. What now?')

    def __eq__(self, other):
        return self.location == other


class Game(dict):
    """Room game class.
    
    Parameters
    ----------
    xrooms: int | list, default=2
        The number, or list of rooms to create in the X-axis, or North/South direction.
    yrooms: int | list, default=3
        The number, or list of rooms to create in the Y-axis, or East/West direction.
    """

    def __init__(self, xrooms=2, yrooms=3):
        xrooms = list(range(xrooms)) if not isinstance(xrooms, list) else xrooms
        yrooms = list(range(yrooms)) if not isinstance(yrooms, list) else yrooms
        rooms = {
            f'room{i+1}': Room(x, y)
            for i, (x, y) in enumerate(zip(xrooms * len(yrooms), yrooms * len(xrooms)))
        }
        super().__init__(rooms)
        self._current_room = Room(0, 0)
        self.gameover = False
    
    def next_input(self):
        """
        Ask the user for the next input.
        
        If there's no room in the chosen direction, set the attribute `gameover`
        to `True`, to indicate the game has ended.
        """
        user_input = input('Select a direction [N, S, W, E]: ').lower()
        xshift, yshift = 0, 0
        if user_input == 'n':    # Move to room North of current room.
            xshift = 1
        elif user_input == 's':  # Move to room South of current room.
            xshift = -1
        elif user_input == 'w':  # Move to room West of current room.
            yshift = -1
        elif user_input == 'e':  # Move to room East of current room.
            yshift = 1
        else:
            write('Please enter a valid response')
            return self.next_input()
        next_room = self._current_room.x + xshift, self._current_room.y + yshift
        clear_console()
        for room_number, room in self.items():
            if room == next_room:
                self._current_room = room
                room.prompt()
                return self.next_input()
        messagebox().showinfo(
            title='Game Over',
            message='You fall to your doom. There are no rooms here!\n\n',
        )
        self.gameover = True


To play the game, you can use a while/loop condition:


game = Game()
while not game.gameover:
    game.next_input()

# Prints:
#
# Select a direction [N, S, W, E]: N
# Another, identical, wood-panelled, four-doored room. What now?
# Select a direction [N, S, W, E]: S
# Another, identical, wood-panelled, four-doored room. What now?
# Select a direction [N, S, W, E]: N
# Another, identical, wood-panelled, four-doored room. What now?
# Select a direction [N, S, W, E]: 
# Please enter a valid response
# Select a direction [N, S, W, E]: S
# Another, identical, wood-panelled, four-doored room. What now?
# Select a direction [N, S, W, E]: s
# Game Over
# You fall to your doom. There are no rooms here!

Notes

The write , and clear_console functions, as well as the messagebox class are simply dummy versions that I've created to make the code run.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM