요약
⏱ 00:001. 시작과 목표
⏱ 00:00이번 튜토리얼에서는 PyTorch를 이용해 스네이크 게임을 플레이하는 AI 모델을 학습하는 과정을 다룹니다. 학습한 모델은 나중에 게임 엔진 안에서 실행할 예정입니다. 먼저 사용자가 키보드로 직접 플레이할 수 있는 스네이크 환경을 만드는 것이 이번 편의 목표입니다.

⏱ 00:342. 격자 렌더링
⏱ 00:34새 파일 snake_env.py에 환경 클래스를 정의하고, 기본 10×10 격자를 갖도록 너비와 높이를 초기화합니다. render 함수는 2차원 배열을 점(.)으로 채운 뒤 각 행을 줄바꿈으로 이어 문자열로 반환합니다. 이어서 플러스와 마이너스 기호로 테두리를 그리고, 좌우에 공백을 넣어 정사각형에 가까운 모양을 만듭니다. 출력이 경계선으로 둘러싸인 보드가 되도록 배열 구조를 단계적으로 다듬는 과정이 나옵니다.

⏱ 08:153. 뱀 초기화와 이동
⏱ 08:15뱀은 deque 자료구조로 몸을 표현합니다. deque는 왼쪽에 머리를 추가하고 오른쪽에서 꼬리를 제거하기 쉬운 구조입니다. 충돌 검사를 빠르게 하기 위해 몸통 좌표는 순서 없는 set에 따로 저장합니다. 방향은 위, 오른쪽, 아래, 왼쪽을 0~3 정수로 두고 기본값은 오른쪽입니다. 머리는 격자 중앙에 두고 몸통 두 칸을 왼쪽에 이어 붙여 초기 상태를 만듭니다.

한 걸음 진행하는 step 함수에서는 방향 벡터를 더해 머리의 다음 칸을 구하고, 꼬리를 제거한 뒤 새 머리를 덱과 set 양쪽에 추가합니다.
⏱ 20:204. 회전 동작과 키 입력
⏱ 20:20행동은 직진(0), 우회전(1), 좌회전(2) 세 가지로 정의합니다. turn 함수는 현재 방향에 1을 더하거나 3을 더한 뒤 4로 나눈 나머지를 취합니다. 나머지 연산을 쓰면 방향 값이 0~3 범위를 벗어나지 않고 한 바퀴 돌아옵니다. 뒤로 가는 동작은 몸통과 겹치므로 허용하지 않습니다.

키보드 입력은 W는 직진, A는 왼쪽, D는 오른쪽으로 매핑하고, 입력 앞뒤 공백을 제거하고 소문자로 바꿔 처리합니다. 실행 중 아래 방향 벡터의 y 값이 잘못 설정된 버그를 발견해 화면 좌표계에 맞게 수정합니다.
⏱ 27:575. 충돌 판정과 게임 종료
⏱ 27:57충돌 판정 함수 is_deadly는 다음 칸이 격자 범위를 벗어나는지 확인합니다. x가 0보다 작거나 너비 이상이거나, y가 0보다 작거나 높이 이상이면 죽은 것으로 판단합니다. step 함수는 새 머리에 대해 이 함수를 호출해 terminated 값을 반환합니다. 이어서 몸통 set을 조회해 자기 몸에 부딪히는 경우도 죽음으로 처리합니다. set 조회는 덱을 순회하는 것보다 빠르므로 충돌 검사에 적합합니다. 종료 값이 참이면 루프를 빠져나와 게임을 멈춥니다.

⏱ 35:456. 먹이 생성과 시드 난수
⏱ 35:45LCG32 클래스는 선형 합동 생성기로 32비트 난수를 만듭니다. 상태 값에 곱셈과 덧셈을 적용하고 32비트 범위로 자르며, 상태를 8비트 오른쪽 시프트한 값을 n으로 나눈 나머지로 정수를 뽑습니다. 같은 시드를 주면 같은 난수열이 나옵니다. 먹이 위치는 몸이 없는 빈 칸 목록을 만든 뒤 이 생성기로 하나를 고르며, 시드는 42로 설정합니다.

먹이를 먹으면 꼬리를 제거하지 않아 뱀 길이가 1 늘어나고 점수가 1 오릅니다. 뱀 길이가 전체 칸 수와 같아지면 승리로 간주하고 먹이를 없앤 뒤 게임을 끝냅니다.
⏱ 46:257. 점수, 단계, 시간 제한
⏱ 46:25초기화 로직을 reset 함수로 옮겨 여러 번 게임을 다시 시작할 수 있게 했고, 선택적 시드 인자를 받도록 했습니다. 화면에는 점수와 단계 수를 함께 표시합니다. 먹이를 먹은 뒤 지나간 단계 수를 세고, 그 값이 100에 뱀 길이를 곱한 한도를 넘으면 시간 초과로 중단(truncated)합니다. 뱀이 목적 없이 돌아다니는 것을 막기 위한 장치입니다.

종료(terminated)와 중단(truncated)을 구분해 반환하고, info 함수로 점수·단계·종료 사유를 전달합니다. Q 키로 사용자가 직접 종료할 수 있게 했습니다.






