Example #1
0
    def get_grid():
        WINDOW = pygame.display.set_mode((settings.WIDTH, settings.WIDTH))
        GRID = picasso.make_grid(settings.ROWS, settings.WIDTH)
        pygame.display.set_caption(settings.WINDOW_TITLE)

        start_pos = None
        end_pos = None

        run = True
        while run:
            picasso.draw(WINDOW, GRID)
            for event in pygame.event.get():
                if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                    run = False
                elif pygame.mouse.get_pressed()[0]:
                    row, col = picasso.get_clicked_pos(pygame.mouse.get_pos())
                    square = GRID[row][col]

                    if not start_pos and square != end_pos and square.state != SquareState.WALL:
                        start_pos = square
                        start_pos.change_state(SquareState.START)
                    elif not end_pos and square != start_pos and square.state != SquareState.WALL:
                        end_pos = square
                        end_pos.change_state(SquareState.END)
                    elif square not in (start_pos, end_pos):
                        square.change_state(SquareState.WALL)

                elif pygame.mouse.get_pressed()[2]:
                    row, col = picasso.get_clicked_pos(pygame.mouse.get_pos())
                    square = GRID[row][col]
                    square.reset()

                    if square == start_pos:
                        start_pos = None
                    elif square == end_pos:
                        end_pos = None

                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RETURN:
                        if start_pos and end_pos:
                            return GRID

        pygame.quit()
Example #2
0
    def find_path():
        def _get_valid_neighbours(r: int, c: int):
            """
            Find valid neighbours for a square:
            valid means it's not a wall, has not been visited
            :param r: row
            :param c: column
            :return: valid neighbours
            :rtype: list()
            """

            up_neighbour = (r, c + 1)
            down_neighbour = (r, c - 1)
            left_neighbour = (r - 1, c)
            right_neighbour = (r + 1, c)

            neighbours = [up_neighbour, down_neighbour, left_neighbour, right_neighbour]
            v_neighbours = list()

            for neighbour in neighbours:
                r, c = neighbour
                if r in range(settings.ROWS) and c in range(settings.ROWS):
                    if grid[r][c].state not in [SquareState.VISITED, SquareState.WALL, SquareState.START]:
                        v_neighbours.append(neighbour)

            return v_neighbours

        def _get_heuristic(p1: tuple, p2: tuple):
            """
            Get approximate distance to p2
            :param p1: position 1
            :param p2: end position
            :return: approximate distance
            :rtype: int
            """
            x1, y1 = p1
            x2, y2 = p2

            return abs(x1 - x2) + abs(y1 - y2)

        def _reconstruct_path(r, c):
            rr, cc = r, c
            moves = list()

            while True:
                try:
                    rr, cc = came_from[rr][cc].get_pos()
                    moves.append((rr, cc))
                except:
                    moves.reverse()
                    return moves

        WINDOW = pygame.display.set_mode((800, 800))
        grid = Creator.get_grid()
        pq = PriorityQueue()

        end_pos = None
        start_pos = None
        start_row, start_col = None, None

        for row in grid:
            for square in row:
                if square.state == SquareState.START:
                    start_pos = square.row, square.col
                    start_row, start_col = start_pos
                elif square.state == SquareState.END:
                    end_pos = square.row, square.col
        print()
        print(f'Starting position: {start_pos}')
        print(f'Ending position: {end_pos}')
        print()

        came_from = defaultdict(dict)

        g_score = defaultdict(dict)
        f_score = defaultdict(dict)

        for rq in grid:
            for cq in rq:
                r, c = cq.get_pos()
                g_score[r][c] = float("inf")
                f_score[r][c] = float("inf")

        g_score[start_row][start_col] = 0
        f_score[start_row][start_col] = _get_heuristic(start_pos, end_pos)

        pq.put((f_score[start_row][start_col], grid[start_row][start_col]))

        finished = False
        while not finished:
            current = pq.get()
            current_square = current[1]
            current_row, current_col = current_square.get_pos()

            for n in _get_valid_neighbours(*current_square.get_pos()):
                n_row, n_col = n
                te_g_score = g_score[current_row][current_col] + 1

                grid[n_row][n_col].change_state(SquareState.PATH)
                if (n_row, n_col) == end_pos:
                    finished = True

                    grid[n_row][n_col].change_state(SquareState.PATH)
                    display_path = True

                    final_moves = _reconstruct_path(current_row, current_col)
                    final_moves.append((current_row, current_col))
                    final_moves.append((n_row, n_col))

                    print(f'Path found, took {len(final_moves)} moves')
                    print(f'Moves: {final_moves}')
                    print()

                    for r, c in final_moves:
                        grid[r][c].change_state(SquareState.PATH)
                        picasso.draw(WINDOW, grid)
                        sleep(0.1)

                    while display_path:
                        for event in pygame.event.get():
                            if event.type == pygame.QUIT:
                                if event.type == pygame.QUIT or (
                                        event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                                    display_path = False
                                    break

                if te_g_score < g_score[n_row][n_col]:
                    came_from[n_row][n_col] = current_square
                    g_score[n_row][n_col] = te_g_score
                    f_score[n_row][n_col] = g_score[n_row][n_col] + _get_heuristic((n_row, n_col), end_pos)

                if (f_score[n_row][n_col], grid[n_row][n_col]) not in pq.queue:
                    pq.put((f_score[n_row][n_col], grid[n_row][n_col]))

                grid[n_row][n_col].change_state(SquareState.VISITED)
            picasso.draw(WINDOW, grid)
        pygame.quit()
    def find_path():
        def _get_valid_neighbours(r: int, c: int):
            """
            Find valid neighbours for a square:
            valid means it's not a wall, has not been visited
            :param r: row
            :param c: column
            :return: valid neighbours
            :rtype: list()
            """
            rs = r
            cs = c

            up_neighbour = (r, c + 1)
            down_neighbour = (r, c - 1)
            left_neighbour = (r - 1, c)
            right_neighbour = (r + 1, c)

            neighbours = [
                up_neighbour, down_neighbour, left_neighbour, right_neighbour
            ]
            v_neighbours = list()

            for neighbour in neighbours:
                r, c = neighbour
                if r in range(settings.ROWS) and c in range(settings.ROWS):
                    if grid[r][c].state not in [
                            SquareState.VISITED, SquareState.WALL,
                            SquareState.START
                    ]:
                        v_neighbours.append(neighbour)

            return v_neighbours

        WINDOW = pygame.display.set_mode((800, 800))
        grid = Creator.get_grid()

        finished = False

        for row in grid:
            for square in row:
                if square.state == SquareState.START:
                    start_pos = square.row, square.col
                elif square.state == SquareState.END:
                    end_pos = square.row, square.col

        print()
        print(f'Starting position: {start_pos}')
        print(f'Ending position: {end_pos}')

        final_moves = None
        q = LifoQueue()
        q.put([start_pos])

        while not finished:
            moves_so_far = q.get()

            rx, cy = moves_so_far[len(moves_so_far) - 1]
            valid_neighbours = _get_valid_neighbours(rx, cy)

            for vn in valid_neighbours:
                moves_so_far_copy = moves_so_far.copy()
                rvn, cvn = vn
                moves_so_far_copy.append(vn)
                q.put(moves_so_far_copy)
                if (rvn, cvn) == end_pos:
                    final_moves = moves_so_far_copy
                    print()
                    print(f'Path found, took {len(final_moves)} moves')
                    print(f'Moves: {final_moves}')
                    print()
                    finished = True

                    [
                        grid[r][c].change_state(SquareState.PATH)
                        for r, c in final_moves
                    ]
                    picasso.draw(WINDOW, grid)

                    display_path = True
                    while display_path:
                        for event in pygame.event.get():
                            if event.type == pygame.QUIT or (
                                    event.type == pygame.KEYDOWN
                                    and event.key == pygame.K_ESCAPE):
                                display_path = False
                    break

                grid[rvn][cvn].change_state(SquareState.VISITED)
            picasso.draw(WINDOW, grid)
        pygame.quit()
Example #4
0
    def find_path():
        def _get_start_and_end_pos():
            start_pos, end_pos = None, None
            for row in grid:
                for square in row:
                    if square.state == SquareState.START:
                        start_pos = square.row, square.col
                    elif square.state == SquareState.END:
                        end_pos = square.row, square.col

            return start_pos, end_pos

        def _get_valid_neighbours(r: int, c: int):
            """
            Find valid neighbours for a square:
            valid means it's not a wall, has not been visited
            :param r: row
            :param c: column
            :return: valid neighbours
            :rtype: list()
            """

            up_neighbour = (r, c + 1)
            down_neighbour = (r, c - 1)
            left_neighbour = (r - 1, c)
            right_neighbour = (r + 1, c)

            neighbours = [up_neighbour, down_neighbour, left_neighbour, right_neighbour]
            v_neighbours = list()

            for neighbour in neighbours:
                r, c = neighbour
                if r in range(settings.ROWS) and c in range(settings.ROWS):
                    if grid[r][c].state not in [SquareState.VISITED, SquareState.WALL, SquareState.START]:
                        v_neighbours.append(neighbour)

            return v_neighbours

        def _reconstruct_path():
            path = [end_pos]
            current = end_pos

            while prev[current]:
                path.append(prev[current])
                current = prev[current]
                # print(u)

            path.reverse()
            return path

        WINDOW = pygame.display.set_mode((800, 800))
        grid = Creator.get_grid()

        start_pos, end_pos = _get_start_and_end_pos()

        print()
        print(f'Starting position: {start_pos}')
        print(f'Ending position: {end_pos}')
        print()

        dist = {}
        prev = {}
        q = list()

        finished = False

        while not finished:

            for row in grid:
                for square in row:
                    pos = square.get_pos()

                    dist[square.get_pos()] = float("inf")
                    prev[square.get_pos()] = None
                    if square.state in [SquareState.EMPTY, SquareState.START, SquareState.END]:
                        q.append(pos)

            dist[start_pos] = 0

            while q:
                u = min(q, key=dist.__getitem__)
                q.remove(u)

                for v in _get_valid_neighbours(*u):
                    alt = dist[u] + 1

                    if alt < dist[v]:
                        dist[v] = alt
                        prev[v] = u

                        vr, vc = v
                        grid[vr][vc].change_state(SquareState.VISITED)

                    if v == end_pos:
                        q = list()
                        break

                picasso.draw(WINDOW, grid)
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        finished = True
                        q = list()
                        break

            path = _reconstruct_path()

            for square in path:
                row, col = square
                grid[row][col].change_state(SquareState.PATH)
                picasso.draw(WINDOW, grid)
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        finished = True
                        break

        print(f'Path found, took {len(path)} moves')
        print(f'Moves: {path}')
        print()

        pygame.quit()