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
  #1 (permalink)  
Old June 3rd, 2008, 04:16 PM
Registered User
 
Join Date: Jan 2008
Location: , , .
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default Letter replace in hangman.

Hi, I'm pretty new to JavaScript. I've been trying to make this Hangman game for the longest time. I have everything done except that I can't actually get the correct letter to reveal itself. I got the first letter to show up, but nothing else.

I can't figure out what I've been doing wrong, and I don't know what else to try. Someone suggested that I create an empty string and add it to the masked word, but I honestly have no idea how to get that to work.

Here's my 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 words;
var randy;
var ranword;
var mask;
var wordslong;
var pics;
var guessletter;
var misses;
var i;
var wins;
var loses;
var used;
var lettersguess;
var guessit;
var charguess;
var wordval;
var w;
var h;
var letno;

var alphabit;

var chnum = -1;

w = 0;

h = 0;

misses = 0;

loses = 0;

pics = new Array("hang1.jpg","hang2.jpg","hang3.jpg","hang4.j pg","hang5.jpg","hang6.jpg","hang7.jpg","hangwin.j pg");

words = new Array("bollywood", "chalo", "dekho", "pagal", "rangeela");

alphabit = new Array("a","b","c","d","e","f","g","h","i","j","k", "l","m","n","o","p","q","r","s","t","u","v","w","x ","y","z");

lettersguess = new Array ();

// Function for picking a random word.

// TOUCH AND YOU GET KILLED BY HORRIBLE FIRE.

function pickword()
{

// Set letter guessed to nothing.

        document.hangman.letter.value = "";
        w = 0;
        lettersguess = [];
        chnum = -1;

    // 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 = "";
        wordslong = ranword.length;

    for (i = 0; i < wordslong; i++) {
        mask += "*";
        }

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

}

// Function for number of wins and loses.

// DON'T TOUCH winlost()!

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.");

}

j=0;

// DON'T TOUCH letnomatch()!!!


function letnomatch() {
        // If letter is not in random word, change picture.
             document.hangpic.src = pics[misses+1];
            misses++;


         // Alert upon loss, return everything to zero.
            if (misses == 6) {
                    alert("You lost! The answer was " + ranword);
                         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();
                        }
                }
}


// Function for guessing letters.

function guesslet()
{

    guessit = document.hangman.letter.value;

    // Change letter to lowercase.

    guessletter = guessit.toLowerCase();


    letno = alphabit.indexOf(guessletter);

    if (letno == -1) {

        alert("Please type only letters.");

    }

    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++;


// The evil section which all my problems are hiding.

    var stringTest = " ";


    for (j=0; j<wordslong; j++)
        {

        chnum++;

        charguess = ranword.charAt(chnum);

        var indexlet = ranword.indexOf(guessletter)

        if (indexlet == -1) {
            letnomatch();
        }


        if (guessletter == charguess) {
            document.hangman.word.value = mask.replace(mask.charAt(chnum), guessletter);

        }

        if (!(indexlet == -1) && !(guessletter == charguess)) {
            // Do I need a loop here to go through the numbers? I have this in place so I can see what number it says.
alert(chnum);
        }
    break;}

}

}

}

// DON'T TOUCH!!!


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>


I know, it's a bit of a mess, and I probably have a couple extra defined variables, and I have left myself little messages of what had to be fixed and what was to be left alone.

Like I said, I'm pretty new to JavaScript, so forgive me.

Any help would be muchly appreciated.
  #2 (permalink)  
Old June 3rd, 2008, 05:15 PM
Friend of Wrox
 
Join Date: Jun 2008
Location: Snohomish, WA, USA
Posts: 1,649
Thanks: 3
Thanked 141 Times in 140 Posts
Default

Well, just for starters, you are doing:
   letno = alphabit.indexOf(guessletter);

Ummm...you can't use indexOf on an *ARRAY*!

Try just changing to
   alphabit = "abcdefghijklmnopqrstuvwxyz";

Same thing with lettersguess array:

You've got many many errors in that code. So many that before I'd try fixing it I would just toss it away and start over.

You *NEED* to get yourself a *GOOD* JavaScript debugger. I'd recommend using FireFox browser and the FireBug debugger.
  #3 (permalink)  
Old June 3rd, 2008, 06:45 PM
Registered User
 
Join Date: Jan 2008
Location: , , .
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Quote:
quote:Originally posted by Old Pedant
Ummm...you can't use indexOf on an *ARRAY*!

Try just changing to
alphabit = "abcdefghijklmnopqrstuvwxyz";
So... why does it work? I have had no problem with searching an array with indexOf. I don't have a problem with that.

Quote:
quote:
You *NEED* to get yourself a *GOOD* JavaScript debugger. I'd recommend using FireFox browser and the FireBug debugger.
Other people have been telling me that and I have been using it and FireBug tells me that there are no errors. If something doesn't work it just doesn't do anything at all.

Could you point out examples of these 'errors' I'm having? It would be very helpful.
  #4 (permalink)  
Old June 3rd, 2008, 07:26 PM
Friend of Wrox
 
Join Date: Jun 2008
Location: Snohomish, WA, USA
Posts: 1,649
Thanks: 3
Thanked 141 Times in 140 Posts
Default

Well, I tested it in MSIE 6, with JavaScript debugging enabled and using the Microsoft Script Editor as a debugger. That debugger isn't as good a FireBug by a long shot, but it sure caught those errors I noted. So I fixed those two and then got still more "method not available on that object" and stuff like that and gave up. So I dunno what to tell you. Maybe FireFox does allow indexOf( ) on array.

This looked like a fun thing to try, so here is what I whipped up.

I've never posted code to these forums, so I don't know whether it will get all messed up or not. I guess we'll just have to see:

***** hangman.html *****
Code:
<html>
<head>
<style>
table#WORD { }
table#WORD td { border: solid brown 5px; height: 30px; width: 30px;
                font-family: arial; font-size: 20px; color: brown; text-align: center;

              }

table#LETTERS    {  }
table#LETTERS td { border: solid green 2px; background-color: lightgreen; width: 20px; height: 20px;
                   font-family: arial; font-size: 16px; color: green; text-align: center;
                   padding: 4px; cursor: hand; 
                 }

div#HANGPIC { background-color: yellow; color: red; font-family: arial; text-aligh: center;
              width: 200px; height: 200px;
              border: solid red 10px;
            }

.message { font-family: arial; font-size: x-large; color: brown; }

</style>
<script>
// really should encrypt the words so they aren't visible in the code, 
// but this works for demo purposes:
var words = new Array("AARDVARK","CATASTROPHE","XEBEC","JABBERWOCKY","SPHINX");
// this keeps track of how many words have not yet been guessed:
var available = words.length;
// this is the current word
var WORD = null;
// and this is the number of misses so far
var misses = 0;

// Each time we need a new word, we just call this function:
function init( )
{
    // make sure there are some words not yet attempted
    if ( available < 1 )
    {
         alert("You have played with all the words I have.");
         available = -1;
         return;
    }

    // at least one word left, so init the main display
    misses = 0;
    // here is where we would init image back to no misses...but for now:
    var hang = document.getElementById("HANGPIC");
    hang.innerHTML = "&nbsp;<br/>";
    hang.style.fontSize = 12;

    // choose a word not yet chosen
    var choice = Math.floor( Math.random() * available );
    WORD = words[choice];
    --available;
    words[choice] = words[available]; // so that choice can't get chosen again

    // initialize all the cells where the correct guesses will be placed
    var wLetters = document.getElementById("WORD").getElementsByTagName("td");
    for ( var w = 0; w < wLetters.length; ++w )
    {
        wLetters[w].innerHTML = "&nbsp;"; // *MUST* have content...nbsp is easiest
        var wStyle = wLetters[w].style;
        wStyle.backgroundColor = "yellow";
        wStyle.color = "brown";
        // only show as many cells as there are letters in the word to be guessed
        wStyle.display = ( w < WORD.length ) ? "inline" : "none";
    }
    // and re-init the letter CHOICES so that all are visible again
    var cLetters = document.getElementById("LETTERS").getElementsByTagName("td");
    for ( var c = 0; c < cLetters.length; ++c )
    {
        var cLet = cLetters[c];
        cLet.style.color = "green";
        cLet.style.cursor = "hand";
        cLet.onclick = function() { letterClick(this); }
    }

}

// each time the user clicks on a letter, we call this function:
function letterClick( which )
{
    if ( available < 0 ) return; // game is over...all words guessed

    // if user already clicked on this letter, ignore the click this time:
    if ( which.style.color != "green" ) return;

    // mark this letter as used (by simply hiding the character and changing the cursor)
    which.style.color = "lightgreen";
    which.style.cursor = "arrow";

    // get the letter boxes where the successful guesses are recorded
    var wLetters = document.getElementById("WORD").getElementsByTagName("td");
 
    var letter = which.innerHTML; // this is the letter that was clicked on
    var hit = false; // if this is false after the check, then the user missed
    var matched = 0; // this records total number of letters correctly guessed so far

    // check every letter in the word
    for ( w = 0; w < WORD.length; ++w )
    {
        // if a letter is correct, put it into the word display
        if ( WORD.charAt(w) == letter )
        {
            hit = true; // say user got one!
            wLet = wLetters[w]; 
            wLet.innerHTML = letter; // put the guessed letter into display
            wLet.style.color = "green"; // and give it color
            wLet.style.backgroundColor = "lightgreen"; // and background
        }
        // and count how many letters are correct (from current guess *AND* from prior guesses)
        if ( wLetters[w].style.backgroundColor == "lightgreen" ) ++matched;
    }
    // check to see if all letters guessed:
    if ( matched == WORD.length )
    {
        if ( confirm("YOU WON!!!!\n\nCONGRATULATIONS!!\n\nClick OK to play again.") )
        {
             init( );
        } else {
             available = -1;
        }
        return;
    }

    // not a winner...did he/she hit any letter?
    if ( hit ) return; // yes...all done for this turn.

    // the game plays faster without the following alert, so remove it if you wish:
    alert("Nope, there is no '" + letter + "' in the word!");

    // here is where we would change the image...but for now:
    ++misses;
    var hang = document.getElementById("HANGPIC");
    hang.innerHTML = "&nbsp;<br/>" + misses;
    hang.style.fontSize = (12 + 12 * misses) + "px";

    // and check for end of game
    if ( misses > 6 )
    {
        if ( confirm("You lost!\n\nClick OK to play again.") )
        {
             init( );
        } else {
             available = -1;
        }
    }
}

</script>
<body onload="init( );">
<center>
<p class="message">H A N G M A N !</p>
<br/>
<div id="HANGPIC"></div>
<p>&nbsp;<p>
<table id="WORD">
<tr>
    <td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
    <td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
</tr>
</table>
<p class="message">Click on a letter below to guess it!</p>
<br/>
<table id="LETTERS" cellspacing=4>
<tr>

    <td>A</td><td>B</td><td>C</td><td>D</td><td>E</td><td>F</td><td>G</td>
    <td>H</td><td>I</td><td>J</td><td>K</td><td>L</td><td>M</td><td>N</td>
    <td>O</td><td>P</td><td>Q</td><td>R</td><td>S</td><td>T</td><td>U</td>
    <td>V</td><td>W</td><td>X</td><td>Y</td><td>Z</td>
</tr>
</table>
</body>
</html>
  #5 (permalink)  
Old June 3rd, 2008, 07:27 PM
Friend of Wrox
 
Join Date: Jun 2008
Location: Snohomish, WA, USA
Posts: 1,649
Thanks: 3
Thanked 141 Times in 140 Posts
Default

Thought of a few ways to improve that code, but it will give you a starting point, at least.
  #6 (permalink)  
Old June 15th, 2008, 07:33 PM
Registered User
 
Join Date: Jan 2008
Location: , , .
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default

The code helped me a bit. I'm almost there. I have the strings going to loop through and added together, but I don't know why it's not showing the letters like it's supposed to.

<!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 num;
    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.

        document.hangman.letter.value = "";
        w = 0;
        lettersguess = [];

    // 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'.
        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.

// DON'T TOUCH winlost()!

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();

    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++;
            num = -1;
            foundLets = "";

            for (j=0; j< ranword.length; j++)
                {
                num++;

                if (ranword.charAt(num) == guessletter) {

                    foundLets += ranword.charAt(num);

                         if ((document.hangman.word.value).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();
                                    }
                        }
                }

                else {
                    foundLets += mask.charAt(num);
                // If letter is not in random word, change picture.
                    document.hangpic.src = pics[misses+1];
                    misses++;

                // Alert upon loss, return everything to zero.
                    if (misses == 6) {
                        alert("You lost! The answer was " + ranword);
                        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();
                                }
                    }
                }
            document.hangman.word.value = foundLets;
            break;
            }
        }

    }

}

// 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>
<p>&nbsp;
</p>

</form>

</body>
</html>

  #7 (permalink)  
Old June 16th, 2008, 01:51 PM
Friend of Wrox
 
Join Date: Jun 2008
Location: Snohomish, WA, USA
Posts: 1,649
Thanks: 3
Thanked 141 Times in 140 Posts
Default

Well, I'm using MSIE 6, and it *STILL* does *NOT* allow the indexOf method on an array. So your line
         used = lettersguess.indexOf(guessletter);
*still* doesn't work.

If that method is allowed on arrays in MSIE 7 and/or FireFox, fine. But don't you think you ought to support MSIE 6 and other browsers, as well??
  #8 (permalink)  
Old June 16th, 2008, 02:07 PM
Friend of Wrox
 
Join Date: Jun 2008
Location: Snohomish, WA, USA
Posts: 1,649
Thanks: 3
Thanked 141 Times in 140 Posts
Default

I'm sorry, but your core logic is just too messed up to bother trying to fix this code.

Just for starters, you test the WRONG THING for a "win"!!!

Code:
Code:
                if (ranword.charAt(num) == guessletter) 
                {
                    foundLets += ranword.charAt(num);
                    if ((document.hangman.word.value).indexOf('*') == -1) 
                    {
See? You add the found letter to the list of letters in "foundLets", but *THEN* you check the visible word to see if there are no more asterisks.

But you NEVER UPDATE the visible word with what's in foundLets!!!

Really, it would take me much more time to fix your code than it did for me to write the code all over, which I already did once for you.
  #9 (permalink)  
Old June 16th, 2008, 08:09 PM
Registered User
 
Join Date: Jan 2008
Location: , , .
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thank you for pointing out a couple of my errors, but I gotta say that rewriting code for me doesn't help me. I want to know how to actually do it myself, not practice my copy/pasting.

  #10 (permalink)  
Old June 16th, 2008, 08:35 PM
Friend of Wrox
 
Join Date: Jun 2008
Location: Snohomish, WA, USA
Posts: 1,649
Thanks: 3
Thanked 141 Times in 140 Posts
Default

Well, I don't think I CAN fix it without rewriting it some.

So where's the boundary between fixing and rewriting, for you???




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.