Skip to content

Instantly share code, notes, and snippets.

@mrdrozdov
Created December 5, 2014 02:53
Show Gist options
  • Save mrdrozdov/7a4a5946e37538a6411b to your computer and use it in GitHub Desktop.
Save mrdrozdov/7a4a5946e37538a6411b to your computer and use it in GitHub Desktop.
<body>
<div>Try to guess a correct letter</div>
<div id="incomplete-word"></div>
<div>
<input id="letter-guess"></input>
</div>
<div>Letters Left: <span id="possible-letters"></span>
</div>
<div>Guesses Left: <span id="guesses-left"></span>
</div>
</body>
<script>
// CSS Constants
var cssIncompleteWord = 'incomplete-word';
var cssGuessesLeft = 'guesses-left';
var cssLetterInput = 'letter-guess';
var cssPossibleLetters = 'possible-letters';
// Configuration
var validLetters = 'abcdefghijklmnopqrstuvwxyz';
var lettersToRemove = 3;
var maxGuesses = 5;
var loseMessage = 'So sorry. Try better next time, okey dokey? ^_^';
var winMessage = 'Ta da! You da best! (>\'\')> *@*';
var emptyChar = '_';
var possibleWords = [
'i have the goosebumps',
'up up and away',
'hunter thompson'];
// Globals
var wordToGuessIndex;
var wordToGuess;
var currentWord;
var guessesLeft;
var lettersLeft;
// Event Handlers
document.getElementById(cssLetterInput).onkeypress = function (e) {
if (!e) e = window.event;
var keyCode = e.keyCode || e.which;
var prevValue = getLetterInput();
if (keyCode == '13') {
playRound(prevValue);
} else if (keyCode == '8') {
// backspace
} else if (letterAvailable(lettersLeft, keyCode) && prevValue.length === 0) {
// normal input
} else {
e.preventDefault();
}
}
// Initialization
playGame();
// Game Functions
function letterAvailable(letters, keyCode) {
if (!(keyCode >= 97 && keyCode <= 122)) {
return false;
}
var c = String.fromCharCode(keyCode).toLowerCase();
var i;
for (i = 0; i < letters.length; i++) {
if (letters.charAt(i) === c) {
return true;
}
}
return false;
}
function prepareWord(word, lettersToRemove) {
var letters = validLetters.substr(0);
var lettersRemoved = 0;
var i;
while (lettersRemoved < lettersToRemove) {
var randLetterIndex = randomIntInRange(0, letters.length - 1);
var randLetter = letters[randLetterIndex];
var indexesInWord = getIndexesOfChar(wordToGuess, randLetter);
if (indexesInWord.length > 0) {
for (i = 0; i < indexesInWord.length; i++) {
word = stringByReplacingCharAtIndex(
word, indexesInWord[i], emptyChar);
}
lettersRemoved++;
}
letters = stringByRemovingCharAtIndex(letters, randLetterIndex);
}
for (i = 0; i < word.length; i++) {
if (word.charAt(i) !== emptyChar) {
lettersLeft = lettersLeft.replace(word.charAt(i), '');
}
}
return word;
}
function guessLetter(expectedWord, currentWord, letter) {
var i;
var success = -1;
for (i = 0; i < expectedWord.length; i++) {
if (expectedWord.charAt(i) === letter && currentWord.charAt(i) !== letter) {
currentWord = stringByReplacingCharAtIndex(
currentWord, i, letter);
success++;
}
}
return {
word: currentWord,
success: success
};
}
function playRound(prevValue) {
if (prevValue.length === 1) {
var guessLetterResults = guessLetter(
wordToGuess, currentWord, prevValue);
if (guessLetterResults.success >= 0) {
currentWord = guessLetterResults.word;
if (currentWord === wordToGuess) {
alert(winMessage);
return playGame();
}
} else {
setGuessesLeft(--guessesLeft);
if (guessesLeft < 1) {
alert(loseMessage);
return playGame();
}
}
lettersLeft = stringByRemovingCharAtIndex(
lettersLeft, lettersLeft.indexOf(prevValue));
}
updateUI();
}
function playGame() {
guessesLeft = maxGuesses;
lettersLeft = validLetters.substr(0);
wordToGuessIndex = randomIntInRange(0, possibleWords.length - 1);
wordToGuess = possibleWords[wordToGuessIndex];
currentWord = prepareWord(wordToGuess, lettersToRemove);
updateUI();
}
// Utility
function randomIntInRange(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function stringByRemovingCharAtIndex(str, idx) {
return str.substr(0, idx) + str.substr(idx + 1);
}
function stringByReplacingCharAtIndex(str, idx, replacement) {
return str.substr(0, idx) + replacement + str.substr(idx + 1);
}
function getIndexesOfChar(str, c) {
var results = [];
var i;
for (i = 0; i < str.length; i++) {
if (str.charAt(i) === c) {
results.push(i);
}
}
return results;
}
// UI
function updateUI() {
setLetterInput('');
setIncompleteWord(currentWord);
setPossibleLetters(lettersLeft);
setGuessesLeft(guessesLeft);
}
// Access the DOM
function getLetterInput() {
return document.getElementById(cssLetterInput).value;
}
function setLetterInput(val) {
document.getElementById(cssLetterInput).value = val;
}
function getIncompleteWord() {
return document.getElementById(cssIncompleteWord).innerHTML;
}
function setIncompleteWord(content) {
document.getElementById(cssIncompleteWord).innerHTML = content;
}
function setPossibleLetters(content) {
document.getElementById(cssPossibleLetters).innerHTML = content;
}
function setGuessesLeft(content) {
document.getElementById(cssGuessesLeft).innerHTML = content;
}
/*
Just a note, I prefer using one var statement per line, and am extremely
opposed to Yoda Style commas (in production code). The reasoning is that
Yoda Style commas are harder to lint for (JSHint no longer enforces this
rule). Also, it's been observed that TJ Holowaychuk at one point switched
from Yoda Style to the one var per line style.
*/
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment