Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 88 additions & 8 deletions javascript/canvas.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,114 @@
class HangmanCanvas {
constructor(secretWord) {
this.context = document.getElementById('hangman').getContext('2d');
// ... your code goes here
this.secretWord = secretWord;
}

/**
* Clears the canvas and prepares it for a new game.
*/
createBoard() {
// ... your code goes here
this.context.clearRect(0, 0, 800, 500); // Clear the canvas
this.context.font = '48px Arial';
this.context.fillStyle = 'black';
this.drawLines(); // Draw lines for the secret word
}

/**
* Draws one line for each letter in the secret word.
*/
drawLines() {
// ... your code goes here
const lineWidth = 50;
const gap = 20;
const startX = 200;
const startY = 450;

for (let i = 0; i < this.secretWord.length; i++) {
this.context.beginPath();
this.context.moveTo(startX + i * (lineWidth + gap), startY);
this.context.lineTo(startX + i * (lineWidth + gap) + lineWidth, startY);
this.context.stroke();
}
}

/**
* Writes a correct letter in the appropriate position.
* @param {number} index - Index of the letter in the secret word
*/
writeCorrectLetter(index) {
// ... your code goes here
const lineWidth = 50;
const gap = 20;
const startX = 200;
const startY = 440;

const x = startX + index * (lineWidth + gap) + 10;
const y = startY;

this.context.fillText(this.secretWord[index], x, y);
}

/**
* Writes a wrong letter and displays remaining attempts.
* @param {string} letter - The wrong letter guessed by the user
* @param {number} errorsLeft - Remaining attempts
*/
writeWrongLetter(letter, errorsLeft) {
// ... your code goes here
const startX = 500;
const startY = 100;
const gap = 40;

// Write wrong letter
this.context.fillText(letter, startX + (10 - errorsLeft) * gap, startY);

// Draw hangman
this.drawHangman(errorsLeft);
}

/**
* Draws the hangman figure based on the remaining errors.
* @param {number} errorsLeft - Remaining attempts
*/
drawHangman(errorsLeft) {
// ... your code goes here
const parts = [
() => this.context.fillRect(150, 400, 100, 10), // Base
() => this.context.fillRect(190, 100, 10, 300), // Pole
() => this.context.fillRect(190, 100, 150, 10), // Beam
() => this.context.fillRect(330, 100, 10, 50), // Rope
() => {
// Head
this.context.beginPath();
this.context.arc(335, 180, 30, 0, Math.PI * 2);
this.context.stroke();
},
() => this.context.fillRect(330, 210, 10, 100), // Body
() => this.context.fillRect(330, 310, 40, 10), // Right Arm
() => this.context.fillRect(290, 310, 40, 10), // Left Arm
() => this.context.fillRect(330, 310, 10, 80), // Right Leg
() => this.context.fillRect(290, 310, 10, 80), // Left Leg
];

// Draw the corresponding part
const partIndex = 10 - errorsLeft;
if (parts[partIndex]) parts[partIndex]();
}

/**
* Displays the "Game Over" screen.
*/
gameOver() {
// ... your code goes here
this.context.clearRect(0, 0, 800, 500); // Clear the canvas
this.context.font = '60px Arial';
this.context.fillStyle = 'red';
this.context.fillText('Game Over!', 250, 250);
}

/**
* Displays the "Winner" screen.
*/
winner() {
// ... your code goes here
this.context.clearRect(0, 0, 800, 500); // Clear the canvas
this.context.font = '60px Arial';
this.context.fillStyle = 'green';
this.context.fillText('You Win!', 250, 250);
}
}
109 changes: 91 additions & 18 deletions javascript/hangman.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,128 @@
class Hangman {
constructor(words) {
this.words = words;
// ... your code goes here
this.words = words; // Array of possible words
this.secretWord = this.pickWord(); // Randomly chosen word
this.letters = []; // Array to track already picked letters
this.guessedLetters = ''; // String to store correctly guessed letters
this.errorsLeft = 10; // Number of guesses left
}

/**
* Selects a random word from the words array
* @returns {string} - Random word
*/
pickWord() {
// ... your code goes here
const randomIndex = Math.floor(Math.random() * this.words.length);
return this.words[randomIndex];
}

/**
* Checks if the key pressed is a letter (a-z)
* @param {number} keyCode - Key code of the pressed key
* @returns {boolean} - True if the key is a letter, false otherwise
*/
checkIfLetter(keyCode) {
// ... your code goes here
return keyCode >= 65 && keyCode <= 90; // ASCII codes for A-Z
}

/**
* Checks if the letter has already been clicked
* @param {string} letter - Letter to check
* @returns {boolean} - True if the letter is new, false otherwise
*/
checkClickedLetters(letter) {
// ... your code goes here
return !this.letters.includes(letter); // Returns true if the letter is not already in the array
}

/**
* Adds the correct letter to the guessedLetters property
* @param {string} letter - Letter guessed correctly
*/
addCorrectLetter(letter) {
// ... your code goes here
this.guessedLetters += letter; // Add letter to guessed letters
this.checkWinner(); // Check if the player has won
}

/**
* Adds the wrong letter to the letters array and decreases errorsLeft
* @param {string} letter - Letter guessed incorrectly
*/
addWrongLetter(letter) {
// ... your code goes here
if (!this.letters.includes(letter)) {
this.letters.push(letter); // Add the letter to the tracked letters
this.errorsLeft--; // Decrease the number of attempts left
}
}

/**
* Checks if the game is over
* @returns {boolean} - True if no errors left, false otherwise
*/
checkGameOver() {
// ... your code goes here
return this.errorsLeft <= 0;
}

/**
* Checks if the user has guessed all the letters in the secret word
* @returns {boolean} - True if the player has won, false otherwise
*/
checkWinner() {
// ... your code goes here
const secretWordArray = Array.from(new Set(this.secretWord.split(''))); // Unique letters of the secret word
const guessedLettersArray = Array.from(new Set(this.guessedLetters.split(''))); // Unique guessed letters

return secretWordArray.every((letter) => guessedLettersArray.includes(letter)); // True if all letters are guessed
}
}

// Initialize the Hangman game
let hangman;

// Start button click event
const startGameButton = document.getElementById('start-game-button');

if (startGameButton) {
startGameButton.addEventListener('click', event => {
hangman = new Hangman(['node', 'javascript', 'react', 'miami', 'paris', 'amsterdam', 'lisboa']);
startGameButton.addEventListener('click', () => {
hangman = new Hangman([
'node',
'javascript',
'react',
'miami',
'paris',
'amsterdam',
'lisboa',
]);

// HINT (uncomment when start working on the canvas portion of the lab)
// hangman.secretWord = hangman.pickWord();
// hangmanCanvas = new HangmanCanvas(hangman.secretWord);
hangman.secretWord = hangman.pickWord();
hangmanCanvas = new HangmanCanvas(hangman.secretWord);

// ... your code goes here
console.log(`The secret word is: ${hangman.secretWord}`);
});
}

document.addEventListener('keydown', event => {
// React to user pressing a key
// ... your code goes here
// Handle keyboard events
document.addEventListener('keydown', (event) => {
if (!hangman) return; // If the game hasn’t started, exit

const key = event.key.toLowerCase();
const keyCode = event.keyCode;

if (!hangman.checkIfLetter(keyCode)) return; // Ignore if not a letter
if (!hangman.checkClickedLetters(key)) return; // Ignore if letter already guessed

hangman.letters.push(key); // Track the guessed letter

if (hangman.secretWord.includes(key)) {
// Correct guess
hangman.addCorrectLetter(key);
} else {
// Incorrect guess
hangman.addWrongLetter(key);
}

// Check game status
if (hangman.checkGameOver()) {
alert('Game over! Better luck next time!');
} else if (hangman.checkWinner()) {
alert('Congratulations! You won!');
}
});