KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > TicTacToe


1 /*
2  * @(#)TicTacToe.java 1.12 06/02/22
3  *
4  * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * -Redistribution of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  *
12  * -Redistribution in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * Neither the name of Sun Microsystems, Inc. or the names of contributors may
17  * be used to endorse or promote products derived from this software without
18  * specific prior written permission.
19  *
20  * This software is provided "AS IS," without a warranty of any kind. ALL
21  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
22  * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23  * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
24  * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
25  * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
26  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
27  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
28  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
29  * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  *
32  * You acknowledge that this software is not designed, licensed or intended
33  * for use in the design, construction, operation or maintenance of any
34  * nuclear facility.
35  */

36
37 /*
38  * @(#)TicTacToe.java 1.12 06/02/22
39  */

40
41 import java.awt.*;
42 import java.awt.event.*;
43 import java.awt.image.*;
44 import java.net.*;
45 import java.applet.*;
46
47 /**
48  * A TicTacToe applet. A very simple, and mostly brain-dead
49  * implementation of your favorite game! <p>
50  *
51  * In this game a position is represented by a white and black
52  * bitmask. A bit is set if a position is ocupied. There are
53  * 9 squares so there are 1<<9 possible positions for each
54  * side. An array of 1<<9 booleans is created, it marks
55  * all the winning positions.
56  *
57  * @version 1.2, 13 Oct 1995
58  * @author Arthur van Hoff
59  * @modified 04/23/96 Jim Hagen : winning sounds
60  * @modified 02/10/98 Mike McCloskey : added destroy()
61  */

62 public
63 class TicTacToe extends Applet implements MouseListener {
64     /**
65      * White's current position. The computer is white.
66      */

67     int white;
68
69     /**
70      * Black's current position. The user is black.
71      */

72     int black;
73
74     /**
75      * The squares in order of importance...
76      */

77     final static int moves[] = {4, 0, 2, 6, 8, 1, 3, 5, 7};
78
79     /**
80      * The winning positions.
81      */

82     static boolean won[] = new boolean[1 << 9];
83     static final int DONE = (1 << 9) - 1;
84     static final int OK = 0;
85     static final int WIN = 1;
86     static final int LOSE = 2;
87     static final int STALEMATE = 3;
88
89     /**
90      * Mark all positions with these bits set as winning.
91      */

92     static void isWon(int pos) {
93     for (int i = 0 ; i < DONE ; i++) {
94         if ((i & pos) == pos) {
95         won[i] = true;
96         }
97     }
98     }
99
100     /**
101      * Initialize all winning positions.
102      */

103     static {
104     isWon((1 << 0) | (1 << 1) | (1 << 2));
105     isWon((1 << 3) | (1 << 4) | (1 << 5));
106     isWon((1 << 6) | (1 << 7) | (1 << 8));
107     isWon((1 << 0) | (1 << 3) | (1 << 6));
108     isWon((1 << 1) | (1 << 4) | (1 << 7));
109     isWon((1 << 2) | (1 << 5) | (1 << 8));
110     isWon((1 << 0) | (1 << 4) | (1 << 8));
111     isWon((1 << 2) | (1 << 4) | (1 << 6));
112     }
113
114     /**
115      * Compute the best move for white.
116      * @return the square to take
117      */

118     int bestMove(int white, int black) {
119     int bestmove = -1;
120
121       loop:
122     for (int i = 0 ; i < 9 ; i++) {
123         int mw = moves[i];
124         if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
125         int pw = white | (1 << mw);
126         if (won[pw]) {
127             // white wins, take it!
128
return mw;
129         }
130         for (int mb = 0 ; mb < 9 ; mb++) {
131             if (((pw & (1 << mb)) == 0) && ((black & (1 << mb)) == 0)) {
132             int pb = black | (1 << mb);
133             if (won[pb]) {
134                 // black wins, take another
135
continue loop;
136             }
137             }
138         }
139         // Neither white nor black can win in one move, this will do.
140
if (bestmove == -1) {
141             bestmove = mw;
142         }
143         }
144     }
145     if (bestmove != -1) {
146         return bestmove;
147     }
148
149     // No move is totally satisfactory, try the first one that is open
150
for (int i = 0 ; i < 9 ; i++) {
151         int mw = moves[i];
152         if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
153         return mw;
154         }
155     }
156
157     // No more moves
158
return -1;
159     }
160
161     /**
162      * User move.
163      * @return true if legal
164      */

165     boolean yourMove(int m) {
166     if ((m < 0) || (m > 8)) {
167         return false;
168     }
169     if (((black | white) & (1 << m)) != 0) {
170         return false;
171     }
172     black |= 1 << m;
173     return true;
174     }
175
176     /**
177      * Computer move.
178      * @return true if legal
179      */

180     boolean myMove() {
181     if ((black | white) == DONE) {
182         return false;
183     }
184     int best = bestMove(white, black);
185     white |= 1 << best;
186     return true;
187     }
188
189     /**
190      * Figure what the status of the game is.
191      */

192     int status() {
193     if (won[white]) {
194         return WIN;
195     }
196     if (won[black]) {
197         return LOSE;
198     }
199     if ((black | white) == DONE) {
200         return STALEMATE;
201     }
202     return OK;
203     }
204
205     /**
206      * Who goes first in the next game?
207      */

208     boolean first = true;
209
210     /**
211      * The image for white.
212      */

213     Image notImage;
214
215     /**
216      * The image for black.
217      */

218     Image crossImage;
219
220     /**
221      * Initialize the applet. Resize and load images.
222      */

223     public void init() {
224     notImage = getImage(getCodeBase(), "images/not.gif");
225     crossImage = getImage(getCodeBase(), "images/cross.gif");
226
227     addMouseListener(this);
228     }
229
230     public void destroy() {
231         removeMouseListener(this);
232     }
233
234     /**
235      * Paint it.
236      */

237     public void paint(Graphics g) {
238     Dimension d = getSize();
239     g.setColor(Color.black);
240     int xoff = d.width / 3;
241     int yoff = d.height / 3;
242     g.drawLine(xoff, 0, xoff, d.height);
243     g.drawLine(2*xoff, 0, 2*xoff, d.height);
244     g.drawLine(0, yoff, d.width, yoff);
245     g.drawLine(0, 2*yoff, d.width, 2*yoff);
246
247     int i = 0;
248     for (int r = 0 ; r < 3 ; r++) {
249         for (int c = 0 ; c < 3 ; c++, i++) {
250         if ((white & (1 << i)) != 0) {
251             g.drawImage(notImage, c*xoff + 1, r*yoff + 1, this);
252         } else if ((black & (1 << i)) != 0) {
253             g.drawImage(crossImage, c*xoff + 1, r*yoff + 1, this);
254         }
255         }
256     }
257     }
258
259     /**
260      * The user has clicked in the applet. Figure out where
261      * and see if a legal move is possible. If it is a legal
262      * move, respond with a legal move (if possible).
263      */

264     public void mouseReleased(MouseEvent e) {
265     int x = e.getX();
266     int y = e.getY();
267
268     switch (status()) {
269       case WIN:
270       case LOSE:
271       case STALEMATE:
272         play(getCodeBase(), "audio/return.au");
273         white = black = 0;
274         if (first) {
275         white |= 1 << (int)(Math.random() * 9);
276         }
277         first = !first;
278         repaint();
279         return;
280     }
281
282     // Figure out the row/column
283
Dimension d = getSize();
284     int c = (x * 3) / d.width;
285     int r = (y * 3) / d.height;
286     if (yourMove(c + r * 3)) {
287         repaint();
288
289         switch (status()) {
290           case WIN:
291         play(getCodeBase(), "audio/yahoo1.au");
292         break;
293           case LOSE:
294         play(getCodeBase(), "audio/yahoo2.au");
295         break;
296           case STALEMATE:
297         break;
298           default:
299         if (myMove()) {
300             repaint();
301             switch (status()) {
302               case WIN:
303             play(getCodeBase(), "audio/yahoo1.au");
304             break;
305               case LOSE:
306             play(getCodeBase(), "audio/yahoo2.au");
307             break;
308               case STALEMATE:
309             break;
310               default:
311             play(getCodeBase(), "audio/ding.au");
312             }
313         } else {
314             play(getCodeBase(), "audio/beep.au");
315         }
316         }
317     } else {
318         play(getCodeBase(), "audio/beep.au");
319     }
320     }
321
322     public void mousePressed(MouseEvent e) {
323     }
324
325     public void mouseClicked(MouseEvent e) {
326     }
327
328     public void mouseEntered(MouseEvent e) {
329     }
330
331     public void mouseExited(MouseEvent e) {
332     }
333
334     public String JavaDoc getAppletInfo() {
335     return "TicTacToe by Arthur van Hoff";
336     }
337 }
338
Popular Tags