Advertisement

Need help with python and A*

Started by August 06, 2007 08:21 AM
0 comments, last by Vorpy 17 years, 3 months ago
Hi, people I'm new here, and I have problem with my program that need to solve puzzle usnig A* algorithm. In some cases program can't solve puzzle. Exzample: H A B G D C F E Here is a source:

import pygame
from pygame.locals import*


class Square(pygame.sprite.Sprite):

    def __init__(self, letter, (x , y)):
        pygame.sprite.Sprite.__init__(self)
        self.rect = pygame.Rect(x,y,32,32)
        self.image = pygame.Surface((32,32))
        self.image.fill((255,0,0))
        pygame.draw.rect(self.image, (200,0,0), (1,1,30,30), 2)
        self.letter = letter
        t = font.render(letter, 1, (0,0,0))
        self.image.blit(t, (10,6))
        self.corect_pos = goal[self.letter]

def clockwise(pos):
	if pos[0]== 0 and pos[1] <=32:
		return pos[0], pos[1]+32
	elif pos[0] >=32 and pos[1] == 0:
		return pos[0]-32, pos[1]
	elif pos[0] == 64 and pos[1] >= 32:
		return pos[0], pos[1]-32
	elif pos[0] <=32 and pos[1] ==64:
		return pos[0]+32, pos[1]
	    
def test_combinacion(squares):
    h = 0
    moves = 0
    for s in squares:
        distance = abs(s.rect.left-s.corect_pos[0])+ abs(s.rect.top-s.corect_pos[1])
        if distance !=0:
            distance = distance/32
        moves += distance
        if s.rect.topleft !=(32,32):
            if s.letter != 'A':
                letter_check = chr(ord(s.letter)-1)
            else:
                letter_check = 'H'
            pos_check = clockwise(s.rect.topleft)
            for s in squares:
                if s.letter == letter_check:
                    if s.rect.topleft != pos_check:
                        h+=2
    if space_pos != (32,32):
        h+=1
    h = h*3 + moves
    return h+g

def move(square):
    enable_pos= [(square.rect.left-32, square.rect.top),
                 (square.rect.right, square.rect.top),
                 (square.rect.left, square.rect.top-32),
                 (square.rect.left, square.rect.bottom)]
    
    if space_pos in enable_pos:
        return space_pos,square.rect.topleft
    else:
        return -1           

        
def make_moves(sq):
    global space_pos
    returning =[]
    for s in sq:
        t = move(s)
        if t!= -1:
            temp = s.rect.topleft,space_pos
            s.rect.topleft,space_pos = t
            comb = make_combinacion(squares)
            if comb not in closedlist and comb not in openlist:
                returning.append(comb)
            s.rect.topleft,space_pos  = temp
    return returning

def check(combinacion):
    c =[]
    for l, pos in combinacion:
        if goal.values()[goal.keys().index(l)] == pos:
            c.append(1)
        else:
            c.append(0)
    return all(c)

def broji():
    global counter
    if counter < 6:
        counter+=1
    else:
        counter = 0

g = 0
pygame.init()        
font = pygame.font.Font('freesansbold.ttf', 18)
screen = pygame.display.set_mode((160,96))

start_button= pygame.Rect(112,16, 32,16)

goal = {'A':(0,0),'B':(32,0),'C':(64,0),'D':(64,32),'E':(64,64),'F':(32,64),'G':(0,64),'H':(0,32),'space':(32,32)}
squares= []

for letter, pos in goal.items():
    if letter != 'space':
        squares.append(Square(letter, pos))
    else:
        space_pos = pos



make_combinacion = lambda sq:[(s.letter,s.rect.topleft) for s in sq]+[('space',space_pos)]
make_squares = lambda combinacion: [Square(l, pos) for l, pos in combinacion if l!='space']
openlist =[]
closedlist=[]


clock = pygame.time.Clock()



ch = False
counter = 0
solve =0
while 1:

    clock.tick(40)
    for event in pygame.event.get():
        if event.type == QUIT:
            raise SystemExit()

    #Crtanje svega
    screen.fill((0,0,255))
    pygame.draw.rect(screen, (255,255,255), start_button)
    for s in squares:
        screen.blit(s.image,s.rect)
    pygame.display.flip()
    
    #Program
    if solve:
        #Algoritam
        broji()
        if ch != True and counter ==5:
            openlist = make_moves(squares)
            g+=1
            fs =[]
            for x in openlist:
                squares = make_squares(x)
                space_pos = x[-1][1]
                fs.append(test_combinacion(squares))
            c = openlist[fs.index(min(fs))]
            space_pos = c[-1][1]
            ch = check(c)
            squares = make_squares(c)
            closedlist.extend(openlist)
        if ch == True:
            solve =0
            closedlist =[]

    else:
        #Postavljaj kockice
        mstate = pygame.mouse.get_pressed()
        if mstate[0]:
            mpos = pygame.mouse.get_pos()
            for s in squares:
                if s.rect.collidepoint(mpos):
                    t = move(s)
                    if t != -1:
                        s.rect.topleft, space_pos = t
            if start_button.collidepoint(mpos):
                ch =check(make_combinacion(squares))
                openlist = [make_combinacion(squares)]
                g = 0
                solve = 1
                

[edit: formatting -SiCrane]
It looks like you're appending the entire open list to the closed list instead of just the state that was expanded.

You're also assuming that A*'s first guess is always correct, but that is not the case. If you always make the move that looks best then you have to backtrack sometimes. A* needs to find a complete solution path, not just one move at a time.

This topic is closed to new replies.

Advertisement