Skip to content

Commit 678c6c8

Browse files
Merge pull request #53 from Guma15/feature/number-guessing-game
Implement Number Guessing Game Logic
2 parents a06ee28 + 2474d71 commit 678c6c8

3 files changed

Lines changed: 165 additions & 17 deletions

File tree

projects/number-guessing-game/index.html

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,20 @@
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>Number Guessing Game</title>
7+
<link rel="stylesheet" href="../../assets/styles.css">
78
<link rel="stylesheet" href="styles.css">
89
</head>
910
<body>
1011
<h1>Number Guessing Game</h1>
11-
<div id="game-container">
12-
<!-- TODO: Input for user guess -->
13-
<!-- TODO: Button to submit guess -->
14-
<!-- TODO: Display feedback (too high, too low, correct) -->
15-
<!-- TODO: Show number of attempts -->
16-
<!-- TODO: Option to restart game -->
12+
<div id="game-container" class="card">
13+
<p id="instructions">I'm thinking of a number between 1 and 100. Can you guess it?</p>
14+
<div id="controls" class="controls">
15+
<input id="guess-input" type="number" min="1" max="100" placeholder="Enter your guess" />
16+
<button id="guess-btn" type="button">Guess</button>
17+
</div>
18+
<p id="feedback" aria-live="polite"></p>
19+
<p id="attempts">Attempts: <span id="attempt-count">0</span></p>
20+
<button id="restart-btn" type="button">Restart</button>
1721
</div>
1822
<script src="main.js"></script>
1923
</body>
Lines changed: 87 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,92 @@
1-
// TODO: Generate a random number
2-
// TODO: Handle user guess input
3-
// TODO: Compare guess to target number
4-
// TODO: Provide feedback (too high, too low, correct)
5-
// TODO: Track number of attempts
6-
// TODO: Restart game functionality
1+
// Utility to generate a random integer in [min, max]
2+
function generateRandomInteger(min, max) {
3+
const minCeil = Math.ceil(min);
4+
const maxFloor = Math.floor(max);
5+
return Math.floor(Math.random() * (maxFloor - minCeil + 1)) + minCeil;
6+
}
77

88
function initNumberGuessingGame() {
9-
// TODO: Generate random number
10-
// TODO: Handle user input and feedback
11-
// TODO: Track attempts
12-
// TODO: Restart game
9+
const input = document.getElementById('guess-input');
10+
const guessBtn = document.getElementById('guess-btn');
11+
const feedback = document.getElementById('feedback');
12+
const attemptsText = document.getElementById('attempts');
13+
const attemptCount = document.getElementById('attempt-count');
14+
const restartBtn = document.getElementById('restart-btn');
15+
16+
const MIN = 1;
17+
const MAX = 100;
18+
19+
let targetNumber = generateRandomInteger(MIN, MAX);
20+
let attempts = 0;
21+
let gameOver = false;
22+
23+
function setFeedback(message, type) {
24+
feedback.textContent = message;
25+
feedback.dataset.type = type || '';
26+
}
27+
28+
function setGameOver(over) {
29+
gameOver = over;
30+
input.disabled = over;
31+
guessBtn.disabled = over;
32+
if (over) {
33+
input.blur();
34+
}
35+
}
36+
37+
function validateGuess(value) {
38+
if (value === '') return { ok: false, msg: 'Please enter a number.' };
39+
const num = Number(value);
40+
if (!Number.isFinite(num)) return { ok: false, msg: 'That is not a valid number.' };
41+
if (!Number.isInteger(num)) return { ok: false, msg: 'Please enter a whole number.' };
42+
if (num < MIN || num > MAX) return { ok: false, msg: `Enter a number between ${MIN} and ${MAX}.` };
43+
return { ok: true, value: num };
44+
}
45+
46+
function handleGuess() {
47+
if (gameOver) return;
48+
const { ok, msg, value } = validateGuess(input.value.trim());
49+
if (!ok) {
50+
setFeedback(msg, 'error');
51+
return;
52+
}
53+
attempts += 1;
54+
attemptCount.textContent = String(attempts);
55+
56+
if (value === targetNumber) {
57+
setFeedback(`Correct! The number was ${targetNumber}.`, 'success');
58+
setGameOver(true);
59+
return;
60+
}
61+
if (value < targetNumber) {
62+
setFeedback('Too low. Try a higher number.', 'low');
63+
} else {
64+
setFeedback('Too high. Try a lower number.', 'high');
65+
}
66+
input.select();
67+
}
68+
69+
function restartGame() {
70+
targetNumber = generateRandomInteger(MIN, MAX);
71+
attempts = 0;
72+
attemptCount.textContent = '0';
73+
setFeedback('', '');
74+
input.value = '';
75+
setGameOver(false);
76+
input.focus();
77+
}
78+
79+
guessBtn.addEventListener('click', handleGuess);
80+
input.addEventListener('keydown', function onKeyDown(event) {
81+
if (event.key === 'Enter') {
82+
handleGuess();
83+
}
84+
});
85+
restartBtn.addEventListener('click', restartGame);
86+
87+
// Init state
88+
attemptsText.hidden = false;
89+
setFeedback('', '');
1390
}
1491

1592
window.addEventListener('DOMContentLoaded', initNumberGuessingGame);
Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,68 @@
1-
/* TODO: Style game container, input, button, feedback, attempts, restart button */
1+
/* Basic reset */
2+
/* Page-level layout is handled by assets/styles.css; only tweak specifics here */
3+
html, body { height: 100%; }
4+
body {
5+
display: flex;
6+
flex-direction: column;
7+
align-items: center;
8+
background: var(--bg);
9+
color: var(--text);
10+
}
11+
12+
h1 { margin: 24px 0 12px; font-size: 24px; font-weight: 700; color: var(--text); }
13+
14+
#game-container {
15+
width: 100%;
16+
max-width: 420px;
17+
background: var(--card);
18+
border: 1px solid #262631;
19+
border-radius: 12px;
20+
padding: 20px;
21+
box-shadow: 0 0 0 1px rgba(255,255,255,0.02) inset;
22+
}
23+
24+
#instructions { margin: 0 0 12px; color: var(--muted); }
25+
26+
#controls {
27+
display: flex;
28+
gap: 8px;
29+
}
30+
31+
#guess-input {
32+
flex: 1 1 auto;
33+
padding: 10px 12px;
34+
border: 1px solid #2a2a33;
35+
border-radius: 8px;
36+
font-size: 14px;
37+
outline: none;
38+
background: #0e0e13;
39+
color: var(--text);
40+
}
41+
#guess-input::placeholder { color: var(--muted); }
42+
#guess-input:focus { border-color: #93c5fd; box-shadow: 0 0 0 3px rgba(147,197,253,0.2); }
43+
44+
button {
45+
padding: 10px 14px;
46+
border-radius: 8px;
47+
border: 1px solid #1e3a8a;
48+
background: linear-gradient(135deg, var(--accent), var(--accent-2));
49+
color: #0b1020;
50+
font-weight: 600;
51+
cursor: pointer;
52+
}
53+
button:hover { filter: brightness(1.05); }
54+
button:disabled { background: #1f1f27; border-color: #2a2a33; color: var(--muted); cursor: not-allowed; }
55+
56+
#feedback { min-height: 22px; margin: 12px 0 8px; }
57+
#feedback[data-type="error"] { color: #f87171; }
58+
#feedback[data-type="low"], #feedback[data-type="high"] { color: #fbbf24; }
59+
#feedback[data-type="success"] { color: var(--accent); }
60+
61+
#attempts { margin: 0 0 12px; color: var(--muted); }
62+
63+
#restart-btn {
64+
width: 100%;
65+
background: linear-gradient(135deg, var(--accent), var(--accent-2));
66+
border-color: #1e3a8a;
67+
}
68+
#restart-btn:hover { filter: brightness(1.05); }

0 commit comments

Comments
 (0)