본 글에서는 딥러닝과 파이토치를 활용하여 몬테카를로 트리 검색(MCTS) 알고리즘을 적용한 틱택토 게임을 구현하는 과정을 설명합니다. 우리는 기본적으로 MCTS가 어떻게 작동하는지, 그리고 이를 통해 어떻게 AI가 틱택토 게임을 플레이할 수 있는지를 이해할 것입니다.
틱택토 게임 개요
틱택토(Tic-Tac-Toe)는 3×3 정사각형 격자에서 두 플레이어가 번갈아 가며 X 또는 O를 놓고, 가로, 세로 또는 대각선으로 3개의 연속된 말을 놓으면 승리하는 게임입니다.
1단계: 환경 설정
이 튜토리얼을 진행하기 위해서는 필요한 패키지를 설치해야 합니다. 다음은 필요한 주요 라이브러리입니다.
pip install torch numpy matplotlib
2단계: 게임 환경 구현
먼저 틱택토 게임 환경을 구현합니다. 게임의 규칙을 정의하고, 상태를 나타내는 클래스를 만들어야 합니다.
import numpy as np
class TicTacToe:
def __init__(self):
self.board = np.zeros((3, 3), dtype=int) # 0: 빈칸, 1: X, -1: O
self.current_player = 1 # 1: X의 차례, -1: O의 차례
def reset(self):
self.board = np.zeros((3, 3), dtype=int)
self.current_player = 1
def make_move(self, row, col):
if self.board[row, col] == 0:
self.board[row, col] = self.current_player
self.current_player *= -1
def check_winner(self):
for player in [1, -1]:
for row in range(3):
if np.all(self.board[row, :] == player): # 행 체크
return player
for col in range(3):
if np.all(self.board[:, col] == player): # 열 체크
return player
if np.all(np.diag(self.board) == player) or np.all(np.diag(np.fliplr(self.board)) == player):
return player
return None if np.any(self.board == 0) else 0 # 게임이 진행 중인 경우
def display(self):
symbols = {1: 'X', -1: 'O', 0: ' '}
for row in self.board:
print("|".join(symbols[x] for x in row))
print("-" * 5)
print("\n")
# 게임 테스트
game = TicTacToe()
game.make_move(0, 0)
game.display()
game.make_move(1, 1)
game.display()
3단계: 몬테카를로 트리 검색(MCTS) 알고리즘
MCTS는 불확실한 상황에서 의사결정 문제를 해결하기 위한 방법입니다. 기본적으로 이 알고리즘은 다음 네 가지 단계로 구성됩니다:
- 선택(Selection): 현재 트리에서 노드를 선택합니다.
- 확장(Expansion): 선택된 노드에서 가능한 행동을 확장합니다.
- 시뮬레이션(Simulation): 확장된 노드에서 게임을 플레이하여 결과를 얻습니다.
- 백업(Backpropagation): 결과를 통해 부모 노드에 정보를 업데이트합니다.
MCTS 클래스 구현
import random
from collections import defaultdict
class MCTSNode:
def __init__(self, state, parent=None):
self.state = state # 현재 게임 상태
self.parent = parent
self.children = [] # 자식 노드
self.wins = 0 # 승리 횟수
self.visits = 0 # 방문 횟수
def ucb1(self):
if self.visits == 0:
return float('inf') # 방문한 적 없는 노드는 우선 선택하도록 함
return self.wins / self.visits + np.sqrt(2 * np.log(self.parent.visits) / self.visits)
class MCTS:
def __init__(self, iterations):
self.iterations = iterations
def search(self, game):
root = MCTSNode(state=game)
for _ in range(self.iterations):
node = self.select(root)
winner = self.simulate(node.state)
self.backpropagate(node, winner)
return max(root.children, key=lambda child: child.visits).state
def select(self, node):
while node.children:
node = max(node.children, key=lambda child: child.ucb1())
if node.visits > 0:
for action in self.get_valid_moves(node.state):
child_state = node.state.copy()
child_state.make_move(action[0], action[1])
child_node = MCTSNode(state=child_state, parent=node)
node.children.append(child_node)
return random.choice(node.children) if node.children else node
def simulate(self, state):
current_player = state.current_player
while True:
winner = state.check_winner()
if winner is not None:
return winner
valid_moves = self.get_valid_moves(state)
move = random.choice(valid_moves)
state.make_move(move[0], move[1])
def backpropagate(self, node, winner):
while node is not None:
node.visits += 1
if winner == 1: # X의 승리
node.wins += 1
node = node.parent
def get_valid_moves(self, state):
return [(row, col) for row in range(3) for col in range(3) if state.board[row, col] == 0]
# MCTS 사용 사례
mcts = MCTS(iterations=1000)
move = mcts.search(game)
print("AI의 선택:", move)
4단계: AI와 사용자 간의 게임 구현
이제 완성된 MCTS를 사용하여 사용자와 AI 간의 게임을 구현해 보겠습니다.
def play_game():
game = TicTacToe()
while True:
game.display()
if game.current_player == 1: # 사용자 차례
row, col = map(int, input("행과 열 번호를 입력하세요 (0, 1 또는 2): ").split())
game.make_move(row, col)
else: # AI 차례
print("AI가 선택하는 중...")
move = mcts.search(game)
game.make_move(move[0], move[1])
print(f"AI가 선택한 위치: {move}")
winner = game.check_winner()
if winner is not None:
game.display()
if winner == 1:
print("축하합니다! 당신이 이겼습니다!")
elif winner == -1:
print("AI가 이겼습니다!")
else:
print("무승부입니다!")
break
play_game()
결론
이번 강좌에서는 딥러닝과 파이토치의 기본 가이드라인을 살펴보았습니다. 몬테카를로 트리 검색을 활용하여 간단한 틱택토 AI를 구현하는 과정은 기술적으로 도전이 될 수 있지만, 결과적으로는 매우 흥미로운 경험이었습니다. 앞으로 더 나아가 다양한 알고리즘과 기술을 활용하여 보다 완벽한 AI를 개발할 수 있기를 기대합니다.