오목 [개인 모작]

C CONSOLE 2021. 8. 20. 16:18
반응형
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#include <stdio.h>
 
int board[10][10];                //33의 판정으로 인해 판이 확장되어야 함
void init_board();
void display_board();
int win_lose_Draw();
int player1_do();
void player2_do();
int SamSam_01(int n1, int n2);
 
int player1_do()
{                    //사용자로 하여금 돌의 위치를 입력받음
    int x, y;
    printf("흑의 돌 좌표를 입력하세요(x:1-10 y:1-10):");
    scanf("%d %d"&x, &y);
    x; y;
    x--; y--;
        
    if(x>=10 || y>=10 || x<=-1 || y<=-1){
        printf("오목판을 벗어났습니다. 좌표값 다시 입력!!\n");
        player1_do();
    }
 
    else if(board[x][y] == 'o' || board[x][y] == 'x'){
        printf("이미 놓았습니다. 다시 입력!!\n");
        player1_do();
    }
    else
        board[x][y] = 'x';
 
    if(SamSam_01(x,y)==1){
        printf("금수입니다. 흑이 패하였습니다.\n");
        return 1;
    }
    
    return 0;
}
 
void player2_do()
{                    //사용자로 하여금 돌의 위치를 입력받음
    int x, y;
    printf("백의 돌 좌표를 입력하세요(x:1-10 y:1-10):");
    scanf("%d %d"&x, &y);
    x; y;
    x--; y--;
 
    if(x>=10 || y>=10 || x<=-1 || y<=-1){
        printf("오목판을 벗어났습니다. 좌표값 다시 입력!!\n");
        player2_do();
    }
    else if(board[x][y] == 'o' || board[x][y] == 'x'){
        printf("이미 놓았습니다. 다시 입력!!\n");
        player2_do();
    }
    else
        board[x][y] = 'o';
}
 
int SamSam_01(int n1, int n2)
{
    int h, k=0;                        //h->놓은 돌 위치 보정 || k->돌의 갯수, 값 검열 
    int i=0, count=0;                //i->돌 배열 도움 || count->반환 값
 
    if(n1<2 || n1>9 || n2<2 || n2>9return 0;        //33 가능 위치 기본 조사
    
    for(h=1; h<5; h++)    {            //놓은 돌을 기준으로 주위에 자신의 돌만 세개가 있는지 조사 (가로)
 
        for(i=0; i<6; i++if(board[n1][n2+(i-h)]!='o') k++;
 
        if(k!=6){                    //범위 내에 백이 있을 경우 한 좌표 옆 위치에서 다시 조사
            k=0;
            continue;
        } else if(k==6){            //33 범위 내에 흑의 갯수를 조사
            k=0;
            for(i=0; i<4; i++if(board[n1][n2+(i-h)+1]=='x') k++;
            if(k==3){                //흑이 3개이므로 33의 정의에 합당함
                count++;
                k=0;
                break;
            }
        }
        k=0;                        //조사가 실패 했으므로 다시 돌의 갯수를 0으로 맞춤
    }
 
    for(h=1; h<5; h++)    {            //(세로)
 
        for(i=0; i<6; i++if(board[n1+(i-h)][n2]!='o') k++;
 
        if(k!=6){
            k=0;
            continue;
        } else if(k==6){
            k=0;
            for(i=0; i<4; i++if(board[n1+(i-h)+1][n2]=='x') k++;
            if(k==3){        
                count++;
                k=0;
                break;
            }
        }
        k=0;
    }
 
    for(h=1; h<5; h++)    {        //(정대각)
 
        for(i=0; i<6; i++if(board[n1+(i-h)][n2+(i-h)]!='o') k++;
 
        if(k!=6){
            k=0;
            continue;
        } else if(k==6){
            k=0;
            for(i=0; i<4; i++if(board[n1+(i-h)+1][n2+(i-h)+1]=='x') k++;
            if(k==3){        
                count++;
                k=0;
                break;
            }
        }
        k=0;
    }
 
 
    for(h=1; h<5; h++)    {        //(역대각)
 
        for(i=0; i<6; i++if(board[n1-(i-h)][n2+(i-h)]!='o') k++;
 
        if(k!=6){
            k=0;
            continue;
        } else if(k==6){
            k=0;
            for(i=0; i<4; i++if(board[n1-(i-h)-1][n2+(i-h)+1]=='x') k++;
                if(k==3){        
                count++;
                k=0;
                break;
            }
        }
        k=0;
    }
 
    if(count==2return 1;
    else return 0;
}
 
int win_lose_Draw()
{                    //승패 가르기
    int i,j;
    int cnt;        //더 이상 둘 곳이 없을 경우의 수
 
    for(i=0; i<10; i++){        //가로 열 검열
        for(j=0; j<6; j++){
            if(board[i][j]==board[i][j+1&&
                board[i][j+1]==board[i][j+2&&
                board[i][j+2]==board[i][j+3&&
                board[i][j+3]==board[i][j+4] )
            {
                if(board[i][j+2== 'x')
                    return 1;
                else if(board[i][j+2== 'o')
                    return 2;
            }
        }
    }
 
    for(i=0; i<10; i++){            //세로 열 검열
        for(j=0; j<6; j++){
            if( board[j][i]==board[j+1][i] &&
                board[j+1][i]==board[j+2][i] &&
                board[j+2][i]==board[j+3][i] &&
                board[j+3][i]==board[j+4][i])
            {
                if(board[j+2][i] == 'x')
                    return 1;
                else if(board[j+2][i] == 'o')
                    return 2;
            }
        }
    }
 
    for(i=0; i<6; i++){                //대각선 검열
        for(j=0; j<6; j++){
 
            if( board[i][j]==board[i+1][j+1&&                    //좌에서 우로
                board[i+1][j+1]==board[i+2][j+2&&
                board[i+2][j+2]==board[i+3][j+3&&
                board[i+3][j+3]==board[i+4][j+4] ){
                if(board[i+2][j+2== 'x')
                    return 1;
                else if(board[i+2][j+2== 'o')
                    return 2;
                }
        }
    }
    
    for(i=4; i<10; i++){            //대각선 검열
        for(j=0; j<6; j++){
            if(board[i][j]==board[i-1][j+1&&                    //우에서 좌로
                board[i-1][j+1]==board[i-2][j+2&&
                board[i-2][j+2]==board[i-3][j+3&&
                board[i-3][j+3]==board[i-4][j+4]) {
                
                if(board[i-2][j+2== 'x')
                    return 1;
                else if(board[i-2][j+2== 'o')
                    return 2;
            }
        }
    }
 
    cnt = 99;                //비김 처리
    cnt--;
 
    if (cnt==0)
        return 3;
 
    return 0;                //계속 진행
}
 
 
int main()
{                        //플레이
    int r=0;
    init_board();
    display_board();
 
    while (1) {
        if(player1_do()==1) r=2;
        if(r==2break;
        display_board();
        r=win_lose_Draw();
        if(r!=0)
            break;
 
        player2_do();
        display_board();
        r=win_lose_Draw();
        if(r!=0)
            break;
    }
 
    if(r==1)
        printf("흑이 승리하였습니다!!\n");
    else if(r==2)
        printf("백이 승리하였습니다!!\n");
    else if(r==3)
        printf("비겼습니다!!\n");
}
 
void init_board()
{                        //오목 놓을자리
    int i, j;
    for(i=0; i<10; i++)
        for(j=0; j<10; j++) board[i][j] = '\0';
}
 
void display_board()
{                        //오목판
    int i,j;
 
    printf("\n x    y\t");
    
    for(i=0; i<9; i++printf(" %d |",i+1);        //위 쪽 숫자
 
    printf(" %d"10);        //정리
    printf("\n\n");
 
    for(i=0; i<10; i++){    //오목판 값
 
        printf(" %d \t", i+1);
 
        for(j=0; j<9; j++printf(" %c |", board[i][j]);
 
        printf(" %c \n", board[i][9]);
        
 
        if(i==9){            //마지막 ---을 긋지 않기 위한 탈출문
            printf("\n");
            break;
        }
        
        printf("---\t");
 
        for(j=0; j<9; j++printf("---+");
 
        printf("---\n");
        
    }        
}
cs

 

 

키보드로 입력받기

 

 

금수로 인한 흑의 패배

 

 

금수란

 

 

코드는 메인함수와 게임출력함수를 분리하고 33법칙과 게임의 심판 함수부 역시 함수로 정리하였다.

위와 같은 오목을 만들다 33법칙을 알게 되었는데 본인에게는 꽤나 충격적인 규칙이었다. 놀란 지점은 오목에 금수의 존재로 놀란 게 아니라 무조건 이기는 수가 있었다는 것에서 깊은 충격을 받았다. 그래서 그대로 구현해주었다.

 

방식은 가로든, 세로든 6개의 x, x, x, x, x, x 의 실린더를 놓는 식으로 모든 영역을 검사하게 되는데 좌우 양 끝 x지점이 비어있고 나머지 4개의 착수 지점에서 연속으로 3개의 같은 색, 빈 곳이 위치하면 33돌의 3이 완성되는 곳이다. 그리고 그 지점을 저장해두었다가 역사선, 사선 등 나머지 방향에 대하여 해당 지점과 같은 착수지점이 발생할 경우 금수로 판별하는 것이다.

 

이 오목은 대학교 1학년 때 만들었다. 현재는 2021년... 그런데 아직도 33법칙을 어찌 제작했는지 기억하고 있는 것을 보면 꽤 충격을 받긴했나보다.

 

더하여, 이 전에 썼던 틱택토와 더불어 같이 생각할 문제가 있다. 바로 인공지능이다. 인공지능으로 바둑이란 게임에서 인간을 이겼다. 그럼 하나 묻고 싶은 게 있다. 과연 가위바위보 라는 간단한 게임에서 그와 같은 강력한 인공지능이 필요할까? 그냥 랜덤함수만 써도 된다. 맞다. 그 바둑도 인간이 일부러 이기지 않는 착수, 소위 엉터리로 착수를 하였다면 결과가 어찌될 지는 아무도 모르는 것이다.

 

이는 다른 이의 밥벌이와 연관점이 있다. 인간 세상사 최적화 대로 흘러가지 않는다. 그 상황에서 과학과 기술은 최적화가 가능한 부분은 대체하고 실제로 많은 혜택을 누린다. 필자는 이 부분에서 필시 인공지능으로 대체될 많은 직업들에게 묻고 싶다. 과연, 밑빠진 독이 있지는 않을까? 줄줄 돈이 세어나가는데 그 상황에 고통받는 이들이 필연적으로 생긴다는 것이다. 즉, 본인이 하고 싶은 말은 '우리가 사용하는 연산과 데이터 자체만으로도 지적재산권의 발생'이 가능하다는 것이다. 알고리즘 검색, 음악 추천 등 많은 판단을 기계에 맡기게 될 때에 일어나는 데이터 누수현상은 짚고 인공지능으로 대체해도 괜찮을 것 같다. 왜냐하면 이러한 고려를 넘겨짚고 문제점을 무시한다면 중증환자... 예로 암을 다루는 대학 병원보다 비교적 가벼운 병을 다루는 동네 이비인후과가 훨씬 돈을 많이 버는 기이한 현상이 발생될 수 있다는 것이다. 누가 3일 약만 먹으면 났는 감기나 알레르기 비염에 수십억 장비를 태우며 무려 인공지능 씩이나 돌릴 생각을 할까? 돈을 받는다는 것은 책임을 진다는 말과도 연결이 되는 것 같은데, 그럼 암 치료 로봇을 도입할 경우 아무도 이해 못하는 로봇퍼포먼스를 책임질 이유가 없는가? 그럼 그 퍼포먼스에 들어간 연산과 메모리는 그럼 대체 무엇이란 말인가? 그 내부 코드와 데이터 모두 인적 자원일 수 있다는 것이다.

 

인공지능은 절대값에서 우위를 점하겠지만 상대적인 값에서는 아직 연구 진행조차 되지 않은 것이 현주소라고 보인다. 필자는 당장에 가위바위보를 예시로 들었었다. 가위, 바위, 보 자체는 구현이 될 수 있어도 가위와 바위를 함께 두는 순간 상대적인 가치가 발생해 갑자기 바위가 가위를 이기는 형태가 된다. 이는 철저한 계산 아래 일정 영역을 감싸야만 승리를 쟁취할 수 있는 바둑과는 다른 방식의 게임이라고 생각한다. 여기에 한 가지 보자기라는 딱 하나의 상대적 가치를 더 두게 되면 경우의 수를 거의 셀 수가 없게 되는 것 같다. 가위바위보는 진행하면 할 수록 경우의 수 총합이 늘어난다. 이는 가위바위보가 독립시행, 즉 확률이 계속 유지된다는 점 때문이라고 본다. 즉, 현재 바위를 낸 사람이라 하여도 언제든지 다음에는 가위, 바위, 보 이 셋 중에 하나를 낼 수 있다는 예기며, 착수를 하며 경우의 수를 줄여나가는 바둑과는 다른 방식이라는 것이다. 이러한 확률 유지형 게임을 발달시켜 확률형 게임제작까지 생각해볼 수 있을 것 같다.(현재는 이미 실현 중인 것 같다.) 끝으로 무분별한 인공지능적용은 기술의 적용 기대값과 인간의 줄어들지 않는 확률, 상대적 이해관계(대부분 자본, 돈이 될 것 같다.)로 인해 자칫 오용될 수도 있겠다는 말을 하고 싶다.

 

기술이 특이점을 찍을 날이 머지 않았다고들 한다. 글쎄다. 필자는 인류는 약인공지능으로 이미 그 특이점을 찍었다고 생각한다. 여기서 이 약인공지능에 대한 특이점의 기준은 에니악이다.

 

ENIAC

현대 컴퓨터의 기원은 1946년에 완성된 최초의 대형 전자식 디지털 컴퓨터인 에니악(ENIAC;Electronic Numerical Integrator and Calculator)이랍니다.에니악은 펜실베이니아 대학의 모클리(J.W Mauchil)와 에커트(J

terms.naver.com

 

위 문서를 보면 알겠지만 1946에 최초로 컴퓨터라는 것이 등장하였다. 그리고 2016년에 바둑을 두었다. 인류의 기술이 70년 만에 이렇게 발달하게 된 것이 특이점이라고 생각한다. 즉, 애니악 기준으로는 알파고가 특이점인 셈이다. 그리고 이제는 이 강력한 기술을 '다루어야'한다고 생각한다. 아니면 인터넷부터 내려놓으라는 말을 하고 싶다. 원하는 대로 찌르지도 못하고, 들지도 못하고, 이해하지 못하는 도구를 함부로 다루었다가는 큰일난다는 것이 필자의 생각이며 이는 차후 문학으로 풀어낼 예정이다. 맞다. 이미 이 부분에 대한 이슈는 세상에 제출했었다.

반응형

'C CONSOLE' 카테고리의 다른 글

틱텍토 [개인 모작]  (0) 2021.08.20
Posted by Kestone Black Box
,