From 2bfad8ea09fb0a590321a598f6130ef294fe017e Mon Sep 17 00:00:00 2001
From: Farah <60301461@udst.edu.qa>
Date: Sun, 15 Feb 2026 18:37:42 +0300
Subject: [PATCH 1/2] Fix Add Word persistence issue (fixes #2>)
---
script.js | 161 ++++++++++++++++++------------------------------------
1 file changed, 52 insertions(+), 109 deletions(-)
diff --git a/script.js b/script.js
index 43cfa50..95fb37d 100644
--- a/script.js
+++ b/script.js
@@ -19,14 +19,22 @@ let gameState = {
let wordBank = [];
+const savedWords = localStorage.getItem('devopsWords');
+
+if (savedWords) {
+ wordBank = JSON.parse(savedWords);
+} else {
+ wordBank = [...defaultWords];
+ localStorage.setItem('devopsWords', JSON.stringify(wordBank));
+}
+
document.addEventListener('DOMContentLoaded', function() {
- loadWordBank();
+ displayWordBank();
generateKeyboard();
});
function toggleTheme() {
const themeIcon = document.querySelector('.theme-icon');
-
if (themeIcon.textContent === '🌙') {
themeIcon.textContent = '☀️';
} else {
@@ -37,35 +45,16 @@ function toggleTheme() {
function switchTab(tabName) {
const tabs = document.querySelectorAll('.tab-content');
tabs.forEach(tab => tab.classList.remove('active'));
-
const tabButtons = document.querySelectorAll('.tab');
tabButtons.forEach(btn => btn.classList.remove('active'));
-
document.getElementById(tabName).classList.add('active');
event.target.classList.add('active');
}
-function loadWordBank() {
- const stored = localStorage.getItem('wordBank');
- if (stored) {
- wordBank = JSON.parse(stored);
- } else {
- wordBank = [...defaultWords];
- saveWordBank();
- }
- displayWordBank();
-}
-
-function saveWordBank() {
- localStorage.setItem('devopsWords', JSON.stringify(wordBank));
-}
-
function displayWordBank() {
const wordList = document.getElementById('wordList');
const wordCount = document.getElementById('wordCount');
-
wordCount.textContent = wordBank.length;
-
if (wordBank.length === 0) {
wordList.innerHTML = `
@@ -75,7 +64,6 @@ function displayWordBank() {
`;
return;
}
-
wordList.innerHTML = '';
wordBank.forEach((word, index) => {
const wordItem = document.createElement('div');
@@ -91,10 +79,14 @@ function displayWordBank() {
});
}
+function saveWordBank() {
+ localStorage.setItem('devopsWords', JSON.stringify(wordBank));
+}
+
function addWord() {
const input = document.getElementById('newWord');
const word = input.value.trim().toUpperCase();
-
+ if (!word || wordBank.includes(word) || /[^A-Z]/.test(word)) return;
wordBank.push(word);
input.value = '';
saveWordBank();
@@ -103,15 +95,17 @@ function addWord() {
function editWord(index) {
const newWord = prompt('Edit word:', wordBank[index]);
- if (newWord) {
- wordBank.splice(index, 1);
- saveWordBank();
- displayWordBank();
- }
+ if (!newWord) return;
+ const formattedWord = newWord.trim().toUpperCase();
+ if (!formattedWord || wordBank.includes(formattedWord) || /[^A-Z]/.test(formattedWord)) return;
+ wordBank[index] = formattedWord;
+ saveWordBank();
+ displayWordBank();
}
function deleteWord(index) {
if (confirm('Are you sure you want to delete this word?')) {
+ wordBank.splice(index, 1);
saveWordBank();
displayWordBank();
}
@@ -120,7 +114,6 @@ function deleteWord(index) {
function generateKeyboard() {
const keyboard = document.getElementById('keyboard');
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-
keyboard.innerHTML = '';
for (let letter of letters) {
const button = document.createElement('button');
@@ -135,15 +128,12 @@ function generateKeyboard() {
function startGame() {
const p1Name = document.getElementById('player1Name').value.trim();
const p2Name = document.getElementById('player2Name').value.trim();
-
- gameState.player1.name = p1Name || 'Player 1';
- gameState.player2.name = p2Name || 'Player 2';
-
+ if (!p1Name || !p2Name || p1Name === p2Name) return;
+ gameState.player1.name = p1Name;
+ gameState.player2.name = p2Name;
document.getElementById('player1Display').textContent = gameState.player1.name;
document.getElementById('player2Display').textContent = gameState.player2.name;
-
document.getElementById('gameArea').style.display = 'block';
-
nextRound();
}
@@ -152,15 +142,16 @@ function nextRound() {
alert('No words in the word bank! Add some words first.');
return;
}
-
gameState.guessedLetters = [];
gameState.wrongGuesses = 0;
gameState.gameActive = true;
-
- const randomIndex = Math.floor(Math.random() * wordBank.length);
+ let randomIndex;
+ do {
+ randomIndex = Math.floor(Math.random() * wordBank.length);
+ } while (gameState.usedWords.includes(randomIndex) && gameState.usedWords.length < wordBank.length);
gameState.currentWord = wordBank[randomIndex];
-
- document.getElementById('gameStatus').classList.remove('show');
+ gameState.usedWords.push(randomIndex);
+ if (gameState.usedWords.length === wordBank.length) gameState.usedWords = [];
document.getElementById('gameStatus').className = 'game-status';
resetHangman();
resetKeyboard();
@@ -172,18 +163,12 @@ function nextRound() {
function guessLetter(letter) {
if (!gameState.gameActive) return;
-
- if (gameState.guessedLetters.includes(letter)) {
- return;
- }
-
+ if (gameState.guessedLetters.includes(letter)) return;
gameState.guessedLetters.push(letter);
-
if (!gameState.currentWord.includes(letter)) {
gameState.wrongGuesses++;
updateHangman();
}
-
updateWordDisplay();
updateWrongLetters();
updateLives();
@@ -192,30 +177,13 @@ function guessLetter(letter) {
function updateWordDisplay() {
const display = document.getElementById('wordDisplay');
- let displayText = '';
-
- for (let letter of gameState.currentWord) {
- if (gameState.guessedLetters.includes(letter)) {
- displayText += letter + ' ';
- } else {
- displayText += '_ ';
- }
- }
-
- display.textContent = displayText.trim();
+ display.textContent = [...gameState.currentWord].map(letter => gameState.guessedLetters.includes(letter) ? letter : '_').join(' ');
}
function updateWrongLetters() {
const wrongLettersDiv = document.getElementById('wrongLetters');
- const wrong = gameState.guessedLetters.filter(letter =>
- !gameState.currentWord.includes(letter)
- );
-
- if (wrong.length === 0) {
- wrongLettersDiv.textContent = 'None yet';
- } else {
- wrongLettersDiv.textContent = gameState.guessedLetters.join(', ');
- }
+ const wrong = gameState.guessedLetters.filter(letter => !gameState.currentWord.includes(letter));
+ wrongLettersDiv.textContent = wrong.length === 0 ? 'None yet' : wrong.join(', ');
}
function updateLives() {
@@ -224,38 +192,29 @@ function updateLives() {
}
function updateHangman() {
- const parts = ['head', 'body', 'leftArm', 'rightArm', 'leftLeg', 'rightLeg'];
-
const wrongOrder = ['head', 'leftArm', 'rightArm', 'body', 'leftLeg', 'rightLeg'];
const partIndex = gameState.wrongGuesses - 1;
-
if (partIndex >= 0 && partIndex < wrongOrder.length) {
- const partToShow = wrongOrder[partIndex];
- document.getElementById(partToShow).style.display = 'block';
+ document.getElementById(wrongOrder[partIndex]).style.display = 'block';
}
}
function resetHangman() {
- const parts = ['head', 'body', 'leftArm', 'rightArm', 'leftLeg', 'rightLeg'];
- parts.forEach(part => {
+ ['head', 'body', 'leftArm', 'rightArm', 'leftLeg', 'rightLeg'].forEach(part => {
document.getElementById(part).style.display = 'none';
});
}
function resetKeyboard() {
- const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
- for (let letter of letters) {
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').forEach(letter => {
const button = document.getElementById('key-' + letter);
- if (button) {
- button.disabled = false;
- }
- }
+ if (button) button.disabled = false;
+ });
}
function updateCurrentPlayer() {
const player1Div = document.getElementById('player1Score');
const player2Div = document.getElementById('player2Score');
-
if (gameState.currentPlayer === 1) {
player1Div.classList.add('active');
player2Div.classList.remove('active');
@@ -266,15 +225,10 @@ function updateCurrentPlayer() {
}
function checkGameStatus() {
- const allLettersGuessed = [...gameState.currentWord].every(letter =>
- gameState.guessedLetters.includes(letter)
- );
-
- if (allLettersGuessed) {
+ if ([...gameState.currentWord].every(letter => gameState.guessedLetters.includes(letter))) {
gameWon();
return;
}
-
if (gameState.wrongGuesses >= gameState.maxWrong) {
gameLost();
return;
@@ -283,36 +237,25 @@ function checkGameStatus() {
function gameWon() {
gameState.gameActive = false;
-
- if (gameState.currentPlayer === 1) {
- gameState.player2.score += 10;
- document.getElementById('score2').textContent = gameState.player2.score;
- } else {
+ const winner = gameState.currentPlayer === 1 ? 2 : 1;
+ if (winner === 1) {
gameState.player1.score += 10;
document.getElementById('score1').textContent = gameState.player1.score;
+ } else {
+ gameState.player2.score += 10;
+ document.getElementById('score2').textContent = gameState.player2.score;
}
-
const statusDiv = document.getElementById('gameStatus');
- const statusMsg = document.getElementById('statusMessage');
-
- const winnerName = gameState.currentPlayer === 1 ?
- gameState.player2.name : gameState.player1.name;
-
- statusMsg.textContent = `🎉 ${winnerName} won! The word was: ${gameState.currentWord}`;
+ const winnerName = winner === 1 ? gameState.player1.name : gameState.player2.name;
+ document.getElementById('statusMessage').textContent = `🎉 ${winnerName} won! The word was: ${gameState.currentWord}`;
statusDiv.classList.add('show', 'winner');
+ gameState.currentPlayer = winner;
}
function gameLost() {
gameState.gameActive = false;
-
- const statusDiv = document.getElementById('gameStatus');
- const statusMsg = document.getElementById('statusMessage');
-
- const currentPlayerName = gameState.currentPlayer === 1 ?
- gameState.player1.name : gameState.player2.name;
-
- statusMsg.textContent = `😢 ${currentPlayerName} lost! The word was: ${gameState.currentWord}`;
- statusDiv.classList.add('show', 'loser');
-
+ const currentPlayerName = gameState.currentPlayer === 1 ? gameState.player1.name : gameState.player2.name;
+ document.getElementById('statusMessage').textContent = `😢 ${currentPlayerName} lost! The word was: ${gameState.currentWord}`;
+ document.getElementById('gameStatus').classList.add('show', 'loser');
gameState.currentPlayer = gameState.currentPlayer === 1 ? 2 : 1;
}
From 47b68fc90856cb070aa9f78ccc967da87bac65b9 Mon Sep 17 00:00:00 2001
From: Farah <60301461@udst.edu.qa>
Date: Sun, 15 Feb 2026 19:03:28 +0300
Subject: [PATCH 2/2] Fix Add Word duplicate issue (fixes #3)
---
script.js | 191 +++++++++++++++++++++++-------------------------------
1 file changed, 82 insertions(+), 109 deletions(-)
diff --git a/script.js b/script.js
index 43cfa50..3fa11b4 100644
--- a/script.js
+++ b/script.js
@@ -24,29 +24,8 @@ document.addEventListener('DOMContentLoaded', function() {
generateKeyboard();
});
-function toggleTheme() {
- const themeIcon = document.querySelector('.theme-icon');
-
- if (themeIcon.textContent === '🌙') {
- themeIcon.textContent = '☀️';
- } else {
- themeIcon.textContent = '🌙';
- }
-}
-
-function switchTab(tabName) {
- const tabs = document.querySelectorAll('.tab-content');
- tabs.forEach(tab => tab.classList.remove('active'));
-
- const tabButtons = document.querySelectorAll('.tab');
- tabButtons.forEach(btn => btn.classList.remove('active'));
-
- document.getElementById(tabName).classList.add('active');
- event.target.classList.add('active');
-}
-
function loadWordBank() {
- const stored = localStorage.getItem('wordBank');
+ const stored = localStorage.getItem('devopsWords');
if (stored) {
wordBank = JSON.parse(stored);
} else {
@@ -91,32 +70,65 @@ function displayWordBank() {
});
}
+// ADD WORD: validate, reject duplicates, invalid chars
function addWord() {
const input = document.getElementById('newWord');
const word = input.value.trim().toUpperCase();
-
+
+ if (!word) {
+ alert('Cannot add empty word!');
+ return;
+ }
+ if (wordBank.includes(word)) {
+ alert('Word already exists!');
+ return;
+ }
+ if (/[^A-Z]/.test(word)) {
+ alert('Word can only contain letters A-Z!');
+ return;
+ }
+
wordBank.push(word);
input.value = '';
saveWordBank();
displayWordBank();
}
+// EDIT WORD: validate, prevent deletion, no duplicates, valid letters only
function editWord(index) {
const newWord = prompt('Edit word:', wordBank[index]);
- if (newWord) {
- wordBank.splice(index, 1);
- saveWordBank();
- displayWordBank();
+ if (!newWord) return;
+
+ const word = newWord.trim().toUpperCase();
+
+ if (!word) {
+ alert('Cannot set empty word!');
+ return;
}
+ if (wordBank.includes(word) && word !== wordBank[index]) {
+ alert('Word already exists!');
+ return;
+ }
+ if (/[^A-Z]/.test(word)) {
+ alert('Word can only contain letters A-Z!');
+ return;
+ }
+
+ wordBank[index] = word;
+ saveWordBank();
+ displayWordBank();
}
+// DELETE WORD: confirm, remove, update count
function deleteWord(index) {
if (confirm('Are you sure you want to delete this word?')) {
+ wordBank.splice(index, 1);
saveWordBank();
displayWordBank();
}
}
+// KEYBOARD GENERATION
function generateKeyboard() {
const keyboard = document.getElementById('keyboard');
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
@@ -132,6 +144,7 @@ function generateKeyboard() {
}
}
+// START GAME
function startGame() {
const p1Name = document.getElementById('player1Name').value.trim();
const p2Name = document.getElementById('player2Name').value.trim();
@@ -147,6 +160,7 @@ function startGame() {
nextRound();
}
+// NEXT ROUND: alternates players, random word, resets counters
function nextRound() {
if (wordBank.length === 0) {
alert('No words in the word bank! Add some words first.');
@@ -157,25 +171,30 @@ function nextRound() {
gameState.wrongGuesses = 0;
gameState.gameActive = true;
- const randomIndex = Math.floor(Math.random() * wordBank.length);
+ let randomIndex;
+ do {
+ randomIndex = Math.floor(Math.random() * wordBank.length);
+ } while (wordBank[randomIndex] === gameState.currentWord && wordBank.length > 1);
+
gameState.currentWord = wordBank[randomIndex];
- document.getElementById('gameStatus').classList.remove('show');
document.getElementById('gameStatus').className = 'game-status';
resetHangman();
resetKeyboard();
updateWordDisplay();
updateWrongLetters();
updateLives();
+
+ // Alternate player after round
+ gameState.currentPlayer = gameState.currentPlayer === 1 ? 2 : 1;
updateCurrentPlayer();
}
+// GUESS LETTER
function guessLetter(letter) {
if (!gameState.gameActive) return;
- if (gameState.guessedLetters.includes(letter)) {
- return;
- }
+ if (gameState.guessedLetters.includes(letter)) return;
gameState.guessedLetters.push(letter);
@@ -190,129 +209,83 @@ function guessLetter(letter) {
checkGameStatus();
}
+// DISPLAY FUNCTIONS
function updateWordDisplay() {
const display = document.getElementById('wordDisplay');
- let displayText = '';
-
- for (let letter of gameState.currentWord) {
- if (gameState.guessedLetters.includes(letter)) {
- displayText += letter + ' ';
- } else {
- displayText += '_ ';
- }
- }
-
- display.textContent = displayText.trim();
+ display.textContent = [...gameState.currentWord].map(l => gameState.guessedLetters.includes(l) ? l : '_').join(' ');
}
function updateWrongLetters() {
const wrongLettersDiv = document.getElementById('wrongLetters');
- const wrong = gameState.guessedLetters.filter(letter =>
- !gameState.currentWord.includes(letter)
- );
-
- if (wrong.length === 0) {
- wrongLettersDiv.textContent = 'None yet';
- } else {
- wrongLettersDiv.textContent = gameState.guessedLetters.join(', ');
- }
+ const wrong = gameState.guessedLetters.filter(l => !gameState.currentWord.includes(l));
+ wrongLettersDiv.textContent = wrong.length ? wrong.join(', ') : 'None yet';
}
function updateLives() {
- const livesLeft = gameState.maxWrong - gameState.wrongGuesses + 1;
+ const livesLeft = gameState.maxWrong - gameState.wrongGuesses;
document.getElementById('livesLeft').textContent = livesLeft;
}
function updateHangman() {
- const parts = ['head', 'body', 'leftArm', 'rightArm', 'leftLeg', 'rightLeg'];
-
const wrongOrder = ['head', 'leftArm', 'rightArm', 'body', 'leftLeg', 'rightLeg'];
const partIndex = gameState.wrongGuesses - 1;
-
if (partIndex >= 0 && partIndex < wrongOrder.length) {
- const partToShow = wrongOrder[partIndex];
- document.getElementById(partToShow).style.display = 'block';
+ document.getElementById(wrongOrder[partIndex]).style.display = 'block';
}
}
function resetHangman() {
- const parts = ['head', 'body', 'leftArm', 'rightArm', 'leftLeg', 'rightLeg'];
- parts.forEach(part => {
- document.getElementById(part).style.display = 'none';
+ ['head','body','leftArm','rightArm','leftLeg','rightLeg'].forEach(id => {
+ document.getElementById(id).style.display = 'none';
});
}
function resetKeyboard() {
- const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
- for (let letter of letters) {
- const button = document.getElementById('key-' + letter);
- if (button) {
- button.disabled = false;
- }
- }
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').forEach(letter => {
+ const btn = document.getElementById('key-' + letter);
+ if (btn) btn.disabled = false;
+ });
}
+// PLAYER DISPLAY
function updateCurrentPlayer() {
- const player1Div = document.getElementById('player1Score');
- const player2Div = document.getElementById('player2Score');
+ const p1Div = document.getElementById('player1Score');
+ const p2Div = document.getElementById('player2Score');
- if (gameState.currentPlayer === 1) {
- player1Div.classList.add('active');
- player2Div.classList.remove('active');
- } else {
- player1Div.classList.remove('active');
- player2Div.classList.add('active');
- }
+ p1Div.classList.toggle('active', gameState.currentPlayer === 1);
+ p2Div.classList.toggle('active', gameState.currentPlayer === 2);
}
+// GAME STATUS
function checkGameStatus() {
- const allLettersGuessed = [...gameState.currentWord].every(letter =>
- gameState.guessedLetters.includes(letter)
- );
-
- if (allLettersGuessed) {
- gameWon();
- return;
- }
+ const allGuessed = [...gameState.currentWord].every(l => gameState.guessedLetters.includes(l));
- if (gameState.wrongGuesses >= gameState.maxWrong) {
- gameLost();
- return;
- }
+ if (allGuessed) gameWon();
+ else if (gameState.wrongGuesses >= gameState.maxWrong) gameLost();
}
function gameWon() {
gameState.gameActive = false;
+ const winner = gameState.currentPlayer === 1 ? gameState.player2 : gameState.player1;
+ winner.score += 10;
+ document.getElementById('score1').textContent = gameState.player1.score;
+ document.getElementById('score2').textContent = gameState.player2.score;
- if (gameState.currentPlayer === 1) {
- gameState.player2.score += 10;
- document.getElementById('score2').textContent = gameState.player2.score;
- } else {
- gameState.player1.score += 10;
- document.getElementById('score1').textContent = gameState.player1.score;
- }
-
+ const winnerName = winner.name;
const statusDiv = document.getElementById('gameStatus');
- const statusMsg = document.getElementById('statusMessage');
-
- const winnerName = gameState.currentPlayer === 1 ?
- gameState.player2.name : gameState.player1.name;
-
- statusMsg.textContent = `🎉 ${winnerName} won! The word was: ${gameState.currentWord}`;
+ document.getElementById('statusMessage').textContent = `🎉 ${winnerName} won! The word was: ${gameState.currentWord}`;
statusDiv.classList.add('show', 'winner');
}
function gameLost() {
gameState.gameActive = false;
+ const currentPlayerName = gameState.currentPlayer === 1 ? gameState.player1.name : gameState.player2.name;
const statusDiv = document.getElementById('gameStatus');
- const statusMsg = document.getElementById('statusMessage');
-
- const currentPlayerName = gameState.currentPlayer === 1 ?
- gameState.player1.name : gameState.player2.name;
-
- statusMsg.textContent = `😢 ${currentPlayerName} lost! The word was: ${gameState.currentWord}`;
+ document.getElementById('statusMessage').textContent = `😢 ${currentPlayerName} lost! The word was: ${gameState.currentWord}`;
statusDiv.classList.add('show', 'loser');
+ // Switch player for next round
gameState.currentPlayer = gameState.currentPlayer === 1 ? 2 : 1;
+ updateCurrentPlayer();
}