AutoMine - 밑바닥부터 시작하는 지뢰찾기 AI (0): 프로젝트 개요

장준수·2026년 1월 22일

github 주소 (전 소스코드 공개중)

https://github.com/levelstage/AutoMine

결과물


자동으로 지뢰찾기를 하는 인공지능을 밑바닥부터 만들었다. 내부 인공지능 로직은 파이썬으로, 게임 클라이언트는 C# MonoGame으로 만들었다.

개발 동기

고등학교 때 "밑바닥부터 시작하는 딥러닝"이라는 물고기가 그려진 일본 책을 인상깊게 읽고, 딥러닝 기법을 활용해 간단한 지뢰찾기 인공지능을 만들어 본 적이 있다.

결과는 대실패로, 지금와서 생각해보면 학습 데이터 준비부터 신경망 설계까지 모두 엉터리였다.

그러다 군대를 제대하고 복학을 앞둔 최근에 문득 그때 생각이 났다. 지금이라면 더 잘 할 수 있지 않을까 하는 생각 + 복학을 대비해 딥러닝을 공부해보자는 느낌으로 다시 한번 만들어보자는 생각이 들었고, 바로 노트북에 파이썬을 깔았다.

참고자료

책은 고등학교 때와 똑같은 "밑바닥부터 시작하는 딥러닝(사이토 고키, 2017)"을 참고했고, 그때에는 상상도 할 수 없었던 인공지능 선생님 Gemini의 도움도 받았다. (주로 NumPy 문법 부분에서 도움을 받았다. 파이썬 문법은 익숙하지 않아서... 추가로 중간 결과를 확인하기 위한 임시 시각화의 경우에도 인공지능이 생성한 코드를 적극 활용했다.)

구현 방식

필자는 파이썬 언어 및 딥러닝 프레임워크에 대한 이해가 상당히 낮았기 때문에 모든 과정을 프레임워크 없이 NumPy로 밑바닥부터 구현하며 이해를 높이고자 하였다. 산출물을 내는 것보다 학습의 목적이 강한 프로젝트이기 때문에 im2col처럼 책에서 구현을 생략한 함수들도 일일이 구현했다.

왜 지뢰찾기였을까

내가 딥러닝 책을 어느정도 읽은 다음 바로 지뢰찾기 인공지능을 만드려고 한 이유는, 내가 처음으로 배운 신경망이 이미지 인식 신경망이었기 때문이었을 것이다. 내가 공부한 책은 NumPy를 이용해서 MNIST 손글씨 숫자(0~9) 데이터를 인식하는 신경망을 밑바닥부터 만들고자 하는 책이었으니까. 지금의 나도 딥러닝 프레임워크를 하나도 모르는데, 당시의 내가 그런 도구를 알 턱이 없었고, 자연스럽게 책에서 배운 내용만을 활용해서 무언가 만들어 보려고 했을 것이다. 게임을 너무나도 좋아하는 나는 바로 지뢰찾기를 떠올릴 수 밖에 없었을 것이고 말이다.

지뢰찾기는 NM의 그리드에 K개의 지뢰가 배치되었을 때, 안전한 NM-K개의 칸 혹은 K개의 지뢰를 모두 찾으면 승리하는 게임이다. 플레이어는 N*M개의 그리드의 상태를 알 수 있고, 그 상태를 기반으로 본인이 생각하는 가장 안전한 칸을 클릭해 추가적인 정보를 얻어나가며 게임을 진행한다. 여기서 지뢰찾기의 한 게임판의 상태를 S = {모르는 칸, 0, 1, 2, 3, 4, 5, 6, 7, 8} 집합의 원소로 구성된 그리드로 생각할 수 있으며, 이는 10개의 채널을 가진 이미지로 환원될 수 있다고 생각했다.

즉, 지뢰찾기의 각 게임판 상태는 이미지이며, 이미지 분석 신경망을 잘 개조하면 지뢰찾기 인공지능으로 만들어 볼 수 있지 않을까 하고 생각한 것이다.

중요한 아이디어들

내가 만들어낸 지뢰찾기 인공지능의 근간이 되는 중요한 아이디어들은 다음과 같았다.

1. 지뢰찾기의 "Greedy"성
지뢰찾기는 정보가 점점 공개되어가며 과거에서 미래로 나아가는 게임이지만, 현재 게임판에서 앞으로 나아가기 위해 과거의 게임판 정보가 필요한 게임은 아니다. 즉, 어떤 플레이어가 지뢰찾기를 하다가 갑자기 아무것도 모르는 다른 플레이어를 데려와서 게임을 이어하게 시켜도 그 플레이어가 지뢰찾기의 규칙만 알고 있다면 클리어에 아무런 지장이 없다. 이 아이디어는 인공지능에게 한 게임 단위가 아닌 한 게임판 단위로 학습시켜도 아무 문제가 없다는 논리, 나아가 지뢰찾기의 한 게임판을 다음 게임판으로 진행시키는 과정을 이미지 분석과 연결시키는 논리로 이어졌다.

2. 확률 게임
지뢰찾기는 복수 정답을 인정하는 게임이고(한 게임판에 대하여), 정답이 아예 없는 상황(찍기 상황)이 나오기도 하는 게임이다. 과거에는 해당 사실을 인지하지 못해 Softmax를 활용해 인공지능이 특정한 칸을 "분류"하도록 했는데(책의 신경망을 그대로 갖다 쓰려고 한 것의 영향이기도 하다.), 이번에는 그 문제를 해결하기 위해 "모든 칸"에 대한 "안전 확률"을 계산하는 것을 목표로 잡았다. 즉 이번 인공지능은 눌러야 하는 단 하나의 칸이 아니라 눌러도 안전할 것으로 보이는 칸들을 찾는 것을 목표로 한다. 이를 위해 정답 레이블은 이전처럼 안전한 칸은 0, 지뢰는 -1 이런 식으로 쓰는 것이 아니라 따로 Teacher 프로그램을 만들어서 각 게임판에 대한 근사 안전 확률을 계산하고 그것을 활용했다. 이 Teacher는 애매한 칸의 확률 계산보다 확실히 안전한 칸과 확실히 지뢰인 칸을 잘 구분하도록 만들어 두었다. 지뢰찾기를 실제로 플레이하면 후자가 더 중요하기 때문이다. 다음 나올 아이디어는 이 확률 게임에 대한 처리를 더욱 깔끔하게 하기 위해 고안해냈다.

3. 마스킹과 가중 손실
신경망을 설계하면서 가장 애먹었던 부분 중 하나는 "열린 칸"에 대한 처리였다. 논리적으로 열린 칸은 안전도가 1.0이어야 맞겠지만, 그렇게 되어버리면 인공지능이 1에 가까운 값만 뱉어내며, 열린 칸들을 계속 맞추고 "아 1.0에 가까운 값만 뱉어내면 손실함수가 낮아지네?"하고 생각할 위험이 있었다. 그래서 초기에는 열린 칸의 안전도를 0.0으로 설정하고 안전도에 대한 해석을 "눌러도 되는 칸"으로 바꾸면 되는거 아닌가 하고 생각했다.

결과는 별로 좋지 않았다.

이것이 해당 아이디어를 적용했을 때의 학습 결과인데, 열린 칸을 기똥차게 잘 맞추긴 하지만, 나머지 칸에 대한 예측은 아주 꽝이었다. 거기서 생각해 낸 것이 바로 마스킹으로, 애초에 채점을 닫힌 칸에 대해서만 하는 것이었다. 거기에 추가로 닫힌 칸 중에서도, Teacher가 확정 지뢰 혹은 확정 안전으로 분류한 칸을 틀렸을 경우 n배의 손실을 부여하는 기능까지 추가했다.

마무리

이 포스트는 프로젝트를 마무리하고, 시각화 모듈만 만들면 되는 상황에서 작성되었고, 프로젝트의 개요를 소개하는 데에 그 목적을 두고 있다. 따라서 내가 겪은 시행착오들이 상당히 압축되어 있는데, 앞으로 올릴 포스트들은 이런 시행착오들을 단계별로 정리해서 올릴 예정이다. 이렇게 이미 지나간 개발 과정을 정리하며 되돌아보는 것이 앞으로 이 인공지능을 발전시키거나, 새로운 프로젝트를 시작할 때 분명 도움이 될거라 믿기 때문이다.

profile
ㅇㅁㅇ;;

0개의 댓글