반응형
#include <stdio.h>
#include <stdlib.h>

void init_board(char board[][3]);
int get_player_move(int player, char board[][3]);
void disp_board(char board[][3]);

int main(void)
{
    char board[3][3];
    int quit=0;

    init_board(board);

    do
    {
        disp_board(board);
        quit = get_player_move(0, board);
        disp_board(board);
        quit = get_player_move(1, board);
    } while(quit == 0);

    return 0;
}

void init_board(char board[][3])
{
    int x, y;
    for(x=0; x<3; x++)
    {
        for(y=0; y<3; y++)
        {
            board[x][y] = ' ';
        }
    }
}

int get_player_move(int player, char board[3][3])
{
    int x, y, done = 0;

    while(done != 1)
    {
        printf("(x, y) 좌표(종료-1, -1): ");
        scanf("%d,%d",&x, &y);

        if(x == -1 && y == -1)
            return 1;

        if(board[x][y] == ' ')
            break;
        else
            printf("잘못된 위치입니다.\n");
    }

    if(player == 0)
        board[x][y] = 'X';
    else
        board[x][y] = '0';
    return 0;
}

void disp_board(char board[3][3])
{
    int i;

    for(i=0; i<3; i++)
    {
        printf("---|---|---\n");
        printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
        printf("---|---|---\n");
    }
}

 

위의 소스코드는 tic-tac-toe 게임의 소스코드이다.

일단 stdio와 stdlib 헤더파일들을 포함시켜주고, 

 

좀 더 편하게 작성하기 위해 함수를 만들어서 모듈화가 되어있다.

 

-

 

메인 함수가 시작되고 char형 2차원 배열 board와 정수형 변수 quit를 선언한다. 

 

그리고 정수형 변수 quit는 0으로 초기값을 정해준다.

 


 

(1. init_board함수)

 

일단 main함수가 실행되고 처음 실행하는 함수가 init_board이다.

 

init_board함수의 원형을 보면 void init_board(char board[][3]); 이다.

 

char형 2차원 배열 board를 인자로 받도록 매개변수가 선언되어있다.

 

이제 위에 코드에서 init_board함수의 정의 부분을 해석해본다.

 

init_board함수 내에서 정수형 변수 x 와 y가 선언되었고, for문으로 어떠한 작업을 반복한다.

 

그 작업을 해석해보면 먼저 x를 0으로 초기화 해줬고 x가 3보다 작으면 다음 문장을 실행한다.

 

그런데 다음 문장도 for문이다. 

 

그렇다 2차원 배열 board를 쓰기 때문에 이 구역은 현재 이중 for문으로 되어있다. 

 

2번째 for문에서도 x와 같이 y를 0으로 초기화해주고 3번 반복한다.

 

그리고 2차원 배열 board[x][y]의 원소에 for문으로 모두 공백을 넣는다.

 

그리고 init_board 함수에 인자로 2차원 배열 board를 넘겨준다. 

 

이렇게 init_board 함수는 보드를 초기화 해주는 역할을 한다.

 

-

 

그 다음 do ~ while문이 실행되는데 이 부분이 이번 tic-tac-toe 게임의 핵심소스부분이다,

 

처음 do문이 나오기 때문에 일단 한 번 실행되고 while문을 만나서

 

조건을 검사 한 뒤 참이면 do문을 다시 실행하는 구조이다.

 

do ~ while 문이 시작되고 disp_board 함수가 처음으로 실행이 되는데,

 

disp_board 함수의 인자로 2차원 배열 board가 넘겨졌다.

 

그리고 disp_board 함수의 원형만 보면 일단 반환값이 없는 함수이고, 

 

추가로 2차원 배열 board가 인자로 넘겨진다는것도 알 수 있다.

 


 

(2. disp_board 함수)

 

그렇다면 이제 disp_board 함수의 정의 부분 흐름을 봐보도록 한다.

 

먼저 disp_board 함수 내에서만 쓸 수 있고 소멸되는 정수형 변수 i가 선언 됬다.

 

그리고 for문이 나와서 반복을 해주게 되는데, 먼저 i를 0으로 초기값을 정해주고, 

 

i가 3보다 작을때까지라고 조건을 해놨으니 for문은 총 3번 반복을 한다.

 

그리고 그 다음 printf함수를 실행하는데,

 

첫 번째 printf문은 ---|---|--- 을 출력하고 줄바꿈을 하도록 한다.

 

두번째 printf함수는 문자 하나씩 총 3개를 출력하는데,

 

board[i][0]의 값, board[i][1]의 값, board[i][2]의 값을 

 

첫번째 %c , 두번째 %c, 세번째 %c 형식지정자에 넣어준다.

근데 현재 board배열은 모두 공백으로 init_board함수에서 초기화 되었기 때문에

 

printf함수를 총 3번을 출력하고 나면 

 

---|---|---

    |   |

---|---|---

---|---|---

    |   |

---|---|---

---|---|---

    |   |

---|---|---

 

이러한 모양이 출력된다.

 

이렇게 처음 호출된 disp_board 함수의 역할은 보드의 현재 상태가 화면에 출력되게 해준다.

 

-

 

이제 disp_board 함수가 호출되서 보드를 화면에 띄우고 나면,

 

get_player_move 함수가 호출되는데 이 때 값을 quit변수에 저장한다.

 


 

(3. get_player_move 함수)

 

위에 소스코드를 보면 get_player_move 함수의 값은 quit 변수에 저장이 된다.

 

그렇다면 일단 get_player_move 함수의 정의 부분을 봐보도록 한다.

 

이 함수의 정의 부분도 init_board 함수의 정의 부분과 같이 정수형 변수 x와 y가 선언됬고,

 

추가로 정수형 변수 done을 선언하면서 0으로 초기화 해주었다.

 

그 다음 while문이 나오는데 while문 조건을 보면 

 

변수 done의 값이 1이랑 비교했을때 다르면 계속 실행하라는 조건이다.

 

그리고 나서 printf문이 실행되고 scanf문이 실행되는데 사용자로부터 좌표값을 입력 받는다.

 

그리고 if문이 두개 나오는데 첫 번째 if문은 x의 값이 -1이랑 같고 y의 값도 -1이랑 같으면 

 

프로그램을 종료하도록 한다.

 

두 번째 if문은 scanf문으로 형식에 맞게 좌표 값을 받아서 2차원 배열 board원소 x 와 y에 저장하는데 

 

사용자로부터 2차원 배열 board의 원소부분에 저장된 x와 y값이 좌표 상에서 위치하는 곳이 

 

공백으로 비어있으면 반복루프를 나가도록 한다.

 

 

예를 들어 사용자가 0,0 이라는 좌표값을 주면 get_player_move 함수내에서 while문 내에 

 

두 번째 if문이 좌표에서 0,0 번째를 검사하는데 공백으로 되어있다면 while문을 나가고,

 

공백으로 되어있지 않다면 else문이 실행되서 '잘못된 위치입니다' 라고 출력해준다.

 

이렇게 while문을 나가고 나면 그 다음 if문이 조건을 검사하게 되는데

 

( get_player_move 함수 매개변수 부분을 보면 정수형 변수 player가 선언되어있고 

 

첫 번째 get_player_move 함수를 호출할때 0을 인자로 줘서 변수 player에는 0이 저장된다. )

 

player의 값이 0이랑 같다면 사용자로부터 입력받은 좌표값에 X를 저장한다.

 

그리고 만약 player의 값이 0과 다르다면 O을 좌표값에 저장한다.

 

이렇게 get_player_move 함수는 사용자로부터 좌표 값을 입력받고 2차원 배열 board를 

 

이용해서 해당하는 좌표 위치에 X 또는 O 을 저장하고 출력해 준다.

 

그리고 프로그램을 종료 할건지 안할건지와 사용자 구분을 해주는 역할을 한다.

 

-

 

이제 다시 main함수부분을 보면 다시 disp_board 함수가 호출이 되는데,

 

첫번째로 호출 됬을 때와 같이 2차원 배열 board를 인자로 넘겨줬다.

 

아까도 정리했듯이 disp_board 함수는 보드의 현재 상태를 화면에 출력하는 역할을 한다.

 

그래도 두번째 disp_board 함수가 호출 됬을 때는 get_player_move 함수의 결과값까지 반영된

 

현재 상태의 보드가 출력 된다. 그리고 나서 또 get_player_move 함수가 호출되고 그 값이

 

quit에 저장이 되는데 이번엔 인자값을 0이 아닌 1로 넘겨줬다. 

 

이 부분은 그냥 사용자를 구분하기 위함이다.

 

get_player_move 함수의 정의 부분에 while문을 나가고 난뒤 실행되는 if-else문을 보면

 

인자 값으로 0이 넘겨져서 player의 값이 0이면 X를 출력하고 

 

인자 값으로 1이 넘겨져서 player의 값이 1이면 O을 출력하도록 한다.

 

쉽게 말해서 player변수에 넘겨지는 인자가 0이면 X를 출력 아니면 O를 출력한다.

 

그리고 이제 while문이 조건을 검사하는데 이때 quit가 0이면 계속 루프되도록 되어있다. 

 

그럼 이제 어떻게 quit에 0 또는 다른 숫자가 들어가는지 보면 

 

get_player_move 함수의 정의 부분내에 while문 내에 scanf 함수 다음 줄에 나와있는 

 

if문을 보고 알 수 있다.

 

scanf 함수로 인해 사용자는 입력을 할 수 있는데 이때 입력된 값들은 x와 y에 저장이 된다. 

 

그렇지만 x와 y의 값이 -1이면 return 1을 반환한다고 되어있다. 

 

그럼 이때 이 반환되는 1이 quit에 저장이 되는데 1을 반환하는 if문이 실행되지 않으면

 

마지막 return 문을 만나서 0을 반환하게 되고 

 

그래서 -1을 입력 하지 않았을 때에는 quit에 0이 저장 되므로 

 

main함수 내에 do ~ while 문은 계속 루프를 돌 수 있는 것이다.

 

그리고 마지막으로 main 함수내에 return문을 만나서 프로그램은 종료하게 된다.

 


 

main 함수 흐름

 

1. 보드를 나타내기 위해 char형 2차원 문자 배열 board를 선언한다. 

   그리고 int형 정수 변수 quit를 선언한다.

 

2. init_board 함수를 호출해서 보드를 초기화 해준다.

 

3. do ~ while문을 실행시키는데 먼저 프로그램을 한번 실행시키고 조건을 검사한 뒤 참이면 

   참이면 계속 반복루프를 실행한다.

 

4. disp_board 함수로 현재 상태의 보드를 화면에 출력한다.

 

5. get_player_move 함수를 호출해서 프로그램을 종료할지와 사용자 구분 그리고 사용자로부     터 입력을 받는 작업을 한다. 지금은 1번째 플레이어로 구분한다.

 

6. 다시 disp_board 함수를 호출해서 get_player_move의 값이 반영된 

   현재 상태의 보드를 출력한다. 이 부분에서 X와 O이 화면에 출력된다.

 

7. 다시 get_player_move 함수를 호출해서 5번과 같은 작업을 한다. 

   하지만 이번엔 2번째 플레이어로 구분한다.

 

8. do 문이 끝나고 while문이 조건을 검사하고 quit가 0이면 반복하고 

   1이면 반복루프가 종료된다. 

 

9. return문으로 인해 프로그램이 종료된다.

반응형

+ Recent posts