Transfer in to JPNB
This commit is contained in:
381
JPNB/AI_P1_1.ipynb
Normal file
381
JPNB/AI_P1_1.ipynb
Normal file
File diff suppressed because one or more lines are too long
544
JPNB/AI_P1_2.ipynb
Normal file
544
JPNB/AI_P1_2.ipynb
Normal file
@@ -0,0 +1,544 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "e063ba00",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# A* Algorithm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "868592a7",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Install Requirements"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "26dff129",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"create a virtual environment in current directory by \n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"python3 -m venv .env # macos\n",
|
||||
"python -m venv .env # linux\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "55fa613b",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:23.660320Z",
|
||||
"start_time": "2025-05-07T21:40:22.973705Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%pip install pygame"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "db35c098",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Imports"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "e7034eee",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:23.825797Z",
|
||||
"start_time": "2025-05-07T21:40:23.718944Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"pygame 2.6.1 (SDL 2.28.4, Python 3.13.3)\n",
|
||||
"Hello from the pygame community. https://www.pygame.org/contribute.html\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import pygame\n",
|
||||
"import math"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "77d18f1b",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Global Variables"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"id": "60b63344",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:23.877569Z",
|
||||
"start_time": "2025-05-07T21:40:23.873797Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"BLACK = (0, 0, 0)\n",
|
||||
"WHITE = (255, 255, 255)\n",
|
||||
"BLUE = (0, 0, 255)\n",
|
||||
"GREEN = (0, 255, 0)\n",
|
||||
"RED = (255, 0, 0)\n",
|
||||
"ORANGE = (255, 165, 0)\n",
|
||||
"GREY = (128, 128, 128)\n",
|
||||
"\n",
|
||||
"WIDTH = 25\n",
|
||||
"HEIGHT = 25\n",
|
||||
"MARGIN = 3\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "87a05a3b",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Classes "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"id": "84ad596c",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:24.013443Z",
|
||||
"start_time": "2025-05-07T21:40:24.010202Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Queue:\n",
|
||||
" def __init__(self, type, sort_by = ''):\n",
|
||||
" self.type = type\n",
|
||||
" self.items = []\n",
|
||||
" self.sort_by = sort_by\n",
|
||||
"\n",
|
||||
" def clear(self):\n",
|
||||
" self.items.clear()\n",
|
||||
" \n",
|
||||
" def is_empty(self):\n",
|
||||
" if len(self.items) > 0:\n",
|
||||
" return False\n",
|
||||
" else:\n",
|
||||
" return True\n",
|
||||
"\n",
|
||||
" def push(self, element):\n",
|
||||
" self.items.append(element)\n",
|
||||
" '''\n",
|
||||
" queue = [element_0, element_1, ... , element_n] <- element_n+1\n",
|
||||
" '''\n",
|
||||
" if self.type == 'PRIO':\n",
|
||||
" '''\n",
|
||||
" Sorting so lowest cost/ value is at [0]\n",
|
||||
" queue = [element_0 < element_1 < ... < element_n < element_n+1]\n",
|
||||
" '''\n",
|
||||
" if self.sort_by == '':\n",
|
||||
" self.items.sort(key=lambda item: item.value)\n",
|
||||
" elif self.sort_by == 'f':\n",
|
||||
" self.items.sort(key=lambda item: item.f)\n",
|
||||
"\n",
|
||||
" def pop(self):\n",
|
||||
" if not self.is_empty():\n",
|
||||
" if self.type == 'LIFO':\n",
|
||||
" ''' LIFO\n",
|
||||
" queue = [element_0, elemente_1, ... , element_n]\n",
|
||||
" -> pop element_n\n",
|
||||
" '''\n",
|
||||
" return self.items.pop()\n",
|
||||
" else:\n",
|
||||
" ''' FIFO & PRIO\n",
|
||||
" queue = [element_0, element_1, ... , element_n]\n",
|
||||
" -> pop element_0\n",
|
||||
" '''\n",
|
||||
" return self.items.pop(0)\n",
|
||||
" return None"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"id": "d3b77c0a",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:24.044268Z",
|
||||
"start_time": "2025-05-07T21:40:24.041113Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Field:\n",
|
||||
" def __init__(self, x, y):\n",
|
||||
" self.x = x\n",
|
||||
" self.y = y\n",
|
||||
" self.state = \"free\" # states: free, obstacale, start, target\n",
|
||||
"\n",
|
||||
" self.g = float('inf')\n",
|
||||
" self.h = 0\n",
|
||||
" self.f = float('inf')\n",
|
||||
" self.parent = None\n",
|
||||
"\n",
|
||||
" def draw(self, screen):\n",
|
||||
" # state based coloring\n",
|
||||
" color = WHITE\n",
|
||||
" if self.state == \"obstacale\":\n",
|
||||
" color = BLACK\n",
|
||||
" elif self.state == \"start\":\n",
|
||||
" color = BLUE\n",
|
||||
" elif self.state == \"target\":\n",
|
||||
" color = GREEN\n",
|
||||
" elif self.state == \"path\":\n",
|
||||
" color = ORANGE\n",
|
||||
" elif self.state == \"current\":\n",
|
||||
" color = RED\n",
|
||||
" elif self.state == \"visited\":\n",
|
||||
" color = GREY\n",
|
||||
"\n",
|
||||
" x_calc = (MARGIN + WIDTH) * self.x + MARGIN\n",
|
||||
" y_calc = (MARGIN + HEIGHT) * (grid_size - 1 - self.y) + MARGIN # flipping\n",
|
||||
"\n",
|
||||
" pygame.draw.rect(\n",
|
||||
" screen,\n",
|
||||
" color,\n",
|
||||
" [x_calc, y_calc, WIDTH, HEIGHT]\n",
|
||||
" )"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"id": "b3d9f04f",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:24.125218Z",
|
||||
"start_time": "2025-05-07T21:40:24.120389Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Grid:\n",
|
||||
" def __init__(self, cols, rows):\n",
|
||||
" self.cols = cols # x\n",
|
||||
" self.rows = rows # y\n",
|
||||
" self.grid = []\n",
|
||||
"\n",
|
||||
" i = 0\n",
|
||||
" while i < cols: # col = x\n",
|
||||
" col = []\n",
|
||||
" j = 0\n",
|
||||
" while j < rows: # row = y\n",
|
||||
" col.append(Field(i, j)) # (x,y)\n",
|
||||
" j += 1\n",
|
||||
" self.grid.append(col)\n",
|
||||
" i += 1\n",
|
||||
"\n",
|
||||
" self.start = None\n",
|
||||
" self.target = None\n",
|
||||
"\n",
|
||||
" def draw(self, screen):\n",
|
||||
" for col in self.grid:\n",
|
||||
" for field in col:\n",
|
||||
" field.draw(screen)\n",
|
||||
"\n",
|
||||
" def heuristic(self, field):\n",
|
||||
" return math.sqrt((field.x - self.target[0]) ** 2 + (field.y - self.target[1]) ** 2)\n",
|
||||
"\n",
|
||||
" def get_state(self, x, y):\n",
|
||||
" return self.grid[x][y].state\n",
|
||||
"\n",
|
||||
" def set_state(self, state, x, y):\n",
|
||||
" if state == \"free\" or state == \"obstacale\" or state == \"start\" or state == \"target\" or state == \"path\" or state == \"current\" or state == \"visited\":\n",
|
||||
" self.grid[x][y].state = state\n",
|
||||
"\n",
|
||||
" def set_free(self, x, y):\n",
|
||||
" self.set_state(\"free\", x, y)\n",
|
||||
"\n",
|
||||
" def set_obstacle(self, x, y):\n",
|
||||
" self.set_state(\"obstacale\", x, y)\n",
|
||||
" \n",
|
||||
" def set_current(self, x, y):\n",
|
||||
" self.set_state(\"current\", x, y)\n",
|
||||
" \n",
|
||||
" def set_visited(self, x,y):\n",
|
||||
" self.set_state(\"visited\", x, y)\n",
|
||||
"\n",
|
||||
" def set_path(self, x, y):\n",
|
||||
" if not (x == self.start[0] and y == self.start[1]) and not (x == self.target[0] and y == self.target[1]):\n",
|
||||
" self.set_state(\"path\", x, y)\n",
|
||||
"\n",
|
||||
" def set_start(self, x, y):\n",
|
||||
" # reset old start if it exits\n",
|
||||
" if self.start:\n",
|
||||
" self.set_free(self.start[0], self.start[1])\n",
|
||||
"\n",
|
||||
" self.set_state(\"start\", x, y)\n",
|
||||
" self.grid[x][y].parent = self.grid[x][y]\n",
|
||||
" self.grid[x][y].g = 0\n",
|
||||
" self.grid[x][y].h = self.heuristic(self.grid[x][y])\n",
|
||||
" self.grid[x][y].f = self.grid[x][y].h + self.grid[x][y].g\n",
|
||||
" self.start = (x, y)\n",
|
||||
"\n",
|
||||
" def set_target(self, x, y):\n",
|
||||
" # reset old target if it exits\n",
|
||||
" if self.target:\n",
|
||||
" self.set_free(self.target[0], self.target[1])\n",
|
||||
"\n",
|
||||
" self.set_state(\"target\", x, y)\n",
|
||||
"\n",
|
||||
" self.target = (x, y)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "a01bed4a",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Defining Grid Parameters"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"id": "53c20ed6",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:24.289574Z",
|
||||
"start_time": "2025-05-07T21:40:24.250017Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"grid_size = 20\n",
|
||||
"window_width = grid_size * (WIDTH + MARGIN) + MARGIN\n",
|
||||
"window_height = grid_size * (HEIGHT + MARGIN) + MARGIN\n",
|
||||
"size = (window_width, window_height) # made size variable\n",
|
||||
"\n",
|
||||
"start = (0, 0)\n",
|
||||
"target = (19, 19)\n",
|
||||
"grid = Grid(grid_size, grid_size)\n",
|
||||
"\n",
|
||||
"# check if start an target are valid\n",
|
||||
"if 0 <= start[0] < grid.cols and 0 <= target[0] < grid.cols and 0 <= start[1] < grid.cols and 0 <= target[\n",
|
||||
" 1] < grid.cols:\n",
|
||||
" grid.set_target(target[0], target[1])\n",
|
||||
" grid.set_start(start[0], start[1])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "e67b33e5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Creating Obsticales"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"id": "d01d53b0",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:24.329858Z",
|
||||
"start_time": "2025-05-07T21:40:24.327366Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for i in range(0, 10):\n",
|
||||
" grid.set_obstacle(9, i)\n",
|
||||
"\n",
|
||||
"for j in range(4, 10):\n",
|
||||
" grid.set_obstacle(j, 9)\n",
|
||||
"\n",
|
||||
"for i in range(9, 20):\n",
|
||||
" grid.set_obstacle(16, i)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "334e0e61",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Initialize A* Parameters"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"id": "d480bcf1",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:24.378185Z",
|
||||
"start_time": "2025-05-07T21:40:24.374640Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"open = Queue('PRIO', 'f')\n",
|
||||
"open.push(grid.grid[0][0])\n",
|
||||
"closed = Queue('PRIO', 'f')\n",
|
||||
"neighbors = []\n",
|
||||
"path = []\n",
|
||||
"done = False"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "6898177d",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Initialize PyGame Window"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a8c78a46",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:25.086317Z",
|
||||
"start_time": "2025-05-07T21:40:24.429636Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pygame.init()\n",
|
||||
"screen = pygame.display.set_mode(size)\n",
|
||||
"pygame.display.set_caption(\"A* Algorithm\")\n",
|
||||
"clock = pygame.time.Clock()\n",
|
||||
"\n",
|
||||
"def update_screen():\n",
|
||||
" screen.fill(BLACK)\n",
|
||||
" grid.draw(screen)\n",
|
||||
" pygame.display.flip()\n",
|
||||
" clock.tick(30)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "3939b45f",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## A*-Algorithm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "4c138642",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-05-07T21:40:49.022562Z",
|
||||
"start_time": "2025-05-07T21:40:25.146989Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"while not done:\n",
|
||||
" for event in pygame.event.get():\n",
|
||||
" if event.type == pygame.QUIT:\n",
|
||||
" done = True\n",
|
||||
"\n",
|
||||
" while not open.is_empty():\n",
|
||||
" current_field = open.pop()\n",
|
||||
" grid.set_current(current_field.x, current_field.y)\n",
|
||||
" \n",
|
||||
" update_screen()\n",
|
||||
"\n",
|
||||
" if current_field.x == grid.target[0] and current_field.y == grid.target[1]: \n",
|
||||
" path.append(current_field)\n",
|
||||
" grid.set_path(current_field.x, current_field.y)\n",
|
||||
" \n",
|
||||
" while not (current_field.x == grid.start[0] and current_field.y == grid.start[1]):\n",
|
||||
" current_field = current_field.parent\n",
|
||||
" path.insert(0, current_field)\n",
|
||||
" grid.set_path(current_field.x, current_field.y)\n",
|
||||
"\n",
|
||||
" update_screen()\n",
|
||||
"\n",
|
||||
" open.clear()\n",
|
||||
" done = True\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" closed.push(current_field)\n",
|
||||
" grid.set_visited(current_field.x, current_field.y)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" for dx, dy in [(0, -1), (-1, 0), (0, 1), (1, 0)]:\n",
|
||||
" nx = current_field.x + dx\n",
|
||||
" ny = current_field.y + dy\n",
|
||||
"\n",
|
||||
" if 0 <= nx < grid.cols and 0 <= ny < grid.rows:\n",
|
||||
" neighbor = grid.grid[nx][ny]\n",
|
||||
"\n",
|
||||
" if neighbor.state == \"obstacale\" or closed.items.__contains__(neighbor):\n",
|
||||
" continue\n",
|
||||
"\n",
|
||||
" tentative_g = current_field.g + 1\n",
|
||||
"\n",
|
||||
" if tentative_g < neighbor.g:\n",
|
||||
" neighbor.parent = current_field\n",
|
||||
" neighbor.g = tentative_g\n",
|
||||
" neighbor.h = grid.heuristic(neighbor)\n",
|
||||
" neighbor.f = neighbor.g + neighbor.h\n",
|
||||
"\n",
|
||||
" if open.items.__contains__(neighbor):\n",
|
||||
" open.items.sort(key=lambda item: item.f)\n",
|
||||
" else:\n",
|
||||
" open.push(neighbor)\n",
|
||||
"\n",
|
||||
" update_screen()\n",
|
||||
" \n",
|
||||
"if len(path) == 0:\n",
|
||||
" print(\"No path between\")\n",
|
||||
"else:\n",
|
||||
" path.print()\n",
|
||||
"\n",
|
||||
"pygame.quit()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".env",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.13.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
53
P1/graph.py
53
P1/graph.py
@@ -1,12 +1,11 @@
|
||||
from prettytable import PrettyTable
|
||||
from pygame.event import set_keyboard_grab
|
||||
|
||||
from utils import *
|
||||
|
||||
|
||||
class Node:
|
||||
|
||||
def __init__(self, name, x=None, y=None, state="free"):
|
||||
def __init__(self, name, x=None, y=None):
|
||||
self.parent = None
|
||||
self.name = name
|
||||
self.edges = []
|
||||
@@ -42,7 +41,7 @@ class Graph:
|
||||
for node in node_list:
|
||||
edge_values = ['X'] * len(node_list)
|
||||
for edge in node.edges:
|
||||
edge_values[next((i for i, e in enumerate(node_list) if e.name == edge.end.name), -1)] = edge.g
|
||||
edge_values[next((i for i, e in enumerate(node_list) if e.name == edge.end.name), -1)] = edge.value
|
||||
t.add_row([node.name] + edge_values)
|
||||
print(t)
|
||||
|
||||
@@ -53,36 +52,42 @@ class Queue:
|
||||
self.items = []
|
||||
self.sort_by = sort_by
|
||||
|
||||
def empty(self):
|
||||
return len(self.items) == 0
|
||||
def clear(self):
|
||||
self.items.clear()
|
||||
|
||||
def pop(self):
|
||||
if not self.empty():
|
||||
if self.type == 'LIFO':
|
||||
''' LIFO
|
||||
queue = [node_0, node_1, ... , node_n]
|
||||
-> pop node_n
|
||||
'''
|
||||
return self.items.pop()
|
||||
else:
|
||||
''' FIFO & PRIO
|
||||
queue = [node_0, node_1, ... , node_n]
|
||||
-> pop node_0
|
||||
'''
|
||||
return self.items.pop(0)
|
||||
return None
|
||||
def is_empty(self):
|
||||
if len(self.items) > 0:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def push(self, node):
|
||||
self.items.append(node)
|
||||
def push(self, element):
|
||||
self.items.append(element)
|
||||
'''
|
||||
queue = [node_0, node_1, ... , node_n] <- node_n+1
|
||||
queue = [element_0, element_1, ... , element_n] <- element_n+1
|
||||
'''
|
||||
if self.type == 'PRIO':
|
||||
'''
|
||||
Sorting so lowest cost/ value is at [0]
|
||||
queue = [node_0 < node_1 < ... < node_n < node_n+1]
|
||||
queue = [element_0 < element_1 < ... < element_n < element_n+1]
|
||||
'''
|
||||
if self.sort_by == '':
|
||||
self.items.sort(key=lambda item: item.value)
|
||||
elif self.sort_by == 'f':
|
||||
self.items.sort(key=lambda item: item.f)
|
||||
|
||||
def pop(self):
|
||||
if not self.is_empty():
|
||||
if self.type == 'LIFO':
|
||||
''' LIFO
|
||||
queue = [element_0, elemente_1, ... , element_n]
|
||||
-> pop element_n
|
||||
'''
|
||||
return self.items.pop()
|
||||
else:
|
||||
''' FIFO & PRIO
|
||||
queue = [element_0, element_1, ... , element_n]
|
||||
-> pop element_0
|
||||
'''
|
||||
return self.items.pop(0)
|
||||
return None
|
||||
92
P1/grid.py
92
P1/grid.py
@@ -40,8 +40,10 @@ class Field:
|
||||
color = GREEN
|
||||
elif self.state == "path":
|
||||
color = ORANGE
|
||||
elif self.state == "current":
|
||||
color = RED
|
||||
elif self.state == "visited":
|
||||
color = WHITE
|
||||
color = GREY
|
||||
|
||||
x_calc = (MARGIN + WIDTH) * self.x + MARGIN
|
||||
y_calc = (MARGIN + HEIGHT) * (grid_size - 1 - self.y) + MARGIN # flipping
|
||||
@@ -52,13 +54,15 @@ class Field:
|
||||
[x_calc, y_calc, WIDTH, HEIGHT]
|
||||
)
|
||||
|
||||
|
||||
'''
|
||||
# Render the heuristic value as text
|
||||
if self.state != "obstacale": # Don't display on obstacles
|
||||
# Create a font object
|
||||
font = pygame.font.Font(None, 16) # None means default font, 14 is the size
|
||||
|
||||
# Round the heuristic value to 1 decimal place for better display
|
||||
f_text = f"{self.f:.1f}"
|
||||
f_text = f"{self.g:.1f}"
|
||||
|
||||
# Render the text
|
||||
text = font.render(f_text, True, BLACK) # True for anti-aliasing, BLACK for text color
|
||||
@@ -68,6 +72,7 @@ class Field:
|
||||
|
||||
# Draw the text on the screen
|
||||
screen.blit(text, text_rect)
|
||||
'''
|
||||
|
||||
|
||||
class Grid:
|
||||
@@ -101,7 +106,7 @@ class Grid:
|
||||
return self.grid[x][y].state
|
||||
|
||||
def set_state(self, state, x, y):
|
||||
if state == "free" or state == "obstacale" or state == "start" or state == "target" or state == "path" or state == "visited":
|
||||
if state == "free" or state == "obstacale" or state == "start" or state == "target" or state == "path" or state == "current" or state == "visited":
|
||||
self.grid[x][y].state = state
|
||||
|
||||
def set_free(self, x, y):
|
||||
@@ -110,14 +115,16 @@ class Grid:
|
||||
def set_obstacle(self, x, y):
|
||||
self.set_state("obstacale", x, y)
|
||||
|
||||
def set_current(self, x, y):
|
||||
self.set_state("current", x, y)
|
||||
|
||||
def set_visited(self, x,y):
|
||||
self.set_state("visited", x, y)
|
||||
|
||||
def set_path(self, x, y):
|
||||
if not (x == self.start[0] and y == self.start[1]) and not (x == self.target[0] and y == self.target[1]):
|
||||
self.set_state("path", x, y)
|
||||
|
||||
def set_visited(self, x, y):
|
||||
if not (x == self.start[0] and y == self.start[1]) and not (x == self.target[0] and y == self.target[1]):
|
||||
self.set_state("visited", x, y)
|
||||
|
||||
def set_start(self, x, y):
|
||||
# reset old start if it exits
|
||||
if self.start:
|
||||
@@ -127,7 +134,7 @@ class Grid:
|
||||
self.grid[x][y].parent = self.grid[x][y]
|
||||
self.grid[x][y].g = 0
|
||||
self.grid[x][y].h = self.heuristic(self.grid[x][y])
|
||||
|
||||
self.grid[x][y].f = self.grid[x][y].h + self.grid[x][y].g
|
||||
self.start = (x, y)
|
||||
|
||||
def set_target(self, x, y):
|
||||
@@ -144,7 +151,7 @@ class Grid:
|
||||
Initializing the Grid
|
||||
'''
|
||||
start = (0, 0)
|
||||
target = (19, 19)
|
||||
target = (19, 0)
|
||||
grid = Grid(grid_size, grid_size)
|
||||
|
||||
# check if start an target are valid
|
||||
@@ -163,7 +170,7 @@ for i in range(9, 20):
|
||||
grid.set_obstacle(16, i)
|
||||
|
||||
'''
|
||||
Initializing A* Comps
|
||||
Initializing A* Components
|
||||
'''
|
||||
|
||||
open = Queue('PRIO', 'f')
|
||||
@@ -172,9 +179,11 @@ closed = Queue('PRIO', 'f')
|
||||
neighbors = []
|
||||
path = []
|
||||
|
||||
pygame.init()
|
||||
'''
|
||||
Initializing Visuals
|
||||
'''
|
||||
|
||||
# window
|
||||
pygame.init()
|
||||
window_width = grid_size * (WIDTH + MARGIN) + MARGIN
|
||||
window_height = grid_size * (HEIGHT + MARGIN) + MARGIN
|
||||
size = (window_width, window_height) # made size variable
|
||||
@@ -185,11 +194,19 @@ pygame.display.set_caption("A* Algorithm")
|
||||
done = False
|
||||
clock = pygame.time.Clock()
|
||||
|
||||
while not done:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
done = True
|
||||
|
||||
def a_star():
|
||||
neighbor = None
|
||||
while not open.empty():
|
||||
while not open.is_empty():
|
||||
current_field = open.pop()
|
||||
grid.set_current(current_field.x, current_field.y)
|
||||
screen.fill(BLACK)
|
||||
|
||||
grid.draw(screen)
|
||||
pygame.display.flip()
|
||||
clock.tick(15)
|
||||
|
||||
if current_field.x == grid.target[0] and current_field.y == grid.target[1]:
|
||||
path.append(current_field)
|
||||
@@ -198,61 +215,44 @@ def a_star():
|
||||
current_field = current_field.parent
|
||||
path.insert(0, current_field)
|
||||
grid.set_path(current_field.x, current_field.y)
|
||||
grid.draw(screen)
|
||||
pygame.display.flip()
|
||||
clock.tick(15)
|
||||
open.clear()
|
||||
|
||||
break
|
||||
|
||||
closed.push(current_field)
|
||||
grid.set_visited(current_field.x, current_field.y)
|
||||
|
||||
# Nachbarn finden
|
||||
|
||||
for dx, dy in [(0, -1), (-1, 0), (0, 1), (1, 0)]:
|
||||
nx = current_field.x + dx
|
||||
ny = current_field.y + dy
|
||||
|
||||
# Prüfen, ob der Nachbar gültig ist
|
||||
if 0 <= nx < grid.cols and 0 <= ny < grid.rows:
|
||||
neighbor = grid.grid[nx][ny]
|
||||
|
||||
# Hindernis oder bereits in geschlossener Liste -> überspringen
|
||||
if neighbor.state == "obstacale" or neighbor in [item for item in closed.items]:
|
||||
if neighbor.state == "obstacale" or closed.items.__contains__(neighbor):
|
||||
continue
|
||||
|
||||
# Neuen g-Wert berechnen
|
||||
tentative_g = current_field.g + 1 # Kosten für einen Schritt = 1
|
||||
tentative_g = current_field.g + 1
|
||||
|
||||
# Wenn Nachbar nicht in offener Liste oder neuer Pfad besser
|
||||
if neighbor not in [item for item in open.items] or tentative_g < neighbor.g:
|
||||
if tentative_g < neighbor.g:
|
||||
neighbor.parent = current_field
|
||||
neighbor.g = tentative_g
|
||||
neighbor.h = grid.heuristic(neighbor)
|
||||
neighbor.f = neighbor.g + neighbor.h
|
||||
|
||||
# Knoten zur offenen Liste hinzufügen oder aktualisieren
|
||||
if neighbor not in [item for item in open.items]:
|
||||
open.push(neighbor)
|
||||
else:
|
||||
# Queue aktualisieren
|
||||
if open.items.__contains__(neighbor):
|
||||
open.items.sort(key=lambda item: item.f)
|
||||
else:
|
||||
open.push(neighbor)
|
||||
|
||||
|
||||
def a_star_main():
|
||||
global done
|
||||
while not done:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
done = True
|
||||
|
||||
a_star()
|
||||
screen.fill(BLACK)
|
||||
grid.draw(screen)
|
||||
|
||||
# refresh display
|
||||
screen.fill(BLACK)
|
||||
grid.draw(screen)
|
||||
pygame.display.flip()
|
||||
|
||||
# refreshrate
|
||||
clock.tick(120)
|
||||
|
||||
|
||||
a_star_main()
|
||||
clock.tick(30)
|
||||
|
||||
pygame.quit()
|
||||
|
||||
10
P1/main.py
10
P1/main.py
@@ -25,17 +25,15 @@ romania = Graph(['Or', 'Ne', 'Ze', 'Ia', 'Ar', 'Si', 'Fa',
|
||||
def main():
|
||||
# Task 1
|
||||
graph = romania
|
||||
ucs(graph, 'Si', 'Bu')
|
||||
ucs(graph, 'Ti', 'Bu')
|
||||
|
||||
graph = romania
|
||||
bfs(graph, 'Si', 'Bu')
|
||||
bfs(graph, 'Ti', 'Bu')
|
||||
|
||||
graph = romania
|
||||
dfs(graph, 'Si', 'Bu')
|
||||
dfs(graph, 'Ti', 'Bu')
|
||||
|
||||
# Task 3 A*
|
||||
a_star_main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
@@ -63,5 +63,3 @@ def dfs(graph, start_node_name, target_node_name):
|
||||
|
||||
def ucs(graph, start_node_name, target_node_name):
|
||||
traverse(graph, Queue('PRIO'), start_node_name, target_node_name)
|
||||
|
||||
|
||||
|
||||
45
P1/utils.py
45
P1/utils.py
@@ -1,47 +1,2 @@
|
||||
def getNode(name, l):
|
||||
return next((i for i in l if i.name == name), -1)
|
||||
|
||||
|
||||
def print_grid_direct(self, path=None):
|
||||
"""
|
||||
Gibt das Grid in der Konsole aus, direkt wie es im Array gespeichert ist.
|
||||
Die y-Achse nimmt nach unten zu (0 ist oben), entsprechend der Array-Struktur.
|
||||
Optionaler Parameter 'path' ist eine Liste von (x,y)-Koordinaten, die den Pfad darstellen.
|
||||
"""
|
||||
# Symbole für verschiedene Zustände
|
||||
symbols = {
|
||||
"free": ".",
|
||||
"obstacale": "#", # Tippfehler aus Original-Code beibehalten
|
||||
"start": "S",
|
||||
"target": "G",
|
||||
"path": "o"
|
||||
}
|
||||
|
||||
# Ausgabe des Grids mit Koordinatenachsen
|
||||
print("\n ", end="")
|
||||
# Obere x-Achsen-Beschriftung
|
||||
for x in range(self.cols):
|
||||
print(f"{x:2d}", end=" ")
|
||||
print("\n " + "-" * (self.cols * 3))
|
||||
|
||||
# Grid mit y-Achsen-Beschriftung
|
||||
for y in range(self.rows):
|
||||
print(f"{y:2d} |", end=" ")
|
||||
for x in range(self.cols):
|
||||
field = self.grid[x][y]
|
||||
if path and (x, y) in path and field.state != "start" and field.state != "target":
|
||||
print(f"{symbols['path']:2s}", end=" ")
|
||||
else:
|
||||
print(f"{symbols[field.state]:2s}", end=" ")
|
||||
print() # Zeilenumbruch
|
||||
|
||||
print("\nLegende:")
|
||||
print(" . = frei")
|
||||
print(" # = Hindernis")
|
||||
print(" S = Start")
|
||||
print(" G = Ziel")
|
||||
print(" o = Pfad")
|
||||
|
||||
# Zusätzliche Statistiken, falls ein Pfad vorhanden ist
|
||||
if path:
|
||||
print(f"Pfadlänge: {len(path)} Felder")
|
||||
Reference in New Issue
Block a user