Basic Technic

Basic Method
オセロの基本
ニューラルネット云々を組み込む前に、オセロにおける基本処理をまとめておく.ニューラルネットばかりが出来上がっても、基本の部分が出来てなければ、意味無いからね.
(Jan.9/2001)

  • マップ
    オセロのボードには、升目が64個有るので、char型配列 char MAP[8][8]を用意しておく.配列の第一引数は、ボードの横方向を示し、第2引数は縦方向とする.これが採る値は、白:1,黒:−1,及び無し:0のみとする.また、ポイント(打石)可能な場所を示すマップを一面用意する.char PMAP[8][8],これについては、石の色に関わらず、CHAR型8ビット中,石を返せる方向のビットを立てる,即ち、置けない場所は0となる.
    (Jan.9/2001)

  • 打石可能位置の検出
    打石が可能な位置は、下記条件を満足した場所である,

    1. 打石しようとする位置の隣に、違う色の石が有る.
    2. 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)


Since Nov.25/2000 last update Jan.9/2000,

Return