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 }