Вы находитесь на странице: 1из 7

GoMoku.java 1 import java.awt.*; 2 import java.awt.event.*; 3 import java.applet.

*; 4 5 public class GoMoku extends Applet { 6 7 /* The main applet class only lays out the applet. The work of 8 the game is all done in the GoMokuCanvas object. Note that 9 the Buttons and Label used in the applet are defined as 10 instance variables in the GoMokuCanvas class. The applet 11 class gives them their visual appearance and sets their 12 size and positions.*/ 13 14 public void init() { 15 16 setLayout(null); // I will do the layout myself. 17 18 setBackground(new Color(0,150,0)); // Dark green background. 19 20 /* Create the components and add them to the applet. */ 21 22 GoMokuCanvas board = new GoMokuCanvas(); 23 // Note: The constructor creates the buttons board.resignButton 24 // and board.newGameButton and the Label board.message. 25 add(board); 26 27 board.newGameButton.setBackground(Color.lightGray) ; 28 add(board.newGameButton); 29 30 board.resignButton.setBackground(Color.lightGray); 31 add(board.resignButton); 32 33 board.message.setForeground(Color.green); 34 board.message.setFont(new Font("Serif", Font.BOLD, 14)); 35 add(board.message); 36 37 /* Set the position and size of each component by calling 38 its setBounds() method. */ 39 40 board.setBounds(16,16,172,172); // Note: size MUST be 172-by-172 ! 41 board.newGameButton.setBounds(210, 60, 100, 30); 42 board.resignButton.setBounds(210, 120, 100, 30); 43 board.message.setBounds(0, 200, 330, 30); 44 } 45 46 } // end class GoMoku 47 48 49 50 51 class GoMokuCanvas extends Canvas implements ActionListener, MouseListener { 52 53 Button resignButton; // Current player can resign by clicking this button. 54 Button newGameButton; // This button starts a new game. It is enabled only 55 // when the current game has ended. 56 57 Label message; // A label for displaying messages to the user. Page 1

GoMoku.java 58 59 int[][] board; // The data for the board is kept here. The values 60 // in this array are chosen from the following constants. 61 62 static final int EMPTY = 0, // Represents an empty square. 63 WHITE = 1, // A white piece. 64 BLACK = 2; // A black piece. 65 66 boolean gameInProgress; // Is a game currently in progress? 67 68 int currentPlayer; // Whose turn is it now? The possible values 69 // are WHITE and BLACK. (This is valid only while 70 // a game is in progress.) 71 72 int win_r1, win_c1, win_r2, win_c2; // When a player wins by getting five or more 73 // pieces in a row, the squares at the 74 // ends of the row are (win_r1,win_c1) 75 // and (win_r2,win_c2). A red line is 76 // drawn between these squares. When there 77 // are no five pieces in a row, the value of 78 // win_r1 is -1. The values are set in the 79 // count() method. The value of win_r1 is 80 // tested in the paint() method. 81 82 83 public GoMokuCanvas() { 84 // Constructor. Create the buttons and label. Listen for mouse 85 // clicks and for clicks on the buttons. Create the board and 86 // start the first game. 87 setBackground(Color.lightGray); 88 addMouseListener(this); 89 setFont(new Font("Serif", Font.BOLD, 14)); 90 resignButton = new Button("Resign"); 91 resignButton.addActionListener(this); 92 newGameButton = new Button("New Game"); 93 newGameButton.addActionListener(this); 94 message = new Label("",Label.CENTER); 95 board = new int[13][13]; 96 doNewGame(); 97 } 98 99 100 public void actionPerformed(ActionEvent evt) { 101 // Respond to user's click on one of the two buttons. 102 Object src = evt.getSource(); 103 if (src == newGameButton) 104 doNewGame(); 105 else if (src == resignButton) 106 doResign(); 107 } 108 109 110 void doNewGame() { 111 // Begin a new game. 112 if (gameInProgress == true) { 113 // This should not be possible, but it doesn't 114 // hurt to check. Page 2

GoMoku.java 115 message.setText("Finish the current game first!"); 116 return; 117 } 118 for (int row = 0; row < 13; row++) // Fill the board with EMPTYs 119 for (int col = 0; col < 13; col++) 120 board[row][col] = EMPTY; 121 currentPlayer = BLACK; // BLACK moves first. 122 message.setText("BLACK: Make your move."); 123 gameInProgress = true; 124 newGameButton.setEnabled(false); 125 resignButton.setEnabled(true); 126 win_r1 = -1; // This value indicates that no red line is to be drawn. 127 repaint(); 128 } 129 130 131 void doResign() { 132 // Current player resigns. Game ends. Opponent wins. 133 if (gameInProgress == false) { 134 // This should not be possible. 135 message.setText("There is no game in progress!"); 136 return; 137 } 138 if (currentPlayer == WHITE) 139 message.setText("WHITE resigns. BLACK wins."); 140 else 141 message.setText("BLACK resigns. WHITE wins."); 142 newGameButton.setEnabled(true); 143 resignButton.setEnabled(false); 144 gameInProgress = false; 145 } 146 147 148 void gameOver(String str) { 149 // The game ends. The parameter, str, is displayed as a message. 150 message.setText(str); 151 newGameButton.setEnabled(true); 152 resignButton.setEnabled(false); 153 gameInProgress = false; 154 } 155 156 157 void doClickSquare(int row, int col) { 158 // This is called by mousePressed() when a player clicks on the 159 // square in the specified row and col. It has already been checked 160 // that a game is, in fact, in progress. 161 162 /* Check that the user clicked an empty square. If not, show an 163 error message and exit. */ 164 165 if ( board[row][col] != EMPTY ) { 166 if (currentPlayer == BLACK) 167 message.setText("BLACK: Please click an empty square."); 168 else 169 message.setText("WHITE: Please click an empty square."); 170 return; 171 } Page 3

GoMoku.java 172 173 /* Make the move. Check if the board is full or if the move 174 is a winning move. If so, the game ends. If not, then it's 175 the other user's turn. */ 176 177 board[row][col] = currentPlayer; // Make the move. 178 Graphics g = getGraphics(); 179 drawPiece(g, currentPlayer, row, col); 180 g.dispose(); 181 182 if (winner(row,col)) { // First, check for a winner. 183 if (currentPlayer == WHITE) 184 gameOver("WHITE wins the game!"); 185 else 186 gameOver("BLACK wins the game!"); 187 Graphics w = getGraphics(); 188 drawWinLine(w); 189 w.dispose(); 190 return; 191 } 192 193 boolean emptySpace = false; // Check if the board is full. 194 for (int i = 0; i < 13; i++) 195 for (int j = 0; j < 13; j++) 196 if (board[i][j] == EMPTY) 197 emptySpace = true; 198 if (emptySpace == false) { 199 gameOver("The game ends in a draw."); 200 return; 201 } 202 203 /* Continue the game. It's the other player's turn. */ 204 205 if (currentPlayer == BLACK) { 206 currentPlayer = WHITE; 207 message.setText("WHITE: Make your move."); 208 } 209 else { 210 currentPlayer = BLACK; 211 message.setText("BLACK: Make your move."); 212 } 213 214 } // end doClickSquare() 215 216 217 private boolean winner(int row, int col) { 218 // This is called just after a piece has been played on the 219 // square in the specified row and column. It determines 220 // whether that was a winning move by counting the number 221 // of squares in a line in each of the four possible 222 // directions from (row,col). If there are 5 squares (or more) 223 // in a row in any direction, then the game is won. 224 225 if (count( board[row][col], row, col, 1, 0 ) >= 5) 226 return true; 227 if (count( board[row][col], row, col, 0, 1 ) >= 5) 228 return true; Page 4

GoMoku.java 229 if (count( board[row][col], row, col, 1, -1 ) >= 5) 230 return true; 231 if (count( board[row][col], row, col, 1, 1 ) >= 5) 232 return true; 233 234 /* When we get to this point, we know that the game is not 235 won. The value of win_r1, which was changed in the count() 236 method, has to be reset to -1, to avoid drawing a red line 237 on the board. */ 238 239 win_r1 = -1; 240 return false; 241 242 } // end winner() 243 244 245 private int count(int player, int row, int col, int dirX, int dirY) { 246 // Counts the number of the specified player's pieces starting at 247 // square (row,col) and extending along the direction specified by 248 // (dirX,dirY). It is assumed that the player has a piece at 249 // (row,col). This method looks at the squares (row + dirX, col+dirY), 250 // (row + 2*dirX, col + 2*dirY), ... until it hits a square that is 251 // off the board or is not occupied by one of the players pieces. 252 // It counts the squares that are occupied by the player's pieces. 253 // Furthermore, it sets (win_r1,win_c1) to mark last position where 254 // it saw one of the player's pieces. Then, it looks in the 255 // opposite direction, at squares (row - dirX, col-dirY), 256 // (row - 2*dirX, col - 2*dirY), ... and does the same thing. 257 // Except, this time it sets (win_r2,win_c2) to mark the last piece. 258 // Note: The values of dirX and dirY must be 0, 1, or -1. At least 259 // one of them must be non-zero. 260 261 int ct = 1; // Number of pieces in a row belonging to the player. 262 263 int r, c; // A row and column to be examined 264 265 r = row + dirX; // Look at square in specified direction. 266 c = col + dirY; 267 while ( r >= 0 && r < 13 && c >= 0 && c < 13 && board[r][c] == player ) { 268 // Square is on the board and contains one of the players's pieces. 269 ct++; 270 r += dirX; // Go on to next square in this direction. 271 c += dirY; 272 } 273 274 win_r1 = r - dirX; // The next-to-last square looked at. 275 win_c1 = c - dirY; // (The LAST one looked at was off the board or 276 // did not contain one of the player's pieces. 277 278 r = row - dirX; // Look in the opposite direction. 279 c = col - dirY; 280 while ( r >= 0 && r < 13 && c >= 0 && c < 13 && board[r][c] == player ) { 281 // Square is on the board and contains one of the players's pieces. 282 ct++; 283 r -= dirX; // Go on to next square in this direction. 284 c -= dirY; 285 } Page 5

GoMoku.java 286 287 win_r2 = r + dirX; 288 win_c2 = c + dirY; 289 290 // At this point, (win_r1,win_c1) and (win_r2,win_c2) mark the endpoints 291 // of the line of pieces belonging to the player. 292 293 return ct; 294 295 } // end count() 296 297 298 public void paint(Graphics g) { 299 300 /* Draw a two-pixel black border around the edges of the canvas, 301 and draw grid lines in darkGray. */ 302 303 g.setColor(Color.darkGray); 304 for (int i = 1; i < 13; i++) { 305 g.drawLine(1 + 13*i, 0, 1 + 13*i, getSize().height); 306 g.drawLine(0, 1 + 13*i, getSize().width, 1 + 13*i); 307 } 308 g.setColor(Color.black); 309 g.drawRect(0,0,getSize().width-1,getSize().height-1); 310 g.drawRect(1,1,getSize().width-3,getSize().height-3); 311 312 /* Draw the pieces that are on the board. */ 313 314 for (int row = 0; row < 13; row++) 315 for (int col = 0; col < 13; col++) 316 if (board[row][col] != EMPTY) 317 drawPiece(g, board[row][col], row, col); 318 319 /* If the game has been won, then win_r1 >= 0. Draw a line to mark 320 the five winning pieces. */ 321 322 if (win_r1 >= 0) 323 drawWinLine(g); 324 325 } // end paint() 326 327 328 private void drawPiece(Graphics g, int piece, int row, int col) { 329 // Draw a piece in the square at (row,col). The color is specified 330 // by the piece parameter, which should be either BLACK or WHITE. 331 if (piece == WHITE) 332 g.setColor(Color.white); 333 else 334 g.setColor(Color.black); 335 g.fillOval(3 + 13*col, 3 + 13*row, 10, 10); 336 } 337 338 339 private void drawWinLine(Graphics g) { 340 // Draw a 2-pixel wide red line from the middle of the square at 341 // (win_r1,win_c1) to the middle of the square at (win_r2,win_c2). 342 // This routine is called to mark the 5 pieces that won the game. Page 6

GoMoku.java 343 // The values of the variables are set in the count() method. 344 g.setColor(Color.red); 345 g.drawLine( 8 + 13*win_c1, 8 + 13*win_r1, 8 + 13*win_c2, 8 + 13*win_r2 ); 346 if (win_r1 == win_r2) 347 g.drawLine( 8 + 13*win_c1, 7 + 13*win_r1, 8 + 13*win_c2, 7 + 13*win_r2 ); 348 else 349 g.drawLine( 7 + 13*win_c1, 8 + 13*win_r1, 7 + 13*win_c2, 8 + 13*win_r2 ); 350 } 351 352 353 public Dimension getPreferredSize() { 354 // Specify desired size for this component. Note: 355 // the size MUST be 172 by 172. 356 return new Dimension(172, 172); 357 } 358 359 360 public Dimension getMinimumSize() { 361 return new Dimension(172, 172); 362 } 363 364 365 public void mousePressed(MouseEvent evt) { 366 // Respond to a user click on the board. If no game is 367 // in progress, show an error message. Otherwise, find 368 // the row and column that the user clicked and call 369 // doClickSquare() to handle it. 370 if (gameInProgress == false) 371 message.setText("Click \"New Game\" to start a new game."); 372 else { 373 int col = (evt.getX() - 2) / 13; 374 int row = (evt.getY() - 2) / 13; 375 if (col >= 0 && col < 13 && row >= 0 && row < 13) 376 doClickSquare(row,col); 377 } 378 } 379 380 381 public void mouseReleased(MouseEvent evt) { } 382 public void mouseClicked(MouseEvent evt) { } 383 public void mouseEntered(MouseEvent evt) { } 384 public void mouseExited(MouseEvent evt) { } 385 386 387 }

Page 7

Вам также может понравиться