안녕하세요.
현재 TICTACTOE문제를 풀고 있습니다.
책을 보면서 문제를 풀고, 혼자 힘으로 풀어보고 있습니다.
책에 나와 있는 bijection 계산 부분이 맘에 들지 않아(?)
보드의 상태를 0~19682 범위의 숫자만을 전달하고, 풀어냅니다.
#include<iostream>#include<cstring>#define THREE_9 19683usingnamespacestd;intV,CACHE[THREE_9],POW3[9]={1,3,9,27,81,243,729,2187,6561};//보드의 초기 상태를 받아서 그 상태를 숫자로 리턴합니다.(0~19682 범위)//player 에는 보드의 초기 상태에서 이번이 누구의 차례인지가 결정됩니다.//o : 1, x : 2 입니다.intinput(int&player){inti,value=1,ret=0,c=0;chartemp;for(i=0;i<9;i++){cin>>temp;if(temp=='.'){ret+=(0*value);}elseif(temp=='o'){ret+=(1*value);c++;}else{ret+=(2*value);c++;}value*=3;}if(c%2==1){player=1;}else{player=2;}returnret;}//다음 플레이어를 리턴합니다.//1->2, 2->1로 리턴합니다.intnexp(intplayer){if(player==1){return2;}return1;}//승자가 결정됬는지를 검사합니다.//승자가 결정됬다면 true, 아니라면 false 입니다.booldecision(intS){if((S/POW3[0])%10!=0&&(S/POW3[0])%10==(S/POW3[1])%10&&(S/POW3[0])%10==(S/POW3[2])%10){returntrue;}if((S/POW3[3])%10!=0&&(S/POW3[3])%10==(S/POW3[4])%10&&(S/POW3[3])%10==(S/POW3[5])%10){returntrue;}if((S/POW3[6])%10!=0&&(S/POW3[6])%10==(S/POW3[7])%10&&(S/POW3[6])%10==(S/POW3[8])%10){returntrue;}if((S/POW3[0])%10!=0&&(S/POW3[0])%10==(S/POW3[3])%10&&(S/POW3[0])%10==(S/POW3[6])%10){returntrue;}if((S/POW3[1])%10!=0&&(S/POW3[1])%10==(S/POW3[4])%10&&(S/POW3[1])%10==(S/POW3[7])%10){returntrue;}if((S/POW3[2])%10!=0&&(S/POW3[2])%10==(S/POW3[5])%10&&(S/POW3[2])%10==(S/POW3[8])%10){returntrue;}if((S/POW3[0])%10!=0&&(S/POW3[0])%10==(S/POW3[4])%10&&(S/POW3[0])%10==(S/POW3[8])%10){returntrue;}if((S/POW3[2])%10!=0&&(S/POW3[2])%10==(S/POW3[4])%10&&(S/POW3[2])%10==(S/POW3[6])%10){returntrue;}returnfalse;}//보드가 꽉 찼는지를 검사합니다.//보드가 꽉 찼다면 true, 아니라면 false 입니다.boolisFull(intS){inti,ret=true;for(i=0;i<9;i++){if((S/POW3[i])%10==0){ret=false;break;}}returnret;}//보드의 상태가 S이고 이번이 P의 차례일때, 이길 수 있는지를 리턴합니다.//TIE : 0, WIN : 1, LOSE : 2 입니다.intcanWin(intP,intS){inti,temp,&ret=CACHE[S];if(ret==-1){//승자가 결정 된 상태라면 이번 차례의 플레이어는 무조건 집니다.if(decision(S)){ret=2;}//승자가 경정 되지 않은 상태에서, 보드가 꽉 차있다면 비긴 경우입니다.elseif(isFull(S)){ret=0;}//그 외의 경우들 입니다.//보드의 각 빈 위치에 수를 두었을때,//다음 차례의 플레이어 필패 경우 -> 필승이므로 ret에 WIN을 메모이제이션한 후 for문을 나옵니다.//다음 차례의 플레이어의 최적 수가 비기는 경우 -> ret에 TIE를 저장 후 for문을 마저 순회 합니다.//그 외의 경우 -> LOSE 입니다.else{ret=2;for(i=0;i<9;i++){if((S/POW3[i])%10==0){temp=canWin(nexp(P),S+P*POW3[i]);if(temp==2){ret=1;break;}if(temp==0){ret=0;}}}}}returnret;}intmain(void){intT,P;cin>>T;while(T--){V=input(P);memset(CACHE,-1,sizeof(int)*THREE_9);cout<<canWin(P,V)<<endl;}return0;}
다른 함수들의 간단한 오류는 확인하였고, 아마 canWin함수 부분에 오류가 있는 듯 합니다.
책과 다른 점이라고는,
1. 보드 대신 숫자를 전달하는 점,
2. 승무패를 min함수가 아닌 for문 순회로 찾는점.
뿐인데 자꾸 틀린 값을 내놓는 이유가 무었인가요?
답변 기다립니다.
canuyes
TICTACTOE문제
안녕하세요.
현재 TICTACTOE문제를 풀고 있습니다.
책을 보면서 문제를 풀고, 혼자 힘으로 풀어보고 있습니다.
책에 나와 있는 bijection 계산 부분이 맘에 들지 않아(?)
보드의 상태를 0~19682 범위의 숫자만을 전달하고, 풀어냅니다.
다른 함수들의 간단한 오류는 확인하였고, 아마 canWin함수 부분에 오류가 있는 듯 합니다.
책과 다른 점이라고는,
1. 보드 대신 숫자를 전달하는 점,
2. 승무패를 min함수가 아닌 for문 순회로 찾는점.
뿐인데 자꾸 틀린 값을 내놓는 이유가 무었인가요?
답변 기다립니다.
11년 전