diff --git a/30DaysOfJavaScript/assets/36.png b/30DaysOfJavaScript/assets/36.png new file mode 100644 index 00000000..63022d60 Binary files /dev/null and b/30DaysOfJavaScript/assets/36.png differ diff --git a/36 - Hangman/assets/hangman-game.png b/36 - Hangman/assets/hangman-game.png new file mode 100644 index 00000000..9e2c33bc Binary files /dev/null and b/36 - Hangman/assets/hangman-game.png differ diff --git a/36 - Hangman/index.html b/36 - Hangman/index.html new file mode 100644 index 00000000..ba10ed73 --- /dev/null +++ b/36 - Hangman/index.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html> +<head> + <link rel="shortcut icon" href="assets/hangman-game.png" type="image/x-icon"> + <link rel="stylesheet" href="./styles.css"> + <title>Hangman</title> +</head> +<body> + <div id="main"> + <h1>HANGMAN</h1> + <p class="desc">Here's your popular word guessing game <br> Build a missing word by guessing one letter at a time. <br> After 5 incorrect guesses, the game ends and the player loses.<br> Correctly identify all the letters of the missing word to win.</p> + <div class="puzzle-box"> + <div id="puzzle" class="puzzle"></div> + <p id="guesses"></p> + <button id="reset" class="button">Reset</button> + </div> + </div> + <script src="./scripts/request.js"></script> + <script src="./scripts/hangman.js"></script> + <script src="./scripts/app.js"></script> +</body> +</html> \ No newline at end of file diff --git a/36 - Hangman/scripts/app.js b/36 - Hangman/scripts/app.js new file mode 100644 index 00000000..fec27d28 --- /dev/null +++ b/36 - Hangman/scripts/app.js @@ -0,0 +1,30 @@ +let game1 +const puzzleDIV = document.querySelector('#puzzle'); +const remainingDIV = document.querySelector('#guesses'); + +window.addEventListener('keypress', (e) => { + + const guess = String.fromCharCode(e.charCode); + game1.makeGuess(guess); + render() +}) + +const render = () => { + puzzleDIV.innerHTML = '' + remainingDIV.textContent = game1.statusMessage; + + game1.puzzle.split('').forEach((letter) => { + const letterEl = document.createElement('span') + letterEl.textContent = letter + puzzleDIV.appendChild(letterEl) + }) +} + +const startGame = async () => { + const puzzle = await getPuzzle('3') + game1 = new Hangman(puzzle, 5) + render() +} + +document.querySelector('#reset').addEventListener('click', startGame) +startGame() \ No newline at end of file diff --git a/36 - Hangman/scripts/hangman.js b/36 - Hangman/scripts/hangman.js new file mode 100644 index 00000000..56b5cd15 --- /dev/null +++ b/36 - Hangman/scripts/hangman.js @@ -0,0 +1,66 @@ +class Hangman { + constructor(word, remainingGuesses){ + this.word = word.toLowerCase().split(''); + this.remainingGuesses = remainingGuesses; + this.guessedLetters = []; + this.status = 'playing'; + } + + get puzzle() { + let puzzle = ''; + this.word.forEach((letter) => { + if (this.guessedLetters.includes(letter) || letter === ' '){ + puzzle += letter; + } else { + puzzle += '*' + } + }) + return puzzle; + } + + makeGuess (guess){ + guess = guess.toLowerCase(); + const isUnique = !this.guessedLetters.includes(guess); + const isBadGuess = !this.word.includes(guess); + + if (this.status !== 'playing'){ + return + } + + if (isUnique){ + this.guessedLetters.push(guess) + } + + if (isUnique && isBadGuess){ + this.remainingGuesses-- + } + this.calculateStatus(); + } + + get statusMessage(){ + if (this.status === 'playing'){ + return `Guesses left: ${this.remainingGuesses}` + } else if (this.status === 'failed') { + return `Nice try! The word was "${this.word.join('')}" ` + } else { + return 'Great work! You guessed the word right!' + } + } + + calculateStatus(){ + const finished = this.word.every((letter) => this.guessedLetters.includes(letter) || letter === ' ') + + if (this.remainingGuesses === 0){ + this.status = 'failed' + } else if (finished){ + this.status = 'finished' + } else { + this.status = 'playing' + } + } + +} + + + + diff --git a/36 - Hangman/scripts/request.js b/36 - Hangman/scripts/request.js new file mode 100644 index 00000000..58c53ffd --- /dev/null +++ b/36 - Hangman/scripts/request.js @@ -0,0 +1,10 @@ +const getPuzzle = async (wordCount) => { + const response = await fetch(`https://puzzle.mead.io/puzzle?wordCount=${wordCount}`) + if (response.status === 200){ + const data = await response.json() + return data.puzzle + } else { + throw new Error('Unable to fetch puzzle') + } +} + \ No newline at end of file diff --git a/36 - Hangman/styles.css b/36 - Hangman/styles.css new file mode 100644 index 00000000..a21b0557 --- /dev/null +++ b/36 - Hangman/styles.css @@ -0,0 +1,82 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html { + font-size: 62.5%; +} + +#main{ + margin-top: 100px; +} + +body { + background: #19172e; + color: #fafafa; + font-family: Helvetica, Arial, sans-serif; + font-size: 1.6rem; + display: flex; + justify-content: center; + min-height: 100vh; + text-align: center; +} + +span { + border-bottom: 1px solid #534f59; + display: inline-block; + font-size: 2rem; + height: 2.4rem; + line-height: 2.4rem; + margin: 0 .1rem; + text-align: center; + text-transform: uppercase; + width: 2.4rem; +} + +h1{ + color: #976dc4; + font-weight: 600; + font-size: 4rem; +} + +.desc{ + word-wrap: break-word; + max-width: 600px; + margin: 20px auto; + text-align: center; + font-size: 1.7rem; + line-height: 1.5; +} + +p { + font-weight: 300; + margin-bottom: .8rem; +} + +.puzzle { + display: flex; + margin-bottom: 4.8rem; +} + +.puzzle-box{ + margin-top: 150px; + text-align: center; +} + +.button { + background: #7044a0; + border: none; + border-bottom: 2px solid #603a88; + cursor: pointer; + color: white; + font-size: 1.4rem; + font-weight: 300; + padding: .8rem; + transition: background .3s ease, color .3s ease; +} + +.button:hover { + background: #5F3A87; +} \ No newline at end of file diff --git a/index.html b/index.html index a56230b2..adc0ef95 100644 --- a/index.html +++ b/index.html @@ -250,7 +250,14 @@ <h4>Decimal to Binary</h4> <img src="30DaysOfJavaScript/assets/35.png" alt="Virtual Piano"> </a> </div> + <div class="item"> + <a target="_blank" href="36 - Hangman/index.html"> + <h4>Hangman</h4> + <img src="30DaysOfJavaScript/assets/36.png" alt="Hangman" /> + </a> + </div> </div> + <footer> <p>< / > with ❤️ by <a href="https://swapnilsparsh.github.io/">Swapnil Srivastava</a>