home *** CD-ROM | disk | FTP | other *** search
/ Computer Life: Multimedia Mega Pac / Multimedia_Mega-Pac_Computer_Life_1996.iso / hotjava / demo / classes / tictacto.jav < prev   
Text File  |  1995-05-19  |  6KB  |  286 lines

  1. /*
  2.  * @(#)TicTacToe.java    1.9 95/03/14 Arthur van Hoff
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. import awt.*;
  21. import net.www.html.*;
  22. import browser.*;
  23. import browser.audio.*;
  24.  
  25. /**
  26.  * A TicTacToe applet. A very simple, and mostly brain-dead
  27.  * implementation of your favorite game! <p>
  28.  *
  29.  * In this game a position is represented by a white and black
  30.  * bitmask. A bit is set if a position is ocupied. There are
  31.  * 9 squares so there are 1<<9 possible positions for each
  32.  * side. An array of 1<<9 booleans is created, it marks
  33.  * all the winning positions.
  34.  *
  35.  * @author     Arthur van Hoff
  36.  * @version     1.9, 14 Mar 1995
  37.  */
  38. class TicTacToe extends Applet {
  39.     /**
  40.      * White's current position. The computer is white.
  41.      */
  42.     int white;
  43.  
  44.     /**
  45.      * Black's current position. The user is black.
  46.      */
  47.     int black;
  48.  
  49.     /**
  50.      * The squares in order of importance...
  51.      */
  52.     final static int moves[] = {4, 0, 2, 6, 8, 1, 3, 5, 7};
  53.  
  54.     /**
  55.      * The winning positions.
  56.      */
  57.     static boolean won[] = new boolean[1 << 9];
  58.     static final int DONE = (1 << 9) - 1;
  59.     static final int OK = 0;
  60.     static final int WIN = 1;
  61.     static final int LOSE = 2;
  62.     static final int STALEMATE = 3;
  63.  
  64.     /**
  65.      * Mark all positions with these bits set as winning.
  66.      */
  67.     static void isWon(int pos) {
  68.     for (int i = 0 ; i < DONE ; i++) {
  69.         if ((i & pos) == pos) {
  70.         won[i] = true;
  71.         }
  72.     }
  73.     }
  74.  
  75.     /**
  76.      * Initialize all winning positions.
  77.      */
  78.     static {
  79.     isWon((1 << 0) | (1 << 1) | (1 << 2));
  80.     isWon((1 << 3) | (1 << 4) | (1 << 5));
  81.     isWon((1 << 6) | (1 << 7) | (1 << 8));
  82.     isWon((1 << 0) | (1 << 3) | (1 << 6));
  83.     isWon((1 << 1) | (1 << 4) | (1 << 7));
  84.     isWon((1 << 2) | (1 << 5) | (1 << 8));
  85.     isWon((1 << 0) | (1 << 4) | (1 << 8));
  86.     isWon((1 << 2) | (1 << 4) | (1 << 6));
  87.     }
  88.  
  89.     /**
  90.      * Compute the best move for white.
  91.      * @return the square to take
  92.      */
  93.     int bestMove(int white, int black) {
  94.     int bestmove = -1;
  95.     
  96.       outer:
  97.     for (int i = 0 ; i < 9 ; i++) {
  98.         int mw = moves[i];
  99.         if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
  100.         int pw = white | (1 << mw);
  101.         if (won[pw]) {
  102.             // white wins, take it!
  103.             return mw;
  104.         }
  105.         for (int mb = 0 ; mb < 9 ; mb++) {
  106.             if (((pw & (1 << mb)) == 0) && ((black & (1 << mb)) == 0)) {
  107.             int pb = black | (1 << mb);
  108.             if (won[pb]) {
  109.                 // black wins, take another
  110.                 continue outer;
  111.             }
  112.             }
  113.         }
  114.         // Neither white nor black can win in one move, this will do.
  115.         if (bestmove == -1) {
  116.             bestmove = mw;
  117.         }
  118.         }
  119.     }
  120.     if (bestmove != -1) {
  121.         return bestmove;
  122.     }
  123.  
  124.     // No move is totally satisfactory, try the first one that is open
  125.     for (int i = 0 ; i < 9 ; i++) {
  126.         int mw = moves[i];
  127.         if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
  128.         return mw;
  129.         }
  130.     }
  131.  
  132.     // No more moves
  133.     return -1;
  134.     }
  135.  
  136.     /**
  137.      * User move.
  138.      * @return true if legal
  139.      */
  140.     boolean yourMove(int m) {
  141.     if ((m < 0) || (m > 8)) {
  142.         return false;
  143.     }
  144.     if (((black | white) & (1 << m)) != 0) {
  145.         return false;
  146.     }
  147.     black |= 1 << m;
  148.     return true;
  149.     }
  150.  
  151.     /**
  152.      * Computer move.
  153.      * @return true if legal
  154.      */
  155.     boolean myMove() {
  156.     if ((black | white) == DONE) {
  157.         return false;
  158.     }
  159.     int best = bestMove(white, black);
  160.     white |= 1 << best;
  161.     return true;
  162.     }
  163.  
  164.     /**
  165.      * Figure what the status of the game is.
  166.      */
  167.     int status() {
  168.     if (won[white]) {
  169.         return WIN;
  170.     }
  171.     if (won[black]) {
  172.         return LOSE;
  173.     }
  174.     if ((black | white) == DONE) {
  175.         return STALEMATE;
  176.     }
  177.     return OK;
  178.     }
  179.  
  180.     /**
  181.      * Who goes first in the next game?
  182.      */
  183.     boolean first = true;
  184.  
  185.     /**
  186.      * The image for white.
  187.      */
  188.     Image notImage;
  189.  
  190.     /**
  191.      * The image for black.
  192.      */
  193.     Image crossImage;
  194.  
  195.     /**
  196.      * Initialize the applet. Resize and load images.
  197.      */
  198.     public void init() {
  199.     resize(120, 120);
  200.     notImage = getImage("images/not.gif");
  201.     crossImage = getImage("images/cross.gif");
  202.     }
  203.  
  204.     /**
  205.      * Paint it.
  206.      */
  207.     public void paint(Graphics g) {
  208.     int xoff = width / 3;
  209.     int yoff = height / 3;
  210.     g.drawLine(xoff, 0, xoff, height);
  211.     g.drawLine(2*xoff, 0, 2*xoff, height);
  212.     g.drawLine(0, yoff, width, yoff);
  213.     g.drawLine(0, 2*yoff, width, 2*yoff);
  214.  
  215.     int i = 0;
  216.     for (int r = 0 ; r < 3 ; r++) {
  217.         for (int c = 0 ; c < 3 ; c++, i++) {
  218.         if ((white & (1 << i)) != 0) {
  219.             g.drawImage(notImage, c*xoff + 1, r*yoff + 1);
  220.         } else if ((black & (1 << i)) != 0) {
  221.             g.drawImage(crossImage, c*xoff + 1, r*yoff + 1);
  222.         }
  223.         }
  224.     }
  225.     }
  226.  
  227.     /**
  228.      * The user has clicked in the applet. Figure out where
  229.      * and see if a legal move is possible. If it is a legal
  230.      * move, respond with a legal move (if possible).
  231.      */
  232.     public void mouseUp(int x, int y) {
  233.     switch (status()) {
  234.       case WIN:
  235.       case LOSE:
  236.       case STALEMATE:
  237.         play("audio/return.au");
  238.         white = black = 0;
  239.         if (first) {
  240.         white |= 1 << (int)(Math.random() * 9);
  241.         }
  242.         first = !first;
  243.         repaint();
  244.         return;
  245.     }
  246.  
  247.     // Figure out the row/colum
  248.     int c = (x * 3) / width;
  249.     int r = (y * 3) / height;
  250.     if (yourMove(c + r * 3)) {
  251.         repaint();
  252.  
  253.         switch (status()) {
  254.           case WIN:
  255.         play("audio/joy.au");
  256.         break;
  257.           case LOSE:
  258.         play("audio/joy.au");
  259.         break;
  260.           case STALEMATE:
  261.         break;
  262.           default:
  263.         if (myMove()) {
  264.             repaint();
  265.             switch (status()) {
  266.               case WIN:
  267.             play("audio/joy.au");
  268.             break;
  269.               case LOSE:
  270.             play("audio/joy.au");
  271.             break;
  272.               case STALEMATE:
  273.             break;
  274.               default:
  275.             play("audio/ding.au");
  276.             }
  277.         } else {
  278.             play("audio/beep.au");
  279.         }
  280.         }
  281.     } else {
  282.         play("audio/beep.au");
  283.     }
  284.     }
  285. }
  286.