/* * @(#)TicTacToe.java 1.2 95/10/13 * @author Arthur van Hoff */ import java.awt.*; import java.awt.image.*; import java.net.*; import java.applet.*; public class test016 extends Applet { int white; int black; final static int moves[] = {4, 0, 2, 6, 8, 1, 3, 5, 7}; static boolean won[] = new boolean[1 << 9]; static final int DONE = (1 << 9) - 1; static final int OK = 0; static final int WIN = 1; static final int LOSE = 2; static final int STALEMATE = 3; static void isWon(int pos) { for (int i = 0 ; i < DONE ; i++) { if ((i & pos) == pos) { won[i] = true; } } } static { isWon((1 << 0) | (1 << 1) | (1 << 2)); isWon((1 << 3) | (1 << 4) | (1 << 5)); isWon((1 << 6) | (1 << 7) | (1 << 8)); isWon((1 << 0) | (1 << 3) | (1 << 6)); isWon((1 << 1) | (1 << 4) | (1 << 7)); isWon((1 << 2) | (1 << 5) | (1 << 8)); isWon((1 << 0) | (1 << 4) | (1 << 8)); isWon((1 << 2) | (1 << 4) | (1 << 6)); } int bestMove(int white, int black) { int bestmove = -1; loop: for (int i = 0 ; i < 9 ; i++) { int mw = moves[i]; if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) { int pw = white | (1 << mw); if (won[pw]) { // white wins, take it! return mw; } for (int mb = 0 ; mb < 9 ; mb++) { if (((pw & (1 << mb)) == 0) && ((black & (1 << mb)) == 0)) { int pb = black | (1 << mb); if (won[pb]) { // black wins, take another continue loop; } } } // Neither white nor black can win in one move, this will do. if (bestmove == -1) { bestmove = mw; } } } if (bestmove != -1) { return bestmove; } // No move is totally satisfactory, try the first one that is open for (int i = 0 ; i < 9 ; i++) { int mw = moves[i]; if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) { return mw; } } // No more moves return -1; } boolean yourMove(int m) { if ((m < 0) || (m > 8)) { return false; } if (((black | white) & (1 << m)) != 0) { return false; } black |= 1 << m; return true; } boolean myMove() { if ((black | white) == DONE) { return false; } int best = bestMove(white, black); white |= 1 << best; return true; } int status() { if (won[white]) { return WIN; } if (won[black]) { return LOSE; } if ((black | white) == DONE) { return STALEMATE; } return OK; } boolean first = true; Image notImage; Image crossImage; public void init() { notImage = getImage(getCodeBase(), "gif/not.gif"); crossImage = getImage(getCodeBase(), "gif/cross.gif"); } public void paint(Graphics g) { Dimension d = size(); g.setColor(Color.black); int xoff = d.width / 3; int yoff = d.height / 3; g.drawLine(xoff, 0, xoff, d.height); g.drawLine(2*xoff, 0, 2*xoff, d.height); g.drawLine(0, yoff, d.width, yoff); g.drawLine(0, 2*yoff, d.width, 2*yoff); int i = 0; for (int r = 0 ; r < 3 ; r++) { for (int c = 0 ; c < 3 ; c++, i++) { if ((white & (1 << i)) != 0) { g.drawImage(notImage, c*xoff + 1, r*yoff + 1, this); } else if ((black & (1 << i)) != 0) { g.drawImage(crossImage, c*xoff + 1, r*yoff + 1, this); } } } } public boolean mouseUp(Event evt, int x, int y) { switch (status()) { case WIN: case LOSE: case STALEMATE: white = black = 0; if (first) { white |= 1 << (int)(Math.random() * 9); } first = !first; repaint(); return true; } // Figure out the row/colum Dimension d = size(); int c = (x * 3) / d.width; int r = (y * 3) / d.height; if (yourMove(c + r * 3)) { repaint(); switch (status()) { case WIN: break; case LOSE: break; case STALEMATE: break; default: if (myMove()) { repaint(); switch (status()) { case WIN: break; case LOSE: break; case STALEMATE: break; default: } } } } return true; } public String getAppletInfo() { return "TicTacToe by Arthur van Hoff"; } }