import java.io.*; import java.util.*; // 手とその評価値を表す抽象クラス abstract class Move { // 評価値は doubleで表す double value; // 評価値の getter double getValue(){ return value; } // 評価値の setter void setValue(double value){ this.value=value; } } // 動かした盤面を元に戻せるように記憶 abstract class TrailStack{ } // 盤面の状態を表す abstract class State{ // 次の可能手の MoveのVectorを返す abstract Vector nextMoves(); // 手にしたがって盤面を変化させる. // TrailStackを返す abstract TrailStack doMove(Move move); // TrailStackに従って盤面を戻す abstract void undoMove(TrailStack trail); // 盤面の評価値 abstract double eval(); } // 次の手を決めるアルゴリズム abstract class Search { // 次の手を返す abstract Move bestMove(State state); } // Depth1Search // 可能手を全部生成して,その盤面の評価値で最良のものを選択する // class Depth1Search extends Search { // return null if there exists no moves Move bestMove(State state){ // 可能な手を全部生成する Vector moves=state.nextMoves(); int size=moves.size(); // 最良の手が複数あるのでそれを管理する Vector bestMoves=new Vector(); Move best=null; // 最良の手の値を負の無限大に設定しておく double bestVal=Double.NEGATIVE_INFINITY; for(int i=0;i0){ int selected=(int)(Math.random()*bestSize); return (Move)bestMoves.elementAt(selected); } else return null; } } class OthelloMove extends Move{ int position; OthelloMove(int position,double value){ this.position=position; this.value=value; } OthelloMove(int position){ this(position,0.0); } int getPosition(){ return position; } int getX(){ return position%10; } int getY(){ return position/10; } } class OthelloTrail extends TrailStack{ int position; Vector reverses=new Vector(); OthelloTrail(int position){ this.position=position; } void add(int position){ reverses.addElement(new Integer(position)); } int getPosition(){ return position; } int size(){ return reverses.size(); } int get(int index){ return ((Integer)(reverses.get(index))).intValue(); } } class OthelloState extends State{ static final int Black=1; static final int White=-1; static final int Empty=0; // 盤外かどうかのチェックをさぼるためには以下のチェックが有効 static final int Edge=2; int board[]=new int[10*10]; int turn; // 初期状態のオセロ盤を作る OthelloState(){ int color; for(int x=0;x<10;x++) for(int y=0;y<10;y++){ if(x==0 || x==9 || y==0 || y==9) color=Edge; else if((x==4 && y==4)||(x==5 && y==5)) color=White; else if((x==4 && y==5)||(x==5 && y==4)) color=Black; else color=Empty; board[y*10+x]=color; } turn=Black; } static final int directions[]={-11,-10,-9,-1,1,9,10,11}; int opponent(int turn){ return -turn; } boolean checkDir(int position,int dir){ // System.out.println("checkDir("+position+","+dir+")"); int oturn=opponent(turn),piece; if(board[position+dir]!=oturn) return false; for(position+=dir*2;(piece=board[position])==oturn;position+=dir){ // System.out.println("board["+position+"]="+piece); } // System.out.println("lastpiece="+piece+",turn="+turn); if(piece!=turn) return false; return true; } void reverseDir(int position,int dir,OthelloTrail trail){ int oturn=opponent(turn),piece; for(position+=dir;(piece=board[position])==oturn;position+=dir){ board[position]=turn; trail.add(position); } } boolean legalMove(int position){ if(board[position]!=Empty)return false; for(int dir=0;dir0) System.out.println("黒が"+result+"個勝ちました"); else if(result<0) System.out.println("白が"+(-result)+"個勝ちました"); else System.out.println("引き分けです"); System.exit(0); } void startGame(Search players[]) throws IOException { for(int player=0;;player=1-player){ game.showState(); if(game.canPass()){ game.doPass(); if(game.canPass()){ gameEnd(); } System.out.println("次に打てる手はないのでパスします"); } else{ int x,y; OthelloMove bestMove=(OthelloMove)players[player].bestMove(game); System.out.println("着手は "+ " abcdefgh".charAt(bestMove.getX())+ " 12345678".charAt(bestMove.getY())+"です."); System.out.println("評価値は "+bestMove.getValue()+"です."); game.doMove(bestMove); } } } // main関数 public static void main(String args[]) throws IOException{ Othello othello=new Othello(); BufferedReader d=new BufferedReader(new InputStreamReader(System.in)); Search players[]=new Search[2]; // players[0]=new HumanSearch(d); // players[0]=new Depth1Search(); players[0]=new MinMaxSearch(6); players[1]=new MinMaxSearch(6); othello.startGame(players); } }