Python实现可运行解密游戏游戏框架

```html

<!DOCTYPE html>

<html lang="zh">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<title>🔍 解密游戏框架</title>

<style>

* {

margin: 0;

padding: 0;

box-sizing: border-box;

font-family: 'Segoe UI', Roboto, system-ui, sans-serif;

}

body {

background: linear-gradient(145deg, #0b1a2b 0%, #1a2f3f 100%);

min-height: 100vh;

display: flex;

justify-content: center;

align-items: center;

padding: 16px;

}

.game-container {

max-width: 680px;

width: 100%;

background: rgba(28, 40, 51, 0.85);

backdrop-filter: blur(8px);

-webkit-backdrop-filter: blur(8px);

border-radius: 48px;

padding: 28px 24px 32px;

box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6), inset 0 1px 2px rgba(255, 255, 255, 0.08);

border: 1px solid rgba(255, 255, 255, 0.04);

transition: all 0.2s ease;

}

h1 {

font-size: 2rem;

font-weight: 500;

letter-spacing: 2px;

color: #d4e9ff;

text-shadow: 0 2px 6px rgba(0, 20, 40, 0.7);

display: flex;

align-items: center;

gap: 12px;

margin-bottom: 20px;

border-bottom: 1px solid rgba(255, 255, 255, 0.06);

padding-bottom: 14px;

}

h1 small {

font-size: 0.9rem;

font-weight: 300;

color: #8bb4d0;

margin-left: auto;

letter-spacing: 0.3px;

}

.puzzle-panel {

background: #1f3345;

border-radius: 32px;

padding: 28px 24px;

margin-bottom: 28px;

box-shadow: inset 0 6px 12px rgba(0, 0, 0, 0.5), 0 2px 4px rgba(255, 255, 255, 0.02);

border: 1px solid #2f4a5e;

}

.puzzle-header {

display: flex;

justify-content: space-between;

align-items: center;

margin-bottom: 12px;

color: #aac3d6;

font-size: 0.9rem;

letter-spacing: 0.4px;

}

.puzzle-id {

background: #0d1e2b;

padding: 4px 16px;

border-radius: 40px;

font-weight: 500;

color: #b3d6f0;

border: 1px solid #2a4b5e;

}

.puzzle-text {

font-size: 1.3rem;

line-height: 1.6;

color: #ebf5ff;

font-weight: 400;

padding: 8px 0 4px;

text-shadow: 0 1px 2px rgba(0,0,0,0.3);

min-height: 4.2rem;

}

.clue-box {

background: #132433;

border-radius: 20px;

padding: 14px 20px;

margin: 18px 0 12px;

border-left: 5px solid #4b8bb8;

color: #cfdef0;

font-size: 1rem;

box-shadow: inset 0 2px 6px rgba(0,0,0,0.4);

}

.clue-box span {

font-weight: 300;

color: #95bedb;

margin-right: 8px;

}

.input-area {

display: flex;

flex-direction: column;

gap: 14px;

margin-top: 18px;

}

.input-row {

display: flex;

flex-wrap: wrap;

gap: 12px;

}

.input-row input {

flex: 2;

min-width: 180px;

background: #0f1f2d;

border: 1px solid #2f4a5e;

border-radius: 48px;

padding: 14px 22px;

font-size: 1rem;

color: #e5f0fa;

outline: none;

transition: 0.25s;

box-shadow: inset 0 4px 8px rgba(0, 0, 0, 0.5);

}

.input-row input:focus {

border-color: #5b9bc7;

background: #122b3b;

box-shadow: 0 0 0 3px rgba(70, 140, 200, 0.3), inset 0 4px 8px rgba(0,0,0,0.6);

}

.input-row input::placeholder {

color: #6a8aa3;

font-weight: 300;

letter-spacing: 0.3px;

}

.action-group {

display: flex;

flex: 1;

gap: 10px;

flex-wrap: wrap;

}

.btn {

background: #2f4d63;

border: none;

border-radius: 48px;

padding: 12px 24px;

font-weight: 500;

font-size: 1rem;

color: #f0faff;

cursor: pointer;

transition: all 0.15s ease;

box-shadow: 0 6px 0 #0e1e2b, 0 4px 12px rgba(0, 0, 0, 0.4);

display: inline-flex;

align-items: center;

justify-content: center;

gap: 6px;

flex: 1;

min-width: 100px;

letter-spacing: 0.5px;

border: 1px solid #4c7088;

}

.btn:active {

transform: translateY(4px);

box-shadow: 0 2px 0 #0e1e2b;

}

.btn-primary {

background: #3d7b9e;

border-color: #6aa9cc;

box-shadow: 0 6px 0 #1b4053, 0 4px 12px rgba(0, 0, 0, 0.4);

}

.btn-success {

background: #3a8b6e;

border-color: #5eb894;

box-shadow: 0 6px 0 #1d4d3b, 0 4px 12px rgba(0, 0, 0, 0.4);

}

.btn-warning {

background: #b5793a;

border-color: #dba35a;

box-shadow: 0 6px 0 #704a1f, 0 4px 12px rgba(0, 0, 0, 0.4);

}

.btn:disabled {

opacity: 0.5;

transform: translateY(2px);

box-shadow: 0 3px 0 #0e1e2b;

pointer-events: none;

}

.message-box {

margin-top: 18px;

padding: 12px 18px;

border-radius: 30px;

background: #10212e;

color: #b6d6ed;

border: 1px solid #2a4a5e;

font-size: 0.95rem;

min-height: 3.2rem;

display: flex;

align-items: center;

gap: 8px;

flex-wrap: wrap;

box-shadow: inset 0 2px 6px rgba(0,0,0,0.4);

}

.message-box .emoji {

font-size: 1.4rem;

}

.status-badge {

margin-left: auto;

background: #1d3545;

padding: 4px 14px;

border-radius: 40px;

font-size: 0.8rem;

color: #9abdd9;

border: 1px solid #355d74;

}

.footer-actions {

display: flex;

gap: 12px;

margin-top: 24px;

flex-wrap: wrap;

}

.footer-actions .btn {

flex: 1;

min-width: 100px;

}

.progress-indicator {

display: flex;

justify-content: center;

gap: 12px;

margin: 16px 0 6px;

}

.dot {

width: 12px;

height: 12px;

border-radius: 20px;

background: #2a475b;

border: 1px solid #3e6279;

transition: 0.2s;

}

.dot.active {

background: #6ab0d9;

border-color: #a2d4f0;

box-shadow: 0 0 12px #3f94c2;

}

.dot.solved {

background: #5cb58b;

border-color: #8fd6b0;

}

@media (max-width: 480px) {

.game-container { padding: 16px; }

.puzzle-panel { padding: 20px 16px; }

.puzzle-text { font-size: 1.1rem; }

.input-row input { min-width: 140px; }

.btn { padding: 12px 14px; min-width: 70px; }

}

</style>

</head>

<body>

<div class="game-container" id="app">

<h1>

🕵️ 解密·框架

<small id="puzzleCounter">1 / 4</small>

</h1>

<div class="puzzle-panel">

<div class="puzzle-header">

<span class="puzzle-id" id="puzzleId"># 谜题 1</span>

<span class="status-badge" id="statusBadge">🔒 未解</span>

</div>

<div class="puzzle-text" id="puzzleText">

点击「线索」或输入答案...

</div>

<div class="clue-box" id="clueBox">

<span>💡 线索</span> <span id="clueText">输入框内输入答案, 点击验证</span>

</div>

<div class="input-area">

<div class="input-row">

<input type="text" id="answerInput" placeholder="输入你的答案..." autocomplete="off" />

<div class="action-group">

<button class="btn btn-primary" id="checkBtn">🔎 验证</button>

<button class="btn btn-warning" id="hintBtn">💬 线索</button>

</div>

</div>

</div>

<div class="message-box" id="messageBox">

<span class="emoji">📌</span>

<span id="messageText">准备开始解谜</span>

<span class="status-badge" id="detailBadge">⚡</span>

</div>

</div>

<!-- 进度点 -->

<div class="progress-indicator" id="progressDots"></div>

<div class="footer-actions">

<button class="btn" id="resetBtn">🔄 重置进度</button>

<button class="btn btn-success" id="nextBtn">▶ 下一题</button>

</div>

</div>

<script>

(function() {

// ---------- 谜题库 ----------

const PUZZLES = [

{

id: 1,

text: '我生于黑暗,却在光中消逝。我随你而行,却从不说话。我是什么?',

clue: '想想你的影子... 或者更具体的,夜晚的伙伴。',

answer: '影子',

// 可接受多种答案(转小写比较)

normalize: (s) => s.trim().toLowerCase().replace(/\s+/g, '')

},

{

id: 2,

text: '我有城市,没有房屋;有森林,没有树木;有河流,没有水滴。我是什么?',

clue: '一张纸上的世界,却能装下整个地球。',

answer: '地图',

normalize: (s) => s.trim().toLowerCase().replace(/\s+/g, '')

},

{

id: 3,

text: '我越老越年轻,但永远不会死去。我存在每个地方,但从未被看见。我是?',

clue: '无形的流逝,每个瞬间都在改变。',

answer: '时间',

normalize: (s) => s.trim().toLowerCase().replace(/\s+/g, '')

},

{

id: 4,

text: '我拥有钥匙却打不开锁,我有空间却没有房间,你可以进入却无法离开。我是什么?',

clue: '键盘上的世界,每天都会遇见。',

answer: '键盘',

normalize: (s) => s.trim().toLowerCase().replace(/\s+/g, '')

}

];

// ---------- 状态 ----------

let currentIndex = 0; // 0-based

let solvedStatus = false, false, false, false;

let gameCompleted = false;

// DOM 元素

const puzzleTextEl = document.getElementById('puzzleText');

const puzzleIdEl = document.getElementById('puzzleId');

const clueTextEl = document.getElementById('clueText');

const statusBadge = document.getElementById('statusBadge');

const answerInput = document.getElementById('answerInput');

const checkBtn = document.getElementById('checkBtn');

const hintBtn = document.getElementById('hintBtn');

const nextBtn = document.getElementById('nextBtn');

const resetBtn = document.getElementById('resetBtn');

const messageText = document.getElementById('messageText');

const messageBox = document.getElementById('messageBox');

const puzzleCounter = document.getElementById('puzzleCounter');

const progressDots = document.getElementById('progressDots');

const detailBadge = document.getElementById('detailBadge');

// ---------- 辅助函数 ----------

function renderProgressDots() {

progressDots.innerHTML = '';

for (let i = 0; i < PUZZLES.length; i++) {

const dot = document.createElement('span');

dot.className = 'dot';

if (i === currentIndex) dot.classList.add('active');

if (solvedStatusi) dot.classList.add('solved');

progressDots.appendChild(dot);

}

}

// 更新界面 (根据 currentIndex 和 solvedStatus)

function updatePuzzleUI() {

const puzzle = PUZZLEScurrentIndex;

const isSolved = solvedStatuscurrentIndex;

// 文本

puzzleTextEl.textContent = puzzle.text;

puzzleIdEl.textContent = `# 谜题 ${puzzle.id}`;

// 只显示当前谜题的线索(点击线索按钮会刷新)

clueTextEl.textContent = puzzle.clue;

// 状态徽章

if (isSolved) {

statusBadge.innerHTML = '✅ 已解';

statusBadge.style.color = '#8cd4b0';

} else {

statusBadge.innerHTML = '🔒 未解';

statusBadge.style.color = '#9abdd9';

}

// 更新计数器

const solvedCount = solvedStatus.filter(v => v === true).length;

puzzleCounter.textContent = `{currentIndex+1} / {PUZZLES.length}`;

// 更新进度点

renderProgressDots();

// 如果全部解开,特殊显示

if (solvedCount === PUZZLES.length && !gameCompleted) {

gameCompleted = true;

messageText.textContent = '🎉 恭喜!所有谜题已解开! 你太棒了!';

detailBadge.textContent = '🏆';

messageBox.style.borderColor = '#5cb58b';

// 自动把下一题禁用? 但下一题按钮可以循环,但已经完成所有谜题

} else {

// 重置消息(如果完成状态被清除)

if (gameCompleted && solvedCount < PUZZLES.length) {

gameCompleted = false;

messageBox.style.borderColor = '#2a4a5e';

messageText.textContent = '继续解谜吧...';

detailBadge.textContent = '⚡';

}

}

// 如果当前谜题已解,输入框可置灰? 但依然可以输入,但验证会提示已解。

// 让输入框保持可用,但验证时会有提示。

answerInput.value = '';

answerInput.focus();

// 联动 nextBtn 禁用逻辑:如果当前谜题未解,nextBtn 不能直接跳转(但允许强制跳转?我们设定为可以跳,但会提示)

// 但设计上允许自由跳转,但是解锁下一个谜题建议必须解开当前? 我们采用自由跳转,但给出提醒。

// 但最好保留自由,不然会卡住。 我们就自由,但验证时判断。

}

// 显示消息

function setMessage(text, emoji = '📌', isSuccess = false, isError = false) {

messageText.textContent = text;

document.querySelector('.message-box .emoji').textContent = emoji;

if (isSuccess) {

messageBox.style.borderLeft = '5px solid #5cb58b';

} else if (isError) {

messageBox.style.borderLeft = '5px solid #c97a5a';

} else {

messageBox.style.borderLeft = '5px solid #4b8bb8';

}

}

// 检查当前谜题答案

function checkAnswer() {

const puzzle = PUZZLEScurrentIndex;

const userAnswer = answerInput.value;

if (!userAnswer.trim()) {

setMessage('请输入答案再验证', '✍️', false, true);

return;

}

const normalize = puzzle.normalize || ((s) => s.trim().toLowerCase().replace(/\s+/g, ''));

const normalizedUser = normalize(userAnswer);

const normalizedCorrect = normalize(puzzle.answer);

if (normalizedUser === normalizedCorrect) {

// 正确!

if (!solvedStatuscurrentIndex) {

solvedStatuscurrentIndex = true;

setMessage(`✅ 完全正确!谜题 ${puzzle.id} 已解开!`, '🎯', true, false);

// 更新UI

updatePuzzleUI();

// 检查是否全部完成

if (solvedStatus.every(v => v === true)) {

setMessage('🎉 恭喜!所有谜题已解开! 你太棒了!', '🏆', true, false);

gameCompleted = true;

detailBadge.textContent = '🏆';

} else {

// 解开后自动显示下一个? 可以给用户选择, 但我们不自动跳转,提示下一题可用

setMessage(`✅ 谜题 ${puzzle.id} 已解开!点击「下一题」继续`, '👉', true, false);

}

} else {

setMessage(`⏳ 谜题 ${puzzle.id} 已经解开过了,试试下一题吧`, '🔄', false, false);

}

} else {

setMessage(`❌ 答案不对,再想想或者查看线索`, '🤔', false, true);

}

}

// 显示线索 (把线索放入消息区)

function showHint() {

const puzzle = PUZZLEScurrentIndex;

const clue = puzzle.clue;

setMessage(`💡 线索: ${clue}`, '🔍', false, false);

// 同时更新clueBox

clueTextEl.textContent = clue;

}

// 跳转到下一题 (循环)

function goToNextPuzzle() {

if (solvedStatus.every(v => v === true)) {

setMessage('🎉 所有谜题已解!你可以重置重新挑战', '🌟', false, false);

return;

}

// 如果当前未解,可以提示,但允许跳转,我们提供警告并跳转

if (!solvedStatuscurrentIndex) {

setMessage(`⚠️ 当前谜题尚未解开,但你可以自由跳转`, '🔄', false, true);

} else {

setMessage(`➡️ 进入下一题`, '📖', false, false);

}

// 循环到下一个未解谜题? 更自然:直接下一个,循环

let nextIndex = (currentIndex + 1) % PUZZLES.length;

// 如果下一个已经解了并且不是所有都解,找最近的未解,但循环太复杂,简单递增

// 但为了避免一直显示已解,跳过已解? 使用户体验更好:尝试找最近的未解谜题

let attempts = 0;

while (solvedStatusnextIndex && attempts < PUZZLES.length) {

nextIndex = (nextIndex + 1) % PUZZLES.length;

attempts++;

}

// 如果所有都解了,上面已经处理了

currentIndex = nextIndex;

updatePuzzleUI();

// 清空消息

if (!solvedStatuscurrentIndex) {

setMessage(`🔍 谜题 ${PUZZLEScurrentIndex.id} 待解`, '📌', false, false);

} else {

setMessage(`✅ 谜题 ${PUZZLEScurrentIndex.id} 已解,继续挑战`, '🎯', false, false);

}

}

// 重置进度

function resetGame() {

solvedStatus = false, false, false, false;

currentIndex = 0;

gameCompleted = false;

messageBox.style.borderLeft = '5px solid #4b8bb8';

updatePuzzleUI();

setMessage('🔄 已重置所有谜题,重新开始吧', '🔄', false, false);

detailBadge.textContent = '⚡';

answerInput.focus();

}

// ---------- 绑定事件 ----------

function init() {

// 渲染初始

updatePuzzleUI();

setMessage('输入答案,点击验证或按 Enter', '📌', false, false);

// 按钮事件

checkBtn.addEventListener('click', checkAnswer);

hintBtn.addEventListener('click', showHint);

nextBtn.addEventListener('click', goToNextPuzzle);

resetBtn.addEventListener('click', resetGame);

// 回车键

answerInput.addEventListener('keydown', (e) => {

if (e.key === 'Enter') {

e.preventDefault();

checkAnswer();

}

});

// 点击输入框的时候如果有消息提示可以清除? 但是保留

answerInput.addEventListener('focus', () => {

// 小细节,如果当前已解,可以提示

if (solvedStatuscurrentIndex) {

setMessage(`💡 谜题 ${PUZZLEScurrentIndex.id} 已解,试试下一题`, '📌', false, false);

}

});

// 当点击进度点可以跳转? 简单交互: 点进度点跳转到对应谜题 (用户体验)

progressDots.addEventListener('click', (e) => {

const dot = e.target.closest('.dot');

if (!dot) return;

const index = Array.from(progressDots.children).indexOf(dot);

if (index === -1 || index === currentIndex) return;

// 跳转

currentIndex = index;

updatePuzzleUI();

const puzzle = PUZZLEScurrentIndex;

if (solvedStatuscurrentIndex) {

setMessage(`✅ 谜题 ${puzzle.id} 已解`, '📌', false, false);

} else {

setMessage(`🔍 谜题 ${puzzle.id} 待解`, '📌', false, false);

}

answerInput.focus();

});

}

// 页面完全加载后初始化

if (document.readyState === 'loading') {

document.addEventListener('DOMContentLoaded', init);

} else {

init();

}

})();

</script>

</body>

</html>

```

玩法与交互说明

玩家将依次挑战N个谜题,通过输入答案并验证来推进游戏。整个框架围绕"解谜-反馈-推进"的核心循环设计。

· 谜题与线索:每个谜题都配有文字描述和一条可查看的线索。可以在输入框中作答,或点击"线索"按钮获取提示。

· 验证与反馈:输入答案后点击"验证"或按回车键,系统会立即判断对错,并通过消息区域和状态徽章给出清晰反馈。

· 进度与导航:顶部的进度点和计数器会显示您的整体进度。通过"下一题"按钮或点击进度点自由切换谜题,"重置进度"按钮则可随时重新开始。

相关推荐
YUS云生2 小时前
Python学习笔记·第31天:FastAPI入门——路由、路径参数、查询参数与请求体
笔记·python·学习
智写-AI2 小时前
真实有效的免费降英文AI工具服务商
人工智能·python
yuhuofei20212 小时前
【Python入门】了解掌握Python中函数的基本使用
python
白帽小阳4 小时前
2026前端面试题!(附答案及解析)
javascript·网络·python·安全·web安全·网络安全·护网行动
乱写代码4 小时前
Python开发技巧--类型注解Literal
python
卷无止境4 小时前
Python FFI 技术深度解析:ctypes、cffi 与 pybind11 的性能差异与实践挑战
后端·python
郝学胜-神的一滴5 小时前
算法实战:最小k个数——大顶堆的优雅解法
开发语言·数据结构·c++·python·程序人生·算法·排序算法
万笑佛5 小时前
Python 实现Kafka SASL认证生产消费
python