메뉴
Omok Game (Connect-5 Game; 오목)

2012. 2. 22. 01:48

개요

아래 코드는 바둑판 위에 랜덤하게 바둑돌을 배치했을 때,
전체 바둑판에서 오목의 개수가 각각 몇개인지 세는 프로그램이다.
이미 체크한 바둑돌을 다시 체크하지 않게 하기 위해서,
각 방향(가로, 세로, 대각선)별로 각각 한번만 지나가면서 체크하도록 했다.
오목이외의 6목 7목... 등도 찾도록 했고, if문만 걸어주면 '오목'만 찾도록 할 수 있다.
발견 지점을 좌표로 표기하도록 했고, 코드의 양을 최소화하는데 목적을 두고 코딩했다.




코드

#include <stdio.h>
#include <stdlib.h>

#define MAX 19

void draw_MAP(int oMAP[][MAX], int NUM_STONE);
void result (int w, int b);
void initialize (int d[]);
void find5 (int a[][MAX], int i, int j, int d[]) ;
void check_HV (int a[][MAX],int *w, int *b);
void check_D (int a[][MAX],int *w, int *b);
void printf_MAP (int a[][MAX]);

void main() {    
    int w=0,b=0;
    int oMAP[MAX][MAX];
    int USER_INPUT,NUM_STONE;
    do {
        printf(" Input any integer 0 ~ 2147483647 to generate map > ");
        scanf_s("%d",&USER_INPUT);
    }while (USER_INPUT<0 || USER_INPUT>2147483647);
    // Get user input for a random seed
    do {
        printf(" Input any integer number of stones 50 ~ 150 > ");
        scanf_s("%d",&NUM_STONE);
    }while (NUM_STONE<50 || NUM_STONE>150);
    // Get user input for the number of each stone
    srand(USER_INPUT);
    draw_MAP(oMAP,NUM_STONE*2); // Draw the 'omok' map
    printf_MAP(oMAP); // Print the map
    check_HV (oMAP,&w,&b); // Check Horizontal
    check_D (oMAP,&w,&b); // Check Diagonal
    result(w,b); // Print result
}

void draw_MAP(int oMAP[][MAX], int NUM_STONE){
    int i,j,k;
    for (i=0;i<MAX;i++)
        for (j=0;j<MAX;j++)
            oMAP[i][j] = 0; // Initialize
    for (i=0;i<NUM_STONE;){
        j=rand()%MAX; k=rand()%MAX; // Get random location
        if (oMAP[j][k] == 0){ oMAP[j][k] = i%2 + 1; i++;} // Check Duplication
        // If it is duplicated, find another location
    }
}

void initialize (int d[]){
    if (d[0]>=5) {d[4]=(d[3]*2-3)*d[0];}
    // Check the counter if counter is 5, 5-set-complete has color information.    
    d[0]=0; d[3]=0;
    // Initialize counter and color information.
}
void find5 (int a[][MAX], int i, int j, int d[]) {
    /*********************************************************
     For the array 'd'
     0: counter, 1: X_before, 2: Y_before, 3: COLOR_before,
     4: 5-or-more-set-complete, 5: BLACK_counter, 6:WHITE_counter,
     7, 8: Coordinate Offset.
    *********************************************************/
    if (d[3] == a[i][j] && a[i][j]>0) { // if current color is same as before, counter is increased.
        d[0]++;
    } else { // if it is different, counter becomes 1.
        if (d[0]>=5) {d[4]=(d[3]*2-3)*d[0];}
    // Check the counter if counter is 5, 5-set-complete has color information.
            d[0]=1;
    }
    if (d[4] <= -5) {
        printf(" (%d-White at (x,y): (%2d,%2d)~(%2d,%2d))\n",d[4]*(-1),d[2]+(d[7]*(d[4]+1)*(-1)+1),d[1]+(d[8]*(d[4]+1)*(-1)+1),d[2]+1,d[1]+1);
        d[5]++; // Increase Black counter
        d[4]=0; // Initialize 5-or-more-set-complete
    }
    if (d[4] >= 5) {
        printf(" (%d-Black at (x,y): (%2d,%2d)~(%2d,%2d))\n",d[4],d[2]+(d[7]*(d[4]-1)+1),d[1]+(d[8]*(d[4]-1)+1),d[2]+1,d[1]+1);
        d[6]++; // Increase White counter
        d[4]=0; // Initialize 5-or-more-set-complete
    }
    // Print out 5-or-more-set-complete color and the information of its location.
    // And then initialize color information and increase the COLOR counter.
    d[1]=i;
    d[2]=j;
    d[3]=a[i][j];
    // Save current i, j, color information for the next pass.
}

void result (int w, int b){
    // Print the result
    printf(" [ RESULT ] White: %d, Black: %d ----- ",w,b);
    (w>b) ? printf("White Win!") : ((w==b)? printf("Draw!") : printf("Black Win!"));
    printf("\n\n");
}

void check_HV (int a[][MAX],int *w, int *b) {
    int i,j;
    int d[11] = {0,0,0,0,0,0,0,-1,0}; // horizontal
    int e[11] = {0,0,0,0,0,0,0,0,-1}; // vertical
    // 0: counter, 1: X_before, 2: Y_before, 3: COLOR_before,
    // 4: 5-or-more-set-complete, 5: BLACK_counter, 6:WHITE_counter,
    // 7, 8: Coordinate Offset.
    for (i=0;i<MAX;i++){
        initialize (d); // For a new row of horizontal check, Do initialize
        initialize (e); // Same as vertical cols.
        for (j=0;j<MAX;j++){
            find5(a, i, j, d); // find 5-or-more-set-complete of horizontal
            find5(a, j, i, e); // find 5-or-more-set-complete of vertical
        }
    }
    find5(a, i, j, d); // find 5-or-more-set-complete of horizontal for the last several stones
    find5(a, j, i, e); // find 5-or-more-set-complete of vertical for the last several stones
    printf(" [ Horizontal ] White: %d, Black: %d\n",d[5],d[6]);
    printf(" [ Vertical ] White: %d, Black: %d\n\n",e[5],e[6]); // print partial results
    *w += d[5]+e[5];
    *b += d[6]+e[6]; // 'w' and 'b' for the final result
}

void check_D (int a[][MAX],int *w, int *b) {
    int i,j,k;
    int d[11] = {0,0,0,0,0,0,0,-1,1}; // diagonal ↗ËO
    int e[11] = {0,0,0,0,0,0,0,1,1}; // diagonal ↘ËU
    for(i=0,j=0,k=0;i<MAX*MAX;i++){    
    if (j>=0 && k<MAX) { // For NOT out of range
        find5(a, j, k, d); // find 5-or-more-set-complete of diagonal ↗
        find5(a, j, MAX-1-k, e); // find 5-or-more-set-complete of diagonal ↘
        j--; k++; // Next move
    }
    if (j<0 || k==MAX) { // Check out of range
        initialize (d); // Initialize
        initialize (e);
        if (k==MAX) { k=j+k-MAX+2;    j=MAX-1; }
        else { j=j+k+1;    k=0; } // Set next location
        }
    }
    printf(" [ Diagonal↗ ] White: %d, Black: %d\n",d[5],d[6]);
    printf(" [ Diagonal↘ ] White: %d, Black: %d\n\n",e[5],e[6]); // print partial results
    *w += d[5]+e[5];
    *b += d[6]+e[6]; // 'w' and 'b' for the final result
}

void printf_MAP (int a[][MAX]) {
    int i,j,k,l=0,m=0;
    char base[9][4] = {"┌","┬","┐","├","┼","┤","└","┴","┘"};
    // An Array for Omok board
    printf("\n ");
    for (i=0;i<MAX;i++){
        printf("%2d",i+1); // print col numbers
    }
    printf("\n");
    for (i=0;i<MAX;i++){
        printf(" %2d ",i+1); // print row numbers
        for (j=0;j<MAX;j++){
            if (a[i][j] == 0) {
                k=0;
                if (i > 0 && i<MAX-1) k+=3; // Middle rows
                if (i==MAX-1) k+=6; // Border of bottom
                if (j > 0 && j<MAX-1) k+=1; // Middle cols
                if (j ==MAX-1) k+=2; // Border of right
                printf("%s",base[k]); // Print board shape
            } else if (a[i][j] == 1) {
                printf("○");
                l++; // Counter for white stones
            } else if (a[i][j] == 2) {
                printf("●");
                m++; // Counter for black stones
            }
        }
        printf("\n");
    }
    printf("\n Check the number of stones >\n White: %d, Black: %d\n\n",l,m);
}



결과