- マップ
オセロのボードには、升目が64個有るので、char型配列 char MAP[8][8]を用意しておく.配列の第一引数は、ボードの横方向を示し、第2引数は縦方向とする.これが採る値は、白:1,黒:−1,及び無し:0のみとする.また、ポイント(打石)可能な場所を示すマップを一面用意する.char PMAP[8][8],これについては、石の色に関わらず、CHAR型8ビット中,石を返せる方向のビットを立てる,即ち、置けない場所は0となる.
(Jan.9/2001)
- 打石可能位置の検出
打石が可能な位置は、下記条件を満足した場所である,
- 打石しようとする位置の隣に、違う色の石が有る.
- n個の違う色の石を挟んで、同じ色の石が有る.
従って、以下の様なアルゴリズムで考える,
int thru_view(int x,int y,int dx,int dy,int c)
{
int i,f ;
f=0 ;
x+=dx ; y+=dy ;
if(x>7 || x<0 || y>7 || y<0) return(0) ;
if(MAP[x][y]==0 || MAP[x][y]==c) return(0) ;
for(i=1 ; i<7 ; i++){
x+=dx ; y+=dy ;
if(x>7 || x<0 || y>7 || y<0) break ;
if(MAP[x][y]==0) break ;
if(MAP[x][y]==c){
f=1 ; break ;
}
}
return(f) ;
}
int is_pointable(int x,int y,int c)
{
int retx ;
retx=0 ;
if(c!=1 && c!=-1) return(0) ;
if(MAP[x][y]) return(0) ;
if(thru_view(x,y,1,1,c)) retx|=0x80 ;
if(thru_view(x,y,1,0,c)) retx|=0x40 ;
if(thru_view(x,y,1,-1,c)) retx|=0x20 ;
if(thru_view(x,y,0,-1,c)) retx|=0x10 ;
if(thru_view(x,y,-1,-1,c)) retx|=0x08 ;
if(thru_view(x,y,-1,1,c)) retx|=0x04 ;
if(thru_view(x,y,-1,0,c)) retx|=0x02 ;
if(thru_view(x,y,0,1,c)) retx|=0x01 ;
return(retx) ;
}
int make_pointable_map(int col)
{
int i,j,f=0 ;
for(i=0 ; i<8 ; i++){
for(j=0 ; j<8 ; j++){
PMAP[i][j]=is_pointable(i,j,col) ;
if(PMAP[i][j]) f++ ;
}
}
return(f) ;
}
|
関数thru_view()は、ボード上の位置(x、y)から、dx,dyの示す方向に向かって、石の色cに関して、上記条件を満たすか否かを検討し、満たしていれば1を返す関数である.
関数is_pointable()は、ボード上の位置(x、y)から8方向thru_view()を実行し、石の色cが、打石可能/不可能かを判断する.また、石を返せる方向をCHAR型8ビットのビットを立てて返す関数である.
関数make_pointable_map()は、is_pointable()をボード上全てに実行し、石の色colの打石可能位置及び石を返せる方向をPMAP[8][8]に格納する関数である.尚、この関数は、打石可能な位置の数を返す.
従って、ユーザは、make_pointable_map(今から打石しようとする石の色) ;をコールすれば、ボード上の打石可能位置を、PMAP[][]より知る事が出来,同関数の戻り値より、打石可能/不可能を知る事が出来る.
(Jan.9/2001)
- 石をひっくり返す
打石位置が確定した時点で、石をひっくり返すといった操作が必要になる.これについては、上記で、打石可能位置を検出した時点で、ひっくり返せる方向を格納しているので、以下の様に行う,
int reverse(int x,int y,int dx,int dy,int c)
{
int i,f,co ;
f=0 ;
x+=dx ; y+=dy ;
if(x>7 || x<0 || y>7 || y<0) return(0) ;
if(MAP[x][y]==0) return(0) ;
if(MAP[x][y]==c) return(0) ;
MAP[x][y]=c ; f++ ;
for(i=1 ; i<7 ; i++){
x+=dx ; y+=dy ;
if(x>7 || x<0 || y>7 || y<0) break ;
if(MAP[x][y]==0) break ;
if(MAP[x][y]==c) break ;
MAP[x][y]=c ; f++ ;
}
return(f) ;
}
int point(int x,int y,int c)
{
int px,rx=0 ;
px=PMAP[x][y] ;
if(!px) return(0) ;
if(c!=1 && c!=-1) return(0) ;
if(MAP[x][y]) return(0) ;
MAP[x][y]=c ; rx++ ;
if(px&0x80) rx+=reverse(x,y,1,1,c) ;
if(px&0x40) rx+=reverse(x,y,1,0,c) ;
if(px&0x20) rx+=reverse(x,y,1,-1,c) ;
if(px&0x10) rx+=reverse(x,y,0,-1,c) ;
if(px&0x08) rx+=reverse(x,y,-1,-1,c) ;
if(px&0x04) rx+=reverse(x,y,-1,1,c) ;
if(px&0x02) rx+=reverse(x,y,-1,0,c) ;
if(px&0x01) rx+=reverse(x,y,0,1,c) ;
return(rx) ;
}
|
関数reverse()は、ボード上の位置(x、y)から、dx,dyの示す方向に向かって、石をひっくり返していく関数で、ひっくり返した石の数を返す.
関数point()は、先に検出した、ひっくり返せる方向に向かって、reverse()を呼び、石をひっくり返す.また、ひっくり返した全ての石の数を返す.
(Jan.9/2001)
(修正)point()で、自分の置いた場所を忘れていたので修正(Jan.11/2001)
|