이 블로그는 방문자 통계를 위해 티스토리 기본 기능과 Woopra를 사용합니다. 원하지 않으신다면 사용하시는 웹 브라우저에 내장된 DNT 헤더를 켜고, JavaScript를 끄셔도 무방합니다.
이 블로그 방문자의 약 60%는 네이버 검색을 사용하십니다. 을 이용하시면 더 유용한 정보를 쉽게 얻게 되실 수도 있습니다. [mediatoday]
« 2021/5 »
            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 27 28 29
30 31          
블로그 이미지
제가 주제인 블로그... 그냥 주제 없는 블로그입니다. 전공 분야나 예전 관심 분야 등등에 관한 글이 우선입니다만, 두어 문단을 넘길 만한 글이라면 대강 정리해 기록합니다. 학부생입니다. 트위터에서 볼 수 있습니다. http://aurynj.net/ 어­리


환타 오목 게임 재구성. (1)

Sablog Models/자작자작 | 2009. 6. 6. 19:29 | Posted by 어­리

지환태 님의 미니홈피에서 가져온 오목 게임입니다.
상당히 끌려서 말입니다-_-; 도와드리지 않고는 못 배기겠더군요.(?)

일단 아래는 원본.



상태가 약간 이뭐병입니다. 전역변수는 물론이고 덜떨어진 가독성이 돋보이는군요.

제가 만든다고 얼마나 나을지는 모르겠습니다만,

이 소스는 무개념으로 충만하다 못해 아주 넘치는 것 같아요.


.....-_- 장난이었구요, 죄송합니다.



코드를 살펴보면 구조가 상당히 난해합니다.

일단 main()에서 move()를 무한 반복해서 모든 프로세싱을 넘겨 줍니다.

이 때 move()는 한 번에 커서 한 칸 움직이거나 돌 한 번 놓기밖에 수행할 줄 모릅니다.

전역변수 x, y, oldx, oldy, who[3][3]가 move()에서만 쓰임에도 불구하고,

전역변수로 선언되어 있는 것은 move 내에 선언하면 변수가 계속 바뀌기 때문입니다.



아무래도 판을 수행하는 부분은 main()에 남겨 놓고,

커서를 움직이거나 돌을 움직이는 부분은 move()에 남겨 놓되,

판의 승패를 결정하고 move()를 반복하는 부분은 또 다른 함수로 바꾸어야 되겠습니다.

새로운 함수의 이름을 five_in_a_row()로 합시다.


근데 상당히 짜증나네요.

나머지 함수들은 모조리 헤더 파일 하나에 몰아 넣어 봐야 되겠습니다.

그럼 C 파일의 내용은 일단....

#include "five_in_a_row.h"

int main()
{
    while (!(five_in_a_row()));
    return 0;
}

애석하게도 대충 이따구로 변형할 수 있겠습니다.

그리고 아래는 five_in_a_row.h입니다.
/* five_in_a_row.h
 * by ZFanta & UNique
 */
#ifndef FIVE_IN_A_ROW
#define FIVE_IN_A_ROW


#include "tool.h"

#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
#define ENTER 13

int x = 0, y = 0;
int oldx = 0, oldy = 0;
int board[38][19];
int turn = 1;
char who[3][3] = {"", "흑", "백"};
char stone[3][3] = {"", "○", "●"}; 


void draw()
{        
    char a[39][39]=
    {
        "┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐",
        "├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤",
        "└┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┘"
    };
    int count;
    printf("%s\n", a[0]); 
    for(count = 0; count < 17; count++)
        printf("%s\n", a[1]);
    printf("%s", a[2]);
}

int check(int x, int y, int turn)
{
    int px, py;
    int count;

    //가로
    px = x;
    py = y;
    count = 0;    

    while(px > 1 && board[px-2][y] == turn)
        px -= 2;
    while(px <= 36 && board[px][y] == turn)
    {
        count++;
        px += 2;
    }

    if(count == 5)
    {
        return 1;
    }

    //세로
    px = x;
    py = y;
    count = 0;

    while(py > 0 && board[x][py-1] == turn)
        py--;
    while(py <= 18 && board[x][py++] == turn)
        count++;

    if(count==5)
    {
        return 1;
    }

    //대각선 ↘
    px = x;
    py = y;
    count = 0;

    while(px > 0 && py > 0 && board[px-2][py-1] == turn)
    {
        px -= 2;
        py--;
    }

    while(px <= 36 && py <= 18 && board[px][py++] == turn)
    {
        px += 2;
        count++;
    }
    if(count == 5)
    {
        return 1;
    }

    //대각선 ↙
    px = x;
    py = y;
    count = 0;

    while(px < 36 && py > 0 && board[px+2][py-1] == turn)
    {
        px += 2;
        py--;
    }

    while(px >= 0 && py <= 18 && board[px][py++] == turn)
    {
        px -= 2;
        count++;
    }
    if(count == 5)
    {
        return 1;
    }
    return 0;
}

int knock(int x, int y)
{
    gotoxy(x,y);
    puts(stone[board[x][y]]);
    if(board[x][y] != 0)
        return 0;

    else
        return 1;
}

int move()
{
    char input = 0;
    input = getch();

    switch(input)
    {
    case UP :
        if(y>0)
        {
            y -= 1;
            oldy = y + 1;
            gotoxy(x, y);
            puts("⊙");
            if(knock(x, oldy))
            {
                gotoxy(x, oldy);
                if(oldy == 18)
                {
                    if(x == 0)
                    {
                        puts("└");
                    }
                    if(x == 36)
                    {
                        puts("┘");
                    }
                    else if(x != 0 && x != 36)
                    {
                        puts("┴");
                    }
                }
                else if(x == 0)
                {
                    puts("├");
                }
                else if(x == 36)
                {
                    puts("┤");
                }
                else
                {
                    puts("┼");
                }
            }

        }
        return 1;
        break;

    case DOWN :
        if(y<18)
        {
            y+=1;
            oldy=y-1;
            gotoxy(x,y);
            puts("⊙");
            if(knock(x, oldy))
            {
                gotoxy(x, oldy);
                if(oldy == 0)
                {
                    if(x == 0)
                    {
                        puts("┌");
                    }
                    if(x == 36)
                    {
                        puts("┐");
                    }
                    else if(x != 0 && x != 36)
                    {
                        puts("┬");
                    }
                }
                else if(x == 0)
                {
                    puts("├");
                }
                else if(x == 36)
                {
                    puts("┤");
                }
                else
                {
                    puts("┼");
                }
            }

        }
        return 1;
        break;

    case LEFT :
        if(x>0)
        {
            x -= 2;
            oldx = x + 2;
            gotoxy(x, y);
            puts("⊙");
            if(knock(oldx, y))
            {
                gotoxy(oldx, y);
                if(oldx == 36)
                {
                    if(y == 0)
                    {
                        puts("┐");
                    }
                    if(y == 18)
                    {
                        puts("┘");
                    }
                    else if(y != 0 && y != 36)
                    {
                        puts("┤");
                    }
                }
                else if(y == 18)
                {
                    puts("┴");
                }
                else if(y == 0)
                {
                    puts("┬");
                }
                else
                {
                    puts("┼");
                }
            }

        }
        return 1;
        break;

    case RIGHT :
        if(x<36)
        {
            x += 2;
            oldx = x-2;
            gotoxy(x, y);
            puts("⊙");
            if(knock(oldx, y))
            {
                gotoxy(oldx, y);
                if(oldx == 0)
                {
                    if(y == 0)
                    {
                        puts("┌");
                    }
                    if(y == 18)
                    {
                        puts("└");
                    }
                    else if(y != 0 && y != 36)
                    {
                        puts("├");
                    }
                }
                else if(y == 18)
                {
                    puts("┴");
                }
                else if(y == 0)
                {
                    puts("┬");
                }
                else
                {
                    puts("┼");
                }
            }

        }
        return 1;
        break;

    case ENTER :
        if(board[x][y] == 0)
        { 
            board[x][y] = turn;
            gotoxy(x, y);
            puts(stone[turn]);
            if(check(x, y, turn))
            {
                return 0;
            }
            turn++;
            if(turn == 3)
                turn = 1;
        }
        return 1;
        break;
    }
    return 1;
}

int five_in_a_row()
{
    /* If user wants to re-match, returns 0; or not, returns 1.
     * (only if one game successfully ended)
     */
    int i, j;
    system("CLS");
    draw();
    for (i = 0; i < 38; i++)
        for (j = 0; j < 19; j++)
            board[i][j] = 0;
    while (move());
    system("CLS");
    printf("%s 승리", who[turn]);
    system("PAUSE");

    return 0;
}


#endif

위에 보면 다른 헤더 파일이 없고 tool.h만 있습니다.

getch 관련해서 꼬박 반나절을 삽질한 탓에 열받아서 분리시켜 버렸죠.
/* tool.h (for five_in_a_row.h)
 * supports gotoxy(x, y) and getch()
 */
#include <stdio.h>
#include <windows.h>

void gotoxy(int x, int y)
{
    COORD XY = {x, y};
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), XY);
}

#if defined(_MSC_VER) && (_MSC_VER > 1000)
_CRTIMP _getch();
#define getch() _getch()
#elif defined(__GNUC__) || defined(__GNUG__)
#include <termios.h>
int getch()
{
    char ch;
	struct termios buffer, status;

    tcgetattr( STDIN_FILENO, &buffer );
    status = buffer;
    status.c_lflag &= ~(ECHO | ICANON);
    tcsetattr( STDIN_FILENO, TCSANOW, &status );
    read( 0, &ch, 1 );
    tcsetattr( STDIN_FILENO, TCSANOW, &buffer );

    return ch;
}
#else
#include <conio.h>
#endif


일단 제 코딩 스타일로 가독성을 약간 높였습니다.

여전히 저 switch-case 제어문은 쩔어주게 기네요. 아니 더 길어진 듯?

저걸 처리할 방법을 다음 글에서 다루도록 하죠.

댓글을 달아 주세요

  1. 지환태 2009.06.11 23:55 신고  댓글주소  수정/삭제  댓글쓰기

    1년 전엔 공책에 열심히 한 건데 지금 보니 코드가 상당히 더럽네요 ㅎㅎ
    저거 만든지도 벌써 1년이 ㅇㅅㅇ;
    저도 새로 만들어 봐야겠네요 ㅋㅋ