classes/FaceGame.java



import FaceBoard;
import BoardCell;
import awt.Graphics;
import awt.Color;
import awt.Image;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.StringTokenizer;

/**
  顔ゲーム FaceGame クラス
 */
class FaceGame extends FaceBoard {

     public int removedNum=0;
     public boolean undoFlag=false;
     protected int old_score;
     protected int old_i=-1, old_j=-1;
     protected FaceCell removableCell=null;  // 少なくとも1つはある消せるセル
     protected boolean showHighScoreFlag=false;

     protected String highScoreFile=null;
     public FileInputStream inputScore;
     public FileOutputStream outputScore;

    /**
     初期設定の関数。アプレットのサイズを設定。
     */
       protected void init() {

             super.init();    // 親のクラスで定義された処理

             old_score = score;

             highScoreFile = getAttribute("highscorefile");
             if( highScoreFile == null )
                 highScoreFile = "/home/net/staff/tatsuo/www/kouki95/11shuu/score";
       }

    /** 
     アプレットの表示(初期状態)を行う関数。
     */
       public void paint( Graphics g ) {

            super.paint( g );         // 親のクラスで定義された処理
       }

    /** 
     アプレットの再表示を行う関数。
    */
       public void update( Graphics g ) {

             for( int i=0; i<iMax; i++ )
               for( int j=0; j<jMax; j++ ){
                  if( paint_table[i][j] == true )
                     if( state[i][j] != 0 )
                         cell[i][j].paint( g );
                     else
                         cell[i][j].clear( g );
             }

            if( score != old_score  || undoFlag == false )
                drawScore( g );

            drawFrame( g );

            if( showHighScoreFlag )
                drawHighScore( g );
       }

    /** 
     アプレットの周囲の枠を表示する関数。
    */
       public void drawFrame( Graphics g ) {

             g.setForeground( Color.black );

             for( int i=0; i<iMax; i++ )
               for( int j=0; j<jMax; j++ ){
                  if( paint_frame_table[i][j] == true ) {

                      if( state[i][j] != 0 )
                          cell[i][j].paintFrame( g );
                  }
             }

       }

    /** 
     ファイルから一行読み込む関数。
    */
       public int getLine( char buf[] ) {

             for( int i=0; i<52; i++ ) {

                 buf[i] = (char)inputScore.read();
             }

             return 51;
       }

    /** 
     ファイルに一行書き出す関数。
    */
       public void putLine( String str ) {

             for( int i=0; i<str.length(); i++ ) {

                outputScore.write( (int)( str.charAt(i) ) );
             }
                outputScore.write( (int)'\n' );
       }

    /** 
     ハイスコアのウィンドウを表示する関数。
    */
       public void drawHighScore( Graphics g ) {

             char buf[][];
             int  length;
             String  lines[];
             String  fields1[];
             String  fields2[];
             String  fields3[];
             String  words[];
             Integer si[];
             int scores[];

             buf = new char[10][80];
             lines = new String[10];
             fields1 = new String[10];
             fields2 = new String[10];
             fields3 = new String[10];
             words = new String[10];
             si = new Integer[10];
             scores = new int[10];

             boolean insertFlag=true;
             String newscore=null;

             inputScore = new FileInputStream( highScoreFile );

             for( int j=0; j<10; j++ ){

                 g.setForeground( Color.white );
                 g.paint3DRect( (width-420)/2, (height-200)/2 + j*20,
                                420, 20, true, false );

                 length = getLine( buf[j] );
                 lines[j] = new String( buf[j], 0, length );

                 g.setForeground( Color.black );
                 g.drawString( lines[j],
                               (width-420)/2 + 4,
                               (height-200)/2 + j*20 + 17 );
             }
             inputScore.close();
             inputScore = null;

             for( int j=0; j<10; j++ ){

                 fields1[j] = lines[j].substring( 0, 2 );
                 fields2[j] = lines[j].substring( 3, 44 );
                 fields3[j] = lines[j].substring(46);

                 for( int i=0; i<5; i++ ){
                    if( fields3[j].charAt(i) != ' '){
                        words[j] = fields3[j].substring( i );
                        break;
                    }
                 }

                 si[j] = new Integer( words[j] );
                 scores[j] = si[j].intValue();
             }

             if( score <= scores[9] ) return;

             outputScore = new FileOutputStream( highScoreFile );

             newscore = "     " + score;
             
             for( int j=0; j<10; j++ ){

                 g.setForeground( Color.white );
                 g.paint3DRect( (width-420)/2, (height-200)/2 + j*20,
                                420, 20, true, false );
                 g.setForeground( Color.black );
                 
                 if( score < scores[j] ){
                     putLine( lines[j] );
                     g.drawString( lines[j],
                               (width-420)/2 + 4,
                               (height-200)/2 + j*20 + 17 );
                 }
                 else if( insertFlag ){
                     putLine( fields1[j] + ":" + fields2[j] + ": " +
                       newscore.substring( newscore.length()-5,
                                           newscore.length() ) );
                     g.drawString(
                           fields1[j] + ":" + fields2[j] + ": " +
                           newscore.substring( newscore.length()-5,
                           newscore.length() ),
                               (width-420)/2 + 4,
                               (height-200)/2 + j*20 + 17 );
                     insertFlag = false;
                 }
                 else {
                     putLine( fields1[j] + ":" + fields2[j-1] + ": " + fields3[j-1]);
                     g.drawString(
                               fields1[j] + ":" + fields2[j-1] 
                               + ": " + fields3[j-1],
                               (width-420)/2 + 4,
                               (height-200)/2 + j*20 + 17 );
                 }
             }
             outputScore.close();
             outputScore = null;
       }

    /**
     セルの状態変化を調べる
     */
       protected void checkCell( int i, int j,
                                 int given_state, boolean given_table[][] ) {
 
        //   if( i<0 || i>=iMax || j<0 || j>=jMax ) return;
        //   if( given_table[i][j] == 0 ) return;
             if( state[i][j] == 0 ) return;
             if( state[i][j] != given_state ) return;
             else {
                    given_table[i][j] = true;

                    if( (i-1) >= 0 && given_table[i-1][j] == false ) {
                        checkCell( i-1, j, given_state, given_table );
                    }
                    if( (i+1) < iMax && given_table[i+1][j] == false ) {
                        checkCell( i+1, j, given_state, given_table );
                    }
                    if( (j-1) >= 0 && given_table[i][j-1] == false ) {
                        checkCell( i, j-1, given_state, given_table );
                    }
                    if( (j+1) < jMax && given_table[i][j+1] == false ) {
                        checkCell( i, j+1, given_state, given_table );
                    }
             }
       }

    /**
     セルの状態を再設定する
     */
       protected void resetCells() {
 
             for( int i=0; i<iMax; i++ )
               for( int j=0; j<jMax; j++ ) {
                   cell[i][j].setState( state[i][j] );
               }
       }

    /**
     セルの消去を実行する
     */
       protected void removeCells() {

             removedNum=0;
 
             for( int i=0; i<iMax; i++ ) {
               for( int j=0; j<jMax; j++ ) {
                   if( remove_table[i][j] == true ) {
                     state[i][j] = 0;
                     paint_table[i][j] = true;
                     removedNum++;
                   }
                   else
                     paint_table[i][j] = false;
                }
             }

             addScore();
             resetCells();
       }

    /**
     イメージの落下と左寄せを実行する
     */
       protected void fallDownCells() {

             boolean flag;

             for( int i=0; i<iMax; i++ ) {
               if( state[i][0] == 0 ) {
                   paint_table[i][0] = true;
               }
               for( int j=1; j<jMax; j++ ) {
                   if( state[i][j] == 0 ) {
                      for( int k=j; k>0; k-- ) {
                         state[i][k] = state[i][k-1];
                         paint_table[i][k] = true;
                         paint_table[i][k-1] = true;
                      }
                      state[i][0]=0;
                      paint_table[i][0] = true;
                   }
                }
             }

             for( int i=iMax-2; i>=0; i-- ) {
                 flag = true;
                 for( int j=0; j<jMax; j++ ) {
                    if( state[i][j] != 0 ) flag = false;
                 }
                 if( flag ) {
                    for( int m=i; m<iMax-1; m++ )
                      for( int k=0; k<jMax; k++ ){
                         state[m][k]=state[m+1][k];
                         paint_table[m][k] = true;
                         paint_table[m+1][k] = true;
                    }
                    for( int k=0; k<jMax; k++ ){
                         state[iMax-1][k]=0;
                         paint_table[iMax-1][k] = true;
                    }
                 }
             }

             resetCells();
       }

    /**
     マウスがクリックされた時の処理
     */
       public void mouseDown( int x, int y ) {

             if( x>wborder && x<width-wborder
              && y>hborder+mergin && y<height-hborder-mergin ) {

                int i = ( x - wborder )/cell[0][0].width;
                int j = ( y - hborder - mergin )/cell[0][0].height;

                if( state[i][j] == 0 ) return;

                if( isRemovable( i, j ) ) {

                    copyTable( state, old_state );
                    undoFlag = false;

                    clearTable( remove_table );
                    checkCell( i, j, state[i][j], remove_table );
                    removeCells();
                    clearTable( check_table );
                    //repaint();
                    fallDownCells();
                    undoFlag = true;
                    if ( isGameOver() ) {
                       undoFlag = false;
                       showHighScoreFlag = true;
                    }
                    repaint();
                }
                else  return;
             }
             // NewGameボタン
             else if( x>button_x0 && x<button_x0+button_width
                   && y>button_y0 && y<button_y0+button_height ) {

                showHighScoreFlag = false;
                setTable( paint_table );
                clearTable( remove_table );
                clearTable( check_table );
                initTable();
                resetCells();
                score = -(totalCellNum);
                copyTable( state, old_state );
                undoFlag = false;
                repaint();
             }
             // Undoボタン
             else if( x>button_x0 + button_width + button_x_mergin
                   && x<button_x0 + button_width*2 + button_x_mergin
                   && y>button_y0 && y<button_y0+button_height ) {

                if( undoFlag ) {
                    setTable( paint_table );
                    clearTable( remove_table );
                    clearTable( check_table );
                    copyTable( old_state, state );
                    score = old_score;
                    resetCells();
                    undoFlag = false;
                    repaint();
                }
            }
       }

    /**
      スコアの計算
    */
       protected void addScore() {

             old_score = score;
             score += (removedNum-1)*(removedNum-1);
       }

    /**
     マウス・カーソルが移動した時の処理
     */
       public void mouseMove( int x, int y ) {

             if( x>wborder && x<width-wborder
              && y>hborder+mergin && y<height-hborder-mergin ) {

                int i = ( x - wborder )/cell[0][0].width;
                int j = ( y - hborder - mergin )/cell[0][0].height;

                if( state[i][j] == 0 ) return;

                if( i == old_i && j == old_j ) return;

                if( isRemovable( i, j ) ) {

                    copyTable( check_table, paint_frame_table );
                    clearTable( check_table );
                    checkCell( i, j, state[i][j], check_table );
                    orTable( check_table, paint_frame_table );
                    clearTable( paint_table );
                    repaint();
                }

              old_i=i; old_j=j;
             }
       }

    /**
     4方をチェックしてセルが消去可能かチェックする処理
     */
       public boolean isRemovable( int i, int j ) {

                boolean flag=false;

                if( state[i][j] == 0 ) return false;

                if( (i-1) >= 0 ) 
                    flag = flag || ( state[i-1][j] == state[i][j] );
                if( (i+1) <iMax ) 
                    flag = flag || ( state[i+1][j] == state[i][j] );
                if( (j-1) >= 0 ) 
                    flag = flag || ( state[i][j-1] == state[i][j] );
                if( (j+1) <jMax ) 
                    flag = flag || ( state[i][j+1] == state[i][j] );

                return flag;
       }

    /**
     ゲームが終了したか判定する処理
     */
       public boolean isGameOver() {

                int m=0,n=0;
                boolean flag=false;

                if( removableCell != null ) {
                    if( isRemovable( removableCell.i, removableCell.j ) )
                         return false;
                }

                for( int i=0; i<iMax; i++ ) {
                   for( int j=jMax-1; j>=0; j-- ) {
                      if( state[i][j]==0 ) continue;
                      if( isRemovable( i, j ) ) {
                         m=i; n=j;
                         flag = true;
                         break;
                      }
                   }
                   if( flag ) break;
                }

               if( flag ){
                  if( removableCell != null ){
                      removableCell.i=m;  removableCell.j=n;
                  }
                  else{
                      removableCell = new FaceCell( this, m, n,
                                           cell[0][0].width, cell[0][0].height,
                                           0 );
                  }
            }
            return (!flag);
       }
}