Path to a python character

Asked

Viewed 1,977 times

2

I adapted a program in Python that solves labyrinths, and I’m improving it, but I had problems with the minimum path (I even studied in Graphs), I was able to understand everything. But I’m having trouble finding the position(x,y) of the goal. I tried to use index() but as it has sub-lists it didn’t work very well.

I used this pattern to base the map on a Cartesian plan.

maze = """\
###########################
#       #             ## ##
# ##### ### # # ######## ##
#     #     ### #     #   #   
# ### # ##### # # ### ### # 
#     #       #     #   # # 
### #### #### ######### # # 
###    #   ##      ## # # # 
# ### ##   ## #### ## #   # 
# ### ## #### ## # ## ### #
#     #    ## ## # ## #   #
### ### ######## # ## ## ##
#             ##         X#
###########################
"""
EMPTY, BLOCK, STEP, END =" ", "*", ".", "X"
UP, DOWN, LEFT, RIGHT = "˄", "˅", "<", ">"

def solve(maze, x, y, move):

    found = False
    if 0 <= x < len(maze[0]) and 0 <= y < len(maze):
        if maze[y][x] == EMPTY:
            maze[y][x] = BLOCK

            if (solve(maze, x+1, y, RIGHT) or solve(maze, x, y+1, DOWN) or
                solve(maze, x-1, y, LEFT) or solve(maze, x, y-1, UP)):
                maze[y][x] = move
                found = True

        elif maze[y][x] == END:

            found = True 

    return found

if __name__ == "__main__":
    maze = [list(line) for line in maze.splitlines()]
    solve(maze, 1, 8, EMPTY)

    for line in maze:      
        print("".join(line))

how can I find the position of a term using this pattern?

  • I think you mean that: maze[1][2] to know the content of the sublist, and place the entire code when you can!

  • Ss, but how do I do this with the index? because I need to know the position of the (END) on the map, I use the list for the y-axis and the sub-list for x, but I don’t know how to locate the variable. I think about making a loop while, but I’m out of ideas.

  • I think this is it: Maze.find(END)

  • Would there be another way to return the position in numbers? type the position of the END[13][26] (sub-list 13, at heading 26)??

1 answer

1


Congratulations on the initiative!

So here we go: The "easy to start and hard to continue" way of doing this kind of thing is to use sequences within sequences.

Anyway, you’re defining your maze as a multiline string - so you’d better turn it into a list-in-lists data structure so you can address each point automatically. To do this, we can take the following steps: break the string with the whole maze where there is a line break (character n). Use each obtained substring as "as is" since a string is a string. (A \n the more you put right into the inpicio of the maze avoids an empty line at the beginning of the same and it is important):

maze = maze.split("\n")

Ready. Now maze[1][5] will access the sixth character in the second line. The "split" method breaks a string into a list of strings in the specified separator (and omits the separator), and is sufficient for this. Both lists and strings are sequences - so maze[n] will retrieve you a line from the maze.

Now, mazes of this kind are pretty cool things to start understanding Python Object Orientation. Just implement the method __getitem__ in a class, and Python can retrieve elements from there with the syntax [ ], as if it were a native sequence - and, if our __getitem__ support indices separated by ,, that are passed as tuples, we can access elements in the maze as maze[x, y] with only a few lines of code.

To allow the maze to be changeable, this is: you can insert new elements into it after created, I will use lists inside lists instead of strings inside lists:

class Maze:
   def __init__(self, text_maze):
        self.maze = [[char for char in line]  for line in text_maze.split() if line.strip()]

   def __getitem__(self, index):
        # getitem simples, vai retornar um erro do próprio Python
        # se for acessado um elemento com índice errado
        x, y = index
        return self.maze[y][x]

   def __setitem__(self, index, value):
       x, y = index
       self.maze[y][x] = value

   def __len__(self):
      return len(self.maze) 

   def __repr__(self):
      return "\n".join("".join(char for char in line) for line in self.maze)

Now, you will continue there, will give more tarbalho you plot elements within the maze (like a character walking, or even the algorithm showing the paths already traveled) in text mode, to which use a True graphic mode and see the maze as colored blobs on the screen. The terminal is full of pranks - while graphic functions are made for this.

Look at - taking advantage of what I had made of OOP, I inherited the class labyrinth, and put the extra code for the labrinto draw using the Tkinter.

See what you can do with another 40 lines (well spaced) and using the Tkinter - (the reference for the Tkinter canvas is here: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/canvas-methods.html )

maze_data = """\
###########################
#       #             ## ##
# ##### ### # # ######## ##
#     #     ### #     #   #
# ### # ##### # # ### ### #
#     #       #     #   # #
### #### #### ######### # #
###    #   ##      ## # # #
# ### ##   ## #### ## #   #
# ### ## #### ## # ## ### #
#     #    ## ## # ## #   #
### ### ######## # ## ## ##
#             ##         X#
###########################
"""

import tkinter

class Maze:
   def __init__(self, text_maze):
        self.maze = [[char for char in line]  for line in text_maze.split("\n") if line.strip()]
        print(self)

   def __getitem__(self, index):
        # getitem simples, vai retornar um erro do próprio Python
        # se for acessado um elemento com índice errado
        x, y = index
        return self.maze[y][x]

   def __setitem__(self, index, value):
       x, y = index
       self.maze[y][x] = value

   def __len__(self):
      return len(self.maze)

   def __repr__(self):
      return "\n".join("".join(char for char in line) for line in self.maze)

   width = property(lambda self: len(self.maze[0]))
   height = property(lambda self: len(self.maze))

BLOCK_SIZE = 24

COLORS = {"#": "#000", " ": "#fff", "X":"#f00"}

class TkinterMaze(Maze):
    def __init__(self, root, text_maze):
        super().__init__(text_maze)
        self.root = root
        self.canvas = tkinter.Canvas(root, width=self.width * BLOCK_SIZE, height=self.height  * BLOCK_SIZE)
        self.canvas.pack()
        self.rectangles = {}
        self.update()

    def clear(self):
        for coordinates, rect_id in self.rectangles.items():
            self.canvas.delete(rect_id)

    def update(self):
        self.clear()
        for (x, y), char in self:
            color = COLORS[char]
            rect_id = self.canvas.create_rectangle(
                x * BLOCK_SIZE,
                y * BLOCK_SIZE,
                (x + 1) * BLOCK_SIZE,
                (y + 1) * BLOCK_SIZE,
                fill = color,
                width = 0
            )
            self.rectangles[x, y] = rect_id


    def __iter__(self):
        for y, line in enumerate(self.maze):
            for x, char in enumerate(line):
                yield ((x,y), char)


def main():
    window = tkinter.Tk()
    maze = TkinterMaze(window, maze_data)
    window.bind("destroy", window.destroy)
    tkinter.mainloop()

main()

Looking at the Tkinter documentation a little bit, you can use the "bind" of events to receive keystrokes and make the character walk through the maze. (A better implementation will be with persongaem in a separate class, with a reference to the labyrinth - ai using the "getitem" it can know where it can go where it can’t go. He can share the ". canvas" of the maze to draw on the same screen, or the labrinto can incorporate another "layer" to draw objects that are not wall)

  • Great !! Thank you very much!! I was trying to find a way for a week kkk, classes are not my strong, I will give an extra study in POO to go to graphic mode. But for now I think I can plot the elements in the maze kk. Clean and objective explanation! obg guy!!

  • After seeing this code, I’ll have to learn to use this Tkinter kkk, it got really fucked !!

  • I actually always do things like this maze with pygame - but besides needing a separate installation, pygame is kind of "raw": the programmer has to do everything, and if he needs to use text in the program, he has to basically re-invent the wheel. O Tkinter.

  • Already starting in this part of the maze, this question of finding the location in (END), is to try to apply the A* in the code to make the minimum path, more this requires more than I thought. I’ve heard a lot about Tkinter, but I still don’t use it because I’m using the Blender game engine, it makes some things easier for me that I don’t have much experience yet.

  • The Blender game engine is a good one for that too. What would be bad would only be trying to stay in text mode.

  • there complicates, but I try to keep the balance between the text mode and all the rest, not to be too dependent.

  • The porblema is that in text mode you don’t have something consistent, cross-platform, to print colors, or print a collar in a specific position. to do this is more work than using a library to do it graphically. Impose a maze underneath each other every time the character a position is pretty ugly. But in text mode on Unix (Macos/Linux), there is the "curses" module - take a look.

  • I didn’t know that, I’ll take a look yes.

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.