Sablog Models/자작자작

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

어­리 2009. 9. 17. 21:13
이 코드를 리팩토링하기 시작한 후로 상당히 많은 시간이 흘렀는데....

제대로 된 개선은 한 적이 없다.

미쳤구나.

시간이 많던 방학 동안에는 아예 안 건드렸다.



원래 check()를 바꿔 보려고 했습니다만 더 최적화시키기는 어려워 보입니다.-_-;;


대신에 move()의 길이를 좀 더 줄여 보도록 하겠습니다.


/* 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
#define ESC 27
#define BOARD_SIZE 19

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

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

    // 가로로 오목이 있는지 검사
    px = x;
    py = y;
    count = 0;

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

    if(count == 5)
        return 1;


    // 세로로 오목이 있는지 검사
    px = x;
    py = y;
    count = 0;

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

    if(count == 5)
        return 1;


    // 좌상우하로 오목이 있는지 검사
    px = x;
    py = y;
    count = 0;

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

    if(count == 5)
        return 1;


    // 우상좌하로 오목이 있는지 검사
    px = x;
    py = y;
    count = 0;

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

    if(count == 5)
        return 1;

    return 0;
}

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

void load(int x, int y)
{
    gotoxy(x * 2, y);
    puts("⊙");
}

void board_write(int x, int y)
{
    x *= 2;
    gotoxy(x, y);
    if (x == 0)
    {
        if (y == 0)
            puts("┌");
        else if (y == (BOARD_SIZE - 1))
            puts("└");
        else
            puts("├");
    }
    else if (x == (BOARD_SIZE - 1) * 2)
    {
        if (y == 0)
            puts("┐");
        else if (y == (BOARD_SIZE - 1))
            puts("┘");
        else
            puts("┤");
    }
    else
    {
        if (y == 0)
            puts("┬");
        else if (y == (BOARD_SIZE - 1))
            puts("┴");
        else
            puts("┼");
    }
}

void draw()
{        
    int i, j;
    for (i = 0; i < BOARD_SIZE; i++)
        for (j = 0; j < BOARD_SIZE; j++)
            board_write(i, j);
}

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

    if(input != ENTER)
    {
        oldx = x;
        oldy = y;
        if(input == UP && y > 0)
            y--;
        else if(input == DOWN && y < BOARD_SIZE - 1)
            y++;
        else if(input == LEFT && x > 0)
            x--;
        else if(input == RIGHT && x < BOARD_SIZE - 1)
            x++;
        if(knock(oldx, oldy))
            board_write(oldx, oldy);
        load(x, y);
    }
    else if(board[x][y] == 0)
    { 
        board[x][y] = turn;
        gotoxy(x * 2, y);
        puts(stone[turn]);
        if(check(x, y, turn))
            return 0;
        turn ^= 3;
    }

    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 < BOARD_SIZE; i++)
        for (j = 0; j < BOARD_SIZE; j++)
            board[i][j] = 0;
    load(x, y);
    while (move());
    system("CLS");
    printf("%s 승리.\n계속하려면 아무 키나 누르십시오(종료 Esc):", who[turn]);
    if (getch() == ESC)
        return 1;
    else
        return 0;
}


#endif

-_-;;

여전히 코드 수준이 그다지 나아지지 않고 있는 것 같군요.


날로 먹는 이 느낌은 뭘까요.

+ 아, 그래도 251 Line에서 212 Line으로 40줄 가량 줄였습니다.
거의 goto에 버금가는 C언어의 switch-case도 없애 버리고요.