SitePoint Sponsor

User Tag List

Results 1 to 12 of 12
  1. #1
    SitePoint Member
    Join Date
    Sep 2013
    Posts
    8
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Allow keys to be only pressed one time

    I'm making a hangman game and I would like the ability to use the keyboard when guessing letters. The issue I'm stuck on is I'm not sure how to let the keys be triggered/pressed only one time. I'm using the Keypress library right now and can't seem to find a way to disable keys once they have been pressed. After googling for a while I found that maybe returning 'false' after the key is pressed will disable it but for some reason it only works on keys: 'a', 'g', and 'i'.

    Code:
    keypress.combo("a",  function(){
      letterClicked('a');
       return false;
        
    });
    
    keypress.combo("b", function(){
      letterClicked('b');
      return false;
    });
    
    keypress.combo("c", function(){
      letterClicked('c');
      return false;
    });
    
    keypress.combo("d", function(){
      letterClicked('d');
      return false;
       
    });
    
    keypress.combo("e", function(){
      letterClicked('e');
      return false;
    }); ////............ and it goes like this for the rest of the alphabet.

  2. #2
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    6,043
    Mentioned
    219 Post(s)
    Tagged
    12 Thread(s)
    Ok, well with hangman you'll only be interested in capturing the keys a - z
    These are represented by the keycodes 65 - 90.

    You can capture a keycode thus:

    Code JavaScript:
    $(document).keyup(function(e) {
        // Key's value is held in e.keyCode; 
    });

    You don't have to use jQuery to do this, but it smooths out a couple of cross-browser compatibility issues, so I'll do so for this example.
    We're also using the .keyup() method, to prevent firing multiple events if a user holds a key down for a long time.

    Then, you need some way of storing keys pressed, so that the user can only press them once:

    Code JavaScript:
    var keysPressed = [];
     
    $(document).keydown(function(e) {
        // Key's value is held in e.keyCode; 
    });

    And you'll need a way of mapping these keycodes to actual letters. For this we can use an object literal:

    Code JavaScript:
    var keysPressed = [];
     
    var keyCodes = {
      65: "a", 
      66: "b", 
      67: "c", 
      68: "d", 
      69: "e", 
      70: "f", 
      71: "g", 
      72: "h", 
      73: "i", 
      74: "j", 
      75: "k", 
      76: "l", 
      77: "m", 
      78: "n", 
      79: "o", 
      80: "p", 
      81: "q", 
      82: "r", 
      83: "s", 
      84: "t", 
      85: "u", 
      86: "v", 
      87: "w", 
      88: "x", 
      89: "y", 
      90: "z" 
    }
     
    $(document).keydown(function(e) {
        // Key's value is held in e.keyCode; 
    });

    Now we'll need some kind of check to see if we are interested in the key pressed:
    You can do this by using an if/else statement and checking that the key code is within the desired range.
    We'll also need somewhere to display the results. Let's use a <p> tag and give it a unique id:

    HTML Code:
    <p id="results">Nothing pressed yet</p>
    Code JavaScript:
    $(document).keydown(function(e) {
      if(e.keyCode > 64 && e.keyCode < 91){
        $("#results").text("You pressed: " + keyCodes[e.keyCode]);
      } else {
        $("#results").text("Key not recognized");
      }
    });

    I'm using the .text() method to alter the contents of the p tag.

    Now we can recognize keys which are relevant for the game and display them on screen.
    The next thing to do is to store them in the array.

    Code JavaScript:
    keysPressed.push(e.keyCode);

    And to stop the array from growing to silly proportions, let's strip out any duplicate values immediately after adding the keypress value.

    Code JavaScript:
    keysPressed = $.unique(keysPressed);

    Note: this is maybe not the best way to do this, but I'm trying to keep things simple.

    Then when a key is pressed, all we need to do is to check the array to see if has been pressed before.
    We can do this using jQuery's .inArray() method.

    Code JavaScript:
    if($.inArray(e.keyCode, keysPressed) === -1){
      $("#results").text("You pressed: " + keyCodes[e.keyCode]);
    } else {
      $("#results").text("You have pressed this key before!!");
    }

    And for good measure, let's give the player some kind of feedback as to what they have pressed:

    HTML Code:
    <p>So far, you have pressed: <span id="keysPressed">nothing</span></p>
    Code JavaScript:
    var keys = keysPressed.map(function(value){
      return keyCodes[value];
    }).sort().join(', ');
     
    $("#keysPressed").text(keys);

    We can do this by looping over our array in which we stored the values of the key presses and mapping them to actual letters.

    Here's everything together. I added a bit of styling and altered the user feedback ever so slightly.

    Code:
    <!DOCTYPE HTML>
    <html>
      <head>
        <meta charset="utf-8">
        <title>keypress example</title>
        <style>
          body{
            background: black;
            padding:15px;
            color: lime;
            font-family: 'Lucida Console', Monaco, monospace;
          }
          
          .warning{
            color: yellow;
          }
        </style>
      </head>
      
      <body>
        <p>Press a key!</p>
        <p id="results">Nothing pressed yet</p>
        <div>So far, you have pressed: <span id="keysPressed">nothing</span></div>
        
        <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
        <script>
          var keysPressed = [];
          
          var keyCodes = {
            65: "a", 
            66: "b", 
            67: "c", 
            68: "d", 
            69: "e", 
            70: "f", 
            71: "g", 
            72: "h", 
            73: "i", 
            74: "j", 
            75: "k", 
            76: "l", 
            77: "m", 
            78: "n", 
            79: "o", 
            80: "p", 
            81: "q", 
            82: "r", 
            83: "s", 
            84: "t", 
            85: "u", 
            86: "v", 
            87: "w", 
            88: "x", 
            89: "y", 
            90: "z" 
          }
          
          $(document).keydown(function(e) {
            if(e.keyCode > 64 && e.keyCode < 91){
              $("#results").text("You pressed: " + keyCodes[e.keyCode]);
              
              if($.inArray(e.keyCode, keysPressed) !== -1){
                $("#results").append("<span class='warning';> - you have pressed this key before!!</span>");
              }
              
              keysPressed.push(e.keyCode);
              keysPressed = $.unique(keysPressed);
            } else {
              $("#results").text("Key not recognized");
            }
            
            var keys = keysPressed.map(function(value){
              return keyCodes[value];
            }).sort().join(', ');
            
            $("#keysPressed").text(keys);
          });
        </script>
      </body>
    </html>
    And here's a demo.

    I hope that helps.

  3. #3
    SitePoint Member
    Join Date
    Sep 2013
    Posts
    8
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well I got this code but it's not running the way I want. The program doesn't know when the key has already been pressed and also the 'letterClicked()' function keeps getting called when the same key is pressed (I tried 'keyup' too). I only want to the user to be able run the letterClicked() function once per key press and never again for the current game. Here is a link to the code if your curious.

    Code:
    $(document).keydown(function(e){
      if(e.keyCode === 65){
        letterClicked('a');
      }
       else if(e.keyCode === 66){
          letterClicked('b');
        }
        else if(e.keyCode === 67){
          letterClicked('c');
        }
    
       else if($.inArray(e.keyCode, keysPressed) !== -1){
          alert("you already pressed this key before.")
          return false;
       
    
        keysPressed.push(e.keyCode);
        keysPressed = $.unique(keysPressed);
       } 
    
      
    });

  4. #4
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    6,043
    Mentioned
    219 Post(s)
    Tagged
    12 Thread(s)
    Hi there,

    It seems the problem is your letterClicked() function.
    It contains a lot of duplicate functionality and has multiple responsibilities which makes the code hard to read and maintain.

    I'm afraid I don't know how to "just make it work", but if you are interested, I can show you how to structure your code better, tidy things up and reduce the duplication.
    Were we to do this, I'm sure your problem would basically solve itself.

    Let me know if you are interested in this.

  5. #5
    SitePoint Member
    Join Date
    Sep 2013
    Posts
    8
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes I'm very interested! I will have many questions on why this is not working but I do want the user to have 2 options when guessing letters, either keyboard or mouse clicking. Is it possible to have both? Anyways I await your help and thank you very much.

  6. #6
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    6,043
    Mentioned
    219 Post(s)
    Tagged
    12 Thread(s)
    Ok then, well I guess the first thing to do is to get a sensible structure in our HTML file.

    I've taken the code you linked to and done the following:
    • tidied up the formatting
    • added a charset declaration
    • removed the links to font-awesome.min.css, buttons.css, buttons.js (all 404)
    • removed the link to the unnecessary keypress.js library
    • moved the jQuery include to the bottom of the page
    • moved the CSS into an external file
    • moved the inline CSS into the same external file
    • moved the JS into an external file
    • removed the inline event handlers (this breaks things)

    That makes things a little less cluttered already.
    I've attached the updated files to this post, so that you can see what I've done.

    Now the next thing to do is to work out the flow of the game.
    I would say something like this:
    • draw the board
    • chose a word
    • wait for user input
    • analyse user input
    • update board
    • check if user has won or lost
    • if not, then go back to waiting for input
    • if so, then display an appropriate message and exit

    Of course these steps can be broken down into many further steps, but I think this describes the gist of it.

    I've got to head off now, but I'll make a start on things later tonight.
    In the meantime, let me know if you have any questions.
    Attached Files Attached Files

  7. #7
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    6,043
    Mentioned
    219 Post(s)
    Tagged
    12 Thread(s)
    Ok then, so the next steps are to select a word, set up the board and to create squares for the individual letters of the words.

    We'll start off by defining a few variables, namely:
    • the elements we'll be dealing with (so we don't have to continuously query the DOM)
    • the words array
    • the current word
    • an object literal containing the seven states of the hangman


    This'll look like this:

    Code JavaScript:
    var board = $("#board"),
        wordContainer = $("wordContainer"),
     
        frames = {
          1:  " \n"+ 
              "_______________ \n" +
              "|                \n" +
              "|                 \n" +   
              "|                  \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n",
     
          2:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|             [   \n" +   
              "|                \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n", 
     
          3:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|             [ ] \n" +   
              "|                \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n",
     
          4:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|             [ ] \n" +   
              "|             L  \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n",
     
          5:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|             [ ] \n" +   
              "|             L L \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n",
     
          6:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|            -[ ] \n" +   
              "|             L L \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n",
     
          7:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|            -[ ]- \n" +   
              "|             L L \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n" 
        },
     
        words = ["happy", "saab", "charles", "computer", "amiga"],
        word;

    This will help us to keep things in one place and to avoid spaghetti code later on.

    Then we want to define some kind of main control structure, where we can write:

    Code JavaScript:
    assignWord();
    updateHangman(frames[1]);
    createWordSquares();

    to select a word and set up the board.

    Those functions look like this:

    Code JavaScript:
    function assignWord(){
      word = words[Math.floor(Math.random() * words.length)]
    }
     
    function updateHangman(frame){
      board.text(frame);
    }
     
    function createWordSquares(){
      for(var i=0, len = word.length; i < len; i++){
        var id = 'letter_' + i;
        $('<div>', {id: id, class: 'wordy'}).appendTo(wordContainer);
      }
    }

    I've attached iteration two of the code to this post, so you can see how things are taking shape.
    Attached Files Attached Files

  8. #8
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    6,043
    Mentioned
    219 Post(s)
    Tagged
    12 Thread(s)
    I'm getting right into this now.

    I've now added an attachEventHandlers() method to attach the click and keyup event handlers to the letters.

    This is as simple as this:

    Code JavaScript:
    var doc = $(document),
        buttons = $(".hov");
     
    function attachEventhandlers(){
      doc.on("keyup", function(e){
        handleKeyPress(e.keyCode);
      });
     
      buttons.on("click", function(){
        handleClick();
      });
    }

    the handleKeyPress() function looks like this:

    Code JavaScript:
    function handleKeyPress(keyCode){
      // Ignore anything but a-z
      // ignore keys already pressed
      //
      if(keyCode < 64 || keyCode > 91 || keyAlreadyPressed(keyCode)){
        return;
      }
     
      // Add key code of key pressed to list of pressed keys
      keysPressed.push(keyCode);
      keysPressed = $.unique(keysPressed);
     
      highlightPressedKey(keyCode);
      var guess = checkGuess();
      if (guess){
        updateWord();
      } else {
        wrongGuesses++;
        updateHangman(frames[wrongGuesses]);
      }
     
      checkResult();
    }

    It basically ignores any input that is not a - z (determined via key code).
    It also ignores any keys which have already been pressed:

    Code JavaScript:
    function keyAlreadyPressed(keyCode){
      return $.inArray(keyCode, keysPressed) !== -1
    }

    This should hopefully be understandable from my original post.

    If it is a valid key which has not been pressed before I am adding a class to the input element representing that key.

    Code JavaScript:
    function highlightPressedKey(keyCode){
      var id = "#" + keyCodes[keyCode];
      $(id).addClass("pressed"); 
    }

    For this to work, I had to give all of the iputs ids:

    HTML Code:
    <input class="hov" id="a" type="button" value="a" />
    <input class="hov" id="b" type="button" value="b" />
    <input class="hov" id="c" type="button" value="c" />
    ...
    This is styled in styles.css:

    Code CSS:
    .pressed{
      color: white
    }
     
    input.pressed:hover{
      background-color: black;
    }

    The rest of the handleKeypress function has yet to be implemented, but I didn't want to run away with myself.
    Attached Files Attached Files

  9. #9
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    6,043
    Mentioned
    219 Post(s)
    Tagged
    12 Thread(s)
    Here's the final iteration for tonight.

    What I've done is to implement the checkGuess(), updateWord() and checkResult() functions.

    These look as follows:

    Code JavaScript:
    function checkGuess(letter){
      return word.indexOf(letter) != -1;
    }

    This returns true if the key pressed is contained within the word, otherwise false.

    Code JavaScript:
    function updateWord(letter){
      var els = word.split('')
                         .map( function(e,i){ if(e === letter) return '#letter_' + i;} )
                         .filter(Boolean)
     
      $.each(els, function(index, value){
        $(value).text(letter).addClass("correct");
      });
    }

    This finds the index(es) at which the letter occurs within the word and returns an array containing the corresponding ids of the lements that have to be updated. It then adds the letter to these elements. I also add a class of "correct" to any letters filled in.

    Code JavaScript:
    function checkResult(){
      var lettersNeeded = word.length,
          lettersCorrect = $(".correct").length,
          gameOver = false;
     
      if (lettersNeeded === lettersCorrect){
        alert("You Won!");
        gameOver = true; 
      } else if(wrongGuesses > 6){
        alert("You lost!");
        gameOver = true; 
      }
     
      if (gameOver){
        removeEventHandlers();
      }
    }

    This is hopefully straight forward. It checks the amount of elements with the class "correct" against the length of the word and reacts accordingly.
    It also checks to see if the maximum number of guesses has been exceeded.

    If the game is deemed to be over, the event handlers are removed, so that the user does not get any more feedback if they click on a button or press a letter key.

    So, I hope that has helped you.

    The game itself is actually playable right now and I'm sure you'll agree, the code is much cleaner and easier to read.

    Over the weekend, I'll implement the click handler, then we'll have the complete game.

    If you have any questions, just let me know.
    Attached Files Attached Files

  10. #10
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    6,043
    Mentioned
    219 Post(s)
    Tagged
    12 Thread(s)
    Ok, so who needs sleep??

    I just finished off the click handler:

    Code JavaScript:
    function handleClick(elClicked){
      var letter = elClicked.attr("id"),
          keyCode = Object.keys(keyCodes).filter(function(key) {
            return keyCodes[key] === letter
          })[0];
     
      if(keyAlreadyPressed(keyCode)){
        return;
      }
     
      keysSelected.push(keyCode);
      keysSelected = $.unique(keysSelected);
     
      highlightPressedKey(letter);
     
      var guess = checkGuess(letter);
      if (guess){
        updateWord(letter);
      } else {
        wrongGuesses++;
        updateHangman(frames[wrongGuesses]);
      }
     
      checkResult();
    }

    Add this to the previous code and you're good to go.

    However, there is quite a lot of duplication between this and the handleKeyPress() function, so it's best to refactor this.
    I'll have a look at that tomorrow.

  11. #11
    SitePoint Member
    Join Date
    Sep 2013
    Posts
    8
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow. Even though the code you wrote is pretty simple to many on this forum, I'm just impressed at how much more it makes sense (even though I don't fully understand everything). I wish I was at this level of programming already. Never in a million years would I have come up with this code but then again I've barely used Jquery so that's where some of the code still is not so clear. So based on the code I wrote, what would you say I should start focusing on? I feel that I struggle at logic and proper structure. Any books I should read, Tips etc..? I will study your code over the next couple days and hopefully things will start to make more sense.

  12. #12
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    6,043
    Mentioned
    219 Post(s)
    Tagged
    12 Thread(s)
    Hi there,

    Just to be complete, I've refactored the event handlers a little.

    Here's the complete code:

    HTML Code:
    <!DOCTYPE HTML>
    <html>
      <head>
        <meta charset="utf-8">
        <link href='http://fonts.googleapis.com/css?family=Monoton' rel='stylesheet' type='text/css'>
        <link href='styles.css' rel='stylesheet' type='text/css'>
      </head>
    
      <body>
        <div class="wrapper">
          <h1>Mr. Synth's Hangman</h1>
          <div class="border1">
            <button name="res" class="button button-rounded button-flat-primary"  type="button">CLEAR</button>
            <div id="winLoose"></div> 
            <pre id="board"></pre>
            <div id="wordContainer"></div>
            <br><br>
            
            <input class="hov" id="a" type="button" value="a" />
            <input class="hov" id="b" type="button" value="b" />
            <input class="hov" id="c" type="button" value="c" />
            <input class="hov" id="d" type="button" value="d" />
            <input class="hov" id="e" type="button" value="e" />
            <input class="hov" id="f" type="button" value="f" />
            <input class="hov" id="g" type="button" value="g" />
            <input class="hov" id="h" type="button" value="h" />
            <input class="hov" id="i" type="button" value="i" />
            <input class="hov" id="j" type="button" value="j" />
            <input class="hov" id="k" type="button" value="k" />
            <input class="hov" id="l" type="button" value="l" />
            <input class="hov" id="m" type="button" value="m" />
            <input class="hov" id="n" type="button" value="n" />
            <input class="hov" id="o" type="button" value="o" />
            <input class="hov" id="p" type="button" value="p" />
            <input class="hov" id="q" type="button" value="q" />
            <input class="hov" id="r" type="button" value="r" />
            <input class="hov" id="s" type="button" value="s" />
            <input class="hov" id="t" type="button" value="t" />
            <input class="hov" id="u" type="button" value="u" />
            <input class="hov" id="v" type="button" value="v" />
            <input class="hov" id="w" type="button" value="w" />
            <input class="hov" id="x" type="button" value="x" />
            <input class="hov" id="y" type="button" value="y" />
            <input class="hov" id="z" type="button" value="z" />
          </div><!--end border1-->
        </div><!--end wrapper-->
        
        <script src="http://code.jquery.com/jquery-latest.min.js"></script>
        <script src="main.js"></script>
      </body>
    </html>
    Code CSS:
    @font-face{
      font-family:digi;
      src:url('https://dl.dropboxusercontent.com/u/1957768/Fonts/ds_digital/DS-DIGIT.TTF') 
      ,url('https://dl.dropboxusercontent.com/u/1957768/Fonts/ds_digital/DS-DIGII.TTF')
      ,url('https://dl.dropboxusercontent.com/u/1957768/Fonts/ds_digital/DS-DIGIB.TTF')
      ,url('https://dl.dropboxusercontent.com/u/1957768/Fonts/ds_digital/DS-DIGI.TTF');
    }
     
    body{
      background-color: #ffc49e;
      color:#d65139;
    }
     
    .border1{
      border:1px solid;
      width:300px;
      height:350px;
      padding-left: 20px;
      padding-top: 20px;
      background-color: dimgray;
      border-radius: 9px;
      box-shadow: 0 0 20px 5px #888;
    }
     
    pre{
      font-size: 1.10em;
      font-weight: 900;
      color:#f9e7c0;
    }
     
    #hangmanBox{
      color:lightPink;
    }
     
    .hov{
      font-size: 15px;
      color: orange;
      background-color: black;
      border-radius: 5px;
      border:none;
    }
     
    .hov:hover{
      background-color: white;
    }
     
    .hov:active{
      color:red;
    }
     
    .wordy{
      text-align: center;  
      float:left;
      margin-right: 2px;
      border-radius: 5px;
      color:orange;
      border:solid 1px white;
      padding:2px;
      width:25px;
      height:25px;
      font-size: 20px;
    }
     
    input{
      color:deepPink;
    }
     
    h1{
      font-family: 'Monoton';
      font-size: 3.0em;
    }
     
    .wrapper{
      width:300px;
      display:block;
      margin-left: auto;
      margin-right: auto;
    }
     
    #winLoose{
      font-family: digi;
      margin-right:40px;
      float:right;
      width:100px;
      height:20px;
      border: 1px solid black;
      text-align: center;
      padding-top:5px;
      font-size: 15px;
      color: lightgreen;
      background-color: black;
    }
     
    .pressed{
      color: white
    }
     
    input.pressed:hover{
      background-color: black;
    }

    Code JavaScript:
    var frames = {
          0:  " \n"+ 
              "_______________ \n" +
              "|                \n" +
              "|                 \n" +   
              "|                  \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n",
     
          1:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|                \n" +   
              "|                \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n", 
     
          2:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|             [  \n" +   
              "|                \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n", 
     
          3:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|             [ ] \n" +   
              "|                \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n",
     
          4:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|             [ ] \n" +   
              "|             L  \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n",
     
          5:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|             [ ] \n" +   
              "|             L L \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n",
     
          6:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|            -[ ] \n" +   
              "|             L L \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n",
     
          7:  " \n"+ 
              "_______________\n" +
              "|              @ \n" +
              "|            -[ ]- \n" +   
              "|             L L \n" +   
              "| \n" +
              "| \n" +
              "| \n" +
              "| \n" +
              "======= \n" 
        },
     
        keyCodes = {
          65: "a", 
          66: "b", 
          67: "c", 
          68: "d", 
          69: "e", 
          70: "f", 
          71: "g", 
          72: "h", 
          73: "i", 
          74: "j", 
          75: "k", 
          76: "l", 
          77: "m", 
          78: "n", 
          79: "o", 
          80: "p", 
          81: "q", 
          82: "r", 
          83: "s", 
          84: "t", 
          85: "u", 
          86: "v", 
          87: "w", 
          88: "x", 
          89: "y", 
          90: "z" 
        },
        keysSelected = [],
        board = $("#board"),
        wordContainer = $("#wordContainer"),
        doc = $(document),
        buttons = $(".hov"),
        words = ["happy", "saab", "charles", "computer", "amiga"],
        word,
        wrongGuesses = 0;
     
    function assignWord(){
      word = words[Math.floor(Math.random() * words.length)]
    }
     
    function updateHangman(frame){
      board.text(frame);
    }
     
    function createWordSquares(){
      for(var i=0, len = word.length; i < len; i++){
        var id = 'letter_' + i;
        $('<div>', {id: id, class: 'wordy'}).appendTo(wordContainer);
      }
    }
     
    function attachEventhandlers(){
      doc.on("keyup", function(e){
        handleKeyPress(e.keyCode);
      });
     
      buttons.on("click", function(){
        handleClick($(this));
      });
    }
     
    function keyAlreadyPressed(keyCode){
      return $.inArray(keyCode, keysSelected) !== -1
    }
     
    function highlightPressedKey(letter){
      var id = "#" + letter;
      $(id).addClass("pressed"); 
    }
     
    function guessedCorrectly(letter){
      return word.indexOf(letter) != -1;
    }
     
    function updateWord(letter){
      var els = word.split('')
                    .map( function(e,i){ if(e === letter) return '#letter_' + i;} )
                    .filter(Boolean)
     
      $.each(els, function(index, value){
        $(value).text(letter).addClass("correct");
      });
    }
     
    function checkResult(){
      var lettersNeeded = word.length,
          lettersCorrect = $(".correct").length,
          gameOver = false;
     
      if (lettersNeeded === lettersCorrect){
        alert("You Won!");
        gameOver = true; 
      } else if(wrongGuesses > 6){
        alert("You lost!");
        gameOver = true; 
      }
     
      if (gameOver){
        removeEventHandlers();
      }
    }
     
    function removeEventHandlers(){
      doc.off("keyup");
      buttons.off("click");
    }
     
    function addKeyodeToArray(keyCode){
    	keysSelected.push(keyCode);
      keysSelected = $.unique(keysSelected);
    }
     
    function checkGuess(letter){
      if (guessedCorrectly(letter)){
        updateWord(letter);
      } else {
        wrongGuesses++;
        updateHangman(frames[wrongGuesses]);
      }
    }
     
    function handleKeyPress(keyCode){
      if(keyCode < 64 || keyCode > 91 || keyAlreadyPressed(keyCode)){
        return;
      }
     
      var letter = keyCodes[keyCode];
     
    	addKeyodeToArray(keyCode);
      highlightPressedKey(letter);
    	checkGuess(letter);
      checkResult();
    }
     
    function handleClick(elClicked){
      if(keyAlreadyPressed(keyCode)){
        return;
      }
     
      var letter = elClicked.attr("id"),
          keyCode = Object.keys(keyCodes).filter(function(key) {
            return keyCodes[key] === letter
          })[0];
     
    	addKeyodeToArray(keyCode);
      highlightPressedKey(letter);
    	checkGuess(letter);
      checkResult();
    }
     
    // Setup 
    assignWord();
    console.log(word);
    updateHangman(frames[wrongGuesses]);
    createWordSquares();
    attachEventhandlers();

    Quote Originally Posted by oxxi View Post
    So based on the code I wrote, what would you say I should start focusing on? I feel that I struggle at logic and proper structure. Any books I should read, Tips etc..?
    To be honest, the use of jQuery is incidental here. It was purely to make my life easier when helping you with this, so it shouldn't be a "new technology" to learn.
    If you want to get a bit deeper into JavaScript, I would recommend a book such as Eloquent JavaScript. It's free to read online, so you can try before you buy.

    My suggestions of how to take this forward:


    I hope that helps. Just let me know if you have any questions (although I am off on vacation soon, so won't be around for a couple of weeks).


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •