From 26f221b97972829deb7bea5d5c0f7d52b090bd32 Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 11:27:55 +0000 Subject: [PATCH 01/12] complete class Hangman constructor --- javascript/hangman.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/javascript/hangman.js b/javascript/hangman.js index ee01d18..5a658c2 100644 --- a/javascript/hangman.js +++ b/javascript/hangman.js @@ -1,11 +1,14 @@ class Hangman { constructor(words) { - this.words = words; - // ... your code goes here + this.words = words; // All the possible words + this.secretWord = this.pickWord(); // Random selected word + this.letters = []; // Already selected letters + this.guessedLetters = ""; // Correct letters string + this.errorsLeft = 10; // Errors allowed } pickWord() { - // ... your code goes here + } checkIfLetter(keyCode) { From 4d763d8981631fc8f8f66687903c5723c32794fb Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 11:29:02 +0000 Subject: [PATCH 02/12] complete pickWord() --- javascript/hangman.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/hangman.js b/javascript/hangman.js index 5a658c2..5ab7892 100644 --- a/javascript/hangman.js +++ b/javascript/hangman.js @@ -8,7 +8,8 @@ class Hangman { } pickWord() { - + const randIndex = Math.floor(Math.random() * this.words.length); + return this.words[randIndex]; } checkIfLetter(keyCode) { From 319c5fa7bc583835c041621c6d13fd5b0f69173d Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 11:31:45 +0000 Subject: [PATCH 03/12] complete checkIfLetter() --- javascript/hangman.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/hangman.js b/javascript/hangman.js index 5ab7892..c6d257c 100644 --- a/javascript/hangman.js +++ b/javascript/hangman.js @@ -7,13 +7,15 @@ class Hangman { this.errorsLeft = 10; // Errors allowed } + // Return randomly selected word from the words array pickWord() { const randIndex = Math.floor(Math.random() * this.words.length); return this.words[randIndex]; } + // Check if keyCode is A-Z checkIfLetter(keyCode) { - // ... your code goes here + return keyCode >= 65 && keyCode <= 90; } checkClickedLetters(letter) { From bc8a04d5ade0985765bae094ceec5bec933357a2 Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 11:33:49 +0000 Subject: [PATCH 04/12] complete checkClickedLetters() --- javascript/hangman.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/hangman.js b/javascript/hangman.js index c6d257c..d6b8d13 100644 --- a/javascript/hangman.js +++ b/javascript/hangman.js @@ -18,8 +18,9 @@ class Hangman { return keyCode >= 65 && keyCode <= 90; } + // Check if letter was already clicked (true means NOT clicked yet) checkClickedLetters(letter) { - // ... your code goes here + return !this.letters.includes(letter); } addCorrectLetter(letter) { From 46ed32b5d068115d878dc7540b3911fb75cccff0 Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 11:37:43 +0000 Subject: [PATCH 05/12] complete addCorrectLetter() --- javascript/hangman.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/javascript/hangman.js b/javascript/hangman.js index d6b8d13..5cda1ad 100644 --- a/javascript/hangman.js +++ b/javascript/hangman.js @@ -23,8 +23,11 @@ class Hangman { return !this.letters.includes(letter); } + // Add correct letter to guessedLetters addCorrectLetter(letter) { - // ... your code goes here + this.guessedLetters += letter; + // Check if player has guessed all the letters (win condition) + return this.checkWinner(); } addWrongLetter(letter) { From f3ab8f03b6cf961eaef727be9a6ad61f728d367c Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 11:40:29 +0000 Subject: [PATCH 06/12] complete addWrongLetter() --- javascript/hangman.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/javascript/hangman.js b/javascript/hangman.js index 5cda1ad..e96e2e7 100644 --- a/javascript/hangman.js +++ b/javascript/hangman.js @@ -30,8 +30,12 @@ class Hangman { return this.checkWinner(); } + // Add wrong letter and reduce errors addWrongLetter(letter) { - // ... your code goes here + if(!this.letters.includes(letter)) { + this.letters.push(letter); //store tried letters + } + this.errorLeft -= 1; } checkGameOver() { From 576d0fe454b090aa2b1e75d9184a97d3114166ea Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 11:41:55 +0000 Subject: [PATCH 07/12] complete checkGameOver() --- javascript/hangman.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/hangman.js b/javascript/hangman.js index e96e2e7..88f7c27 100644 --- a/javascript/hangman.js +++ b/javascript/hangman.js @@ -38,8 +38,9 @@ class Hangman { this.errorLeft -= 1; } + // If no errors left -> game over checkGameOver() { - // ... your code goes here + return this.errorsLeft <= 0; } checkWinner() { From d18979b7ac1916c5dcd6f58e8b1871cf59e0f76b Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 11:43:43 +0000 Subject: [PATCH 08/12] complete checkWinner() --- javascript/hangman.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/javascript/hangman.js b/javascript/hangman.js index 88f7c27..7b757aa 100644 --- a/javascript/hangman.js +++ b/javascript/hangman.js @@ -43,8 +43,14 @@ class Hangman { return this.errorsLeft <= 0; } + // Player wins if guessedLetters contains all letters of secretWord checkWinner() { - // ... your code goes here + for (let char of this.secretWord) { + if (!this.guessedLetters.includes(char)) { + return false; + } + } + return true; } } From edddd3c0cc7a63dcdda7cbb2e1de9872141e8a5d Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 14:03:43 +0000 Subject: [PATCH 09/12] complete canvas.js --- javascript/canvas.js | 142 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 133 insertions(+), 9 deletions(-) diff --git a/javascript/canvas.js b/javascript/canvas.js index ad78760..e301621 100644 --- a/javascript/canvas.js +++ b/javascript/canvas.js @@ -1,34 +1,158 @@ class HangmanCanvas { constructor(secretWord) { - this.context = document.getElementById('hangman').getContext('2d'); - // ... your code goes here + this.secretWord = secretWord; + this.canvas = document.getElementById('hangman'); + this.context = this.canvas.getContext('2d'); } createBoard() { - // ... your code goes here + this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); + this.drawLines(); } drawLines() { - // ... your code goes here + const ctx = this.context; + const startX = 200; + const startY = 500; + const lineWidth = 50; + const gap = 15; + + ctx.lineWidth = 3; + + for (let i = 0; i < this.secretWord.length; i++) { + let x = startX + i * (lineWidth + gap); + + ctx.beginPath(); + ctx.moveTo(x, startY); + ctx.lineTo(x + lineWidth, startY); + ctx.stroke(); + ctx.closePath(); + } } writeCorrectLetter(index) { - // ... your code goes here + const ctx = this.context; + const letter = this.secretWord[index].toUpperCase(); + + const startX = 200; + const startY = 495; + const lineWidth = 50; + const gap = 15; + + ctx.font = "40px Arial"; + ctx.fillStyle = "black"; + + const x = startX + index * (lineWidth + gap) + 10; + + ctx.fillText(letter, x, startY - 10); } writeWrongLetter(letter, errorsLeft) { - // ... your code goes here + const ctx = this.context; + + ctx.font = "40px Arial"; + ctx.fillStyle = "red"; + + // Wrong letters area + const x = 700; + const y = 100 + (10 - errorsLeft) * 45; + + ctx.fillText(letter.toUpperCase(), x, y); } drawHangman(errorsLeft) { - // ... your code goes here + const ctx = this.context; + ctx.lineWidth = 4; + + switch (errorsLeft) { + case 9: // Base + ctx.beginPath(); + ctx.moveTo(100, 500); + ctx.lineTo(300, 500); + ctx.stroke(); + break; + + case 8: // Left vertical + ctx.beginPath(); + ctx.moveTo(150, 500); + ctx.lineTo(150, 100); + ctx.stroke(); + break; + + case 7: // Top bar + ctx.beginPath(); + ctx.moveTo(150, 100); + ctx.lineTo(350, 100); + ctx.stroke(); + break; + + case 6: // Rope + ctx.beginPath(); + ctx.moveTo(350, 100); + ctx.lineTo(350, 150); + ctx.stroke(); + break; + + case 5: // Head + ctx.beginPath(); + ctx.arc(350, 190, 40, 0, Math.PI * 2); + ctx.stroke(); + break; + + case 4: // Body + ctx.beginPath(); + ctx.moveTo(350, 230); + ctx.lineTo(350, 350); + ctx.stroke(); + break; + + case 3: // Left arm + ctx.beginPath(); + ctx.moveTo(350, 260); + ctx.lineTo(300, 310); + ctx.stroke(); + break; + + case 2: // Right arm + ctx.beginPath(); + ctx.moveTo(350, 260); + ctx.lineTo(400, 310); + ctx.stroke(); + break; + + case 1: // Left leg + ctx.beginPath(); + ctx.moveTo(350, 350); + ctx.lineTo(300, 430); + ctx.stroke(); + break; + + case 0: // Right leg + ctx.beginPath(); + ctx.moveTo(350, 350); + ctx.lineTo(400, 430); + ctx.stroke(); + break; + } } + // When user loses gameOver() { - // ... your code goes here + const img = new Image(); + img.src = './images/gameover.png'; + + img.onload = () => { + this.context.drawImage(img, 100, 50, 400, 400); + }; } + // When user wins winner() { - // ... your code goes here + const img = new Image(); + img.src = './images/awesome.png'; + + img.onload = () => { + this.context.drawImage(img, 100, 50, 400, 400); + }; } } From 107b319de247a630ae1c066e12bf7907539d66f4 Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 14:07:59 +0000 Subject: [PATCH 10/12] complete game --- javascript/hangman.js | 80 +++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/javascript/hangman.js b/javascript/hangman.js index 7b757aa..3caed4a 100644 --- a/javascript/hangman.js +++ b/javascript/hangman.js @@ -1,49 +1,41 @@ class Hangman { constructor(words) { - this.words = words; // All the possible words - this.secretWord = this.pickWord(); // Random selected word - this.letters = []; // Already selected letters - this.guessedLetters = ""; // Correct letters string - this.errorsLeft = 10; // Errors allowed + this.words = words; + this.secretWord = this.pickWord(); + this.letters = []; + this.guessedLetters = ""; + this.errorsLeft = 10; } - // Return randomly selected word from the words array pickWord() { const randIndex = Math.floor(Math.random() * this.words.length); return this.words[randIndex]; } - // Check if keyCode is A-Z checkIfLetter(keyCode) { return keyCode >= 65 && keyCode <= 90; } - // Check if letter was already clicked (true means NOT clicked yet) checkClickedLetters(letter) { return !this.letters.includes(letter); } - // Add correct letter to guessedLetters addCorrectLetter(letter) { this.guessedLetters += letter; - // Check if player has guessed all the letters (win condition) return this.checkWinner(); } - // Add wrong letter and reduce errors addWrongLetter(letter) { - if(!this.letters.includes(letter)) { - this.letters.push(letter); //store tried letters + if (!this.letters.includes(letter)) { + this.letters.push(letter); } - this.errorLeft -= 1; + this.errorsLeft -= 1; // FIXED } - // If no errors left -> game over checkGameOver() { return this.errorsLeft <= 0; } - // Player wins if guessedLetters contains all letters of secretWord checkWinner() { for (let char of this.secretWord) { if (!this.guessedLetters.includes(char)) { @@ -54,23 +46,51 @@ class Hangman { } } -let hangman; +startGameButton.addEventListener('click', event => { + hangman = new Hangman([ + 'node', + 'javascript', + 'react', + 'miami', + 'paris', + 'amsterdam', + 'lisboa' + ]); -const startGameButton = document.getElementById('start-game-button'); + hangman.secretWord = hangman.pickWord(); + hangmanCanvas = new HangmanCanvas(hangman.secretWord); + hangmanCanvas.createBoard(); +}); -if (startGameButton) { - startGameButton.addEventListener('click', event => { - hangman = new Hangman(['node', 'javascript', 'react', 'miami', 'paris', 'amsterdam', 'lisboa']); +document.addEventListener('keydown', event => { + if (!hangman) return; // game not started - // HINT (uncomment when start working on the canvas portion of the lab) - // hangman.secretWord = hangman.pickWord(); - // hangmanCanvas = new HangmanCanvas(hangman.secretWord); + const letter = event.key.toLowerCase(); - // ... your code goes here - }); -} + if (!hangman.checkIfLetter(event.keyCode)) return; -document.addEventListener('keydown', event => { - // React to user pressing a key - // ... your code goes here + if (!hangman.checkClickedLetters(letter)) return; + + hangman.letters.push(letter); + + if (hangman.secretWord.includes(letter)) { + hangman.addCorrectLetter(letter); + + [...hangman.secretWord].forEach((char, idx) => { + if (char === letter) hangmanCanvas.writeCorrectLetter(idx); + }); + + if (hangman.checkWinner()) { + hangmanCanvas.winner(); + } + } else { + hangman.addWrongLetter(letter); + + hangmanCanvas.writeWrongLetter(letter, hangman.errorsLeft); + hangmanCanvas.drawHangman(hangman.errorsLeft); + + if (hangman.checkGameOver()) { + hangmanCanvas.gameOver(); + } + } }); From 80570cb51fa39ffdddc0a3f48e365d546a5dfe9b Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 14:36:31 +0000 Subject: [PATCH 11/12] revamp game --- index.html | 46 +++++++++--------- javascript/canvas.js | 107 ++++++------------------------------------ javascript/hangman.js | 68 ++++++++++----------------- 3 files changed, 63 insertions(+), 158 deletions(-) diff --git a/index.html b/index.html index 302e8e5..8c19edc 100644 --- a/index.html +++ b/index.html @@ -1,27 +1,25 @@ - - - - - - Hangman - - -
- -
-
- -
-
- -
- - - + + + + Hangman Game + + + + +

Hangman Game

+ +
+ + + + + + + diff --git a/javascript/canvas.js b/javascript/canvas.js index e301621..d312ecb 100644 --- a/javascript/canvas.js +++ b/javascript/canvas.js @@ -16,12 +16,10 @@ class HangmanCanvas { const startY = 500; const lineWidth = 50; const gap = 15; - ctx.lineWidth = 3; for (let i = 0; i < this.secretWord.length; i++) { - let x = startX + i * (lineWidth + gap); - + const x = startX + i * (lineWidth + gap); ctx.beginPath(); ctx.moveTo(x, startY); ctx.lineTo(x + lineWidth, startY); @@ -33,126 +31,51 @@ class HangmanCanvas { writeCorrectLetter(index) { const ctx = this.context; const letter = this.secretWord[index].toUpperCase(); - const startX = 200; const startY = 495; const lineWidth = 50; const gap = 15; - ctx.font = "40px Arial"; ctx.fillStyle = "black"; - - const x = startX + index * (lineWidth + gap) + 10; - - ctx.fillText(letter, x, startY - 10); + const x = startX + index * (lineWidth + gap) + 12; + ctx.fillText(letter, x, startY - 20); } writeWrongLetter(letter, errorsLeft) { const ctx = this.context; - ctx.font = "40px Arial"; ctx.fillStyle = "red"; - - // Wrong letters area const x = 700; const y = 100 + (10 - errorsLeft) * 45; - ctx.fillText(letter.toUpperCase(), x, y); } drawHangman(errorsLeft) { const ctx = this.context; ctx.lineWidth = 4; - switch (errorsLeft) { - case 9: // Base - ctx.beginPath(); - ctx.moveTo(100, 500); - ctx.lineTo(300, 500); - ctx.stroke(); - break; - - case 8: // Left vertical - ctx.beginPath(); - ctx.moveTo(150, 500); - ctx.lineTo(150, 100); - ctx.stroke(); - break; - - case 7: // Top bar - ctx.beginPath(); - ctx.moveTo(150, 100); - ctx.lineTo(350, 100); - ctx.stroke(); - break; - - case 6: // Rope - ctx.beginPath(); - ctx.moveTo(350, 100); - ctx.lineTo(350, 150); - ctx.stroke(); - break; - - case 5: // Head - ctx.beginPath(); - ctx.arc(350, 190, 40, 0, Math.PI * 2); - ctx.stroke(); - break; - - case 4: // Body - ctx.beginPath(); - ctx.moveTo(350, 230); - ctx.lineTo(350, 350); - ctx.stroke(); - break; - - case 3: // Left arm - ctx.beginPath(); - ctx.moveTo(350, 260); - ctx.lineTo(300, 310); - ctx.stroke(); - break; - - case 2: // Right arm - ctx.beginPath(); - ctx.moveTo(350, 260); - ctx.lineTo(400, 310); - ctx.stroke(); - break; - - case 1: // Left leg - ctx.beginPath(); - ctx.moveTo(350, 350); - ctx.lineTo(300, 430); - ctx.stroke(); - break; - - case 0: // Right leg - ctx.beginPath(); - ctx.moveTo(350, 350); - ctx.lineTo(400, 430); - ctx.stroke(); - break; + case 9: ctx.beginPath(); ctx.moveTo(100, 500); ctx.lineTo(300, 500); ctx.stroke(); break; + case 8: ctx.beginPath(); ctx.moveTo(150, 500); ctx.lineTo(150, 100); ctx.stroke(); break; + case 7: ctx.beginPath(); ctx.moveTo(150, 100); ctx.lineTo(350, 100); ctx.stroke(); break; + case 6: ctx.beginPath(); ctx.moveTo(350, 100); ctx.lineTo(350, 150); ctx.stroke(); break; + case 5: ctx.beginPath(); ctx.arc(350, 190, 40, 0, Math.PI * 2); ctx.stroke(); break; + case 4: ctx.beginPath(); ctx.moveTo(350, 230); ctx.lineTo(350, 350); ctx.stroke(); break; + case 3: ctx.beginPath(); ctx.moveTo(350, 260); ctx.lineTo(300, 310); ctx.stroke(); break; + case 2: ctx.beginPath(); ctx.moveTo(350, 260); ctx.lineTo(400, 310); ctx.stroke(); break; + case 1: ctx.beginPath(); ctx.moveTo(350, 350); ctx.lineTo(300, 430); ctx.stroke(); break; + case 0: ctx.beginPath(); ctx.moveTo(350, 350); ctx.lineTo(400, 430); ctx.stroke(); break; } } - // When user loses gameOver() { const img = new Image(); img.src = './images/gameover.png'; - - img.onload = () => { - this.context.drawImage(img, 100, 50, 400, 400); - }; + img.onload = () => this.context.drawImage(img, 100, 50, 400, 400); } - // When user wins winner() { const img = new Image(); img.src = './images/awesome.png'; - - img.onload = () => { - this.context.drawImage(img, 100, 50, 400, 400); - }; + img.onload = () => this.context.drawImage(img, 100, 50, 400, 400); } } diff --git a/javascript/hangman.js b/javascript/hangman.js index 3caed4a..87ca781 100644 --- a/javascript/hangman.js +++ b/javascript/hangman.js @@ -1,3 +1,8 @@ +let hangman; +let hangmanCanvas; + +const startGameButton = document.getElementById('start-game-button'); + class Hangman { constructor(words) { this.words = words; @@ -8,8 +13,7 @@ class Hangman { } pickWord() { - const randIndex = Math.floor(Math.random() * this.words.length); - return this.words[randIndex]; + return this.words[Math.floor(Math.random() * this.words.length)]; } checkIfLetter(keyCode) { @@ -21,15 +25,14 @@ class Hangman { } addCorrectLetter(letter) { + if (!this.letters.includes(letter)) this.letters.push(letter); this.guessedLetters += letter; return this.checkWinner(); } addWrongLetter(letter) { - if (!this.letters.includes(letter)) { - this.letters.push(letter); - } - this.errorsLeft -= 1; // FIXED + if (!this.letters.includes(letter)) this.letters.push(letter); + this.errorsLeft -= 1; } checkGameOver() { @@ -37,60 +40,41 @@ class Hangman { } checkWinner() { - for (let char of this.secretWord) { - if (!this.guessedLetters.includes(char)) { - return false; - } - } - return true; + return [...this.secretWord].every(char => this.guessedLetters.includes(char)); } } -startGameButton.addEventListener('click', event => { - hangman = new Hangman([ - 'node', - 'javascript', - 'react', - 'miami', - 'paris', - 'amsterdam', - 'lisboa' - ]); - - hangman.secretWord = hangman.pickWord(); - hangmanCanvas = new HangmanCanvas(hangman.secretWord); - hangmanCanvas.createBoard(); -}); +// START BUTTON +if (startGameButton) { + startGameButton.addEventListener('click', () => { + hangman = new Hangman([ + 'node','javascript','react','miami','paris','amsterdam','lisboa' + ]); + hangman.secretWord = hangman.pickWord(); + hangmanCanvas = new HangmanCanvas(hangman.secretWord); + hangmanCanvas.createBoard(); + }); +} -document.addEventListener('keydown', event => { - if (!hangman) return; // game not started +// KEYDOWN HANDLER +document.addEventListener('keydown', (event) => { + if (!hangman) return; const letter = event.key.toLowerCase(); if (!hangman.checkIfLetter(event.keyCode)) return; - if (!hangman.checkClickedLetters(letter)) return; - hangman.letters.push(letter); - if (hangman.secretWord.includes(letter)) { hangman.addCorrectLetter(letter); - [...hangman.secretWord].forEach((char, idx) => { if (char === letter) hangmanCanvas.writeCorrectLetter(idx); }); - - if (hangman.checkWinner()) { - hangmanCanvas.winner(); - } + if (hangman.checkWinner()) hangmanCanvas.winner(); } else { hangman.addWrongLetter(letter); - hangmanCanvas.writeWrongLetter(letter, hangman.errorsLeft); hangmanCanvas.drawHangman(hangman.errorsLeft); - - if (hangman.checkGameOver()) { - hangmanCanvas.gameOver(); - } + if (hangman.checkGameOver()) hangmanCanvas.gameOver(); } }); From 4a6b9a60963a9d49b602f56967194d2529b7df83 Mon Sep 17 00:00:00 2001 From: SiyaM108 Date: Sat, 22 Nov 2025 15:08:34 +0000 Subject: [PATCH 12/12] done --- index.html | 12 ++++++------ styles/styles.css | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index 8c19edc..74dc691 100644 --- a/index.html +++ b/index.html @@ -3,19 +3,19 @@ - Hangman Game + + + Hangman + - -

Hangman Game

- -
+ +
diff --git a/styles/styles.css b/styles/styles.css index 414e79c..f987e84 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -1,5 +1,5 @@ .game-logo { - + text-align: center; } #start-game-button { @@ -10,6 +10,8 @@ padding: 20px 40px; font-size: 30px; border-radius: 5px; + display: block; + margin: auto; } #hangman {