2

I'm building a visualization tool for A* Search in Python and have come across the following error when trying to calculate the g-score of my nodes.

    line 115, in g
    x1, y1 = s
TypeError: cannot unpack non-iterable method object

See code below:

from graphics import *
import pygame, sys
import math
import numpy as np
from queue import PriorityQueue

pygame.init()

# #set the screen size and captions
size = (500, 500)
rows = 50
margin = 1
screen = pygame.display.set_mode(size)
pygame.display.set_caption("A* Pathfinding")
screen.fill((173, 172, 166))

#define colors
aqua = (0, 255, 255)
black = (0, 0, 0)
blue = (0, 0, 255)
green = (0, 128, 0)
red = (255, 0, 0)
white = (255, 255, 255)
purple = (128, 0, 128)

#initialize PriorityQueue
q = PriorityQueue()



#define all possible states of each node
class Node:
    def __init__(self, row, col, width):
        self.row = row
        self.col = col
        self.x = row*width
        self.y = col*width  
        self.color = white
        self.width = width
        self.neighbors = [(col+1, row), (col-1, row), (col, row+1), (col, row-1)]
        #self.neighbors = []
    
    def get_pos(self):
        return self.row, self.col
    
    def is_closed(self):
        return self.color == red
    
    def is_open(self):
        return self.color == aqua
    
    def is_barrier(self):
        return self.color == black
    
    def is_start(self):
        return self.color == green
    
    def is_end(self):
        return self.color == blue
    
    def reset(self):
        return self.color == white
    
    def close(self):
        self.color = red
    
    def open_node(self):
        self.color = blue
    
    def barrier(self):
        self.color = black
    
    def start(self):
        self.color = green
    
    def end(self):
        self.color = aqua
        
    def path(self):
        self.color = purple

    


def init_grid():
    board = []
    for i in range(rows):
        board.append([])
        for j in range(rows):
            node = Node(i, j, size[0]/rows)
            board[i].append(node)
    return board


#heuristic
def h(c, end):
    x1, y1 = c
    x2, y2 = end
    return abs(x1 - x2) + abs(y1 - y2)


#distance between current node and start node
def g(c, s):
    x1, y1 = s
    x2, y2 = c
    return abs(x1 - x2) + abs(y1 - y2)



    

board = init_grid()


barrier = []
frontier = {}
path = {} 


#starting conditions using Node class and associated methods
start = board[5][5]
goal = board[30][35]
current = start
count = 0

q.put(0, (start))


#main game loop
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
            
        #allows user to draw barriers
        elif pygame.mouse.get_pressed()[0]:
            pos = pygame.mouse.get_pos()
            y_pos = int(pos[0] // (board[0][0].width + margin))
            x_pos = int(pos[1] // (board[0][0].width + margin))
            board[x_pos][y_pos].barrier()
            barrier.append(board[x_pos][y_pos].get_pos())
    
    #draw the grid
    for i in range(rows):
        for j in range(rows):
            color = board[i][j].color
            #print(board[i][j].color)
            if board[i][j] == start:
                board[i][j].start()
            elif board[i][j] == goal:
                board[i][j].end()
             
            

            pygame.draw.rect(screen, color, [j*(board[0][0].width + margin), i*(board[0][0].width + margin), board[0][0].width, board[0][0].width])
   
    
    #game loop
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_SPACE:
            while not q.empty():
                for neighbor in current.neighbors:
                    g_temp = g(current.get_pos, start.get_pos) + 1
                    if g_temp < g(neighbor, start.get_pos()): 
                        f = g_temp + h(current.get_pos(), goal.get_pos())
                        if neighbor not in frontier:
                            q.put((f, neighbor))
                            frontier.add(neighbor)
                            board[neighbor[0]][neighbor[1]].open_node()
                
                
                if current != goal:
                    new = q.get()[1]
                    path.add(current)
                    current = board[new[0]][new[1]]
                
                if current == goal:
                    break


    pygame.display.flip()
        
pygame.quit()

I have tried debugging this issue but I don't understand why it is giving me this error. The function should take in two tuple arguments and return an integer as the g-score, which I believe is what I am passing through in the game loop.

Please let me know if there is some obvious error that I missed here, I am still new to programming. Thank you so much for your time and help!

1
  • You are sending g_temp = g(current.get_pos, start.get_pos) + 1 this and expecting the values to be unpacked in x1, y1 = s. Is s a list or tuple to unpack? I hope you understand that x1, y1 = s does not mean x1 = s and y1 = s. Commented Nov 22, 2020 at 19:46

1 Answer 1

3

you have a long piece of code.

It seems you don't pass a tuple to g().

I spotted at least one error: You have to add the "()" after a method call, otherwise you pass the method name instead of the method value to g().

example from your code:

g_temp = g(current.get_pos, start.get_pos) + 1

should be:

g_temp = g(current.get_pos(), start.get_pos()) + 1

This is probably the problem. I haven't checked all the other lines as this code is very long ;) Test and come back tell us.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.