mirror of
https://codeberg.org/andyscott/2D-Puzzle-Solver.git
synced 2024-09-06 21:28:08 -04:00
Added Puzzle.py
This commit is contained in:
parent
8dea1ccff0
commit
2671d317ff
1 changed files with 140 additions and 0 deletions
140
Puzzle.py
Normal file
140
Puzzle.py
Normal file
|
@ -0,0 +1,140 @@
|
|||
from typing import Deque
|
||||
|
||||
|
||||
def solve_puzzle(Board: list, Source: tuple, Destination: tuple):
|
||||
"""Finds a solution to a 2-D puzzle using a breadth first search
|
||||
|
||||
Parameters
|
||||
----------
|
||||
Board : list
|
||||
A graph represented as an adjacency matrix
|
||||
Source : tuple
|
||||
The starting point on the board
|
||||
Destination : tuple
|
||||
The goal position
|
||||
"""
|
||||
|
||||
queue = Deque()
|
||||
queue.append(Source)
|
||||
visited = {}
|
||||
|
||||
if is_valid(Source[0], Source[1], Board, visited):
|
||||
visited[Source] = 0
|
||||
if Source == Destination:
|
||||
return [Destination]
|
||||
else:
|
||||
return None
|
||||
|
||||
while len(queue) > 0:
|
||||
r, c = queue.popleft()
|
||||
possible_moves = [(1, 0), (0, 1), (-1, 0), (0, -1)]
|
||||
for move_row, move_col in possible_moves:
|
||||
row, col = r + move_row, c + move_col
|
||||
if is_valid(row, col, Board, visited):
|
||||
queue.append((row, col))
|
||||
visited[(row, col)] = visited[(r, c)] + 1
|
||||
if (row, col) == Destination:
|
||||
return get_path(row, col, visited)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def is_valid(x: int, y: int, Board: list, visited: dict) -> bool:
|
||||
"""Helper for solve_puzzle() to determine if a move is valid
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : int
|
||||
Row
|
||||
y : int
|
||||
Column
|
||||
Board : list
|
||||
A graph represented as an adjacency matrix
|
||||
visited : dict
|
||||
Coordinates that have been visited
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if the move is valid, otherwise False
|
||||
"""
|
||||
|
||||
exists = False
|
||||
valid = False
|
||||
|
||||
if (x >= 0 and y >= 0) and (x < len(Board) and y < len(Board[0])):
|
||||
exists = True
|
||||
|
||||
target = (x, y)
|
||||
if exists:
|
||||
if Board[x][y] != "#" and target not in visited:
|
||||
valid = True
|
||||
|
||||
return valid and exists
|
||||
|
||||
|
||||
def get_path(row: int, col: int, visited: dict) -> tuple:
|
||||
"""Helper for solve_puzzle() to assemble the steps and moves into lists
|
||||
|
||||
Parameters
|
||||
----------
|
||||
row : int
|
||||
Row on the board
|
||||
col : int
|
||||
Column on the board
|
||||
visited : dict
|
||||
Coordinates that have been visited
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple
|
||||
List of tuples containing coordinates traversed, and list of directions
|
||||
"""
|
||||
|
||||
steps = visited[(row, col)]
|
||||
steps -= 1
|
||||
path = [(row, col)]
|
||||
directions = []
|
||||
|
||||
while steps >= 0:
|
||||
if (row - 1, col) in visited and visited[(row - 1, col)] == steps:
|
||||
path.append((row - 1, col))
|
||||
directions.append("D")
|
||||
row -= 1
|
||||
if (row + 1, col) in visited and visited[(row + 1, col)] == steps:
|
||||
path.append((row + 1, col))
|
||||
directions.append("U")
|
||||
row += 1
|
||||
if (row, col - 1) in visited and visited[(row, col - 1)] == steps:
|
||||
path.append((row, col - 1))
|
||||
directions.append("R")
|
||||
col -= 1
|
||||
if (row, col + 1) in visited and visited[(row, col + 1)] == steps:
|
||||
path.append((row, col + 1))
|
||||
directions.append("L")
|
||||
col += 1
|
||||
steps -= 1
|
||||
|
||||
path.reverse()
|
||||
directions.reverse()
|
||||
return (path, directions)
|
||||
|
||||
|
||||
# ------------------------------ Basic Testing --------------------------------#
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
puzzle = [
|
||||
["-", "-", "-", "-", "-"],
|
||||
["-", "-", "#", "-", "-"],
|
||||
["-", "-", "-", "-", "-"],
|
||||
["#", "-", "#", "#", "-"],
|
||||
["-", "#", "-", "-", "-"],
|
||||
]
|
||||
|
||||
source = (0, 2)
|
||||
destination = (2, 2)
|
||||
# source = (0, 0)
|
||||
# destination = (4, 4)
|
||||
result = solve_puzzle(puzzle, source, destination)
|
||||
print(result)
|
Loading…
Reference in a new issue