Last active
December 31, 2015 00:18
-
-
Save electricg/7906164 to your computer and use it in GitHub Desktop.
Hangman game
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Hangman</title> | |
<meta name="author" content="Giulia Alfonsi"> | |
<meta name="description" content="Giulia Alfonsi's Hangman game"> | |
<style> | |
textarea { | |
border: 1px solid #999; | |
font-family: monospace; | |
font-size: 1.2em; | |
height: 22em; | |
width: 100%; | |
} | |
input { | |
border: 1px solid #999; | |
margin-left: 1em; | |
} | |
</style> | |
</head> | |
<body> | |
<script> | |
var dictionary = [ | |
{ | |
cat: 'colors', | |
words: ['red', 'green', 'yellow', 'blue', 'white', 'black', 'brown', 'orange', 'purple', 'pink', 'cyan', 'magenta'] | |
}, | |
{ | |
cat: 'fruits', | |
words: ['apple', 'orange', 'banana', 'pear', 'strawberry', 'cherry', 'pineapple', 'peach', 'pomegranate', 'apricot', 'raspberry', 'watermelon'] | |
}, | |
{ | |
cat: 'flowers', | |
words: ['rose', 'daisy', 'tulip', 'poppy', 'daffodil', 'bluebell', 'lilly', 'violet', 'narcisuss', 'chrysanthemum', 'carnation'] | |
} | |
]; | |
var _MAX_ATTEMPTS = 10; | |
// I couldn't resist from drawing an ASCII hangman | |
var pictures = [ | |
/* | |
_________ | |
| / | | |
|/ | | |
| @ | |
| /|\ | |
| / \ | |
_|____________ | |
/ | /| | |
/_____________ // | |
|______________|/ | |
*/ | |
'\ | |
\n\ | |
\n\ | |
\n\ | |
\n\ | |
\n\ | |
\n\ | |
______________\n\ | |
/ /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
', | |
'\ | |
\n\ | |
|\n\ | |
|\n\ | |
|\n\ | |
|\n\ | |
|\n\ | |
_|____________\n\ | |
/ | /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
', | |
'\ | |
_________\n\ | |
|\n\ | |
|\n\ | |
|\n\ | |
|\n\ | |
|\n\ | |
_|____________\n\ | |
/ | /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
', | |
'\ | |
_________\n\ | |
| /\n\ | |
|/\n\ | |
|\n\ | |
|\n\ | |
|\n\ | |
_|____________\n\ | |
/ | /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
', | |
'\ | |
_________\n\ | |
| / |\n\ | |
|/ |\n\ | |
|\n\ | |
|\n\ | |
|\n\ | |
_|____________\n\ | |
/ | /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
', | |
'\ | |
_________\n\ | |
| / |\n\ | |
|/ |\n\ | |
| @\n\ | |
|\n\ | |
|\n\ | |
_|____________\n\ | |
/ | /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
', | |
'\ | |
_________\n\ | |
| / |\n\ | |
|/ |\n\ | |
| @\n\ | |
| |\n\ | |
|\n\ | |
_|____________\n\ | |
/ | /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
', | |
'\ | |
_________\n\ | |
| / |\n\ | |
|/ |\n\ | |
| @\n\ | |
| /|\n\ | |
|\n\ | |
_|____________\n\ | |
/ | /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
', | |
'\ | |
_________\n\ | |
| / |\n\ | |
|/ |\n\ | |
| @\n\ | |
| /|\\\n\ | |
|\n\ | |
_|____________\n\ | |
/ | /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
', | |
'\ | |
_________\n\ | |
| / |\n\ | |
|/ |\n\ | |
| @\n\ | |
| /|\\\n\ | |
| /\n\ | |
_|____________\n\ | |
/ | /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
', | |
'\ | |
_________\n\ | |
| / |\n\ | |
|/ |\n\ | |
| @\n\ | |
| /|\\\n\ | |
| / \\\n\ | |
_|____________\n\ | |
/ | /|\n\ | |
/_____________ //\n\ | |
|______________|/\ | |
' | |
]; | |
/** | |
* Core Hangman game API | |
*/ | |
var Hangman = function(words) { | |
var word = '', | |
result = {}, | |
emptyWord = '', | |
usedLetters = '', | |
leftLetters = 'abcdefghijklmnopqrstuvwxyz', | |
attempts = 0, | |
end = false; | |
/** | |
* Pick word to guess | |
* @returns {string} | |
*/ | |
var pickWord = function() { | |
var len = words.length, | |
index = Math.floor(Math.random() * len); | |
return words[index]; | |
}; | |
/** | |
* Check letter against solution | |
* @param {string} c - letter to check | |
* @returns {string} status of the attempt - yes|no | |
*/ | |
var checkLetter = function(c) { | |
var status; | |
if (typeof result[c] === "undefined") { | |
status = 'no'; | |
} | |
else { | |
status = 'yes'; | |
} | |
return status; | |
}; | |
/** | |
* Update current user solution with given letter | |
* @param {string} c - letter to use | |
*/ | |
var updateEmptyWord = function(c) { | |
for (var i = 0; i < result[c].length; i++) { | |
var index = result[c][i]; | |
emptyWord = emptyWord.substr(0, index) + c + emptyWord.substr(index + 1); | |
} | |
}; | |
/** | |
* Check victory/defeat status | |
* @returns {string} | |
*/ | |
this.checkVictory = function() { | |
var status = ''; | |
if (attempts >= _MAX_ATTEMPTS) { | |
if (word === emptyWord) { | |
status = 'victory'; | |
} | |
else { | |
status = 'too many attempts'; | |
} | |
end = true; | |
} | |
else { | |
if (word === emptyWord) { | |
status = 'victory'; | |
end = true; | |
} | |
} | |
return status; | |
}; | |
/** | |
* Return current user solution | |
* @returns {string} | |
*/ | |
this.getEmptyWord = function() { | |
return emptyWord; | |
}; | |
/** | |
* Return attempts | |
* @returns {number} | |
*/ | |
this.getAttempts = function() { | |
return attempts; | |
}; | |
/** | |
* Return tried letters in attempt order | |
* @returns {string} | |
*/ | |
this.getUsedLetters = function() { | |
return usedLetters; | |
}; | |
/** | |
* Return letters yet to try in alphabetic order | |
* @returns {string} | |
*/ | |
this.getLeftLetters = function() { | |
return leftLetters; | |
}; | |
/** | |
* Return solution if game is over | |
* @returns {string} | |
*/ | |
this.getSolution = function() { | |
if (end === true) { | |
return word; | |
} | |
else { | |
return ''; | |
} | |
}; | |
/** | |
* Update game with given letter | |
* @param {string} c - letter to use | |
* @returns {string} status of the input | |
*/ | |
this.input = function(c) { | |
if (end) { | |
return 'game over'; | |
} | |
c = c.toString(); | |
if (c.length !== 1) { | |
return 'only 1 char'; | |
} | |
c = c.toLowerCase(); | |
if (c.charCodeAt(0) < 97 || c.charCodeAt(0) > 122) { | |
return 'only alphabet'; | |
} | |
if (usedLetters.indexOf(c) !== -1) { | |
return 'letter already used'; | |
} | |
var status = checkLetter(c); | |
if (status === 'yes') { | |
updateEmptyWord(c); | |
} | |
else { | |
attempts++; | |
} | |
usedLetters += c; | |
leftLetters = leftLetters.replace(c, ''); | |
return status; | |
}; | |
/** | |
* Start game | |
*/ | |
this.init = function() { | |
word = pickWord(); | |
for (var i = 0; i < word.length; i++) { | |
var w = word[i]; | |
if (typeof result[w] === "undefined") { | |
result[w] = []; | |
} | |
result[w].push(i); | |
emptyWord += '_'; | |
} | |
}; | |
}; | |
/** | |
* Interface | |
* @param {string} output - 'console' for browser console | 'txt' for textarea | |
*/ | |
var HangmanGraphic = function(output) { | |
var h, | |
word, | |
len, | |
att, | |
attLeft, | |
prettyWord, | |
usedLetters, | |
leftLetters, | |
cat; | |
var printOutput, | |
clearOutput, | |
par1, | |
par2, | |
par3; | |
if (output === 'txt') { | |
var fase = 0; | |
var $txt = document.createElement('textarea'), | |
$lbl = document.createElement('label'), | |
$inp = document.createElement('input'), | |
$btn = document.createElement('input'), | |
$form = document.createElement('form'); | |
document.body.appendChild($form); | |
$form.appendChild($txt); | |
$lbl.innerHTML = 'INPUT:'; | |
$form.appendChild($lbl); | |
$lbl.appendChild($inp); | |
$form.appendChild($btn); | |
$txt.readOnly = true; | |
$inp.type = 'text'; | |
$btn.type = 'submit'; | |
$btn.value = 'SEND'; | |
Element.prototype.on = Element.prototype.addEventListener; | |
var prev = function(event) { | |
if (event.preventDefault) { event.preventDefault(); } | |
else { event.returnValue = false; } | |
}; | |
$form.on('submit', function(event) { | |
prev(event); | |
if (fase === 0) { | |
if ($inp.value.toLowerCase() === 'start') { | |
fase++; | |
$inp.value = ''; | |
window.start(); | |
} | |
} | |
else if (fase === 1) { | |
window.cat($inp.value); | |
} | |
else if (fase === 2) { | |
window.use($inp.value); | |
} | |
}); | |
printOutput = function(o) { | |
$txt.value += o + '\n'; | |
}; | |
clearOutput = function() { | |
$txt.value = ''; | |
}; | |
par1 = 'THE number'; | |
par2 = 'THE letter'; | |
par3 = ''; | |
} | |
else if (output === 'console') { | |
printOutput = function() { | |
return console.info.apply( console, arguments ); | |
}; | |
clearOutput = function() { | |
return console.clear.apply( console, arguments ); | |
}; | |
par1 = 'cat(number)'; | |
par2 = 'use("letter")'; | |
par3 = '()'; | |
} | |
else { | |
return; | |
} | |
var printWord = function() { | |
return word.split('').join(' '); | |
}; | |
window.start = function() { | |
clearOutput(); | |
printOutput('===> GAME START'); | |
printOutput('===> CHOOSE ONE OF THE FOLLOWING CATEGORIES:'); | |
for (var i =0; i < dictionary.length; i++) { | |
printOutput('===> ' + (i + 1) + ' - ' + dictionary[i].cat); | |
} | |
printOutput('===> TYPE ' + par1 + ' TO SELECT IT'); | |
}; | |
window.cat = function(n) { | |
n = Math.floor(n); | |
if (isNaN(n) || n < 1 || n > dictionary.length) { | |
printOutput('===> PLEASE ENTER A VALID NUMBER'); | |
return; | |
} | |
clearOutput(); | |
n = n - 1; | |
cat = dictionary[n].cat; | |
h = new Hangman(dictionary[n].words); | |
h.init(); | |
word = h.getEmptyWord(); | |
len = word.length; | |
att = h.getAttempts(); | |
attLeft = _MAX_ATTEMPTS - att; | |
prettyWord = printWord(); | |
printOutput('===> YOU HAVE SELECTED "' + cat + '"'); | |
printOutput('===> TYPE ' + par2); | |
printOutput('===> THE WORD IS: ' + prettyWord + ' (' + len + ' LETTERS) - ' + attLeft + ' ATTEMPTS LEFT'); | |
printOutput(pictures[att]); | |
if (output === 'txt') { | |
fase++; | |
$inp.value = ''; | |
} | |
}; | |
window.use = function(c) { | |
var status = h.input(c), | |
status2 = h.checkVictory(), | |
msg, | |
msg2; | |
word = h.getEmptyWord(); | |
att = h.getAttempts(); | |
attLeft = _MAX_ATTEMPTS - att; | |
prettyWord = printWord(); | |
usedLetters = h.getUsedLetters(); | |
leftLetters = h.getLeftLetters(); | |
switch(status) { | |
case 'yes': | |
msg = '===> GOOD JOB - LETTER FOUND!'; | |
break; | |
case 'no': | |
msg = '===> I AM SORRY - LETTER NOT FOUND!'; | |
break; | |
case 'game over': | |
msg = '===> GAME OVER'; | |
break; | |
case 'only 1 char': | |
msg = '===> ONLY ONE LETTER ALLOWED'; | |
break; | |
case 'letter already used': | |
msg = '===> LETTER ALREADY USED'; | |
break; | |
case 'only alphabet': | |
msg = '===> ONLY ALPHABETIC LETTERS ARE ALLOWED'; | |
break; | |
} | |
switch(status2) { | |
case 'victory': | |
msg2 = '===> CONGRATULATIONS! YOU WON!'; | |
break; | |
case 'too many attempts': | |
msg2 = '===> I AM SORRY - NO ATTEMPTS LEFT\n===> GAME OVER'; | |
word = h.getSolution(); | |
prettyWord = printWord(); | |
break; | |
default: | |
msg2 = ''; | |
break; | |
} | |
if (output === 'txt') { | |
$inp.value = ''; | |
} | |
clearOutput(); | |
printOutput(msg); | |
if (msg2 !== '') { | |
printOutput(msg2); | |
} | |
printOutput('===> THE WORD IS: ' + prettyWord + ' (' + len + ' LETTERS) - ' + attLeft + ' ATTEMPTS LEFT - CATEGORY: ' + cat); | |
printOutput('===> LETTERS USED: ' + usedLetters); | |
printOutput('===> LETTERS LEFT: ' + leftLetters); | |
printOutput(pictures[att]); | |
}; | |
printOutput('===> WELCOME TO HANGMAN'); | |
printOutput('===> TO START, TYPE start' + par3); | |
}; | |
var hangmanGraphic = new HangmanGraphic('txt'); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Live demo at http://giulia.org.uk/demo/hangman.html