graph search

This commit is contained in:
s464923 2024-05-18 17:10:56 +02:00
parent fb4cd44b61
commit 8fcf4fad2b
4 changed files with 120 additions and 155 deletions

View File

@ -2,42 +2,38 @@ import pygame
from constant import size, rows, cols from constant import size, rows, cols
import random import random
class Board: class Board:
def __init__(self): def __init__(self):
self.board = [] self.board = []
self.load_images() self.load_images()
self.generate_board() self.generate_board()
def load_images(self): def load_images(self):
self.grass = pygame.image.load("board/grass.png") self.grass = pygame.image.load("board/grass.png")
self.dirt = pygame.image.load("board/dirt.png") self.dirt = pygame.image.load("board/dirt.png")
self.rock= pygame.image.load("board/rock.png") self.rock = pygame.image.load("board/rock.png")
self.weeds = pygame.image.load("board/weeds.png") self.weeds = pygame.image.load("board/weeds.png")
self.soil = pygame.image.load("board/zyzna.png") self.soil = pygame.image.load("board/zyzna.png")
def generate_board(self): def generate_board(self):
self.board = [[random.choice([0,1,2,3,4,5,6,7,8,9]) for _ in range(rows)] for _ in range(cols)] self.board = [[random.choice([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) for _ in range(cols)] for _ in range(rows)]
def draw_cubes(self, win): def draw_cubes(self, win):
for row in range(rows): for row in range(rows):
for col in range(cols): for col in range(cols):
cube_rect = pygame.Rect(row * size, col * size, size, size) cube_rect = pygame.Rect(col * size, row * size, size, size)
cube=self.board[row][col] cube = self.board[row][col]
if row == 4 and col == 4:
if row==4 and col==4:
win.blit(self.grass, cube_rect) win.blit(self.grass, cube_rect)
elif cube == 0: elif cube == 0:
rock_scale = pygame.transform.scale(self.rock, (size, size)) rock_scale = pygame.transform.scale(self.rock, (size, size))
win.blit(self.dirt, cube_rect) win.blit(self.dirt, cube_rect)
win.blit(rock_scale, cube_rect) win.blit(rock_scale, cube_rect)
elif cube == 1: elif cube == 1:
weed_scale = pygame.transform.scale(self.weeds, (size,size)) weed_scale = pygame.transform.scale(self.weeds, (size, size))
win.blit(self.grass, cube_rect) win.blit(self.grass, cube_rect)
win.blit(weed_scale, cube_rect) win.blit(weed_scale, cube_rect)
elif cube in(2,3,4,5): elif cube in (2, 3, 4, 5):
win.blit(self.grass, cube_rect) win.blit(self.grass, cube_rect)
elif cube == 10: elif cube == 10:
win.blit(self.soil, cube_rect) win.blit(self.soil, cube_rect)
@ -47,14 +43,14 @@ class Board:
def is_rock(self, row, col): def is_rock(self, row, col):
return self.board[row][col] == 0 return self.board[row][col] == 0
def is_weed(self,row,col): def is_weed(self, row, col):
return self.board[row][col] == 1 return self.board[row][col] == 1
def set_grass(self,row,col): def set_grass(self, row, col):
self.board[row][col]=2 self.board[row][col] = 2
def is_dirt(self,row,col): def is_dirt(self, row, col):
return self.board[row][col] in (6,7,8,9) return self.board[row][col] in (6, 7, 8, 9)
def set_soil(self, row, col): def set_soil(self, row, col):
self.board[row][col] = 10 self.board[row][col] = 10

View File

@ -1,80 +1,39 @@
from constant import width, height, rows, cols from constant import rows, cols
class Stan: class Stan:
def __init__(self, row, col, dir): def __init__(self, row, col, direction):
self.p = [] self.p = []
self.a = "" self.a = ""
self.row = row self.row = row
self.col = col self.col = col
self.direction = dir self.direction = direction
def __str__(self): def __str__(self):
return f"row: {self.row}, col: {self.col}, direction: {self.direction}" return f"row: {self.row}, col: {self.col}, direction: {self.direction}"
def parrent(self, stan, action): def parrent(self, stan, action):
if(len(self.p) == 0): if len(self.p) == 0:
self.p.append(stan) self.p.append(stan)
self.a = action self.a = action
def succ(self, action, board): def succ(self, action, board):
if(action == "up"): move_offsets = {
if(self.direction == "left"): "up": {"up": (-1, 0), "left": (0, -1), "down": (1, 0), "right": (0, 1)},
if not board.is_rock(max(self.col - 1, 0), self.row): "left": {"up": "left", "left": "down", "down": "right", "right": "up"},
return Stan( self.row , max(self.col - 1, 0), self.direction) "right": {"up": "right", "right": "down", "down": "left", "left": "up"}
return Stan(self.row, self.col, self.direction) }
if(self.direction == "up"):
if not board.is_rock(self.col, max(self.row - 1, 0)):
return Stan(max(self.row - 1,0) , self.col, self.direction)
return Stan(self.row, self.col, self.direction)
if(self.direction == "right"):
if not board.is_rock(min(self.col + 1, cols - 1), self.row):
return Stan(self.row, min(self.col + 1, cols - 1) , self.direction)
return Stan(self.row, self.col, self.direction)
if(self.direction == "down"):
if not board.is_rock(self.col, min(self.row + 1,rows - 1 )):
return Stan(min(self.row + 1,rows - 1 ) , self.col, self.direction)
return Stan(self.row, self.col, self.direction)
if(action == "left"):
if(self.direction == "left"):
return Stan(self.row , self.col, "down")
if(self.direction == "up"):
return Stan(self.row, self.col, "left")
if(self.direction == "right"):
return Stan(self.row, self.col, "up")
if(self.direction == "down"):
return Stan(self.row, self.col , "right")
if(action == "right"):
if(self.direction == "left"):
return Stan(self.row, self.col, "up")
if(self.direction == "up"):
return Stan(self.row, self.col, "right")
if(self.direction == "right"):
return Stan(self.row, self.col, "down")
if(self.direction == "down"):
return Stan(self.row, self.col,"left")
class Kolejka: if action == "up":
def __init__(self): row_offset, col_offset = move_offsets[action][self.direction]
self.id = 0 new_row = self.row + row_offset
self.len = 0 new_col = self.col + col_offset
self.stany = [] if 0 <= new_row < rows and 0 <= new_col < cols and not board.is_rock(new_row, new_col):
return Stan(new_row, new_col, self.direction)
def dodaj_stan(self, stan): elif action in ["left", "right"]:
self.stany.append(stan) new_direction = move_offsets[action][self.direction]
self.len += 1 return Stan(self.row, self.col, new_direction)
def usun_stan(self):
if not self.czy_pusta():
self.id += 1
return self.stany[self.id - 1]
else:
raise IndexError("Kolejka stanów jest pusta")
def czy_pusta(self): return None
return self.len <= self.id
def check(self, stan):
indeks = 0
for i in self.stany:
if(stan.direction == i.direction and stan.col == i.col and stan.row == i.row):
return True
return False
class Odwiedzone: class Odwiedzone:
def __init__(self): def __init__(self):

95
main.py
View File

@ -2,8 +2,8 @@ import pygame
from board import Board from board import Board
from constant import width, height, rows, cols from constant import width, height, rows, cols
from tractor import Tractor from tractor import Tractor
from kolejka import Stan, Kolejka, Odwiedzone from kolejka import Stan, Odwiedzone
from queue import Queue
@ -13,7 +13,7 @@ WIN = pygame.display.set_mode((width, height))
pygame.display.set_caption('Inteligenty Traktor') pygame.display.set_caption('Inteligenty Traktor')
def goal_test(elem, goaltest, board): def goal_test(elem, goaltest, board):
if board.is_rock(goaltest.col, goaltest.row): if board.is_rock(goaltest.row, goaltest.col):
return True return True
if((elem.row == goaltest.row) and (elem.col == goaltest.col)): if((elem.row == goaltest.row) and (elem.col == goaltest.col)):
return True return True
@ -21,38 +21,46 @@ def goal_test(elem, goaltest, board):
return False return False
def actions(elem, istate): def actions(elem, istate):
akcje = [] akcje = []
while((elem.row != istate.row) or (elem.col != istate.col) or (elem.direction != istate.direction)): while (elem.row != istate.row) or (elem.col != istate.col) or (elem.direction != istate.direction):
akcje.append(elem.a) akcje.append(elem.a)
elem = elem.p[0] elem = elem.p[0]
return akcje[::-1] # Odwracamy kolejność, aby akcje były w poprawnej sekwencji
return akcje
def graphsearch(istate, goaltest, board): def graphsearch(istate, goaltest, board):
explored = Odwiedzone() explored = Odwiedzone()
fringe = Kolejka() fringe = Queue()
fringe.dodaj_stan(istate) fringe.put(istate)
moves = ["up", "left", "right"] moves = ["up", "left", "right"]
while not fringe.czy_pusta(): while not fringe.empty():
elem = fringe.usun_stan() elem = fringe.get()
if goal_test(elem, goaltest, board): if goal_test(elem, goaltest, board):
return actions(elem, istate) return actions(elem, istate)
explored.dodaj_stan(elem) explored.dodaj_stan(elem)
for action in moves: for action in moves:
stan = elem.succ(action, board) stan = elem.succ(action, board)
if((not fringe.check(stan)) and (not explored.check(stan))): if stan is not None:
if((not fringe_check(fringe,stan)) and (not explored.check(stan))):
stan.parrent(elem, action) stan.parrent(elem, action)
fringe.dodaj_stan(stan) fringe.put(stan)
return "Brak sciezki" return "Brak sciezki"
def fringe_check(fringe, stan): # Funkcja pomocnicza do sprawdzania stanu w kolejce
with fringe.mutex:
for item in fringe.queue:
if stan.direction == item.direction and stan.col == item.col and stan.row == item.row:
return True
return False
def main(): def main():
rotation = ["left", "up", "right", "down"]
initial_state = Stan(4,4, "down") initial_state = Stan(4,4, "down")
goaltest = Stan(1,1, "up") goaltest = Stan(1,1, "up")
run = True run = True
clock = pygame.time.Clock() clock = pygame.time.Clock()
board = Board() board = Board()
board.load_images() board.load_images()
actions = graphsearch(initial_state, goaltest, board) akcje = graphsearch(initial_state, goaltest, board)
print("akcje: >",actions ) print("akcje: >",akcje )
tractor = Tractor(4, 4) tractor = Tractor(4, 4)
while run: while run:
clock.tick(fps) clock.tick(fps)
@ -61,63 +69,14 @@ def main():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
run = False run = False
if actions: if akcje:
action = actions.pop() # Pobierz kolejną akcję z listy action = akcje.pop(0) # Pobierz kolejną akcję z listy
if action == "left": if action == "left":
if tractor.direction == "up": tractor.turn_left()
tractor.direction = "left"
elif tractor.direction == "down":
tractor.direction = "right"
elif tractor.direction == "left":
tractor.direction = "down"
elif tractor.direction == "right":
tractor.direction = "up"
elif action == "right": elif action == "right":
if tractor.direction == "up": tractor.turn_right()
tractor.direction = "right"
elif tractor.direction == "down":
tractor.direction = "left"
elif tractor.direction == "left":
tractor.direction = "up"
elif tractor.direction == "right":
tractor.direction = "down"
elif action == "up": elif action == "up":
if (tractor.direction == "up" and tractor.row > 0): tractor.move_forward(board)
if board.is_weed(tractor.col, tractor.row - 1):
board.set_grass(tractor.col, tractor.row - 1)
tractor.row -= 1
elif board.is_dirt(tractor.col, tractor.row - 1):
board.set_soil(tractor.col, tractor.row - 1)
tractor.row -= 1
elif not board.is_rock(tractor.col, tractor.row - 1):
tractor.row -= 1
elif (tractor.direction == "left" and tractor.col > 0):
if board.is_weed(tractor.col - 1, tractor.row):
board.set_grass(tractor.col - 1, tractor.row)
tractor.col -= 1
elif board.is_dirt(tractor.col - 1, tractor.row):
board.set_soil(tractor.col - 1, tractor.row)
tractor.col -= 1
elif not board.is_rock(tractor.col - 1, tractor.row):
tractor.col -= 1
elif (tractor.direction == "down" and tractor.row < rows - 1):
if board.is_weed(tractor.col, tractor.row + 1):
board.set_grass(tractor.col, tractor.row + 1)
tractor.row += 1
elif board.is_dirt(tractor.col, tractor.row + 1):
board.set_soil(tractor.col, tractor.row + 1)
tractor.row += 1
elif not board.is_rock(tractor.col, tractor.row + 1):
tractor.row += 1
elif (tractor.direction == "right" and tractor.col < cols - 1):
if board.is_weed(tractor.col + 1, tractor.row):
board.set_grass(tractor.col + 1, tractor.row)
tractor.col += 1
elif board.is_dirt(tractor.col + 1, tractor.row):
board.set_soil(tractor.col + 1, tractor.row)
tractor.col += 1
elif not board.is_rock(tractor.col + 1, tractor.row):
tractor.col += 1
board.draw_cubes(WIN) board.draw_cubes(WIN)

View File

@ -1,5 +1,6 @@
import pygame import pygame
from constant import size from constant import size, rows, cols
class Tractor: class Tractor:
def __init__(self, row, col): def __init__(self, row, col):
self.row = row self.row = row
@ -8,10 +9,60 @@ class Tractor:
"up": pygame.image.load("tractor/up.png"), "up": pygame.image.load("tractor/up.png"),
"down": pygame.image.load("tractor/down.png"), "down": pygame.image.load("tractor/down.png"),
"left": pygame.image.load("tractor/left.png"), "left": pygame.image.load("tractor/left.png"),
"right":pygame.image.load("tractor/right.png") "right": pygame.image.load("tractor/right.png")
} }
self.direction = "down" self.direction = "down"
def draw(self, win): def draw(self, win):
tractor_image = self.images[self.direction] tractor_image = self.images[self.direction]
win.blit(tractor_image, (self.col*size, self.row*size)) win.blit(tractor_image, (self.col * size, self.row * size))
def turn_left(self):
if self.direction == "up":
self.direction = "left"
elif self.direction == "left":
self.direction = "down"
elif self.direction == "down":
self.direction = "right"
elif self.direction == "right":
self.direction = "up"
def turn_right(self):
if self.direction == "up":
self.direction = "right"
elif self.direction == "right":
self.direction = "down"
elif self.direction == "down":
self.direction = "left"
elif self.direction == "left":
self.direction = "up"
def move_forward(self, board):
if self.direction == "up" and self.row > 0:
if not board.is_rock(self.row - 1, self.col):
if board.is_weed(self.row - 1, self.col):
board.set_grass(self.row - 1, self.col)
elif board.is_dirt(self.row - 1, self.col):
board.set_soil(self.row - 1, self.col)
self.row -= 1
elif self.direction == "left" and self.col > 0:
if not board.is_rock(self.row, self.col - 1):
if board.is_weed(self.row, self.col - 1):
board.set_grass(self.row, self.col - 1)
elif board.is_dirt(self.row, self.col - 1):
board.set_soil(self.row, self.col - 1)
self.col -= 1
elif self.direction == "down" and self.row < rows - 1:
if not board.is_rock(self.row + 1, self.col):
if board.is_weed(self.row + 1, self.col):
board.set_grass(self.row + 1, self.col)
elif board.is_dirt(self.row + 1, self.col):
board.set_soil(self.row + 1, self.col)
self.row += 1
elif self.direction == "right" and self.col < cols - 1:
if not board.is_rock(self.row, self.col + 1):
if board.is_weed(self.row, self.col + 1):
board.set_grass(self.row, self.col + 1)
elif board.is_dirt(self.row, self.col + 1):
board.set_soil(self.row, self.col + 1)
self.col += 1