
came_from 구조를 사용해 경로를 추적한다.# grid map 정의 (0 : 이동 가능, 1 : 장애물)
grid = [
[0, 0, 0, 0, 0],
[0, 1, 1, 1, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 0, 0]
]
# 시작점과 목표 지점 설정
start = (0, 0)
goal = (4, 4)
import math
# 휴리스틱 함수 (유클리드 거리)
def heuristic(node1, node2) :
x1, y1 = node1
x2, y2 = node2
return math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
node1과 node2는 두 노드의 좌표.def jump(grid, current, direction, goal) :
x, y = current
dx, dy = direction
while True :
x += dx
y += dy
# 맵 경계 체크
if x < 0 or y < 0 or x >= len(grid) or y >= len(grid[0]) or grid [x][y] == 1:
return None # 장애물 또는 경계를 넘어섰을 경우
# 목표에 도달
if (x, y) == goal:
return (x, y)
# 강제 점프 포인트 체크
if dx != 0 and dy != 0 : # 대각선 이동
if (grid[x - dx][y] == 1 and grid[x][y - dy] == 0) or (grid[x][y - dy] == 1 and grid[x - dx][y] == 0):
return (x, y)
else : # 직선 이동
if dx != 0: # 수평 이동
if (grid[x][y - 1] == 1 and grid[x][y + 1] == 0) or (grid[x][y + 1] == 1 and grid[x][y - 1] == 0):
return (x, y)
elif dy != 0: # 수직 이동
if (grid[x - 1][y] == 1 and grid[x + 1][y] == 0) or (grid[x + 1][y] == 1 and grid[x - 1][y] == 0):
return (x, y)
current : 현재 노드direction : 점프 방향(dx, dy로 정의)import heapq
def jps(grid, start, goal):
open_set = []
heapq.heappush(open_set, (0 + heuristic(start, goal), 0, start)) # (f, g, node)
came_from = {}
g_costs = {start: 0}
# 가능한 이동 방향
directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (1, 1), (1, -1), (-1, 1)]
while open_set :
_, g, current = heapq.heappop(open_set)
# 목표 지점 도달
if current == goal :
path = []
while current in came_from :
path.append(current)
current = came_from[current]
path.append(start)
return path[::-1] # 경로 반환
# 모든 방향 탐색
for direction in directions :
jump_point = jump(grid, current, direction, goal)
if jump_point :
tentative_g = g + heuristic(current, jump_point)
if jump_point not in g_costs or tentative_g < g_costs[jump_point] :
g_costs[jump_point] = tentative_g
f = tentative_g + heuristic(jump_point, goal)
heapq.heappush(open_set, (f, tentative_g, jump_point))
came_from[jump_point] = current
return None # 경로를 찾을 수 없는 경우
open_setheapq를 사용하여 (f, g, current)의 형태로 저장한다.came_fromg_costsg)를 저장한다.# grid map 정의 (0 : 이동 가능, 1 : 장애물)
grid = [
[0, 0, 0, 0, 0],
[0, 1, 1, 1, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 0, 0]
]
# 시작점과 목표 지점 설정
start = (0, 0)
goal = (4, 4)
path = jps(grid, start, goal)
if path:
print("최단 경로 : ", path)
else :
print("경로를 찾을 수 없습니다.")
최단 경로 : [(0, 0), (1, 0), (2, 1), (3, 2), (3, 3), (4, 4)]
came_from)점프 로직 및 강제 점프 포인트 체크 부분에 개선이 필요했다.
def jump(grid, current, direction, goal):
x, y = current
dx, dy = direction
while True:
x += dx
y += dy
# 맵 경계 체크
if x < 0 or y < 0 or x >= len(grid) or y >= len(grid[0]) or grid[x][y] == 1:
return None # 장애물 또는 맵 경계에 도달
# 목표에 도달
if (x, y) == goal:
return (x, y)
# 강제 점프 포인트 체크
if dx != 0 and dy != 0: # 대각선 이동
if (grid[x - dx][y] == 1 and grid[x][y - dy] == 0) or (grid[x][y - dy] == 1 and grid[x - dx][y] == 0):
return (x, y)
elif dx != 0: # 수평 이동
if ((y - 1 >= 0 and grid[x][y - 1] == 1 and y + 1 < len(grid[0]) and grid[x][y + 1] == 0) or
(y + 1 < len(grid[0]) and grid[x][y + 1] == 1 and y - 1 >= 0 and grid[x][y - 1] == 0)):
return (x, y)
elif dy != 0: # 수직 이동
if ((x - 1 >= 0 and grid[x - 1][y] == 1 and x + 1 < len(grid) and grid[x + 1][y] == 0) or
(x + 1 < len(grid) and grid[x + 1][y] == 1 and x - 1 >= 0 and grid[x - 1][y] == 0)):
return (x, y)
# 대각선 이동 중 장애물이 없는 방향으로 점프
if dx != 0 and dy != 0:
if jump(grid, (x, y), (dx, 0), goal) or jump(grid, (x, y), (0, dy), goal):
return (x, y)
점프 로직을 위와 같이 수정해보았다.
경로를 찾을 수 없습니다.
ㅠㅠ
아마도 점프 함수(jump)가 유효한 점프 포인트를 제대로 반환해주지 못하고 있는 것으로 보인다. (None을 반환함)... 특히 대각선 이동 중 추가적인 점프 조건이 제대로 처리되고 있지 않은 것 같다. 이러한 문제를 해결하기 위해 점프 함수의 논리를 점검하고 수정해야 할 것 같다.
None을 반환하도록 설정했는데, 특정 방향에서 조건이 충족되지 않아서 강제로 점프 포인트를 지나치는 문제가 있을 수 있다.def jump(grid, current, direction, goal) :
x, y = current
dx, dy = direction
while True :
x += dx
y += dy
# 맵 경계 체크
if x < 0 or y < 0 or x >= len(grid) or y >= len(grid[0]) or grid [x][y] == 1:
return None # 장애물 또는 경계를 넘어섰을 경우
# 목표에 도달
if (x, y) == goal:
return (x, y)
# 강제 점프 포인트 체크
if dx != 0 and dy != 0 : # 대각선 이동
if (grid[x - dx][y] == 1 and grid[x][y - dy] == 0) or (grid[x][y - dy] == 1 and grid[x - dx][y] == 0):
return (x, y)
elif dx != 0 : # 수평 이동
if ((y - 1 >= 0 and grid[x][y - 1] == 1 and y + 1 < len(grid[0]) and grid[x][y + 1] == 0) or (y + 1 < len(grid[0]) and grid[x][y + 1] == 1 and y - 1 >=0 and grid[x][y - 1] == 0)) :
return (x, y)
elif dy != 0 : # 수직 이동
if ((x - 1 >= 0 and grid[x - 1][y] == 1 and x + 1 < len(grid) and grid[x + 1][y] == 0) or (x + 1 < len(grid) and grid[x + 1][y] == 1 and x - 1 >= 0 and grid[x - 1][y] == 0)) :
return (x, y)
# 대각선 이동 중 장애물이 없는 방향으로 점프
if dx != 0 and dy != 0 :
next_jump_x = jump(grid, (x, y), (dx, 0), goal)
next_jump_y = jump(grid, (x, y), (0, dy), goal)
if next_jump_x :
return next_jump_x
if next_jump_y :
return next_jump_y
경로를 찾을 수 없습니다.
ㅠㅠㅠ
import math
import heapq
# 휴리스틱 함수 (유클리드 거리)
def heuristic(node1, node2):
x1, y1 = node1
x2, y2 = node2
return math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
# 점프 함수
def jump(grid, current, direction, goal):
x, y = current
dx, dy = direction
while True:
x += dx
y += dy
# 디버깅: 현재 위치와 방향
print(f"Jumping to ({x}, {y}) in direction ({dx}, {dy})")
# 맵 경계 체크
if x < 0 or y < 0 or x >= len(grid) or y >= len(grid[0]) or grid[x][y] == 1:
print(f"Out of bounds or hit obstacle at ({x}, {y})")
return None
# 목표에 도달
if (x, y) == goal:
print(f"Reached goal at ({x}, {y})")
return (x, y)
# 강제 점프 포인트 체크
if dx != 0 and dy != 0: # 대각선 이동
if (grid[x - dx][y] == 1 and grid[x][y - dy] == 0) or (grid[x][y - dy] == 1 and grid[x - dx][y] == 0):
print(f"Found forced jump point at ({x}, {y}) (diagonal)")
return (x, y)
elif dx != 0: # 수평 이동
if (y > 0 and grid[x][y - 1] == 1) or (y < len(grid[0]) - 1 and grid[x][y + 1] == 1):
print(f"Found forced jump point at ({x}, {y}) (horizontal)")
return (x, y)
elif dy != 0: # 수직 이동
if (x > 0 and grid[x - 1][y] == 1) or (x < len(grid) - 1 and grid[x + 1][y] == 1):
print(f"Found forced jump point at ({x}, {y}) (vertical)")
return (x, y)
# 대각선 이동 중 추가 점프
if dx != 0 and dy != 0:
next_jump_x = jump(grid, (x, y), (dx, 0), goal)
next_jump_y = jump(grid, (x, y), (0, dy), goal)
if next_jump_x or next_jump_y:
print(f"Found diagonal jump point at ({x}, {y})")
return (x, y)
# JPS 탐색 함수
def jps(grid, start, goal):
open_set = []
heapq.heappush(open_set, (0 + heuristic(start, goal), 0, start)) # (f, g, node)
came_from = {}
g_costs = {start: 0}
# 가능한 이동 방향
directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (1, 1), (1, -1), (-1, 1)]
while open_set:
_, g, current = heapq.heappop(open_set)
# 디버깅: 현재 처리 중인 노드
print(f"Processing node: {current}, g = {g}")
# 목표 지점 도달
if current == goal:
path = []
while current in came_from:
path.append(current)
current = came_from[current]
path.append(start)
print("Found path:", path[::-1])
return path[::-1] # 경로 반환
# 모든 방향 탐색
for direction in directions:
jump_point = jump(grid, current, direction, goal)
if jump_point:
tentative_g = g + heuristic(current, jump_point)
# 디버깅: 점프 포인트와 비용
print(f"Jump point: {jump_point}, tentative_g = {tentative_g}")
if jump_point not in g_costs or tentative_g < g_costs[jump_point]:
g_costs[jump_point] = tentative_g
f = tentative_g + heuristic(jump_point, goal)
heapq.heappush(open_set, (f, tentative_g, jump_point))
came_from[jump_point] = current
print(f"Added to open set: {jump_point} with f = {f}")
print("경로를 찾을 수 없습니다_jps.")
return None # 경로를 찾을 수 없는 경우
# 테스트 맵 정의
grid = [
[0, 0, 0, 0, 0],
[0, 1, 1, 1, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 0, 0]
]
start = (0, 0)
goal = (4, 4)
path = jps(grid, start, goal)
if path:
print("최단 경로:", path)
else:
print("경로를 찾을 수 없습니다.")
Processing node: (0, 0), g = 0
Jumping to (-1, 0) in direction (-1, 0)
Out of bounds or hit obstacle at (-1, 0)
Jumping to (1, 0) in direction (1, 0)
Found forced jump point at (1, 0) (horizontal)
Jump point: (1, 0), tentative_g = 1.0
Added to open set: (1, 0) with f = 6.0
Jumping to (0, -1) in direction (0, -1)
Out of bounds or hit obstacle at (0, -1)
Jumping to (0, 1) in direction (0, 1)
Found forced jump point at (0, 1) (vertical)
Jump point: (0, 1), tentative_g = 1.0
Added to open set: (0, 1) with f = 6.0
Jumping to (-1, -1) in direction (-1, -1)
Out of bounds or hit obstacle at (-1, -1)
Jumping to (1, 1) in direction (1, 1)
Out of bounds or hit obstacle at (1, 1)
Jumping to (1, -1) in direction (1, -1)
Out of bounds or hit obstacle at (1, -1)
Jumping to (-1, 1) in direction (-1, 1)
Out of bounds or hit obstacle at (-1, 1)
Processing node: (0, 1), g = 1.0
Jumping to (-1, 1) in direction (-1, 0)
Out of bounds or hit obstacle at (-1, 1)
Jumping to (1, 1) in direction (1, 0)
Out of bounds or hit obstacle at (1, 1)
Jumping to (0, 0) in direction (0, -1)
Jumping to (0, -1) in direction (0, -1)
Out of bounds or hit obstacle at (0, -1)
Jumping to (0, 2) in direction (0, 1)
Found forced jump point at (0, 2) (vertical)
Jump point: (0, 2), tentative_g = 2.0
Added to open set: (0, 2) with f = 6.47213595499958
Jumping to (-1, 0) in direction (-1, -1)
Out of bounds or hit obstacle at (-1, 0)
Jumping to (1, 2) in direction (1, 1)
Out of bounds or hit obstacle at (1, 2)
Jumping to (1, 0) in direction (1, -1)
Found forced jump point at (1, 0) (diagonal)
Jump point: (1, 0), tentative_g = 2.414213562373095
Jumping to (-1, 2) in direction (-1, 1)
Out of bounds or hit obstacle at (-1, 2)
Processing node: (1, 0), g = 1.0
Jumping to (0, 0) in direction (-1, 0)
Jumping to (-1, 0) in direction (-1, 0)
Out of bounds or hit obstacle at (-1, 0)
Jumping to (2, 0) in direction (1, 0)
Jumping to (3, 0) in direction (1, 0)
Found forced jump point at (3, 0) (horizontal)
Jump point: (3, 0), tentative_g = 3.0
Added to open set: (3, 0) with f = 7.123105625617661
Jumping to (1, -1) in direction (0, -1)
Out of bounds or hit obstacle at (1, -1)
Jumping to (1, 1) in direction (0, 1)
Out of bounds or hit obstacle at (1, 1)
Jumping to (0, -1) in direction (-1, -1)
Out of bounds or hit obstacle at (0, -1)
Jumping to (2, 1) in direction (1, 1)
Found forced jump point at (2, 1) (diagonal)
Jump point: (2, 1), tentative_g = 2.414213562373095
Added to open set: (2, 1) with f = 6.019764837837084
Jumping to (2, -1) in direction (1, -1)
Out of bounds or hit obstacle at (2, -1)
Jumping to (0, 1) in direction (-1, 1)
Found forced jump point at (0, 1) (diagonal)
Jump point: (0, 1), tentative_g = 2.414213562373095
Processing node: (2, 1), g = 2.414213562373095
Jumping to (1, 1) in direction (-1, 0)
Out of bounds or hit obstacle at (1, 1)
Jumping to (3, 1) in direction (1, 0)
Out of bounds or hit obstacle at (3, 1)
Jumping to (2, 0) in direction (0, -1)
Jumping to (2, -1) in direction (0, -1)
Out of bounds or hit obstacle at (2, -1)
Jumping to (2, 2) in direction (0, 1)
Found forced jump point at (2, 2) (vertical)
Jump point: (2, 2), tentative_g = 3.414213562373095
Added to open set: (2, 2) with f = 6.242640687119286
Jumping to (1, 0) in direction (-1, -1)
Found forced jump point at (1, 0) (diagonal)
Jump point: (1, 0), tentative_g = 3.82842712474619
Jumping to (3, 2) in direction (1, 1)
Found forced jump point at (3, 2) (diagonal)
Jump point: (3, 2), tentative_g = 3.82842712474619
Added to open set: (3, 2) with f = 6.06449510224598
Jumping to (3, 0) in direction (1, -1)
Found forced jump point at (3, 0) (diagonal)
Jump point: (3, 0), tentative_g = 3.82842712474619
Jumping to (1, 2) in direction (-1, 1)
Out of bounds or hit obstacle at (1, 2)
Processing node: (3, 2), g = 3.82842712474619
Jumping to (2, 2) in direction (-1, 0)
Found forced jump point at (2, 2) (horizontal)
Jump point: (2, 2), tentative_g = 4.82842712474619
Jumping to (4, 2) in direction (1, 0)
Jumping to (5, 2) in direction (1, 0)
Out of bounds or hit obstacle at (5, 2)
Jumping to (3, 1) in direction (0, -1)
Out of bounds or hit obstacle at (3, 1)
Jumping to (3, 3) in direction (0, 1)
Found forced jump point at (3, 3) (vertical)
Jump point: (3, 3), tentative_g = 4.82842712474619
Added to open set: (3, 3) with f = 6.242640687119285
Jumping to (2, 1) in direction (-1, -1)
Found forced jump point at (2, 1) (diagonal)
Jump point: (2, 1), tentative_g = 5.242640687119285
Jumping to (4, 3) in direction (1, 1)
Jumping to (5, 3) in direction (1, 0)
Out of bounds or hit obstacle at (5, 3)
Jumping to (4, 4) in direction (0, 1)
Reached goal at (4, 4)
Found diagonal jump point at (4, 3)
Jump point: (4, 3), tentative_g = 5.242640687119285
Added to open set: (4, 3) with f = 6.242640687119285
Jumping to (4, 1) in direction (1, -1)
Found forced jump point at (4, 1) (diagonal)
Jump point: (4, 1), tentative_g = 5.242640687119285
Added to open set: (4, 1) with f = 8.242640687119284
Jumping to (2, 3) in direction (-1, 1)
Out of bounds or hit obstacle at (2, 3)
Processing node: (3, 3), g = 4.82842712474619
Jumping to (2, 3) in direction (-1, 0)
Out of bounds or hit obstacle at (2, 3)
Jumping to (4, 3) in direction (1, 0)
Jumping to (5, 3) in direction (1, 0)
Out of bounds or hit obstacle at (5, 3)
Jumping to (3, 2) in direction (0, -1)
Jumping to (3, 1) in direction (0, -1)
Out of bounds or hit obstacle at (3, 1)
Jumping to (3, 4) in direction (0, 1)
Jumping to (3, 5) in direction (0, 1)
Out of bounds or hit obstacle at (3, 5)
Jumping to (2, 2) in direction (-1, -1)
Found forced jump point at (2, 2) (diagonal)
Jump point: (2, 2), tentative_g = 6.242640687119285
Jumping to (4, 4) in direction (1, 1)
Reached goal at (4, 4)
Jump point: (4, 4), tentative_g = 6.242640687119285
Added to open set: (4, 4) with f = 6.242640687119285
Jumping to (4, 2) in direction (1, -1)
Jumping to (5, 2) in direction (1, 0)
Out of bounds or hit obstacle at (5, 2)
Jumping to (4, 1) in direction (0, -1)
Found forced jump point at (4, 1) (vertical)
Found diagonal jump point at (4, 2)
Jump point: (4, 2), tentative_g = 6.242640687119285
Added to open set: (4, 2) with f = 8.242640687119284
Jumping to (2, 4) in direction (-1, 1)
Found forced jump point at (2, 4) (diagonal)
Jump point: (2, 4), tentative_g = 6.242640687119285
Added to open set: (2, 4) with f = 8.242640687119284
Processing node: (4, 3), g = 5.242640687119285
Jumping to (3, 3) in direction (-1, 0)
Jumping to (2, 3) in direction (-1, 0)
Out of bounds or hit obstacle at (2, 3)
Jumping to (5, 3) in direction (1, 0)
Out of bounds or hit obstacle at (5, 3)
Jumping to (4, 2) in direction (0, -1)
Jumping to (4, 1) in direction (0, -1)
Found forced jump point at (4, 1) (vertical)
Jump point: (4, 1), tentative_g = 7.242640687119285
Jumping to (4, 4) in direction (0, 1)
Reached goal at (4, 4)
Jump point: (4, 4), tentative_g = 6.242640687119285
Jumping to (3, 2) in direction (-1, -1)
Jumping to (2, 2) in direction (-1, 0)
Found forced jump point at (2, 2) (horizontal)
Jumping to (3, 1) in direction (0, -1)
Out of bounds or hit obstacle at (3, 1)
Found diagonal jump point at (3, 2)
Jump point: (3, 2), tentative_g = 6.65685424949238
Jumping to (5, 4) in direction (1, 1)
Out of bounds or hit obstacle at (5, 4)
Jumping to (5, 2) in direction (1, -1)
Out of bounds or hit obstacle at (5, 2)
Jumping to (3, 4) in direction (-1, 1)
Jumping to (2, 4) in direction (-1, 0)
Found forced jump point at (2, 4) (horizontal)
Jumping to (3, 5) in direction (0, 1)
Out of bounds or hit obstacle at (3, 5)
Found diagonal jump point at (3, 4)
Jump point: (3, 4), tentative_g = 6.65685424949238
Added to open set: (3, 4) with f = 7.65685424949238
Processing node: (4, 4), g = 6.242640687119285
Found path: [(0, 0), (1, 0), (2, 1), (3, 2), (3, 3), (4, 4)]
최단 경로: [(0, 0), (1, 0), (2, 1), (3, 2), (3, 3), (4, 4)]
Found forced jump point at (2, 2) (horizontal)
...
Found forced jump point at (2, 4) (diagonal)
최단 경로: [(0, 0), (1, 0), (2, 1), (3, 2), (3, 3), (4, 4)]

출발점 -> (1, 0): 수직 이동(1, 0) -> (2, 1) : 대각선 이동 (장애물 (1, 1) 회피)(2, 1) -> (3, 2) : 대각선 이동(3, 2) -> (3, 3) : 수평 이동(3, 3) -> (4, 4) : 대각선 이동처음에 나왔던 최단 경로가 맞았다... (1차 2차 수정 왜함?)