ka373

소스 공개] C언어로 구현한 CUI 지뢰 찾기 게임(퍼져나가는 0 기능 포함) 본문

12. 프로젝트, 공개 혹은 배포용 프로그램 등

소스 공개] C언어로 구현한 CUI 지뢰 찾기 게임(퍼져나가는 0 기능 포함)

ka373 2019. 9. 9. 08:12

제작한 코드는 깃허브에 올려 두었다:

https://github.com/ka373/SimpleCUIMinesweeperWithSpreadingZeros

 

_______________________________

주말에 취미 삼아 CUI 지뢰 찾기 게임을 구현해 보았다.

 

심플한 게임이지만,

정말 프로그래밍을 하겠다는 생각으로 따져가면 은근히 생각할 부분이 있었다.

 

그리고, 지뢰찾기 게임을 만든 사람들을 보면

0(내가 밟은 자리 주변에 지뢰가 없을 경우)이 퍼져나가는 기능을 구현하지 않은 사람도 많았으나, 본 프로그램에서는 구현해 두었다.

 

또한, 많은 사람은 자료구조나 알고리즘을 자세히 배우기 전에 지뢰 찾기 게임을 구현하고자 하는데, 이 프로그램은 그들도 이해할 수 있도록 만들었다.

 

지금부터 제작한 지뢰찾기 프로그램에 대해서 간단히 소개하겠다.

 

I. 게임의 목적

지뢰를 제외한 보드에 있는 모든 땅을 밟으면 게임을 클리어할 수 있다.

 

II. 게임의 진행

보드가 있고, 그 보드를 밟아 나가거나 지뢰 혹은 ?를 표시하는 식으로 게임을 진행한다.

 

_______________________________

0. 게임의 구조

 게임이 종료될 때까지 1)~4)를 반복

 1) 블럭(땅)의 위치와 타입을 입력 받는다.

 2) 게임 진행 함수에 위치와 타입을 입력한다.

 3) 살았는지 죽었는지 판별한다.

 4) 진행 상황(보드)를 프린트한다.

 

 

1. 보드 만들기

보드에서 진행되는 게임이므로, 보드가 필요하다.

두 개의 보드 1) 내가 탐색해 나가고 있는 보이는 보드(board_visible)와 2)해답 보드(board_kotae)를 만든다. 

 

1
2
int board_visible[NUM_OF_ROWS][NUM_OF_COLUMNS];    // Similar to the board seen by the user
int board_kotae[NUM_OF_ROWS][NUM_OF_COLUMNS];    //Board with numbers and mines (correct answer board)
cs

 

 

 

2. 해답 보드(board_kotae) 구성

 

2.1. 지뢰 만들어서 배치하기

보드 블럭의 개수만큼의 난수를 만들고, 만들어진 난수에 따라 보드에 지뢰를 배치한다.

 

1
2
3
4
5
6
7
8
9
10
    //mine planting
    if (process_NUM_MINE_randoms() == 1) {
        for (i = 0; i < NUM_MINE; i++) {
            int mine_row = obtained_randoms[i] / NUM_OF_ROWS;
            int mine_column = obtained_randoms[i] % NUM_OF_ROWS;
 
            board_kotae[mine_row][mine_column] = MINE;
            //printf("\nLocation of mines: row: %d column: %d\n", mine_row, mine_column);
        }
    }
cs

 

 

2.2. 숫자 설정

배열을 탐색하면서, 해당 블록 주변 블록에 있는 지뢰의 수를 세어서 숫자를 할당한다.

 

 

3. 게임 진행 함수 만들기(process_game)

 

3.1. 입력 받은 위치가 이미 방문한 장소이면 무효처리 한다.

 

3.2. 새로운 블럭을 밟았을 경우

해답 보드를 참고해서 보이는 보드에 값을 입력한다. 

여기서 보이는 보드에 입력하는 값은 보드를 출력 할 때 사용한다.

 

3.2.1. 밟은 곳이 1이상 8이하의 숫자일 경우

보이는 보드에 해당 숫자를 입력한다.

 

3.2.2. 밟은 곳이 지뢰일 경우

보이는 보드에 해당 숫자를 입력한다.

게임 오버를 나타내는 값을 리턴한다.(나의 경우는 is_live = 0; 와 같이 사용)

 

3.2.3. 밟은 곳이 0일 경우(주위에 지뢰가 없을 경우)

선택한 부분이 0일 경우, 0 이외의 숫자가 나올 때까지 0이 퍼져 나간다.

이 게임의 백미이자, 구현 난도가 다른 부분에 비해 높은 부분이라고 생각한다.

하지만 어떻게 하는지 봐 봐버리면 훨씬 쉽게 느껴질 것이다.

그러므로, 지뢰찾기를 스스로의 힘으로 구현하고 싶은 사람은 이 부분을 참고 하기 전에 스스로 이 부분을 해결해 보길 바란다. 

 

나의 경우, 재귀함수를 통해 다음과 같이 구현했다.

밟은 곳이 0일 경우 좌상, 상, 우상, 좌, 우, 좌하, 하, 우하 방향으로 재귀적으로 검사해 나간다.

시간을 잠시 내서 취미 개발처럼 만든 것이라, 이것이 최적화된 알고리즘이라고 할 수는 없겠다.

다만 필요한 성능을 내는 데는 큰 문제가 없는 것 같다.

이 글을 읽는 사람은 다른 더 좋은 알고리즘도 생각해 보길 바란다.

 

일부 경로를 그려보자면 다음과 같다:

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
        /////////////////////////////////////////////////////////////////////////////
        //spreading zeros(0の連鎖爆弾!0의 연쇄폭탄!)
        if (board_visible[row_entered][column_entered] == 0) {
 
            if (can_go(row_entered - 1, column_entered - 1)) {
                process_game(row_entered - 1, column_entered - 1, STEPPED);    //Spread to left upper diagonal ↖
            }
 
            if (can_go(row_entered - 1, column_entered + 1)) {
                process_game(row_entered - 1, column_entered + 1, STEPPED);    //Spread across the upper right diagonal ↗
            }
 
            if (can_go(row_entered + 1, column_entered - 1)) {
                process_game(row_entered + 1, column_entered - 1, STEPPED);    //Spread to left lower diagonal ↙
            }
 
            if (can_go(row_entered + 1, column_entered + 1)) {
                process_game(row_entered + 1, column_entered + 1, STEPPED);    //Spread across the lower right diagonal ↘
            }
 
            if (can_go(row_entered - 1, column_entered)) { process_game(row_entered - 1, column_entered, STEPPED); }//Spread up ↑
            if (can_go(row_entered + 1, column_entered)) { process_game(row_entered + 1, column_entered, STEPPED); }//Spread down ↓
            if (can_go(row_entered, column_entered - 1)) { process_game(row_entered, column_entered - 1, STEPPED); }//Spread left ←
            if (can_go(row_entered, column_entered + 1)) { process_game(row_entered, column_entered + 1, STEPPED); }//Spread to the right →
        }// end of if연쇄폭탄
         /////////////////////////////////////////////////////////////////////////////
cs

 

 

 

_______________________________

지뢰 찾기 게임을 만드는 데 필요한 것들을 몇 가지만 정리해 보았다.

 

그리고, 재귀적인 처리를 통해 지뢰 찾기 게임 구현의 매력 중 하나인 퍼져나가는 0 기능을 구현해 보았다.

 

이렇게, 지뢰 찾기나 간단한 게임, 프로그램 등을 구현함으로서, 

세상에 도움도 되고, 연습도 되고, 프로그래밍 실력이나 구현 능력 향상도 조금은 되지 않을까 싶다.

 

Comments