create-template-html-css 1.8.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +7 -1
- package/demo-games/guess-number/index.html +71 -0
- package/demo-games/guess-number/script.js +216 -0
- package/demo-games/guess-number/style.css +337 -0
- package/demo-games/memory-game/index.html +50 -0
- package/demo-games/memory-game/script.js +216 -0
- package/demo-games/memory-game/style.css +288 -0
- package/demo-games/snake-game/index.html +61 -0
- package/demo-games/snake-game/script.js +360 -0
- package/demo-games/snake-game/style.css +246 -0
- package/demo-games/tic-tac-toe/index.html +57 -0
- package/demo-games/tic-tac-toe/script.js +156 -0
- package/demo-games/tic-tac-toe/style.css +244 -0
- package/package.json +1 -1
- package/templates/guess-number/index.html +71 -0
- package/templates/guess-number/script.js +216 -0
- package/templates/guess-number/style.css +337 -0
- package/templates/memory-game/index.html +50 -0
- package/templates/memory-game/script.js +216 -0
- package/templates/memory-game/style.css +288 -0
- package/templates/snake-game/index.html +61 -0
- package/templates/snake-game/script.js +360 -0
- package/templates/snake-game/style.css +246 -0
- package/templates/tic-tac-toe/index.html +57 -0
- package/templates/tic-tac-toe/script.js +156 -0
- package/templates/tic-tac-toe/style.css +244 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// Tic Tac Toe Game Logic
|
|
2
|
+
|
|
3
|
+
const board = document.getElementById('board');
|
|
4
|
+
const cells = document.querySelectorAll('.cell');
|
|
5
|
+
const currentPlayerDisplay = document.getElementById('currentPlayer');
|
|
6
|
+
const messageDisplay = document.getElementById('message');
|
|
7
|
+
const resetBtn = document.getElementById('resetBtn');
|
|
8
|
+
const resetScoreBtn = document.getElementById('resetScoreBtn');
|
|
9
|
+
const scoreX = document.getElementById('scoreX');
|
|
10
|
+
const scoreO = document.getElementById('scoreO');
|
|
11
|
+
const scoreDraw = document.getElementById('scoreDraw');
|
|
12
|
+
|
|
13
|
+
let currentPlayer = 'X';
|
|
14
|
+
let gameBoard = ['', '', '', '', '', '', '', '', ''];
|
|
15
|
+
let gameActive = true;
|
|
16
|
+
let scores = { X: 0, O: 0, draw: 0 };
|
|
17
|
+
|
|
18
|
+
// Winning combinations
|
|
19
|
+
const winningCombinations = [
|
|
20
|
+
[0, 1, 2], [3, 4, 5], [6, 7, 8], // Rows
|
|
21
|
+
[0, 3, 6], [1, 4, 7], [2, 5, 8], // Columns
|
|
22
|
+
[0, 4, 8], [2, 4, 6] // Diagonals
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
// Initialize game
|
|
26
|
+
function initGame() {
|
|
27
|
+
gameBoard = ['', '', '', '', '', '', '', '', ''];
|
|
28
|
+
gameActive = true;
|
|
29
|
+
currentPlayer = 'X';
|
|
30
|
+
updateCurrentPlayerDisplay();
|
|
31
|
+
messageDisplay.textContent = '';
|
|
32
|
+
messageDisplay.className = 'message';
|
|
33
|
+
|
|
34
|
+
cells.forEach(cell => {
|
|
35
|
+
cell.textContent = '';
|
|
36
|
+
cell.className = 'cell';
|
|
37
|
+
cell.addEventListener('click', handleCellClick);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Handle cell click
|
|
42
|
+
function handleCellClick(e) {
|
|
43
|
+
const cell = e.target;
|
|
44
|
+
const cellIndex = parseInt(cell.getAttribute('data-cell'));
|
|
45
|
+
|
|
46
|
+
if (gameBoard[cellIndex] !== '' || !gameActive) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
makeMove(cell, cellIndex);
|
|
51
|
+
checkResult();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Make a move
|
|
55
|
+
function makeMove(cell, index) {
|
|
56
|
+
gameBoard[index] = currentPlayer;
|
|
57
|
+
cell.textContent = currentPlayer;
|
|
58
|
+
cell.classList.add(`player-${currentPlayer.toLowerCase()}`);
|
|
59
|
+
cell.classList.add('taken');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Check game result
|
|
63
|
+
function checkResult() {
|
|
64
|
+
let roundWon = false;
|
|
65
|
+
let winningCombination = [];
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < winningCombinations.length; i++) {
|
|
68
|
+
const [a, b, c] = winningCombinations[i];
|
|
69
|
+
if (gameBoard[a] && gameBoard[a] === gameBoard[b] && gameBoard[a] === gameBoard[c]) {
|
|
70
|
+
roundWon = true;
|
|
71
|
+
winningCombination = [a, b, c];
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (roundWon) {
|
|
77
|
+
handleWin(winningCombination);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!gameBoard.includes('')) {
|
|
82
|
+
handleDraw();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
switchPlayer();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Handle win
|
|
90
|
+
function handleWin(winningCombination) {
|
|
91
|
+
gameActive = false;
|
|
92
|
+
messageDisplay.textContent = `Player ${currentPlayer} Wins! 🎉`;
|
|
93
|
+
messageDisplay.className = `message show ${currentPlayer === 'X' ? 'win-x' : 'win-o'}`;
|
|
94
|
+
|
|
95
|
+
// Highlight winning cells
|
|
96
|
+
winningCombination.forEach(index => {
|
|
97
|
+
cells[index].classList.add('winner');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Update score
|
|
101
|
+
scores[currentPlayer]++;
|
|
102
|
+
updateScoreDisplay();
|
|
103
|
+
|
|
104
|
+
// Auto reset after 2 seconds
|
|
105
|
+
setTimeout(() => {
|
|
106
|
+
initGame();
|
|
107
|
+
}, 2000);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Handle draw
|
|
111
|
+
function handleDraw() {
|
|
112
|
+
gameActive = false;
|
|
113
|
+
messageDisplay.textContent = "It's a Draw! 🤝";
|
|
114
|
+
messageDisplay.className = 'message show draw';
|
|
115
|
+
|
|
116
|
+
scores.draw++;
|
|
117
|
+
updateScoreDisplay();
|
|
118
|
+
|
|
119
|
+
// Auto reset after 2 seconds
|
|
120
|
+
setTimeout(() => {
|
|
121
|
+
initGame();
|
|
122
|
+
}, 2000);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Switch player
|
|
126
|
+
function switchPlayer() {
|
|
127
|
+
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
|
|
128
|
+
updateCurrentPlayerDisplay();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Update current player display
|
|
132
|
+
function updateCurrentPlayerDisplay() {
|
|
133
|
+
currentPlayerDisplay.textContent = currentPlayer;
|
|
134
|
+
currentPlayerDisplay.className = `player-${currentPlayer.toLowerCase()}`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Update score display
|
|
138
|
+
function updateScoreDisplay() {
|
|
139
|
+
scoreX.textContent = scores.X;
|
|
140
|
+
scoreO.textContent = scores.O;
|
|
141
|
+
scoreDraw.textContent = scores.draw;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Reset score
|
|
145
|
+
function resetScore() {
|
|
146
|
+
scores = { X: 0, O: 0, draw: 0 };
|
|
147
|
+
updateScoreDisplay();
|
|
148
|
+
initGame();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Event listeners
|
|
152
|
+
resetBtn.addEventListener('click', initGame);
|
|
153
|
+
resetScoreBtn.addEventListener('click', resetScore);
|
|
154
|
+
|
|
155
|
+
// Initialize on load
|
|
156
|
+
initGame();
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
* {
|
|
2
|
+
margin: 0;
|
|
3
|
+
padding: 0;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
body {
|
|
8
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
9
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
10
|
+
min-height: 100vh;
|
|
11
|
+
display: flex;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
align-items: center;
|
|
14
|
+
padding: 20px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.container {
|
|
18
|
+
width: 100%;
|
|
19
|
+
max-width: 500px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.game-card {
|
|
23
|
+
background: white;
|
|
24
|
+
border-radius: 16px;
|
|
25
|
+
padding: 30px;
|
|
26
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.game-card h1 {
|
|
30
|
+
text-align: center;
|
|
31
|
+
color: #333;
|
|
32
|
+
margin-bottom: 20px;
|
|
33
|
+
font-size: 2.5rem;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.game-info {
|
|
37
|
+
margin-bottom: 20px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.current-player {
|
|
41
|
+
text-align: center;
|
|
42
|
+
font-size: 1.3rem;
|
|
43
|
+
margin-bottom: 15px;
|
|
44
|
+
font-weight: 600;
|
|
45
|
+
color: #555;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.player-x {
|
|
49
|
+
color: #3b82f6;
|
|
50
|
+
font-weight: bold;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.player-o {
|
|
54
|
+
color: #ef4444;
|
|
55
|
+
font-weight: bold;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.score-board {
|
|
59
|
+
display: flex;
|
|
60
|
+
justify-content: space-around;
|
|
61
|
+
padding: 15px;
|
|
62
|
+
background: #f3f4f6;
|
|
63
|
+
border-radius: 12px;
|
|
64
|
+
margin-bottom: 20px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.score-item {
|
|
68
|
+
text-align: center;
|
|
69
|
+
font-size: 1.1rem;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.score-item span:last-child {
|
|
73
|
+
display: block;
|
|
74
|
+
font-size: 1.5rem;
|
|
75
|
+
font-weight: bold;
|
|
76
|
+
margin-top: 5px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.board {
|
|
80
|
+
display: grid;
|
|
81
|
+
grid-template-columns: repeat(3, 1fr);
|
|
82
|
+
gap: 10px;
|
|
83
|
+
margin: 20px 0;
|
|
84
|
+
padding: 10px;
|
|
85
|
+
background: #f9fafb;
|
|
86
|
+
border-radius: 12px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.cell {
|
|
90
|
+
aspect-ratio: 1;
|
|
91
|
+
background: white;
|
|
92
|
+
border: 3px solid #e5e7eb;
|
|
93
|
+
border-radius: 12px;
|
|
94
|
+
font-size: 3rem;
|
|
95
|
+
font-weight: bold;
|
|
96
|
+
display: flex;
|
|
97
|
+
justify-content: center;
|
|
98
|
+
align-items: center;
|
|
99
|
+
cursor: pointer;
|
|
100
|
+
transition: all 0.3s ease;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.cell:hover:not(.taken) {
|
|
104
|
+
background: #f3f4f6;
|
|
105
|
+
transform: scale(1.05);
|
|
106
|
+
border-color: #9ca3af;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.cell.taken {
|
|
110
|
+
cursor: not-allowed;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.cell.player-x {
|
|
114
|
+
color: #3b82f6;
|
|
115
|
+
animation: scaleIn 0.3s ease;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.cell.player-o {
|
|
119
|
+
color: #ef4444;
|
|
120
|
+
animation: scaleIn 0.3s ease;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.cell.winner {
|
|
124
|
+
background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
|
|
125
|
+
animation: winnerPulse 0.6s ease;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@keyframes scaleIn {
|
|
129
|
+
0% {
|
|
130
|
+
transform: scale(0);
|
|
131
|
+
}
|
|
132
|
+
50% {
|
|
133
|
+
transform: scale(1.2);
|
|
134
|
+
}
|
|
135
|
+
100% {
|
|
136
|
+
transform: scale(1);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@keyframes winnerPulse {
|
|
141
|
+
0%, 100% {
|
|
142
|
+
transform: scale(1);
|
|
143
|
+
}
|
|
144
|
+
50% {
|
|
145
|
+
transform: scale(1.1);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.message {
|
|
150
|
+
text-align: center;
|
|
151
|
+
font-size: 1.3rem;
|
|
152
|
+
font-weight: bold;
|
|
153
|
+
height: 40px;
|
|
154
|
+
display: flex;
|
|
155
|
+
justify-content: center;
|
|
156
|
+
align-items: center;
|
|
157
|
+
margin-bottom: 20px;
|
|
158
|
+
opacity: 0;
|
|
159
|
+
transition: opacity 0.3s ease;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.message.show {
|
|
163
|
+
opacity: 1;
|
|
164
|
+
animation: slideDown 0.4s ease;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.message.win-x {
|
|
168
|
+
color: #3b82f6;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.message.win-o {
|
|
172
|
+
color: #ef4444;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.message.draw {
|
|
176
|
+
color: #8b5cf6;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
@keyframes slideDown {
|
|
180
|
+
from {
|
|
181
|
+
transform: translateY(-20px);
|
|
182
|
+
opacity: 0;
|
|
183
|
+
}
|
|
184
|
+
to {
|
|
185
|
+
transform: translateY(0);
|
|
186
|
+
opacity: 1;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.button-group {
|
|
191
|
+
display: flex;
|
|
192
|
+
gap: 10px;
|
|
193
|
+
justify-content: center;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.btn {
|
|
197
|
+
flex: 1;
|
|
198
|
+
padding: 12px 24px;
|
|
199
|
+
border: none;
|
|
200
|
+
border-radius: 8px;
|
|
201
|
+
font-size: 1rem;
|
|
202
|
+
font-weight: 600;
|
|
203
|
+
cursor: pointer;
|
|
204
|
+
transition: all 0.3s ease;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.btn-primary {
|
|
208
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
209
|
+
color: white;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.btn-primary:hover {
|
|
213
|
+
transform: translateY(-2px);
|
|
214
|
+
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.btn-secondary {
|
|
218
|
+
background: #6b7280;
|
|
219
|
+
color: white;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.btn-secondary:hover {
|
|
223
|
+
background: #4b5563;
|
|
224
|
+
transform: translateY(-2px);
|
|
225
|
+
box-shadow: 0 5px 15px rgba(107, 114, 128, 0.4);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@media (max-width: 480px) {
|
|
229
|
+
.game-card {
|
|
230
|
+
padding: 20px;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.game-card h1 {
|
|
234
|
+
font-size: 2rem;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.cell {
|
|
238
|
+
font-size: 2rem;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.button-group {
|
|
242
|
+
flex-direction: column;
|
|
243
|
+
}
|
|
244
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>{{name}} - Guess Number</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div class="container">
|
|
11
|
+
<div class="game-card">
|
|
12
|
+
<h1>🎯 Guess the Number</h1>
|
|
13
|
+
|
|
14
|
+
<div class="game-info">
|
|
15
|
+
<div class="info-row">
|
|
16
|
+
<span class="label">Range:</span>
|
|
17
|
+
<span id="rangeDisplay" class="value">1 - 100</span>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="info-row">
|
|
20
|
+
<span class="label">Attempts:</span>
|
|
21
|
+
<span id="attempts" class="value">0</span>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="info-row">
|
|
24
|
+
<span class="label">Best Score:</span>
|
|
25
|
+
<span id="bestScore" class="value">-</span>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="hint-section">
|
|
30
|
+
<div class="hint-box" id="hintBox">
|
|
31
|
+
<p id="hintText">I'm thinking of a number...</p>
|
|
32
|
+
<p id="hintDetails">Make your first guess!</p>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="input-section">
|
|
37
|
+
<input
|
|
38
|
+
type="number"
|
|
39
|
+
id="guessInput"
|
|
40
|
+
placeholder="Enter your guess"
|
|
41
|
+
min="1"
|
|
42
|
+
max="100"
|
|
43
|
+
/>
|
|
44
|
+
<button id="guessBtn" class="btn btn-primary">Guess</button>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<div class="history-section">
|
|
48
|
+
<h3>Previous Guesses</h3>
|
|
49
|
+
<div id="guessHistory" class="guess-history">
|
|
50
|
+
<p class="empty-state">No guesses yet</p>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div class="difficulty-section">
|
|
55
|
+
<h3>Difficulty</h3>
|
|
56
|
+
<div class="difficulty-buttons">
|
|
57
|
+
<button class="difficulty-btn active" data-range="100">Easy (1-100)</button>
|
|
58
|
+
<button class="difficulty-btn" data-range="500">Medium (1-500)</button>
|
|
59
|
+
<button class="difficulty-btn" data-range="1000">Hard (1-1000)</button>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div class="button-group">
|
|
64
|
+
<button id="newGameBtn" class="btn btn-success">New Game</button>
|
|
65
|
+
<button id="giveUpBtn" class="btn btn-secondary">Give Up</button>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
<script src="script.js"></script>
|
|
70
|
+
</body>
|
|
71
|
+
</html>
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// Guess the Number Game Logic
|
|
2
|
+
|
|
3
|
+
const guessInput = document.getElementById('guessInput');
|
|
4
|
+
const guessBtn = document.getElementById('guessBtn');
|
|
5
|
+
const newGameBtn = document.getElementById('newGameBtn');
|
|
6
|
+
const giveUpBtn = document.getElementById('giveUpBtn');
|
|
7
|
+
const attemptsDisplay = document.getElementById('attempts');
|
|
8
|
+
const bestScoreDisplay = document.getElementById('bestScore');
|
|
9
|
+
const rangeDisplay = document.getElementById('rangeDisplay');
|
|
10
|
+
const hintBox = document.getElementById('hintBox');
|
|
11
|
+
const hintText = document.getElementById('hintText');
|
|
12
|
+
const hintDetails = document.getElementById('hintDetails');
|
|
13
|
+
const guessHistory = document.getElementById('guessHistory');
|
|
14
|
+
const difficultyBtns = document.querySelectorAll('.difficulty-btn');
|
|
15
|
+
|
|
16
|
+
let targetNumber = 0;
|
|
17
|
+
let attempts = 0;
|
|
18
|
+
let maxRange = 100;
|
|
19
|
+
let guesses = [];
|
|
20
|
+
let bestScores = {
|
|
21
|
+
100: localStorage.getItem('bestScore100') || null,
|
|
22
|
+
500: localStorage.getItem('bestScore500') || null,
|
|
23
|
+
1000: localStorage.getItem('bestScore1000') || null
|
|
24
|
+
};
|
|
25
|
+
let gameActive = true;
|
|
26
|
+
|
|
27
|
+
// Initialize game
|
|
28
|
+
function initGame() {
|
|
29
|
+
targetNumber = Math.floor(Math.random() * maxRange) + 1;
|
|
30
|
+
attempts = 0;
|
|
31
|
+
guesses = [];
|
|
32
|
+
gameActive = true;
|
|
33
|
+
|
|
34
|
+
updateDisplay();
|
|
35
|
+
guessInput.value = '';
|
|
36
|
+
guessInput.disabled = false;
|
|
37
|
+
guessBtn.disabled = false;
|
|
38
|
+
guessInput.focus();
|
|
39
|
+
|
|
40
|
+
hintBox.className = 'hint-box';
|
|
41
|
+
hintText.textContent = "I'm thinking of a number...";
|
|
42
|
+
hintDetails.textContent = 'Make your first guess!';
|
|
43
|
+
|
|
44
|
+
guessHistory.innerHTML = '<p class="empty-state">No guesses yet</p>';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Make a guess
|
|
48
|
+
function makeGuess() {
|
|
49
|
+
if (!gameActive) return;
|
|
50
|
+
|
|
51
|
+
const guess = parseInt(guessInput.value);
|
|
52
|
+
|
|
53
|
+
// Validate input
|
|
54
|
+
if (isNaN(guess) || guess < 1 || guess > maxRange) {
|
|
55
|
+
showHint('invalid', '⚠️ Invalid Input', `Please enter a number between 1 and ${maxRange}`);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check if already guessed
|
|
60
|
+
if (guesses.includes(guess)) {
|
|
61
|
+
showHint('duplicate', '🔄 Already Guessed', 'You already tried this number!');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
attempts++;
|
|
66
|
+
guesses.push(guess);
|
|
67
|
+
updateDisplay();
|
|
68
|
+
addToHistory(guess);
|
|
69
|
+
|
|
70
|
+
// Check if correct
|
|
71
|
+
if (guess === targetNumber) {
|
|
72
|
+
handleWin();
|
|
73
|
+
} else if (guess < targetNumber) {
|
|
74
|
+
const diff = targetNumber - guess;
|
|
75
|
+
if (diff <= 5) {
|
|
76
|
+
showHint('hot', '🔥 Very Hot!', 'You\'re super close! Go higher!');
|
|
77
|
+
} else if (diff <= 10) {
|
|
78
|
+
showHint('warm', '🌡️ Hot!', 'Getting closer! Go higher!');
|
|
79
|
+
} else if (diff <= 20) {
|
|
80
|
+
showHint('cool', '❄️ Warm', 'Go higher!');
|
|
81
|
+
} else {
|
|
82
|
+
showHint('cold', '🧊 Cold', 'Too low! Go much higher!');
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
const diff = guess - targetNumber;
|
|
86
|
+
if (diff <= 5) {
|
|
87
|
+
showHint('hot', '🔥 Very Hot!', 'You\'re super close! Go lower!');
|
|
88
|
+
} else if (diff <= 10) {
|
|
89
|
+
showHint('warm', '🌡️ Hot!', 'Getting closer! Go lower!');
|
|
90
|
+
} else if (diff <= 20) {
|
|
91
|
+
showHint('cool', '❄️ Warm', 'Go lower!');
|
|
92
|
+
} else {
|
|
93
|
+
showHint('cold', '🧊 Cold', 'Too high! Go much lower!');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
guessInput.value = '';
|
|
98
|
+
guessInput.focus();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Handle win
|
|
102
|
+
function handleWin() {
|
|
103
|
+
gameActive = false;
|
|
104
|
+
guessInput.disabled = true;
|
|
105
|
+
guessBtn.disabled = true;
|
|
106
|
+
|
|
107
|
+
showHint('win', '🎉 Congratulations!', `You found it in ${attempts} attempts!`);
|
|
108
|
+
|
|
109
|
+
// Update best score
|
|
110
|
+
if (!bestScores[maxRange] || attempts < bestScores[maxRange]) {
|
|
111
|
+
bestScores[maxRange] = attempts;
|
|
112
|
+
localStorage.setItem(`bestScore${maxRange}`, attempts);
|
|
113
|
+
bestScoreDisplay.textContent = attempts;
|
|
114
|
+
|
|
115
|
+
// Show new record message
|
|
116
|
+
setTimeout(() => {
|
|
117
|
+
hintDetails.textContent = `🏆 New Record: ${attempts} attempts!`;
|
|
118
|
+
}, 1500);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Give up
|
|
123
|
+
function giveUp() {
|
|
124
|
+
if (!gameActive) return;
|
|
125
|
+
|
|
126
|
+
gameActive = false;
|
|
127
|
+
guessInput.disabled = true;
|
|
128
|
+
guessBtn.disabled = true;
|
|
129
|
+
|
|
130
|
+
showHint('give-up', '😔 Game Over', `The number was ${targetNumber}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Show hint
|
|
134
|
+
function showHint(type, title, details) {
|
|
135
|
+
hintBox.className = `hint-box ${type}`;
|
|
136
|
+
hintText.textContent = title;
|
|
137
|
+
hintDetails.textContent = details;
|
|
138
|
+
|
|
139
|
+
// Animate
|
|
140
|
+
hintBox.style.animation = 'none';
|
|
141
|
+
setTimeout(() => {
|
|
142
|
+
hintBox.style.animation = 'bounceIn 0.5s ease';
|
|
143
|
+
}, 10);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Add to history
|
|
147
|
+
function addToHistory(guess) {
|
|
148
|
+
if (guesses.length === 1) {
|
|
149
|
+
guessHistory.innerHTML = '';
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const guessItem = document.createElement('div');
|
|
153
|
+
guessItem.className = 'guess-item';
|
|
154
|
+
|
|
155
|
+
let icon = '';
|
|
156
|
+
if (guess === targetNumber) {
|
|
157
|
+
icon = '🎯';
|
|
158
|
+
guessItem.classList.add('correct');
|
|
159
|
+
} else if (Math.abs(guess - targetNumber) <= 5) {
|
|
160
|
+
icon = '🔥';
|
|
161
|
+
} else if (Math.abs(guess - targetNumber) <= 10) {
|
|
162
|
+
icon = '🌡️';
|
|
163
|
+
} else if (Math.abs(guess - targetNumber) <= 20) {
|
|
164
|
+
icon = '❄️';
|
|
165
|
+
} else {
|
|
166
|
+
icon = '🧊';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
guessItem.innerHTML = `
|
|
170
|
+
<span class="guess-number">${guess}</span>
|
|
171
|
+
<span class="guess-icon">${icon}</span>
|
|
172
|
+
`;
|
|
173
|
+
|
|
174
|
+
guessHistory.prepend(guessItem);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Update display
|
|
178
|
+
function updateDisplay() {
|
|
179
|
+
attemptsDisplay.textContent = attempts;
|
|
180
|
+
bestScoreDisplay.textContent = bestScores[maxRange] || '-';
|
|
181
|
+
rangeDisplay.textContent = `1 - ${maxRange}`;
|
|
182
|
+
guessInput.setAttribute('max', maxRange);
|
|
183
|
+
guessInput.setAttribute('placeholder', `Enter number (1-${maxRange})`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Change difficulty
|
|
187
|
+
function changeDifficulty(newRange) {
|
|
188
|
+
maxRange = parseInt(newRange);
|
|
189
|
+
|
|
190
|
+
// Update active button
|
|
191
|
+
difficultyBtns.forEach(btn => {
|
|
192
|
+
btn.classList.toggle('active', parseInt(btn.dataset.range) === maxRange);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
initGame();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Event listeners
|
|
199
|
+
guessBtn.addEventListener('click', makeGuess);
|
|
200
|
+
newGameBtn.addEventListener('click', initGame);
|
|
201
|
+
giveUpBtn.addEventListener('click', giveUp);
|
|
202
|
+
|
|
203
|
+
guessInput.addEventListener('keypress', (e) => {
|
|
204
|
+
if (e.key === 'Enter') {
|
|
205
|
+
makeGuess();
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
difficultyBtns.forEach(btn => {
|
|
210
|
+
btn.addEventListener('click', () => {
|
|
211
|
+
changeDifficulty(btn.dataset.range);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Initialize on load
|
|
216
|
+
initGame();
|