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);
}
결과