實作2-1
楓資 鄭云晶
目錄
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<title>鍵盤反應遊戲 Ultimate</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="score">分數:0</div>
<div id="highscore">最高分:0</div>
<div id="timer">時間:30</div>
<div id="game"></div>
<div id="gameover">遊戲結束</div>
<button onclick="restartGame()">再玩一次</button>
<script src="main.js"></script>
<link rel="stylesheet" href= "main.css">
</body>
</html>body {
margin: 0;
overflow: hidden;
background: #020617;
color: white;
font-family: Arial;
}
#game {
position: relative;
width: 100vw;
height: 100vh;
}
.letter {
position: absolute;
font-size: 40px;
color: #22c55e;
text-shadow: 0 0 10px #22c55e;
animation: fall linear forwards;
}
@keyframes fall {
from { top: -50px; }
to { top: 100vh; }
}
#score, #timer, #highscore {
position: fixed;
top: 20px;
font-size: 30px;
}
#score { left: 20px; }
#highscore { left: 180px; }
#timer { right: 20px; }
#gameover {
position: fixed;
display: none;
color: #3589ce;
text-shadow: 0 0 10px #7e9cd4;
top: 35%;
width: 100%;
text-align: center;
font-size: 50px;
font-weight: bolder;
}
button {
position: fixed;
top: 55%;
left: 50%;
transform: translateX(-50%);
padding: 12px 25px;
font-size: 18px;
border: none;
border-radius: 10px;
background: #4b8fe7;
cursor: pointer;
display: none;
}
button:hover {
background: #3381e7;
}let letters = "ASDFJKL";
let score = 0;
let time = 30;
let gameActive = true;
let game = document.getElementById("game");
let activeLetters = [];
let highscore = localStorage.getItem("highscore") || 0;
document.getElementById("highscore").innerText = "最高分:" + highscore;
// 生成字母
function spawnLetter() {
if (!gameActive) return;
let div = document.createElement("div");
let letter = letters[Math.floor(Math.random() * letters.length)];
div.className = "letter";
div.innerText = letter;
div.style.left = Math.random() * 90 + "vw";
let duration = 2 + Math.random() * 2;
div.style.animationDuration = duration + "s";
game.appendChild(div);
activeLetters.push({el: div, letter: letter});
// 沒按到扣分
setTimeout(() => {
if (game.contains(div)) {
game.removeChild(div);
activeLetters = activeLetters.filter(l => l.el !== div);
score--;
updateScore();
}
}, duration * 1000);
}
// 鍵盤判定
document.addEventListener("keydown", function(e) {
if (!gameActive) return;
let key = e.key.toUpperCase();
for (let i = 0; i < activeLetters.length; i++) {
if (activeLetters[i].letter === key) {
game.removeChild(activeLetters[i].el);
activeLetters.splice(i, 1);
score++;
updateScore();
return;
}
}
// 按錯扣分
score--;
updateScore();
});
// 更新分數
function updateScore() {
document.getElementById("score").innerText = "分數:" + score;
if (score > highscore) {
highscore = score;
localStorage.setItem("highscore", highscore);
document.getElementById("highscore").innerText = "最高分:" + highscore;
}
if (score <= -5) {
endGame();
}
}
// 遊戲結束
function endGame() {
gameActive = false;
document.getElementById("gameover").style.display = "block";
document.querySelector("button").style.display = "block";
}
// 重新開始
function restartGame() {
score = 0;
time = 30;
gameActive = true;
activeLetters = [];
game.innerHTML = "";
document.getElementById("score").innerText = "分數:0";
document.getElementById("timer").innerText = "時間:30";
document.getElementById("gameover").style.display = "none";
document.querySelector("button").style.display = "none";
startGame();
}
// 遊戲循環
let gameLoop;
let timerLoop;
function startGame() {
gameLoop = setInterval(spawnLetter, 700);
timerLoop = setInterval(() => {
time--;
document.getElementById("timer").innerText = "時間:" + time;
if (time <= 0) {
clearInterval(gameLoop);
clearInterval(timerLoop);
endGame();
}
}, 1000);
}
// 初始化
startGame();html
css
js
html

<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<title>鍵盤反應遊戲</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="letter">A</div>
<div id="score">分數:0</div>
<div id="highscore">最高分:0</div>
<div id="gameover">遊戲結束</div>
<button onclick="restartGame()">再玩一次</button>
<script src="main.js"></script>
<link rel="stylesheet" href= "main.css">
</body>
</html>當按鈕被點擊時,執行 restartGame()函式
<button onclick="restartGame()">再玩一次</button><div id="gameover">遊戲結束</div>區塊元素
css
body {
margin: 0;
overflow: hidden;
background: #020617;
color: white;
font-family: Arial;
}
#game {
position: relative;
width: 100vw;
height: 100vh;
}
#letter {
position: fixed;
top: 25%;
left: 50%;
transform: translateX(-50%);
font-size: 60px;
color: #22c55e;
text-shadow: 0 0 10px #22c55e;
animation: fall linear forwards;
}
#score, #timer, #highscore {
position: fixed;
top: 20px;
font-size: 30px;
}
#score { left: 20px; }
#highscore { left: 180px; }
#timer { right: 20px; }
#gameover {
position: fixed;
display: none;
color: #3589ce;
text-shadow: 0 0 10px #7e9cd4;
top: 35%;
width: 100%;
text-align: center;
font-size: 50px;
font-weight: bolder;
}
button {
position: fixed;
top: 55%;
left: 50%;
transform: translateX(-50%);
padding: 12px 25px;
font-size: 18px;
border: none;
border-radius: 10px;
background: #4b8fe7;
cursor: pointer;
display: none;
}
button:hover {
background: #3381e7;
}css
移除元素周圍的外邊距
body {
margin: 0;
overflow: hidden;
background: #020617;
color: white;
font-family: Arial;
}隱藏超出容器範圍的內容,不顯示捲軸
button {
position: fixed;
top: 55%;
left: 50%;
transform: translateX(-50%);
padding: 12px 25px;
font-size: 20px;
border: none;
border-radius: 10px;
background: #4b8fe7;
cursor: pointer;
display: none;
}按鈕會固定在螢幕的特定位置
按鈕目前是隱藏
起點定位在距離上方 55% 左方 50%
元素水平往回移動自身寬度的 50%
css
text-shadow: 0 0 20px #22c55e;水平偏移
垂直偏移
模糊半徑
顏色
0 0 20px #22c55e;
陰影
js
let letters = "ASDFJKL";
let current = "";
let score = 0;
let gameActive = true;
// 產生新字母
function newLetter() {
current = letters[Math.floor(Math.random() * letters.length)];
document.getElementById("letter").innerText = current;
}
// 更新分數
function updateScore() {
document.getElementById("score").innerText = "分數:" + score;
// 遊戲結束條件
if (score < -5) {
endGame();
}
}
// 遊戲結束
function endGame() {
gameActive = false;
document.getElementById("gameover").style.display = "block";
document.querySelector("button").style.display = "block";
}
// 鍵盤事件
document.addEventListener("keydown", function(e) {
if (!gameActive) return;
if (e.key.toUpperCase() === current) {
score++;
}
else {
score--;
}
updateScore();
newLetter();
});
// 再玩一次
function restartGame() {
score = 0;
gameActive = true;
document.getElementById("score").innerText = "分數:0";
document.getElementById("gameover").style.display = "none";
newLetter();
}
// 初始化
newLetter();let letters = "ASDFJKL";
let current = "";
let score = 0;
let gameActive = true;現在畫面上的字母
遊戲字母
初始分數
隨機字母
function newLetter() {
current = letters[Math.floor(Math.random() * letters.length)];
document.getElementById("letter").innerText = current;
}產生 0 ~ 1 的隨機數
無條件捨去
更新分數
function updateScore() {
document.getElementById("score").innerText = "分數:" + score;
}顯示分數
if (score < -5) {
endGame();
}
}
function endGame() {
gameActive = false;
document.getElementById("gameover").style.display = "block";
document.querySelector("button").style.display = "block";
}
遊戲結束
顯示遊戲結束
關閉遊戲
document.addEventListener("keydown", function(e) {
if (!gameActive) return;
if (e.key.toUpperCase() === current) {
score++;
}
else {
score--;
}
updateScore();
newLetter();
});監聽器
按下任意鍵
轉大寫
更新畫面
產生新字母
鍵盤判斷
function restartGame() {
score = 0;
gameActive = true;
document.getElementById("score").innerText = "分數:0";
document.getElementById("gameover").style.display = "none";
newLetter();
}
newLetter();再玩一次
重設分數、畫面
初始化

- 字母會掉下來
-
按對才消失
-
沒按到會扣分
-
30秒結束
-
最高分
-
再玩一次
下次課程
practical exercises2
By shiny0515
practical exercises2
- 16