Raspberry Pi 위에 SenseHat을 연결하여, 8x8 maze game을 생성
기능
0. 게임 시작 시, 디스플레이 초기화를 통해 초기 화면 구성을 보여줌
1. 자이로스코프 계산을 통해, 기울일 때마다 기울이는 방향으로 S가 이동
2. 조이스틱을 클릭할 때마다, S지점부터 E지점까지 도착하는 경로 출력
- 처음 최단경로를 노란색으로 표시, 연속해서 누를 시 다음 최단경로를 나타냄
- 모든 경로를 표시했을 때 클릭하면, 처음 최단경로를 나타냄
3. E 지점에 도착 시, 게임이 종료되며 "WINNER" 메세지 출력 후 디스플레이 OFF
라이브러리 및 변수 선언
from sense_hat import SenseHat
from time import sleep
from collections import deque
from copy import deepcopy
import sys
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]
sense = SenseHat() # 디스플레이 객체 가져오기
S = [0, 255, 0] # 시작 지점은 Green
E = [0, 0, 255] # 도착 지점은 Blue
RC = [100, 100, 0] # 경로는 Yellow
X = [255, 255, 255] # 벽은 White
O = [0, 0, 0]
R = 8 # Row 크기
C = 8 # Column 크기
flag = -1 # DFS 시작 및 최단경로 저장 idx
cur_x, cur_y = 0, 0 # 현재 지점 표시 - 나중에 초기화
s_y, s_x = 0, 2 # 시작 지점
e_y, e_x = 6, 7 # 도착 지점
visit = [] # BFS 방문 경로
route = [] # BFS 탐색 시 경로 저장
result = [] # 최단 거리를 저장할 경로
maze = [
O, X, O, O, O, O, O, O,
O, X, X, X, X, O, X, O,
O, O, O, O, O, O, O, O,
O, X, X, X, X, O, X, O,
O, O, X, O, O, O, X, O,
O, O, X, O, X, X, X, O,
O, X, X, O, O, O, O, O,
O, O, O, O, X, X, X, X
] # 8x8 LED 초기화
초기화 함수
def init():
global cur_x, cur_y
# 현재 지점을 시작 지점으로 초기화
cur_x = s_x
cur_y = s_y
# 8x8 LED판 초기화
sense.clear()
sleep(1)
# maze 정보대로 LED 판을 초기화
for y in range(R):
for x in range(C):
sense.set_pixel(x, y, maze[R*y+x])
# 시작 지점과 도착 지점 표시
maze[R*s_y + s_x] = S
maze[R*e_y + e_x] = E
sense.set_pixel(s_x, s_y, S)
sense.set_pixel(e_x, e_y, E)
자이로스코프 값에 따른 움직임 기능 구현
# 자이로스코프 값에 따라, 어느 좌표로 움직일 지 결정
def move(num):
if num == 1:
t_x = cur_x - 1
t_y = cur_y
check(t_x, t_y)
elif num == 2:
t_x = cur_x + 1
t_y = cur_y
check(t_x, t_y)
elif num == 3:
t_x = cur_x
t_y = cur_y + 1
check(t_x, t_y)
elif num == 4:
t_x = cur_x
t_y = cur_y - 1
check(t_x, t_y)
# 해당 좌표로 움직여도 되는 지를 판단 및 움직임 구현
def check(j, i):
global cur_x, cur_y, flag
if maze[i*R + j] == E: # 도착 지점 도달 시
sense.clear()
sleep(1)
sense.show_message("WINNER") # 이겼을 시, 메세지 출력
sys.exit()
return
elif (maze[i*R + j] == X) or (0 > i or 0 > j or C <= i or R <= j): # 가면 안 되는 곳
print('Cannot move to there.')
else: # 일반적인 움직임
sense.set_pixel(cur_x, cur_y, O)
sense.set_pixel(j, i, S)
cur_x = j
cur_y = i
flag = -1
조이스틱 클릭 시 경로 탐색 및 디스플레이 표현
# 경로 탐색 알고리즘
def go_BFS(x, y):
if x == e_y and y == e_x:
temp = deepcopy(route)
result.append((len(temp), temp))
return
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if (nx < 0 or ny < 0 or nx >= R or ny >= C): continue
if maze[nx*R + ny] == X: continue
if visit[nx][ny] == 1: continue
visit[nx][ny] = 1
route.append([nx, ny])
go_BFS(nx, ny)
route.pop()
visit[nx][ny] = 0
# 선택된 경로를 LED 판에 나타냄
def light():
global flag
target = result[flag][1]
for i in range(len(target)-1):
y, x = target[i]
sense.set_pixel(x, y, RC)
sleep(1)
for i in range(len(target)-1):
y, x = target[i]
sense.set_pixel(x, y, O)
flag = (flag + 1) % len(result)
return;
이벤트 대기 구현
# Polling 방식을 활용한 구현
while True:
for event in sense.stick.get_events(): # 이벤트 발생 시 체크
if (event.action == 'pressed' and event.direction == 'middle'):
if flag == -1: # 현재 위치가 업데이트가 되었을 경우, 경로 탐색
flag = 0
result = []
visit = [[0 for i in range(R)] for j in range(C)]
visit[cur_y][cur_x] = 1
route = []
go_BFS(cur_y, cur_x)
result.sort()
light()
else: # 현재 위치 비 업데이트 시, 최단 거리 순 경로 표시
light()
ori = sense.get_orientation_degrees() # SenseHat 자이로스코프 측정 값 가져오기
if 20 < ori["pitch"] < 100:
move(1)
elif 260 < ori["pitch"] < 340:
move(2)
elif 20 < ori["roll"] < 100:
move(3)
elif 260 < ori["roll"] < 340:
move(4)
sleep(0.3)
시연 영상
'IT_Study > Personal Project' 카테고리의 다른 글
Linux에서 Application과 Device Driver의 interaction 구현 (0) | 2023.04.20 |
---|---|
API 활용 Web 프로젝트 (2) : Naver Datalab API를 활용한 Data Visualization 하기 (0) | 2023.03.17 |
API 활용 Web 프로젝트 (1) : 요구사항에 따른 DB 설계 및 EC2 상에서의 API 서버 배포 방법 (0) | 2023.03.07 |