wad-lab 1.0.5 → 1.0.7
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/index.js +9 -1
- package/package.json +1 -1
- package/templates/game-memory-cards/index.html +24 -0
- package/templates/game-memory-cards/script.js +90 -0
- package/templates/game-memory-cards/style.css +74 -0
- package/templates/game-rock-paper-scissors/index.html +35 -0
- package/templates/game-rock-paper-scissors/script.js +49 -0
- package/templates/game-rock-paper-scissors/style.css +67 -0
- package/templates/game-tic-tac-toe/index.html +30 -0
- package/templates/game-tic-tac-toe/script.js +82 -0
- package/templates/game-tic-tac-toe/style.css +66 -0
- package/templates/game-whack-a-mole/index.html +34 -0
- package/templates/game-whack-a-mole/script.js +83 -0
- package/templates/game-whack-a-mole/style.css +75 -0
- package/templates/vue-cart-router-pinia/index.html +12 -0
- package/templates/vue-cart-router-pinia/package.json +20 -0
- package/templates/vue-cart-router-pinia/src/App.vue +78 -0
- package/templates/vue-cart-router-pinia/src/main.js +9 -0
- package/templates/vue-cart-router-pinia/src/router/index.js +17 -0
- package/templates/vue-cart-router-pinia/src/stores/cartStore.js +58 -0
- package/templates/vue-cart-router-pinia/src/views/CartView.vue +139 -0
- package/templates/vue-cart-router-pinia/src/views/CheckoutView.vue +144 -0
- package/templates/vue-cart-router-pinia/src/views/ProductCatalogView.vue +73 -0
- package/templates/vue-cart-router-pinia/vite.config.js +6 -0
- package/templates/vue-memory-game/index.html +12 -0
- package/templates/vue-memory-game/package.json +19 -0
- package/templates/vue-memory-game/src/App.vue +106 -0
- package/templates/vue-memory-game/src/main.js +7 -0
- package/templates/vue-memory-game/src/stores/memoryStore.js +64 -0
- package/templates/vue-memory-game/vite.config.js +6 -0
- package/templates/vue-todo-pinia/index.html +12 -0
- package/templates/vue-todo-pinia/package.json +19 -0
- package/templates/vue-todo-pinia/src/App.vue +179 -0
- package/templates/vue-todo-pinia/src/main.js +7 -0
- package/templates/vue-todo-pinia/src/stores/todoStore.js +50 -0
- package/templates/vue-todo-pinia/vite.config.js +6 -0
- package/templates/vue-todo-router/index.html +12 -0
- package/templates/vue-todo-router/package.json +19 -0
- package/templates/vue-todo-router/src/App.vue +55 -0
- package/templates/vue-todo-router/src/data/todoState.js +38 -0
- package/templates/vue-todo-router/src/main.js +7 -0
- package/templates/vue-todo-router/src/router/index.js +17 -0
- package/templates/vue-todo-router/src/views/AddTodoView.vue +85 -0
- package/templates/vue-todo-router/src/views/TodoDetailView.vue +89 -0
- package/templates/vue-todo-router/src/views/TodoListView.vue +77 -0
- package/templates/vue-todo-router/vite.config.js +6 -0
- package/templates/servlet-flow/SERVLET_EXAM_CHEATSHEET.md +0 -389
package/bin/index.js
CHANGED
|
@@ -28,7 +28,15 @@ function copyDirRecursive(src, dest) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const templates = [
|
|
31
|
-
{ name: 'all (Unpack All
|
|
31
|
+
{ name: 'all (Unpack All 27 Templates)', value: 'all' },
|
|
32
|
+
{ name: 'game-rock-paper-scissors (Player vs Computer RPS)', value: 'game-rock-paper-scissors' },
|
|
33
|
+
{ name: 'game-tic-tac-toe (3x3 Turn Grid with Win Check)', value: 'game-tic-tac-toe' },
|
|
34
|
+
{ name: 'game-whack-a-mole (3x3 Mole Whack with Timer)', value: 'game-whack-a-mole' },
|
|
35
|
+
{ name: 'game-memory-cards (3x4 Flashcard Matching Game)', value: 'game-memory-cards' },
|
|
36
|
+
{ name: 'vue-memory-game (Vue 3 + Pinia Flashcard Matching)', value: 'vue-memory-game' },
|
|
37
|
+
{ name: 'vue-todo-pinia (Vue 3 + Pinia Task Manager)', value: 'vue-todo-pinia' },
|
|
38
|
+
{ name: 'vue-todo-router (Vue 3 + Router Multi-View Tasks)', value: 'vue-todo-router' },
|
|
39
|
+
{ name: 'vue-cart-router-pinia (Vue 3 + Router + Pinia Shopping Cart)', value: 'vue-cart-router-pinia' },
|
|
32
40
|
{ name: 'html-css-js (Form Validation & DOM)', value: 'html-css-js' },
|
|
33
41
|
{ name: 'servlet-basic (Tomcat GET + POST)', value: 'servlet-basic' },
|
|
34
42
|
{ name: 'servlet-jdbc (Tomcat + MySQL JDBC)', value: 'servlet-jdbc' },
|
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
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>Memory Card Game</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css">
|
|
8
|
+
<script src="script.js" defer></script>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div class="game-container">
|
|
12
|
+
<h1>Memory Card Game</h1>
|
|
13
|
+
|
|
14
|
+
<div class="stats-bar">
|
|
15
|
+
<div>Moves: <span id="moves">0</span></div>
|
|
16
|
+
<div>Matches: <span id="matches">0</span> / 6</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<button type="button" class="btn-restart" onclick="initGame()">Restart Game</button>
|
|
20
|
+
|
|
21
|
+
<div class="card-grid" id="cardGrid"></div>
|
|
22
|
+
</div>
|
|
23
|
+
</body>
|
|
24
|
+
</html>
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const symbols = ["🐶", "🐱", "🐭", "🐹", "🐰", "🦊"];
|
|
2
|
+
let cards = [];
|
|
3
|
+
let flippedCards = [];
|
|
4
|
+
let matchedCount = 0;
|
|
5
|
+
let moves = 0;
|
|
6
|
+
let lockBoard = false;
|
|
7
|
+
|
|
8
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
9
|
+
initGame();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
function initGame() {
|
|
13
|
+
const grid = document.getElementById("cardGrid");
|
|
14
|
+
grid.innerHTML = "";
|
|
15
|
+
|
|
16
|
+
cards = [...symbols, ...symbols];
|
|
17
|
+
cards.sort(function () {
|
|
18
|
+
return 0.5 - Math.random();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
flippedCards = [];
|
|
22
|
+
matchedCount = 0;
|
|
23
|
+
moves = 0;
|
|
24
|
+
lockBoard = false;
|
|
25
|
+
|
|
26
|
+
document.getElementById("moves").textContent = moves;
|
|
27
|
+
document.getElementById("matches").textContent = matchedCount;
|
|
28
|
+
|
|
29
|
+
cards.forEach(function (symbol, index) {
|
|
30
|
+
const card = document.createElement("div");
|
|
31
|
+
card.classList.add("card");
|
|
32
|
+
card.setAttribute("data-symbol", symbol);
|
|
33
|
+
card.setAttribute("data-index", index);
|
|
34
|
+
card.textContent = "?";
|
|
35
|
+
|
|
36
|
+
card.addEventListener("click", handleCardClick);
|
|
37
|
+
grid.appendChild(card);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function handleCardClick(event) {
|
|
42
|
+
const clickedCard = event.currentTarget;
|
|
43
|
+
|
|
44
|
+
if (lockBoard) return;
|
|
45
|
+
if (clickedCard.classList.contains("flipped") || clickedCard.classList.contains("matched")) return;
|
|
46
|
+
|
|
47
|
+
const symbol = clickedCard.getAttribute("data-symbol");
|
|
48
|
+
clickedCard.textContent = symbol;
|
|
49
|
+
clickedCard.classList.add("flipped");
|
|
50
|
+
|
|
51
|
+
flippedCards.push(clickedCard);
|
|
52
|
+
|
|
53
|
+
if (flippedCards.length === 2) {
|
|
54
|
+
moves++;
|
|
55
|
+
document.getElementById("moves").textContent = moves;
|
|
56
|
+
checkMatch();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function checkMatch() {
|
|
61
|
+
const card1 = flippedCards[0];
|
|
62
|
+
const card2 = flippedCards[1];
|
|
63
|
+
|
|
64
|
+
const symbol1 = card1.getAttribute("data-symbol");
|
|
65
|
+
const symbol2 = card2.getAttribute("data-symbol");
|
|
66
|
+
|
|
67
|
+
if (symbol1 === symbol2) {
|
|
68
|
+
card1.classList.add("matched");
|
|
69
|
+
card2.classList.add("matched");
|
|
70
|
+
matchedCount++;
|
|
71
|
+
document.getElementById("matches").textContent = matchedCount;
|
|
72
|
+
flippedCards = [];
|
|
73
|
+
|
|
74
|
+
if (matchedCount === symbols.length) {
|
|
75
|
+
setTimeout(function () {
|
|
76
|
+
alert("Congratulations! You won in " + moves + " moves! 🎉");
|
|
77
|
+
}, 300);
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
lockBoard = true;
|
|
81
|
+
setTimeout(function () {
|
|
82
|
+
card1.textContent = "?";
|
|
83
|
+
card2.textContent = "?";
|
|
84
|
+
card1.classList.remove("flipped");
|
|
85
|
+
card2.classList.remove("flipped");
|
|
86
|
+
flippedCards = [];
|
|
87
|
+
lockBoard = false;
|
|
88
|
+
}, 800);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
body {
|
|
2
|
+
font-family: Arial, sans-serif;
|
|
3
|
+
display: flex;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
align-items: center;
|
|
6
|
+
min-height: 100vh;
|
|
7
|
+
margin: 0;
|
|
8
|
+
background-color: #f4f4f4;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.game-container {
|
|
12
|
+
text-align: center;
|
|
13
|
+
background: #ffffff;
|
|
14
|
+
padding: 25px;
|
|
15
|
+
border: 1px solid #ccc;
|
|
16
|
+
border-radius: 8px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.stats-bar {
|
|
20
|
+
display: flex;
|
|
21
|
+
justify-content: space-around;
|
|
22
|
+
font-size: 18px;
|
|
23
|
+
font-weight: bold;
|
|
24
|
+
margin: 15px 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.btn-restart {
|
|
28
|
+
padding: 8px 16px;
|
|
29
|
+
font-size: 15px;
|
|
30
|
+
background-color: #2980b9;
|
|
31
|
+
color: white;
|
|
32
|
+
border: none;
|
|
33
|
+
border-radius: 4px;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
margin-bottom: 20px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.btn-restart:hover {
|
|
39
|
+
background-color: #1f618d;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.card-grid {
|
|
43
|
+
display: grid;
|
|
44
|
+
grid-template-columns: repeat(4, 75px);
|
|
45
|
+
grid-gap: 10px;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.card {
|
|
50
|
+
width: 75px;
|
|
51
|
+
height: 75px;
|
|
52
|
+
background-color: #34495e;
|
|
53
|
+
color: white;
|
|
54
|
+
font-size: 32px;
|
|
55
|
+
display: flex;
|
|
56
|
+
justify-content: center;
|
|
57
|
+
align-items: center;
|
|
58
|
+
border-radius: 6px;
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
user-select: none;
|
|
61
|
+
transition: background-color 0.2s ease, transform 0.2s ease;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.card.flipped {
|
|
65
|
+
background-color: #ecf0f1;
|
|
66
|
+
color: #2c3e50;
|
|
67
|
+
cursor: default;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.card.matched {
|
|
71
|
+
background-color: #2ecc71;
|
|
72
|
+
color: white;
|
|
73
|
+
cursor: default;
|
|
74
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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>Rock Paper Scissors</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css">
|
|
8
|
+
<script src="script.js" defer></script>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div class="game-container">
|
|
12
|
+
<h1>Rock Paper Scissors</h1>
|
|
13
|
+
|
|
14
|
+
<div class="score-board">
|
|
15
|
+
<div>Player: <span id="playerScore">0</span></div>
|
|
16
|
+
<div>Computer: <span id="computerScore">0</span></div>
|
|
17
|
+
<div>Ties: <span id="tieScore">0</span></div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="controls">
|
|
21
|
+
<button type="button" class="btn" onclick="playGame('Rock')">✊ Rock</button>
|
|
22
|
+
<button type="button" class="btn" onclick="playGame('Paper')">✋ Paper</button>
|
|
23
|
+
<button type="button" class="btn" onclick="playGame('Scissors')">✌ Scissors</button>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="results-box">
|
|
27
|
+
<p>Your Choice: <strong id="playerChoice">-</strong></p>
|
|
28
|
+
<p>Computer Choice: <strong id="computerChoice">-</strong></p>
|
|
29
|
+
<h2 id="roundResult">Choose an option to start!</h2>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<button type="button" class="btn btn-reset" onclick="resetGame()">Reset Game</button>
|
|
33
|
+
</div>
|
|
34
|
+
</body>
|
|
35
|
+
</html>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
let playerScore = 0;
|
|
2
|
+
let computerScore = 0;
|
|
3
|
+
let tieScore = 0;
|
|
4
|
+
|
|
5
|
+
const choices = ["Rock", "Paper", "Scissors"];
|
|
6
|
+
|
|
7
|
+
function playGame(playerChoice) {
|
|
8
|
+
const randomIndex = Math.floor(Math.random() * choices.length);
|
|
9
|
+
const computerChoice = choices[randomIndex];
|
|
10
|
+
|
|
11
|
+
document.getElementById("playerChoice").textContent = playerChoice;
|
|
12
|
+
document.getElementById("computerChoice").textContent = computerChoice;
|
|
13
|
+
|
|
14
|
+
let result = "";
|
|
15
|
+
|
|
16
|
+
if (playerChoice === computerChoice) {
|
|
17
|
+
result = "It's a Tie!";
|
|
18
|
+
tieScore++;
|
|
19
|
+
document.getElementById("tieScore").textContent = tieScore;
|
|
20
|
+
} else if (
|
|
21
|
+
(playerChoice === "Rock" && computerChoice === "Scissors") ||
|
|
22
|
+
(playerChoice === "Paper" && computerChoice === "Rock") ||
|
|
23
|
+
(playerChoice === "Scissors" && computerChoice === "Paper")
|
|
24
|
+
) {
|
|
25
|
+
result = "You Win! 🎉";
|
|
26
|
+
playerScore++;
|
|
27
|
+
document.getElementById("playerScore").textContent = playerScore;
|
|
28
|
+
} else {
|
|
29
|
+
result = "Computer Wins! 💻";
|
|
30
|
+
computerScore++;
|
|
31
|
+
document.getElementById("computerScore").textContent = computerScore;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
document.getElementById("roundResult").textContent = result;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function resetGame() {
|
|
38
|
+
playerScore = 0;
|
|
39
|
+
computerScore = 0;
|
|
40
|
+
tieScore = 0;
|
|
41
|
+
|
|
42
|
+
document.getElementById("playerScore").textContent = "0";
|
|
43
|
+
document.getElementById("computerScore").textContent = "0";
|
|
44
|
+
document.getElementById("tieScore").textContent = "0";
|
|
45
|
+
|
|
46
|
+
document.getElementById("playerChoice").textContent = "-";
|
|
47
|
+
document.getElementById("computerChoice").textContent = "-";
|
|
48
|
+
document.getElementById("roundResult").textContent = "Choose an option to start!";
|
|
49
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
body {
|
|
2
|
+
font-family: Arial, sans-serif;
|
|
3
|
+
display: flex;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
align-items: center;
|
|
6
|
+
min-height: 100vh;
|
|
7
|
+
margin: 0;
|
|
8
|
+
background-color: #f7f7f7;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.game-container {
|
|
12
|
+
text-align: center;
|
|
13
|
+
background: #ffffff;
|
|
14
|
+
padding: 30px;
|
|
15
|
+
border: 1px solid #ddd;
|
|
16
|
+
border-radius: 8px;
|
|
17
|
+
width: 360px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.score-board {
|
|
21
|
+
display: flex;
|
|
22
|
+
justify-content: space-around;
|
|
23
|
+
font-size: 16px;
|
|
24
|
+
font-weight: bold;
|
|
25
|
+
margin: 20px 0;
|
|
26
|
+
padding: 10px;
|
|
27
|
+
background-color: #eee;
|
|
28
|
+
border-radius: 4px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.controls {
|
|
32
|
+
display: flex;
|
|
33
|
+
justify-content: center;
|
|
34
|
+
gap: 10px;
|
|
35
|
+
margin-bottom: 20px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.btn {
|
|
39
|
+
padding: 10px 15px;
|
|
40
|
+
font-size: 16px;
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
border: 1px solid #ccc;
|
|
43
|
+
background-color: #fff;
|
|
44
|
+
border-radius: 4px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.btn:hover {
|
|
48
|
+
background-color: #f0f0f0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.btn-reset {
|
|
52
|
+
background-color: #e74c3c;
|
|
53
|
+
color: white;
|
|
54
|
+
border: none;
|
|
55
|
+
margin-top: 15px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.btn-reset:hover {
|
|
59
|
+
background-color: #c0392b;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.results-box {
|
|
63
|
+
margin: 20px 0;
|
|
64
|
+
padding: 15px;
|
|
65
|
+
border: 1px dashed #ccc;
|
|
66
|
+
border-radius: 4px;
|
|
67
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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>Tic Tac Toe</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css">
|
|
8
|
+
<script src="script.js" defer></script>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div class="game-container">
|
|
12
|
+
<h1>Tic Tac Toe</h1>
|
|
13
|
+
<h2 id="status">Player X's Turn</h2>
|
|
14
|
+
|
|
15
|
+
<div class="board" id="board">
|
|
16
|
+
<button type="button" class="cell" data-index="0"></button>
|
|
17
|
+
<button type="button" class="cell" data-index="1"></button>
|
|
18
|
+
<button type="button" class="cell" data-index="2"></button>
|
|
19
|
+
<button type="button" class="cell" data-index="3"></button>
|
|
20
|
+
<button type="button" class="cell" data-index="4"></button>
|
|
21
|
+
<button type="button" class="cell" data-index="5"></button>
|
|
22
|
+
<button type="button" class="cell" data-index="6"></button>
|
|
23
|
+
<button type="button" class="cell" data-index="7"></button>
|
|
24
|
+
<button type="button" class="cell" data-index="8"></button>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<button type="button" class="btn-restart" onclick="restartGame()">Restart Game</button>
|
|
28
|
+
</div>
|
|
29
|
+
</body>
|
|
30
|
+
</html>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
let board = ["", "", "", "", "", "", "", "", ""];
|
|
2
|
+
let currentPlayer = "X";
|
|
3
|
+
let gameActive = true;
|
|
4
|
+
|
|
5
|
+
const winningConditions = [
|
|
6
|
+
[0, 1, 2],
|
|
7
|
+
[3, 4, 5],
|
|
8
|
+
[6, 7, 8],
|
|
9
|
+
[0, 3, 6],
|
|
10
|
+
[1, 4, 7],
|
|
11
|
+
[2, 5, 8],
|
|
12
|
+
[0, 4, 8],
|
|
13
|
+
[2, 4, 6]
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
17
|
+
const cells = document.querySelectorAll(".cell");
|
|
18
|
+
cells.forEach(function (cell) {
|
|
19
|
+
cell.addEventListener("click", handleCellClick);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
function handleCellClick(event) {
|
|
24
|
+
const clickedCell = event.target;
|
|
25
|
+
const clickedIndex = parseInt(clickedCell.getAttribute("data-index"), 10);
|
|
26
|
+
|
|
27
|
+
if (board[clickedIndex] !== "" || !gameActive) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
board[clickedIndex] = currentPlayer;
|
|
32
|
+
clickedCell.textContent = currentPlayer;
|
|
33
|
+
|
|
34
|
+
checkResult();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function checkResult() {
|
|
38
|
+
let roundWon = false;
|
|
39
|
+
|
|
40
|
+
for (let i = 0; i < winningConditions.length; i++) {
|
|
41
|
+
const winCondition = winningConditions[i];
|
|
42
|
+
const a = board[winCondition[0]];
|
|
43
|
+
const b = board[winCondition[1]];
|
|
44
|
+
const c = board[winCondition[2]];
|
|
45
|
+
|
|
46
|
+
if (a === "" || b === "" || c === "") {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (a === b && b === c) {
|
|
51
|
+
roundWon = true;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (roundWon) {
|
|
57
|
+
document.getElementById("status").textContent = "Player " + currentPlayer + " Wins! 🎉";
|
|
58
|
+
gameActive = false;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const roundDraw = !board.includes("");
|
|
63
|
+
if (roundDraw) {
|
|
64
|
+
document.getElementById("status").textContent = "Game Draw! 🤝";
|
|
65
|
+
gameActive = false;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
currentPlayer = currentPlayer === "X" ? "O" : "X";
|
|
70
|
+
document.getElementById("status").textContent = "Player " + currentPlayer + "'s Turn";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function restartGame() {
|
|
74
|
+
board = ["", "", "", "", "", "", "", "", ""];
|
|
75
|
+
gameActive = true;
|
|
76
|
+
currentPlayer = "X";
|
|
77
|
+
document.getElementById("status").textContent = "Player X's Turn";
|
|
78
|
+
|
|
79
|
+
document.querySelectorAll(".cell").forEach(function (cell) {
|
|
80
|
+
cell.textContent = "";
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
body {
|
|
2
|
+
font-family: Arial, sans-serif;
|
|
3
|
+
display: flex;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
align-items: center;
|
|
6
|
+
min-height: 100vh;
|
|
7
|
+
margin: 0;
|
|
8
|
+
background-color: #f5f5f5;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.game-container {
|
|
12
|
+
text-align: center;
|
|
13
|
+
background: #ffffff;
|
|
14
|
+
padding: 30px;
|
|
15
|
+
border: 1px solid #ccc;
|
|
16
|
+
border-radius: 8px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#status {
|
|
20
|
+
margin: 15px 0;
|
|
21
|
+
color: #333;
|
|
22
|
+
font-size: 20px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.board {
|
|
26
|
+
display: grid;
|
|
27
|
+
grid-template-columns: repeat(3, 80px);
|
|
28
|
+
grid-gap: 8px;
|
|
29
|
+
margin: 20px auto;
|
|
30
|
+
width: 256px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.cell {
|
|
34
|
+
width: 80px;
|
|
35
|
+
height: 80px;
|
|
36
|
+
background-color: #f9f9f9;
|
|
37
|
+
border: 2px solid #555;
|
|
38
|
+
font-size: 36px;
|
|
39
|
+
font-weight: bold;
|
|
40
|
+
cursor: pointer;
|
|
41
|
+
display: flex;
|
|
42
|
+
justify-content: center;
|
|
43
|
+
align-items: center;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.cell:hover {
|
|
47
|
+
background-color: #eee;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.cell:disabled {
|
|
51
|
+
cursor: not-allowed;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.btn-restart {
|
|
55
|
+
padding: 10px 20px;
|
|
56
|
+
font-size: 16px;
|
|
57
|
+
background-color: #333;
|
|
58
|
+
color: white;
|
|
59
|
+
border: none;
|
|
60
|
+
border-radius: 4px;
|
|
61
|
+
cursor: pointer;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.btn-restart:hover {
|
|
65
|
+
background-color: #555;
|
|
66
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
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>Whack A Mole</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css">
|
|
8
|
+
<script src="script.js" defer></script>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div class="game-container">
|
|
12
|
+
<h1>Whack A Mole</h1>
|
|
13
|
+
|
|
14
|
+
<div class="stats-bar">
|
|
15
|
+
<div>Score: <span id="score">0</span></div>
|
|
16
|
+
<div>Time Left: <span id="timeLeft">30</span>s</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<button type="button" class="btn-start" id="startBtn" onclick="startGame()">Start Game</button>
|
|
20
|
+
|
|
21
|
+
<div class="grid">
|
|
22
|
+
<div class="hole" data-index="0"><div class="mole" onclick="whackMole(this)">🐹</div></div>
|
|
23
|
+
<div class="hole" data-index="1"><div class="mole" onclick="whackMole(this)">🐹</div></div>
|
|
24
|
+
<div class="hole" data-index="2"><div class="mole" onclick="whackMole(this)">🐹</div></div>
|
|
25
|
+
<div class="hole" data-index="3"><div class="mole" onclick="whackMole(this)">🐹</div></div>
|
|
26
|
+
<div class="hole" data-index="4"><div class="mole" onclick="whackMole(this)">🐹</div></div>
|
|
27
|
+
<div class="hole" data-index="5"><div class="mole" onclick="whackMole(this)">🐹</div></div>
|
|
28
|
+
<div class="hole" data-index="6"><div class="mole" onclick="whackMole(this)">🐹</div></div>
|
|
29
|
+
<div class="hole" data-index="7"><div class="mole" onclick="whackMole(this)">🐹</div></div>
|
|
30
|
+
<div class="hole" data-index="8"><div class="mole" onclick="whackMole(this)">🐹</div></div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
let score = 0;
|
|
2
|
+
let timeLeft = 30;
|
|
3
|
+
let gameInterval = null;
|
|
4
|
+
let moleTimeout = null;
|
|
5
|
+
let lastHole = null;
|
|
6
|
+
let isPlaying = false;
|
|
7
|
+
|
|
8
|
+
function startGame() {
|
|
9
|
+
if (isPlaying) return;
|
|
10
|
+
|
|
11
|
+
isPlaying = true;
|
|
12
|
+
score = 0;
|
|
13
|
+
timeLeft = 30;
|
|
14
|
+
|
|
15
|
+
document.getElementById("score").textContent = score;
|
|
16
|
+
document.getElementById("timeLeft").textContent = timeLeft;
|
|
17
|
+
document.getElementById("startBtn").disabled = true;
|
|
18
|
+
|
|
19
|
+
peepMole();
|
|
20
|
+
|
|
21
|
+
gameInterval = setInterval(function () {
|
|
22
|
+
timeLeft--;
|
|
23
|
+
document.getElementById("timeLeft").textContent = timeLeft;
|
|
24
|
+
|
|
25
|
+
if (timeLeft <= 0) {
|
|
26
|
+
endGame();
|
|
27
|
+
}
|
|
28
|
+
}, 1000);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getRandomHole() {
|
|
32
|
+
const holes = document.querySelectorAll(".hole");
|
|
33
|
+
const randomIndex = Math.floor(Math.random() * holes.length);
|
|
34
|
+
const selectedHole = holes[randomIndex];
|
|
35
|
+
|
|
36
|
+
if (selectedHole === lastHole) {
|
|
37
|
+
return getRandomHole();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
lastHole = selectedHole;
|
|
41
|
+
return selectedHole;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function peepMole() {
|
|
45
|
+
if (!isPlaying) return;
|
|
46
|
+
|
|
47
|
+
const hole = getRandomHole();
|
|
48
|
+
hole.classList.add("up");
|
|
49
|
+
|
|
50
|
+
const stayTime = Math.floor(Math.random() * 500) + 600;
|
|
51
|
+
|
|
52
|
+
moleTimeout = setTimeout(function () {
|
|
53
|
+
hole.classList.remove("up");
|
|
54
|
+
if (isPlaying) {
|
|
55
|
+
peepMole();
|
|
56
|
+
}
|
|
57
|
+
}, stayTime);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function whackMole(moleElement) {
|
|
61
|
+
const hole = moleElement.parentElement;
|
|
62
|
+
if (!isPlaying || !hole.classList.contains("up")) return;
|
|
63
|
+
|
|
64
|
+
score++;
|
|
65
|
+
document.getElementById("score").textContent = score;
|
|
66
|
+
hole.classList.remove("up");
|
|
67
|
+
|
|
68
|
+
clearTimeout(moleTimeout);
|
|
69
|
+
setTimeout(peepMole, 200);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function endGame() {
|
|
73
|
+
isPlaying = false;
|
|
74
|
+
clearInterval(gameInterval);
|
|
75
|
+
clearTimeout(moleTimeout);
|
|
76
|
+
|
|
77
|
+
document.querySelectorAll(".hole").forEach(function (hole) {
|
|
78
|
+
hole.classList.remove("up");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
document.getElementById("startBtn").disabled = false;
|
|
82
|
+
alert("Game Over! Your final score is: " + score);
|
|
83
|
+
}
|