1 //用来存储一步的类 2 final class Best { 3 4 int row; 5 int column; 6 int val; 7 8 9 public Best(int v) 10 { 11 this(v,0,0); 12 } 13 public Best(int v,int r,int c) 14 { 15 val=v; 16 row=r; 17 column=c; 18 } 19 }
//position类 final class Position { private int [][]board; public Position (int [][] theBoard) { board=new int [3][3]; for(int i=0;i<3;i++) for(int j=0;j<3;j++) board[i][j]=theBoard[i][j]; } public boolean equals(Object rhs) { if(!(rhs instanceof Position)) return false; //Position other=(Position)hrs; for(int i=0;i<3;i++) for(int j=0;j<3;j++) if(board[i][j]!=((Position)rhs).board[i][j]) return false; return true; } public int hashCode() { int hashVal=0; for(int i=0;i<3;i++) for(int j=0;j<3;j++) hashVal=hashVal*4+board[i][j]; return hashVal; } }
1 import java.awt.Frame; 2 import java.awt.Panel; 3 import java.awt.Button; 4 import java.awt.GridLayout; 5 6 import java.awt.event.WindowAdapter; 7 import java.awt.event.ActionListener; 8 import java.awt.event.ActionEvent; 9 import java.awt.event.WindowEvent; 10 11 public class TicTacMain extends Frame 12 { 13 /** 14 * 15 */ 16 private static final long serialVersionUID = -1712977983195809884L; 17 18 public TicTacMain( ) 19 { 20 add( new TicTacPanel( ) ); 21 22 addWindowListener( new WindowAdapter( ) 23 { 24 public void windowClosing( WindowEvent event ) 25 { 26 System.exit( 0 ); 27 } 28 } ); 29 } 30 31 32 public static void main( String [ ] args ) 33 { 34 Frame f = new TicTacMain( ); 35 f.pack( ); 36 f.setVisible( true ); 37 } 38 39 private static class TicTacPanel extends Panel implements ActionListener 40 { 41 public TicTacPanel( ) 42 { 43 setLayout( new GridLayout( 3, 3 ) ); 44 for( int i = 0; i < 3; i++ ) 45 for( int j = 0; j < 3; j++ ) 46 { 47 squares[ i ][ j ] = new Button( ); 48 add( squares[ i ][ j ] ); 49 squares[ i ][ j ].addActionListener( this ); 50 } 51 52 53 resetBoard( ); 54 } 55 56 public void resetBoard( ) 57 { 58 t = new TicTacToe( ); 59 for( int i = 0; i < 3; i++ ) 60 for( int j = 0; j < 3; j++ ) 61 { 62 squares[ i ][ j ].setLabel( "" ); 63 squares[ i ][ j ].setEnabled( true ); 64 } 65 } 66 67 private int gameNum = 0; 68 69 public void doCompMove( boolean thinkAboutIt ) 70 { 71 Best compMove; 72 73 if( thinkAboutIt ) 74 compMove = t.chooseMove( TicTacToe.COMPUTER ); 75 else 76 { 77 compMove = new Best( 0, gameNum % 3, gameNum / 3 ); 78 gameNum = ( gameNum + 1 ) % 9; 79 } 80 81 System.out.println( " ROW = " + compMove.row + 82 " COL = " + compMove.column ); 83 84 squares[ compMove.row ][ compMove.column ].setLabel( computerSide ); 85 squares[ compMove.row ][ compMove.column ].setEnabled( false ); 86 t.playMove( TicTacToe.COMPUTER, compMove.row, compMove.column ); 87 } 88 89 public boolean resetIfDone( boolean condition, String message, boolean compMoves ) 90 { 91 if( condition ) 92 { 93 System.out.println( message ); 94 System.out.println( "Restarting..." ); 95 resetBoard( ); 96 if( compMoves ) 97 { 98 System.out.println( "I go first..." ); 99 computerSide = "X"; 100 humanSide = "O"; 101 doCompMove( false ); 102 } 103 else 104 { 105 humanSide = "X"; 106 computerSide = "O"; 107 System.out.println( "You go first..." ); 108 } 109 } 110 return condition; 111 } 112 113 114 public void actionPerformed( ActionEvent evt ) 115 { 116 if( evt.getSource( ) instanceof Button ) 117 { 118 ( (Button)evt.getSource( ) ).setLabel( humanSide ); 119 ( (Button)evt.getSource( ) ).setEnabled( false ); 120 121 for( int i = 0; i < 3; i++ ) 122 for( int j = 0; j < 3; j++ ) 123 if( evt.getSource( ) == squares[ i ][ j ] ) 124 t.playMove( TicTacToe.HUMAN, i, j ); 125 126 if( resetIfDone( t.boardIsFull( ), "DRAW", true ) ) 127 return; 128 doCompMove( true ); 129 resetIfDone( t.isAWin( TicTacToe.COMPUTER ), "I WIN!!", true ); 130 resetIfDone( t.boardIsFull( ), "DRAW", false ); 131 132 return; 133 } 134 } 135 136 private Button [ ][ ] squares = new Button[ 3 ][ 3 ]; 137 private TicTacToe t; 138 private String computerSide = "O"; 139 private String humanSide = "X"; 140 } 141 }
1 package s2; 2 3 //结合了置换表和剪枝的TicTacToe类 4 import java.util.Map; 5 import java.util.HashMap; 6 //TicTacToe类的框架 7 class TicTacToe { 8 public static final int HUMAN=0; 9 public static final int COMPUTER=1; 10 public static final int EMPTY=2; 11 12 public static final int HUMAN_WIN=0; 13 public static final int DRAW=1; 14 public static final int UNCLEAR=2; 15 public static final int COMPUTER_WIN=3; 16 17 public TicTacToe() 18 { 19 clearBoard(); 20 21 } 22 23 24 private Map<Position,Integer>transpositions=new HashMap<Position,Integer>(); 25 public Best chooseMove(int size) 26 { 27 return chooseMove(size,HUMAN_WIN,COMPUTER_WIN,0); 28 } 29 //Find optional move 30 private Best chooseMove(int side,int alpha,int beta,int depth) 31 { 32 int opp; 33 Best reply; 34 35 int simpleEval; 36 Position thisPosition=new Position(board); 37 int tableDepth=5; 38 int bestRow=0; 39 int bestColumn=0; 40 int value; 41 42 43 44 45 if((simpleEval=positionValue())!=UNCLEAR) 46 return new Best(simpleEval); 47 if(depth==0) 48 transpositions.clear(); 49 else if(depth>3&&depth<=tableDepth) 50 { 51 Integer lookupVal=transpositions.get(thisPosition); 52 if(lookupVal!=null) 53 return new Best(lookupVal); 54 } 55 if(side==COMPUTER) 56 { 57 opp=HUMAN; 58 value=alpha; 59 } 60 else 61 { 62 opp=COMPUTER; 63 value=beta; 64 } 65 66 Outer: 67 for(int row =0;row<3;row++) 68 for(int column=0;column<3;column++) 69 if(squareIsEmpty(row,column)) 70 { 71 place(row,column,side); 72 reply=chooseMove(opp,alpha,beta,depth+1); 73 place(row,column,EMPTY); 74 if(side==COMPUTER&&reply.val>value||side==HUMAN&&reply.val<value) 75 { 76 if(side==COMPUTER) 77 alpha=value=reply.val; 78 else 79 beta=value=reply.val; 80 81 82 bestRow=row; 83 bestColumn=column; 84 if(alpha>=beta) 85 break Outer; //Refution 86 } 87 } 88 if(depth<=tableDepth) 89 transpositions.put(thisPosition,value); 90 return new Best(value,bestRow,bestColumn); 91 92 93 } 94 private int positionValue() /*估算位置的程序,根据棋盘上的情况返回HUMAN_WINDRAWCOMPUTER_WINUNCLEAR* 95 所使用的策略是最大最小值策略*/ 96 { 97 return isAWin(COMPUTER)?COMPUTER_WIN: 98 isAWin(HUMAN) ?HUMAN_WIN: 99 boardIsFull() ?DRAW :UNCLEAR; 100 101 } 102 public boolean playMove(int row,int column,int side) 103 { 104 if( row < 0 || row >= 3 || column < 0 || column >= 3||board[row][column]!=EMPTY) 105 return false; 106 board[ row ][ column ] = side; 107 return true; 108 } 109 public void clearBoard() 110 { 111 for( int i = 0; i < 3; i++ ) 112 for( int j = 0;j<3;j++) 113 board[i][j]=EMPTY; 114 } 115 public boolean boardIsFull() 116 { 117 for( int row = 0; row < 3; row++ ) 118 for( int column = 0; column < 3; column++ ) 119 if( board[ row ][ column ] == EMPTY ) 120 return false; 121 return true; 122 } 123 public boolean isAWin(int side) 124 { 125 int row, column; 126 127 /* Look for all in a row */ 128 for( row = 0; row < 3; row++ ) 129 { 130 for( column = 0; column < 3; column++ ) 131 if( board[ row ][ column ] != side ) 132 break; 133 if( column >= 3 ) 134 return true; 135 } 136 137 /* Look for all in a column */ 138 for( column = 0; column < 3; column++ ) 139 { 140 for( row = 0; row < 3; row++ ) 141 if( board[ row ][ column ] != side ) 142 break; 143 if( row >= 3 ) 144 return true; 145 } 146 147 /* Look on diagonals */ 148 if( board[ 1 ][ 1 ] == side && board[ 2 ][ 2 ] == side 149 && board[ 0 ][ 0 ] == side ) 150 return true; 151 152 if( board[ 0 ][ 2 ] == side && board[ 1 ][ 1 ] == side 153 && board[ 2 ][ 0 ] == side ) 154 return true; 155 156 return false; 157 } 158 private void place(int row,int column,int piece) 159 { 160 board[row][column]=piece; 161 //Test if a square is Empty 162 } 163 public boolean squareIsEmpty(int row,int column) 164 { 165 return board[row][column]==EMPTY; 166 167 } 168 private int [][]board=new int[3][3]; //创建一个网格 169 }