Wrox Programmer Forums
| Search | Today's Posts | Mark Forums Read
Javascript How-To Ask your "How do I do this with Javascript?" questions here.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the Javascript How-To section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old June 16th, 2008, 09:28 PM
Friend of Wrox
 
Join Date: Jun 2008
Location: Snohomish, WA, USA
Posts: 1,649
Thanks: 3
Thanked 141 Times in 140 Posts
Default

This is about as minimal a rewrite to your code as I could in good conscience do.

The biggest change was to your logic for discovering matching letters, which was just too flawed to even begin working with.

Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<script language="javascript" type="text/javascript">

    var alphabit = "abcdefghijklmnopqrstuvwxyz";
    var foundLets;
    var guessletter;    
    var lettersguess = ""
    var loses = 0;
    var mask;
    var misses = 0;
    var num;
    var pics = new Array("hang1.jpg","hang2.jpg","hang3.jpg","hang4.jpg","hang5.jpg","hang6.jpg","hang7.jpg","hangwin.jpg");
    var randy;
    var ranword;
    var used;
    var w = 0;
    var wins;        
    var words = new Array("bollywood", "chalo", "dekho", "pagal", "rangeela");
    var WORDCOUNT = words.length;
    var finished = false;

function arrayIndexOf( arr, what )
{
    for ( var i = 0; i < arr.length; ++i )
    {
        if ( arr[i] == what ) return i;
    }
    return -1;
}

// Function for picking a random word.
function pickword()
{
    if ( finished ) 
    {
         alert("The game is OVER.  FINISHED.  DONE.");
         return;
    }

     // Set letter guessed to nothing.
     w = 0;
     lettersguess = "";
     document.hangpic.src = pics[0];
     document.hangman.word.value = "";
     document.hangman.letter.value = "";

     // Set image back to first.
     misses = 0;
     num = -1;
     document.hangpic.src = pics[misses];

     // Pick random word from 'words' Array.
     randy = Math.floor(Math.random() * words.length);
     ranword = words[randy];

     // Create mask for 'ranword'.
     // This is MUCH simpler than using a loop, as you did:
     mask = "********************************".substring(0,ranword.length);
     // Display 'ranword' in text box 'word'.
     document.hangman.word.value = mask;

     document.hangman.letter.focus(); // start with focus on letter
}

// Function for guessing letters.
function guesslet()
{
    if ( finished ) 
    {
         alert("The game is OVER.  FINISHED.  DONE.");
         return;
    }

    // Get letter, change to lower case, clear input
    var ltr = document.hangman.letter;
    guessletter = ltr.value.toLowerCase();
    ltr.value = ""; // clear

    if (alphabit.indexOf(guessletter) == -1 || !(guessletter.length == 1)) 
    {
        alert("Please type only letters, and if you are typing letters, only type one at a time.");
        return; // done...get out...don't need an ELSE then!!!
    }

    // Check if letter has already been guessed.
    used = lettersguess.indexOf(guessletter);
    // If already used, alert.
    if (used >= 0) 
    {
         alert("You've already guessed the letter " + guessletter + "! Guess a different letter.");
         return; // again, DONE!  Get out! then no ELSE needed!!!
    } 

    // If not, add to *STRING* (not array), so indexOf will work in all browsers
    lettersguess += guessletter;

    w++;
    foundLets = "";
 
    // I just *HAD* to fix this code...it was too cumbersome to let it live.
    // and it would never have worked, anyway
    var userWord = document.hangman.word.value;
    var prior = userWord; // keep untouched copy

    for (num=0; num< ranword.length; num++)
    {
        if (ranword.charAt(num) == guessletter) 
        {
             userWord = userWord.substring(0,num) + guessletter + userWord.substring(num+1);
        }
    }
    document.hangman.word.value = userWord; // put (maybe) changed word back in place

    if ( userWord != prior )
    {
        if ( userWord == ranword )
        {
            document.hangpic.src = pics[7];
            alert("You won! Congrats! The word was " + ranword + ". Click 'OK' when you're ready to play again.");
            endOfWord( );
            return;
        }
    } else {
        // so if userWord and prior are same, user didn't guess the letter
        misses++;
        document.hangpic.src = pics[misses];

        // *** TEMP CODE: since I don't have pictures:
        document.getElementById("PICNAME").innerHTML = "PICTURE: " + pics[misses];
    }

    // Alert upon loss, return everything to zero.
    if (misses == 6) 
    {
        alert("You lost! The answer was " + ranword);
        loses++;
        endOfWord( );
        return;
    }
    // if still guessing on same word, put focus back on letter:
    document.hangman.letter.focus();

}

// function to end a word...either with win or loss...
function endOfWord( )
{
    words.splice(randy,1);
    // If no words left, alert and inform number of losses.
    if (words.length == 0) 
    {
        winlost();
        return; 
    }
    // If words are left, continue with next game.
    pickword();
}

// Function for number of wins and loses.

// DON'T TOUCH winlost()!
// I *had* to touch it!  It was wrong for any number of words except 5!!!
// Besides, I wanted that "finished" test.
function winlost()
{
    finished = true;
    wins = WORDCOUNT - loses;
    alert("You've gone through all the words! Out of the five games you played, you lost " + loses + ", and won " + wins +"!");
    alert("Press 'Refresh' then 'New Word' to start the games all over again... Even though you already know what all the answers are. 

Cheater.");

}

// Refresh game to start over again, if user wants.
function refreshfunc() 
{
    location.reload(true);
}


</script>

</head>

<body onLoad="pickword( );">

<form name="hangman">

<img name="hangpic" src="" width="200" height="300" />
<h2 id="PICNAME">&nbsp;</h2>
<p>
The word, so far: <input type="text" name="word" readonly size=12
                   style="font-family: courier; font-weight: bold; font-size: large; color: red;"/>
<br />
Your letter: <input type="text" name="letter" size=1 onkeyup="guesslet();" />
</p>

<p> 
<br />
<input type="button" name="playgame" onClick="pickword();" value="New Word"/>
</p>
<p>
<input type="button" name="refreshpage" onClick="refreshfunc();" value="Refresh" />
</p>
<p>&nbsp;
</p>

</form>

</body>
</html>
 
Old June 16th, 2008, 10:52 PM
Registered User
 
Join Date: Jan 2008
Location: , , .
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thank you for replying and everything, but after a bunch of messing around I finally got it to work.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<script language="javascript" type="text/javascript">

    var alphabit = "abcdefghijklmnopqrstuvwxyz";
    var foundLets;
    var guessletter;
    var lettersguess = new Array ();
    var loses = 0;
    var mask;
    var misses = 0;
    var pics = new Array("hang1.jpg","hang2.jpg","hang3.jpg","hang4.j pg","hang5.jpg","hang6.jpg","hang7.jpg","hangwin.j pg");
    var randy;
    var ranword;
    var used;
    var w = 0;
    var wins;
    var words = new Array("bollywood", "chalo", "dekho", "pagal", "rangeela");

// Function for picking a random word.
function pickword()
{
  // Set letter guessed to nothing.
        foundLets = "";
        document.hangman.letter.value = "";
        w = 0;
        lettersguess = [];

    // Set image back to first.
        misses = 0;

        document.hangpic.src = pics[misses];

    // Pick random word from 'words' Array.
        randy = Math.floor(Math.random() * words.length);
        ranword = words[randy];

// Create mask for 'ranword'.
        mask = "";

        for (i = 0; i < ranword.length; i++) {
            mask += "*";
        }

    // Display 'ranword' in text box 'word'.
        document.hangman.word.value = mask;

}

// Function for number of wins and loses.
function winlost()
{
    wins = 5 - loses;
    alert("You've gone through all the words! Out of the five games you played, you lost " + loses + ", and won " + wins +"!");
    alert("Press 'Refresh' then 'New Word' to start the games all over again... Even though you already know what all the answers are. Cheater.");

}

// Function for guessing letters.
function guesslet()
{

    // Change letter to lowercase.
    guessletter = (document.hangman.letter.value).toLowerCase();

    // Make sure user only types letters, and only types them one at a time.
    if (alphabit.indexOf(guessletter) == -1 || !(guessletter.length == 1)) {
        alert("Please type only letters, and if you are typing letters, only type one at a time.");
    }

    else {
        // Check if letter has already been guessed.
        used = lettersguess.indexOf(guessletter);

      // If already used, alert.
        if (used !== -1) {
            alert("You've already guessed the letter " + guessletter + "! Guess a different letter.");
        }

      // If not, add to array.
        if (used == -1) {

            lettersguess[w] = guessletter;

            w++;
            foundLets = "";

            // Loop through random word to find the guessed letter.
            for (j=0; j< ranword.length; j++)
                {
                // If guessed letter is in the random word, add it to the 'foundLets' variable in the correct position.
                if (ranword.charAt(j) == guessletter) {

                    foundLets += ranword.charAt(j);

                }
                // If the letter is not found in the random word, return masked characters.
                else {
                    foundLets += mask.charAt(j);
                }
            }

            // Make the mask, and the display word equal to what was compiled after the guess.
            mask = foundLets;
            document.hangman.word.value = foundLets;

                // If there are no '*', then there's a win! Alert user of win, remove word from list, and start game again.
                if (mask.indexOf('*') == -1) {

                            document.hangpic.src = pics[7];
                            alert("You won! Congrats! The word was " + ranword + ". Click 'OK' when you're ready to play again.");
                            words.splice(randy,1);
                            lettersguess.length = 0;
                            w = 0;
                            document.hangpic.src = pics[0];
                            document.hangman.word.value = "";
                            document.hangman.letter.value = "";

                                  // If no words left, alert and inform number of losses.
                                    if (words.length == 0) {
                                            winlost();
                                    }

                                    // If words are left, continue with next game.
                                    else {
                                            pickword();
                                    }
                }

                // If the guess letter is not found in the word, change picture, and add up misses.
                if (foundLets.indexOf(guessletter) == -1) {

                    document.hangpic.src = pics[misses+1];
                    misses++;

                    // Alert upon loss, return everything to zero.
                    if (misses == 6) {
                        alert("You lost! The answer was " + ranword + "... Nice try though.");
                        loses++;
                        words.splice(randy,1);
                        lettersguess.length = 0;
                        w = 0;
                        document.hangpic.src = pics[0];
                        document.hangman.word.value = "";
                        document.hangman.letter.value = "";

                     // If no words left, alert and inform number of losses.
                                if (words.length == 0) {
                                     winlost();
                                }

                    // If words are left, continue with next game.
                                else {
                                    pickword();
                                }
                    }

                }


        }
    }

}

// Refresh game to start over again, if user wants.
function refreshfunc() {
      location.reload(true);
}


</script>

</head>

<body onLoad="document.hangpic.src = pics[misses];">

<form name="hangman">

<img name="hangpic" src="" width="200" height="300" />

<p>
<input type="text" name="word" />
<br />
<input type="text" name="letter" />
</p>

<p><input type="button" name="guessbut" onClick="guesslet();" value="Guess A Letter" />
<br />
<input type="button" name="playgame" onClick="pickword();" value="New Word"/>
</p>
<p>
<input type="button" name="refreshpage" onClick="refreshfunc();" value="Refresh" />
</p>

</form>

</body>
</html>

It might not be up to your standards or anything, but it works for me, and I'm damn happy about it.

 
Old June 17th, 2008, 12:30 AM
Friend of Wrox
 
Join Date: Jun 2008
Location: Snohomish, WA, USA
Posts: 1,649
Thanks: 3
Thanked 141 Times in 140 Posts
Default

That's well done. A nice solution to the problem you originally had with "foundLets."

The loop you are now using here:
    // Loop through random word to find the guessed letter.
    for (j=0; j< ranword.length; j++)
was indeed the secret.

Your solution is indeed simpler than mine. Congratulations.

I would recommend that you look at what I did for "endOfWord( )", allowing me to eliminate duplicate code. But that's a nice thing, not a necessary thing.

Please understand, I wasn't trying to say your *approach* was wrong. Just that every time I started playing with it I found another error in the details. It really *DID* take me almost exactly as long to finally figure out my "fixed" version of your code as it did to write mine from scratch. This is not surprising. You had your logic; I had mine. We started from different assumptions. I had to learn your assumptions before I could understand and change the code.

So now work on your "human interface". You might note the simple trick I used to get rid of the letter submit button and allow just the typing of the letter to cause the letter to be submitted. And the very simply way that I caused the letter to be replaced, so the user doesn't have to do it each time, and then I set focus on the letter. Minor stuff, really, but it just makes the game more "playable."

Again, congratulations. An auspicious start.




Similar Threads
Thread Thread Starter Forum Replies Last Post
I have records where I need to replace one letter gilgalbiblewheel Classic ASP Databases 2 March 11th, 2005 02:29 AM
hangman games becu BOOK: Beginning PHP4/PHP 5 ISBN: 978-0-7645-4364-7; v5 ISBN: 978-0-7645-5783-5 1 September 19th, 2004 06:42 PM
hangman.php..... joeore BOOK: Beginning PHP4/PHP 5 ISBN: 978-0-7645-4364-7; v5 ISBN: 978-0-7645-5783-5 1 October 3rd, 2003 04:53 PM
hangman.php in chapter 8... joeore BOOK: Beginning PHP4/PHP 5 ISBN: 978-0-7645-4364-7; v5 ISBN: 978-0-7645-5783-5 1 October 3rd, 2003 04:52 PM
Hangman Help Popfaen BOOK: Beginning PHP4/PHP 5 ISBN: 978-0-7645-4364-7; v5 ISBN: 978-0-7645-5783-5 0 July 1st, 2003 05:10 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.