Skip to content
Merged
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
16 changes: 10 additions & 6 deletions projects/number-guessing-game/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Number Guessing Game</title>
<link rel="stylesheet" href="../../assets/styles.css">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Number Guessing Game</h1>
<div id="game-container">
<!-- TODO: Input for user guess -->
<!-- TODO: Button to submit guess -->
<!-- TODO: Display feedback (too high, too low, correct) -->
<!-- TODO: Show number of attempts -->
<!-- TODO: Option to restart game -->
<div id="game-container" class="card">
<p id="instructions">I'm thinking of a number between 1 and 100. Can you guess it?</p>
<div id="controls" class="controls">
<input id="guess-input" type="number" min="1" max="100" placeholder="Enter your guess" />
<button id="guess-btn" type="button">Guess</button>
</div>
<p id="feedback" aria-live="polite"></p>
<p id="attempts">Attempts: <span id="attempt-count">0</span></p>
<button id="restart-btn" type="button">Restart</button>
</div>
<script src="main.js"></script>
</body>
Expand Down
97 changes: 87 additions & 10 deletions projects/number-guessing-game/main.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,92 @@
// TODO: Generate a random number
// TODO: Handle user guess input
// TODO: Compare guess to target number
// TODO: Provide feedback (too high, too low, correct)
// TODO: Track number of attempts
// TODO: Restart game functionality
// Utility to generate a random integer in [min, max]
function generateRandomInteger(min, max) {
const minCeil = Math.ceil(min);
const maxFloor = Math.floor(max);
return Math.floor(Math.random() * (maxFloor - minCeil + 1)) + minCeil;
}

function initNumberGuessingGame() {
// TODO: Generate random number
// TODO: Handle user input and feedback
// TODO: Track attempts
// TODO: Restart game
const input = document.getElementById('guess-input');
const guessBtn = document.getElementById('guess-btn');
const feedback = document.getElementById('feedback');
const attemptsText = document.getElementById('attempts');
const attemptCount = document.getElementById('attempt-count');
const restartBtn = document.getElementById('restart-btn');

const MIN = 1;
const MAX = 100;

let targetNumber = generateRandomInteger(MIN, MAX);
let attempts = 0;
let gameOver = false;

function setFeedback(message, type) {
feedback.textContent = message;
feedback.dataset.type = type || '';
}

function setGameOver(over) {
gameOver = over;
input.disabled = over;
guessBtn.disabled = over;
if (over) {
input.blur();
}
}

function validateGuess(value) {
if (value === '') return { ok: false, msg: 'Please enter a number.' };
const num = Number(value);
if (!Number.isFinite(num)) return { ok: false, msg: 'That is not a valid number.' };
if (!Number.isInteger(num)) return { ok: false, msg: 'Please enter a whole number.' };
if (num < MIN || num > MAX) return { ok: false, msg: `Enter a number between ${MIN} and ${MAX}.` };
return { ok: true, value: num };
}

function handleGuess() {
if (gameOver) return;
const { ok, msg, value } = validateGuess(input.value.trim());
if (!ok) {
setFeedback(msg, 'error');
return;
}
attempts += 1;
attemptCount.textContent = String(attempts);

if (value === targetNumber) {
setFeedback(`Correct! The number was ${targetNumber}.`, 'success');
setGameOver(true);
return;
}
if (value < targetNumber) {
setFeedback('Too low. Try a higher number.', 'low');
} else {
setFeedback('Too high. Try a lower number.', 'high');
}
input.select();
}

function restartGame() {
targetNumber = generateRandomInteger(MIN, MAX);
attempts = 0;
attemptCount.textContent = '0';
setFeedback('', '');
input.value = '';
setGameOver(false);
input.focus();
}

guessBtn.addEventListener('click', handleGuess);
input.addEventListener('keydown', function onKeyDown(event) {
if (event.key === 'Enter') {
handleGuess();
}
});
restartBtn.addEventListener('click', restartGame);

// Init state
attemptsText.hidden = false;
setFeedback('', '');
}

window.addEventListener('DOMContentLoaded', initNumberGuessingGame);
69 changes: 68 additions & 1 deletion projects/number-guessing-game/styles.css
Original file line number Diff line number Diff line change
@@ -1 +1,68 @@
/* TODO: Style game container, input, button, feedback, attempts, restart button */
/* Basic reset */
/* Page-level layout is handled by assets/styles.css; only tweak specifics here */
html, body { height: 100%; }
body {
display: flex;
flex-direction: column;
align-items: center;
background: var(--bg);
color: var(--text);
}

h1 { margin: 24px 0 12px; font-size: 24px; font-weight: 700; color: var(--text); }

#game-container {
width: 100%;
max-width: 420px;
background: var(--card);
border: 1px solid #262631;
border-radius: 12px;
padding: 20px;
box-shadow: 0 0 0 1px rgba(255,255,255,0.02) inset;
}

#instructions { margin: 0 0 12px; color: var(--muted); }

#controls {
display: flex;
gap: 8px;
}

#guess-input {
flex: 1 1 auto;
padding: 10px 12px;
border: 1px solid #2a2a33;
border-radius: 8px;
font-size: 14px;
outline: none;
background: #0e0e13;
color: var(--text);
}
#guess-input::placeholder { color: var(--muted); }
#guess-input:focus { border-color: #93c5fd; box-shadow: 0 0 0 3px rgba(147,197,253,0.2); }

button {
padding: 10px 14px;
border-radius: 8px;
border: 1px solid #1e3a8a;
background: linear-gradient(135deg, var(--accent), var(--accent-2));
color: #0b1020;
font-weight: 600;
cursor: pointer;
}
button:hover { filter: brightness(1.05); }
button:disabled { background: #1f1f27; border-color: #2a2a33; color: var(--muted); cursor: not-allowed; }

#feedback { min-height: 22px; margin: 12px 0 8px; }
#feedback[data-type="error"] { color: #f87171; }
#feedback[data-type="low"], #feedback[data-type="high"] { color: #fbbf24; }
#feedback[data-type="success"] { color: var(--accent); }

#attempts { margin: 0 0 12px; color: var(--muted); }

#restart-btn {
width: 100%;
background: linear-gradient(135deg, var(--accent), var(--accent-2));
border-color: #1e3a8a;
}
#restart-btn:hover { filter: brightness(1.05); }