|
|
|
|
@ -1,237 +0,0 @@
|
|
|
|
|
// 初始化游戏状态
|
|
|
|
|
const gameState = {
|
|
|
|
|
targetNum: null,
|
|
|
|
|
isGameOver: false,
|
|
|
|
|
guessHistory: [],
|
|
|
|
|
guessCount: 0, // 猜数次数统计
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// DOM 元素获取
|
|
|
|
|
const generateBtn = document.getElementById('generateBtn');
|
|
|
|
|
const secretPanel = document.getElementById('secretPanel');
|
|
|
|
|
const secretNum = document.querySelector('.secret-num');
|
|
|
|
|
const guessInput = document.getElementById('guessInput');
|
|
|
|
|
const submitBtn = document.getElementById('submitBtn');
|
|
|
|
|
const guessHistory = document.getElementById('guessHistory');
|
|
|
|
|
const resultText = document.getElementById('resultText');
|
|
|
|
|
const restartBtn = document.getElementById('restartBtn');
|
|
|
|
|
const hintBtn = document.getElementById('hintBtn');
|
|
|
|
|
const hintCount = document.getElementById('hintCount');
|
|
|
|
|
const themeBtn = document.getElementById('themeBtn');
|
|
|
|
|
const themeIcon = themeBtn.querySelector('i');
|
|
|
|
|
|
|
|
|
|
let hintLeft = 0; // 剩余提示次数
|
|
|
|
|
|
|
|
|
|
// 1. 生成随机数逻辑
|
|
|
|
|
generateBtn.addEventListener('click', () => {
|
|
|
|
|
generateTargetNum();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function generateTargetNum(min = 1, max = 100) {
|
|
|
|
|
gameState.targetNum = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
|
|
|
gameState.isGameOver = false;
|
|
|
|
|
gameState.guessHistory = [];
|
|
|
|
|
gameState.guessCount = 0; // 重置次数
|
|
|
|
|
hintLeft = 0; // 重置提示次数
|
|
|
|
|
hintCount.textContent = hintLeft;
|
|
|
|
|
|
|
|
|
|
// 重置UI
|
|
|
|
|
guessInput.value = '';
|
|
|
|
|
guessHistory.innerHTML = '';
|
|
|
|
|
resultText.textContent = '等待猜数...';
|
|
|
|
|
resultText.className = 'text-xl font-bold text-gray-500';
|
|
|
|
|
submitBtn.disabled = false;
|
|
|
|
|
restartBtn.classList.add('hidden');
|
|
|
|
|
// 保密面板重置
|
|
|
|
|
secretNum.textContent = '●●●';
|
|
|
|
|
secretPanel.title = '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 猜数验证逻辑
|
|
|
|
|
submitBtn.addEventListener('click', () => {
|
|
|
|
|
const guessVal = guessInput.value.trim();
|
|
|
|
|
if (validateInput(guessVal)) {
|
|
|
|
|
const guessNum = parseInt(guessVal);
|
|
|
|
|
checkGuess(guessNum);
|
|
|
|
|
} else {
|
|
|
|
|
alert('请输入1-100的整数!');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 回车提交支持
|
|
|
|
|
guessInput.addEventListener('keypress', (e) => {
|
|
|
|
|
if (e.key === 'Enter') {
|
|
|
|
|
submitBtn.click();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function checkGuess(guessNum) {
|
|
|
|
|
if (gameState.isGameOver) return;
|
|
|
|
|
gameState.guessCount++; // 次数+1
|
|
|
|
|
const target = gameState.targetNum;
|
|
|
|
|
let result = '';
|
|
|
|
|
let resultClass = '';
|
|
|
|
|
|
|
|
|
|
if (guessNum > target) {
|
|
|
|
|
result = '大了!';
|
|
|
|
|
resultClass = 'text-red-600';
|
|
|
|
|
} else if (guessNum < target) {
|
|
|
|
|
result = '小了!';
|
|
|
|
|
resultClass = 'text-blue-600';
|
|
|
|
|
} else {
|
|
|
|
|
// 计算评级
|
|
|
|
|
let rank = '';
|
|
|
|
|
if (gameState.guessCount <= 5) rank = '大神';
|
|
|
|
|
else if (gameState.guessCount <= 8) rank = '优秀';
|
|
|
|
|
else if (gameState.guessCount <= 12) rank = '合格';
|
|
|
|
|
else rank = '再接再厉';
|
|
|
|
|
result = `恭喜猜对!目标数是 ${target},你用了 ${gameState.guessCount} 次猜对,评级:${rank}!`;
|
|
|
|
|
resultClass = 'text-green-600';
|
|
|
|
|
gameState.isGameOver = true;
|
|
|
|
|
submitBtn.disabled = true;
|
|
|
|
|
restartBtn.classList.remove('hidden');
|
|
|
|
|
// 礼花特效
|
|
|
|
|
createFireworks();
|
|
|
|
|
// 更新最佳成绩
|
|
|
|
|
const currentDate = new Date().toLocaleDateString();
|
|
|
|
|
const bestRecord = localStorage.getItem('guessGameBest');
|
|
|
|
|
if (!bestRecord || gameState.guessCount < JSON.parse(bestRecord).count) {
|
|
|
|
|
localStorage.setItem(
|
|
|
|
|
'guessGameBest',
|
|
|
|
|
JSON.stringify({ count: gameState.guessCount, date: currentDate })
|
|
|
|
|
);
|
|
|
|
|
alert(`恭喜刷新最佳成绩!当前次数:${gameState.guessCount}次`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 每猜3次增加一次提示机会
|
|
|
|
|
if (gameState.guessCount % 3 === 0 && gameState.guessCount !== 0) {
|
|
|
|
|
hintLeft++;
|
|
|
|
|
hintCount.textContent = hintLeft;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 记录历史
|
|
|
|
|
gameState.guessHistory.push({ num: guessNum, result });
|
|
|
|
|
// 更新UI
|
|
|
|
|
updateGameUI();
|
|
|
|
|
// 更新结果文本与动画
|
|
|
|
|
resultText.textContent = result;
|
|
|
|
|
resultText.className = `text-xl font-bold ${resultClass}`;
|
|
|
|
|
if (resultClass.includes('red') || resultClass.includes('blue')) {
|
|
|
|
|
resultText.classList.add('shake');
|
|
|
|
|
setTimeout(() => resultText.classList.remove('shake'), 500);
|
|
|
|
|
} else {
|
|
|
|
|
resultText.classList.add('scale');
|
|
|
|
|
setTimeout(() => resultText.classList.remove('scale'), 800);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. 输入验证逻辑
|
|
|
|
|
function validateInput(val) {
|
|
|
|
|
const num = Number(val);
|
|
|
|
|
return !isNaN(num) && num >= 1 && num <= 100 && Number.isInteger(num);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 更新历史记录UI
|
|
|
|
|
function updateGameUI() {
|
|
|
|
|
guessHistory.innerHTML = '';
|
|
|
|
|
gameState.guessHistory.forEach((item, index) => {
|
|
|
|
|
const li = document.createElement('li');
|
|
|
|
|
li.className = 'py-1 border-b border-gray-200';
|
|
|
|
|
li.textContent = `第${index + 1}次:${item.num} → ${item.result}`;
|
|
|
|
|
guessHistory.appendChild(li);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5. 重新开始逻辑
|
|
|
|
|
restartBtn.addEventListener('click', () => {
|
|
|
|
|
generateTargetNum();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 6. 提示按钮逻辑
|
|
|
|
|
hintBtn.addEventListener('click', () => {
|
|
|
|
|
if (hintLeft <= 0 || gameState.isGameOver) return;
|
|
|
|
|
hintLeft--;
|
|
|
|
|
hintCount.textContent = hintLeft;
|
|
|
|
|
const isOdd = gameState.targetNum % 2 === 1;
|
|
|
|
|
const range = getRangeHint();
|
|
|
|
|
alert(`提示:目标数是${isOdd ? '奇数' : '偶数'},且在${range[0]}-${range[1]}区间内`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 计算区间提示
|
|
|
|
|
function getRangeHint() {
|
|
|
|
|
const historyNums = gameState.guessHistory.map((item) => item.num);
|
|
|
|
|
let min = 1, max = 100;
|
|
|
|
|
historyNums.forEach((num) => {
|
|
|
|
|
const res = gameState.guessHistory.find((item) => item.num === num).result;
|
|
|
|
|
if (res.includes('大了')) max = Math.min(max, num - 1);
|
|
|
|
|
if (res.includes('小了')) min = Math.max(min, num + 1);
|
|
|
|
|
});
|
|
|
|
|
return [min, max];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 7. 礼花特效函数
|
|
|
|
|
function createFireworks() {
|
|
|
|
|
const fireworks = document.createElement('div');
|
|
|
|
|
fireworks.className = 'fixed inset-0 flex items-center justify-center pointer-events-none';
|
|
|
|
|
fireworks.innerHTML = `
|
|
|
|
|
<div class="w-2 h-2 bg-red-500 rounded-full absolute"></div>
|
|
|
|
|
<div class="w-2 h-2 bg-green-500 rounded-full absolute"></div>
|
|
|
|
|
<div class="w-2 h-2 bg-blue-500 rounded-full absolute"></div>
|
|
|
|
|
<div class="w-2 h-2 bg-yellow-500 rounded-full absolute"></div>
|
|
|
|
|
<div class="w-2 h-2 bg-purple-500 rounded-full absolute"></div>
|
|
|
|
|
`;
|
|
|
|
|
document.body.appendChild(fireworks);
|
|
|
|
|
const dots = fireworks.querySelectorAll('div');
|
|
|
|
|
dots.forEach((dot) => {
|
|
|
|
|
const x = Math.random() * 100 - 50;
|
|
|
|
|
const y = Math.random() * 100 - 50;
|
|
|
|
|
dot.style.transform = `translate(${x}vw, ${y}vh)`;
|
|
|
|
|
dot.style.opacity = '0';
|
|
|
|
|
dot.style.transition = 'all 1s ease';
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
dot.style.opacity = '1';
|
|
|
|
|
dot.style.transform = `translate(${x * 0.5}vw, ${y * 0.5}vh) scale(2)`;
|
|
|
|
|
dot.style.opacity = '0';
|
|
|
|
|
}, 10);
|
|
|
|
|
});
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
document.body.removeChild(fireworks);
|
|
|
|
|
}, 1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 8. 主题切换逻辑
|
|
|
|
|
themeBtn.addEventListener('click', () => {
|
|
|
|
|
document.documentElement.classList.toggle('dark-theme');
|
|
|
|
|
if (document.documentElement.classList.contains('dark-theme')) {
|
|
|
|
|
themeIcon.classList.remove('fa-moon');
|
|
|
|
|
themeIcon.classList.add('fa-sun');
|
|
|
|
|
} else {
|
|
|
|
|
themeIcon.classList.remove('fa-sun');
|
|
|
|
|
themeIcon.classList.add('fa-moon');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 9. 保密面板悬浮显示
|
|
|
|
|
secretPanel.addEventListener('mouseenter', () => {
|
|
|
|
|
if (gameState.targetNum !== null) {
|
|
|
|
|
secretNum.textContent = gameState.targetNum;
|
|
|
|
|
secretPanel.title = '选题人请记住目标数哦~';
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
secretPanel.addEventListener('mouseleave', () => {
|
|
|
|
|
if (gameState.targetNum !== null && !gameState.isGameOver) {
|
|
|
|
|
secretNum.textContent = '●●●';
|
|
|
|
|
secretPanel.title = '';
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 10. 初始化时读取历史最佳
|
|
|
|
|
window.addEventListener('load', () => {
|
|
|
|
|
const bestRecord = localStorage.getItem('guessGameBest');
|
|
|
|
|
if (bestRecord) {
|
|
|
|
|
const { count, date } = JSON.parse(bestRecord);
|
|
|
|
|
alert(`你的历史最佳成绩:${count}次(${date})`);
|
|
|
|
|
}
|
|
|
|
|
});
|