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

  1. /*
  2.  * @(#)Hangman.java    Patrick Chan
  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 java.io.*;
  22. import net.www.html.*;
  23. import browser.*;
  24. import browser.audio.*;
  25.  
  26. /**
  27.  * @author     Patrick Chan
  28.  * @version     1.0
  29.  */
  30. class Hangman extends Applet implements Runnable {
  31.     /* This is the maximum number of incorrect guesses. */
  32.     final int maxTries = 5;
  33.  
  34.     /* This is the maximum length of a secret word. */
  35.     final int maxWordLen = 20;
  36.  
  37.     /* This buffer holds the letters in the secret word. */
  38.     char secretWord[];
  39.  
  40.     /* This is the length of the secret word. */
  41.     int secretWordLen;
  42.  
  43.     /* This buffer holds the letters which the user typed
  44.        but don't appear in the secret word. */
  45.     char wrongLetters[];
  46.  
  47.     /* This is the current number of incorrect guesses. */
  48.     int wrongLettersCount;
  49.  
  50.     /* This buffer holds letters that the user has successfully
  51.        guessed. */
  52.     char word[];
  53.  
  54.     /* Number of correct letters in 'word'. */
  55.     int wordLen;
  56.  
  57.     /* This is the font used to paint correctly guessed letters. */
  58.     Font wordFont;
  59.  
  60.     /* This is the sequence of images for Duke hanging on the gallows. */
  61.     Image hangImages[];
  62.  
  63.     // Dancing Duke related variables
  64.  
  65.     /* This thread makes Duke dance. */
  66.     Thread danceThread;
  67.  
  68.     /* These are the images that make up the dance animation. */
  69.     Image danceImages[];
  70.  
  71.     /* This variable holds the number of valid images in danceImages. */
  72.     int danceImagesLen = 0;
  73.  
  74.     /* These offsets refer to the dance images.  The dance images
  75.        are not of the same size so we need to add these offset 
  76.        in order to make the images "line" up. */
  77.     private int danceImageOffsets[] = { 8, 0, 0, 8, 18, 21, 27 };
  78.  
  79.     /* This represents the sequence to display the dance images
  80.        in order to make Duke "dance".  */
  81.     private int danceSequence[] = { 3, 4, 5, 6, 6, 5, 6, 6, 5, 4, 3, 
  82.             2, 1, 0, 0, 1, 2, 2, 1, 0, 0, 1, 2 };
  83.  
  84.     /* This is the current sequence number.  -1 implies
  85.        that Duke hasn't begun to dance. */
  86.     int danceSequenceNum = -1;
  87.  
  88.     /* This is the maximum width and height of all the dance images. */
  89.     int danceHeight = 0;
  90.  
  91.     /* This variable is used to adjust Duke's x-position while
  92.        he's dancing. */
  93.     int danceX = 0;
  94.  
  95.     /* This variable specifies the currently x-direction of
  96.        Duke's dance.  1=>right and -1=>left. */
  97.     int danceDirection = 1;
  98.  
  99.     /* This is the stream for the dance music. */
  100.     InputStream danceMusic;
  101.  
  102.     /**
  103.      * Initialize the applet. Resize and load images.
  104.      */
  105.     public void init() {
  106.         int i;
  107.  
  108.         // load in dance animation
  109.     danceMusic = getContinuousAudioStream(
  110.         new URL(appletURL, "audio/dance.au"));
  111.     danceImages = new Image[40];
  112.  
  113.     for (i = 1; i < 8; i++) {
  114.         Image im = getImage("images/dancing-duke/T" + i + ".gif");
  115.  
  116.         if (im == null) {
  117.         break;
  118.         }
  119.         danceHeight = Math.max(danceHeight, im.height);
  120.         danceImages[danceImagesLen++] = im;
  121.         }
  122.  
  123.         // load in hangman image sequnce
  124.         hangImages = new Image[maxTries];
  125.         for (i=0; i<maxTries; i++) {
  126.         hangImages[i] = getImage("images/hanging-duke/h"+(i+1)+".gif");
  127.         }
  128.  
  129.         // initialize the word buffers.
  130.         wrongLettersCount = 0;
  131.         wrongLetters = new char[maxTries];
  132.  
  133.         secretWordLen = 0;
  134.         secretWord = new char[maxWordLen];
  135.  
  136.         word = new char[maxWordLen];
  137.         
  138.         wordFont = getFont("Courier", Font.BOLD, 24);
  139.  
  140.     resize((maxWordLen+1) * wordFont.widths['M'] + maxWordLen * 3,
  141.             hangImages[0].height * 2 + wordFont.height);
  142.     }
  143.  
  144.     /**
  145.      * Paint the screen.
  146.      */
  147.     public void paint(Graphics g) {
  148.         int imageW = hangImages[0].width;
  149.         int imageH = hangImages[0].height;
  150.         int baseH = 10;
  151.         int baseW = 30;
  152.         Font font;
  153.         int i, x, y;
  154.  
  155.         // draw gallows pole
  156.         g.drawLine(baseW/2, 0, baseW/2, 2*imageH - baseH/2);
  157.         g.drawLine(baseW/2, 0, baseW+imageW/2, 0);
  158.  
  159.         // draw gallows rope
  160.         g.drawLine(baseW+imageW/2, 0, baseW+imageW/2, imageH/3);
  161.  
  162.         // draw gallows base
  163.         g.fillRect(0, 2*imageH-baseH, baseW, baseH);
  164.  
  165.  
  166.         // draw list of wrong letters
  167.         font = getFont("Courier", Font.PLAIN, 15);
  168.         x = imageW + baseW;
  169.         y = font.height;
  170.     g.setFont(font);
  171.     g.setForeground(Color.red);
  172.         for (i=0; i<wrongLettersCount; i++) {
  173.             g.drawChars(wrongLetters, i, 1, x, y);
  174.             x += font.widths[wrongLetters[i]] + font.widths[' '];
  175.         }
  176.  
  177.         if (secretWordLen > 0) {
  178.         // draw underlines for secret word
  179.         int Mwidth = wordFont.widths['M'];
  180.         int Mheight = wordFont.height;
  181.         g.setFont(wordFont);
  182.         g.setForeground(Color.black);
  183.         x = 0;
  184.         y = height - 1;
  185.         for (i=0; i<secretWordLen; i++) {
  186.         g.drawLine(x, y, x + Mwidth, y);
  187.         x += Mwidth + 3;
  188.         }
  189.  
  190.         // draw known letters in secret word
  191.         x = 0;
  192.         y = height - 3;
  193.             g.setForeground(Color.blue);
  194.         for (i=0; i<secretWordLen; i++) {
  195.         if (word[i] != 0) {
  196.             g.drawChars(word, i, 1, x, y);
  197.         }
  198.         x += Mwidth + 3;
  199.         }
  200.  
  201.             if (wordLen < secretWordLen && wrongLettersCount > 0) {
  202.         // draw Duke on gallows
  203.         g.drawImage(hangImages[wrongLettersCount-1], 
  204.                     baseW, imageH/3);
  205.         }
  206.         }
  207.  
  208.     }
  209.  
  210.     public void update(Graphics g) {
  211.     if (wordLen == 0) {
  212.         g.clearRect(0, 0, width, height);
  213.             paint(g);
  214.     } else if (wordLen == secretWordLen) {
  215.             if (danceSequenceNum < 0) {
  216.         g.clearRect(0, 0, width, height);
  217.         paint(g);
  218.         danceSequenceNum = 0;
  219.         }
  220.             updateDancingDuke(g);
  221.         } else {
  222.             paint(g);
  223.         }
  224.     }
  225.  
  226.     void updateDancingDuke(Graphics g) {
  227.         int baseW = 30;
  228.         int imageH = hangImages[0].height;
  229.     int danceImageNum = danceSequence[danceSequenceNum];
  230.  
  231.     // first, clear Duke's current image
  232.     g.clearRect(danceX+baseW, imageH*2 - danceHeight, 
  233.             danceImageOffsets[danceImageNum]+danceImages[danceImageNum].width, 
  234.             danceHeight);
  235.  
  236.         // update dance position
  237.     danceX += danceDirection;
  238.     if (danceX < 0) {
  239.         danceX = danceDirection = (int)Math.floor(Math.random() * 12) + 5;
  240.     } else if (danceX + baseW > width / 2) {
  241.         //danceDirection = -(int)Math.floor(Math.random() * 12) - 5;
  242.         danceDirection *= -1;
  243.     } else if (Math.random() > .9) {
  244.         danceDirection *= -1;
  245.     }
  246.  
  247.         // update dance sequence
  248.     danceSequenceNum++;
  249.     if (danceSequenceNum >= danceSequence.length) {
  250.         danceSequenceNum = 0;
  251.         }
  252.  
  253.     // now paint Duke's new image
  254.     danceImageNum = danceSequence[danceSequenceNum];
  255.     if ((danceImageNum < danceImagesLen) && (danceImages[danceImageNum] != null)) {
  256.         g.drawImage(danceImages[danceImageNum], 
  257.         danceX+baseW+danceImageOffsets[danceImageNum], 
  258.         imageH*2 - danceHeight);
  259.     }
  260.     }
  261.  
  262.     public void keyDown(int key) {
  263.         int i;
  264.         boolean found = false;
  265.  
  266.         // start new game if user has already won or lost.
  267.         if (secretWordLen == wordLen || wrongLettersCount == maxTries) {
  268.             newGame();
  269.             return;
  270.         }
  271.  
  272.         // check if valid letter
  273.         if (key < 'a' || key > 'z') {
  274.         play("audio/beep.au");
  275.             return;    
  276.         }
  277.         // check if already in secret word
  278.         for (i=0; i<secretWordLen; i++) {
  279.             if (key == word[i]) {
  280.                 found = true;
  281.         play("audio/ding.au");
  282.                 return;
  283.             }
  284.         }
  285.         // check if already in wrongLetters
  286.         if (!found) {
  287.         for (i=0; i<maxTries; i++) {
  288.         if (key == wrongLetters[i]) {
  289.             found = true;
  290.             play("audio/ding.au");
  291.             return;
  292.         }
  293.             }
  294.         }
  295.         // is letter in secret word? If so, add it.
  296.         if (!found) {
  297.             for (i=0; i<secretWordLen; i++) {
  298.                 if (key == secretWord[i]) {
  299.                     word[i] = (char)key;
  300.                     wordLen++;
  301.                     found = true;
  302.                 }
  303.             }
  304.             if (found) {
  305.                 if (wordLen == secretWordLen) {
  306.             play("audio/whoopy.au");
  307.                     startDukeDancing();
  308.         } else {
  309.             play("audio/ah.au");
  310.                 }
  311.             }
  312.         }
  313.         // wrong letter; add to wrongLetters
  314.         if (!found) {
  315.         if (wrongLettersCount < wrongLetters.length) {
  316.         wrongLetters[wrongLettersCount++] = (char)key;
  317.                 if (wrongLettersCount < maxTries) {
  318.             play("audio/ooh.au");
  319.                 } else {
  320.                     // show the answer
  321.                     for (i=0; i<secretWordLen; i++) {
  322.                         word[i] = secretWord[i];
  323.                     }
  324.             play("audio/scream.au");
  325.                 }
  326.             }
  327.         }
  328.         if (wordLen == secretWordLen) {
  329.             danceSequenceNum = -1;
  330.         }
  331.         repaint();
  332.     }
  333.  
  334.     /**
  335.      * Grab the focus and restart the game.
  336.      */
  337.     public void mouseDown(int x, int y) {
  338.         int i;
  339.  
  340.         // grab focus to get keyDown events
  341.         getFocus();
  342.  
  343.         if (secretWordLen > 0 && 
  344.            (secretWordLen == wordLen || wrongLettersCount == maxTries)) {
  345.         newGame();
  346.         } else {
  347.         play("audio/beep.au");
  348.         }
  349.     }
  350.  
  351.     /**
  352.      * Starts a new game.  Chooses a new secret word
  353.      * and clears all the buffers
  354.      */
  355.     public void newGame() {
  356.         int i;
  357.  
  358.         // stop animation thread.
  359.         danceThread = null;
  360.  
  361.         // pick secret word
  362.         String s = wordlist[(int)Math.floor(Math.random() * wordlist.length)];
  363.         
  364.         secretWordLen = Math.min(s.length(), maxWordLen);
  365.         for (i=0; i<secretWordLen; i++) {
  366.             secretWord[i] = s.charAt(i);
  367.         }
  368.  
  369.         // clear word buffers
  370.         for (i=0; i<maxWordLen; i++) {
  371.             word[i] = 0;
  372.         }
  373.         wordLen = 0;
  374.         for (i=0; i<maxTries; i++) {
  375.             wrongLetters[i] = 0;
  376.         }
  377.         wrongLettersCount = 0;
  378.  
  379.         repaint();
  380.     }
  381.  
  382.     /**
  383.      * Start the applet.
  384.      */
  385.     public void start() {
  386.     getFocus();
  387.         // Start a new game only if user has won or lost; otherwise
  388.         // retain the same game.
  389.         if (secretWordLen == wordLen || wrongLettersCount == maxTries) {
  390.             newGame();
  391.         }
  392.     }
  393.  
  394.     /**
  395.      * Stop the applet.  Stop the danceThread.
  396.      */
  397.     public void stop() {
  398.     danceThread = null;
  399.     }
  400.  
  401.     /**
  402.      * Run Duke's dancing animation. This methods is called by class Thread.
  403.      * @see java.lang.Thread
  404.      */
  405.     public void run() {
  406.     Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
  407.  
  408.         // start the dancing music.
  409.     startPlaying(danceMusic);
  410.  
  411.         // increment the sequence count and invoke the paint method.
  412.     while (width > 0 && height > 0 && danceThread != null) {
  413.         repaint();
  414.         Thread.sleep(100);
  415.     }
  416.  
  417.         // The dance is done so stop the music.
  418.     stopPlaying(danceMusic);
  419.     }
  420.  
  421.     /**
  422.      * Starts Duke's dancing animation.
  423.      */
  424.     private void startDukeDancing () {
  425.     if (danceThread == null) {
  426.         danceThread = new Thread(this);
  427.         danceThread.start();
  428.     }
  429.     }
  430.  
  431.     /* This is the hangman's limited word list. */
  432.     String wordlist[] = {
  433.         "abstraction",
  434.         "ambiguous",
  435.         "arithmetic",
  436.         "backslash",
  437.         "bitmap",
  438.         "circumstance",
  439.         "combination",
  440.         "consequently",
  441.         "consortium",
  442.         "decrementing",
  443.         "dependency",
  444.         "disambiguate",
  445.         "dynamic",
  446.         "encapsulation",
  447.         "equivalent",
  448.         "expression",
  449.         "facilitate",
  450.         "fragment",
  451.         "hexadecimal",
  452.         "implementation",
  453.         "indistinguishable",
  454.         "inheritance",
  455.         "internet",
  456.         "java",
  457.         "localization",
  458.         "microprocessor",
  459.         "navigation",
  460.         "optimization",
  461.         "parameter",
  462.         "pickle",
  463.         "polymorphic",
  464.         "rigorously",
  465.         "simultaneously",
  466.         "specification",
  467.         "structure",
  468.         "lexical",
  469.         "likewise",
  470.         "management",
  471.         "manipulate",
  472.         "mathematics",
  473.         "hotjava",
  474.         "vertex",
  475.         "unsigned",
  476.         "traditional"};
  477. }
  478.