春晚魔术程序复刻

春晚魔术程序复刻

  • [🎩 时间魔术计算器 (Time Magic Calculator)](#🎩 时间魔术计算器 (Time Magic Calculator))
    • 项目简介
    • [✨ 核心特性](#✨ 核心特性)
    • [🚀 演出指南(如何使用)](#🚀 演出指南(如何使用))
    • [🧠 原理揭秘](#🧠 原理揭秘)
    • [🛠️ 技术栈](#🛠️ 技术栈)
    • [Show Me The Code:](#Show Me The Code:)

🎩 时间魔术计算器 (Time Magic Calculator)

项目简介

这是一个基于 HTML, CSS 和原生 JavaScript 开发的网页版"魔术"计算器。从表面上看,它拥有与普通计算器类似的 UI 界面,但它的核心是一个互动魔术:无论用户前两次输入什么数字,程序都会通过"幽灵打字"的方式自动补齐第三个数字,使得这三个数字的总和恰好等于当前的系统时间(月、日、时、分)。


✨ 核心特性

  • 步骤级状态控制 :内置严格的状态机(step 1-4),引导观众按照魔术剧本进行操作,防止乱按导致穿帮。
  • 输入长度限制:根据魔术需求,严格限制第一个数字为最高5位,第二个数字为最高6位。
  • 实时时间抓取 :利用 JavaScript 的 Date 对象,实时抓取设备的当前时间,并精确格式化为特定的数字串(如 2月17日15:00 格式化为 2171500)。
  • 幽灵打字动画 :第三个数字并非瞬间出现,而是通过 setInterval 模拟人手或系统计算的延迟,每 150ms 敲击一个数字,极大地增强了魔术的悬疑感和观赏性。

🚀 演出指南(如何使用)

你可以拿这个计算器给你的朋友变个魔术,请按照以下步骤引导他们:

  1. 第一轮输入 :让朋友随意输入一个不超过 5位数 的数字(例如:10000)。
  2. 第一次相加 :让朋友按下 + 号。
  3. 第二轮输入 :让朋友再次随意输入一个不超过 6位数 的数字(例如:100000)。
  4. 触发魔法 :让朋友再次按下 + 号。
    • 此时计算器接管控制权,屏幕上会像有幽灵在敲击键盘一样,逐个跳出第三个神秘数字。
  5. 揭晓奇迹 :让朋友按下 = 号。计算器会得出这三个数字的总和。
  6. 点睛之笔:让朋友看看自己的手表或手机当前时间(例如:2月17号15:00),他们会惊奇地发现,总和数字完美契合当前时间!

🧠 原理揭秘

这个魔术的核心是一道简单的代数题。程序并不关心用户前两次输入了什么,它只做一件事:求差值

  1. 记录用户的输入:设为 Num1Num2
  2. 抓取目标结果:获取当前系统时间,并转换为数字 Time
  3. 倒推第三个数字:程序在后台迅速计算出 Num3 = Time - (Num1 + Num2)
  4. 演出展示:假装第三个数字是随机生成的,并在最后相加时得出必然结果:Num1 + Num2 + Num3 = Time

🛠️ 技术栈

  • 结构: HTML5
  • 样式: CSS3 (Flexbox/Grid 布局, 拟物化阴影与交互动画)
  • 逻辑: Vanilla JavaScript (原生 JS)

Show Me The Code:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>时间魔术计算器</title>
    <style>
        /* 基础页面重置与居中布局 */
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f0f2f5; /* 浅灰色背景,突出计算器 */
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
        }

        /* 计算器外壳样式 */
        .calculator {
            background-color: #333;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); /* 增加立体阴影 */
            padding: 20px;
            width: 320px;
        }

        /* 顶部显示屏样式 */
        .display {
            background-color: #e8f0f2;
            color: #333;
            font-size: 2.5rem;
            text-align: right; /* 数字靠右对齐 */
            padding: 20px;
            border-radius: 10px;
            margin-bottom: 20px;
            overflow-x: auto; /* 数字过长时允许横向滚动 */
            white-space: nowrap;
            box-shadow: inset 0 3px 5px rgba(0,0,0,0.1); /* 内阴影增加真实感 */
        }

        /* 按键网格布局:4列等宽 */
        .buttons {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 15px;
        }

        /* 通用按键样式 */
        button {
            border: none;
            padding: 20px;
            font-size: 1.5rem;
            border-radius: 10px;
            cursor: pointer;
            background-color: #444;
            color: white;
            transition: background-color 0.1s, transform 0.1s; /* 点击动画过渡 */
        }

        /* 按键点击时的缩放效果 */
        button:active {
            transform: scale(0.95);
        }

        button:hover {
            background-color: #555;
        }

        /* 运算符按键样式(橙色) */
        .operator {
            background-color: #ff9500;
        }
        .operator:hover {
            background-color: #ffaa33;
        }

        /* 功能按键样式(灰色,如C键、说明键) */
        .action {
            background-color: #a5a5a5;
            color: black;
        }
        .action:hover {
            background-color: #d4d4d4;
        }
    </style>
</head>
<body>

<div class="calculator">
    <div class="display" id="display">0</div>
    
    <div class="buttons">
        <button class="action" onclick="clearCalc()">C</button>
        <button class="action" onclick="alert('操作指南:\n1. 输入5位数字按+\n2. 输入6位数字按+\n3. 观看自动模拟输入\n4. 按=揭晓魔法时间')">?</button>
        <button class="action" onclick="appendNum('0')">0</button>
        <button class="operator" onclick="handlePlus()">+</button>
        
        <button onclick="appendNum('7')">7</button>
        <button onclick="appendNum('8')">8</button>
        <button onclick="appendNum('9')">9</button>
        <button class="operator" onclick="handleEqual()">=</button>
        
        <button onclick="appendNum('4')">4</button>
        <button onclick="appendNum('5')">5</button>
        <button onclick="appendNum('6')">6</button>
        <button class="operator" style="grid-row: span 2" onclick="handleEqual()">=</button>
        
        <button onclick="appendNum('1')">1</button>
        <button onclick="appendNum('2')">2</button>
        <button onclick="appendNum('3')">3</button>
    </div>
</div>

<script>
    // ===== 核心状态变量 =====
    // step 用于追踪当前进行的步骤:
    // 1: 等待输入第一个数字
    // 2: 等待输入第二个数字
    // 3: 正在/完成模拟输入第三个数字,等待按等于号
    // 4: 已经显示最终结果
    let step = 1; 
    let num1 = 0; // 存储第一个输入的数字
    let num2 = 0; // 存储第二个输入的数字
    let num3 = 0; // 存储由系统计算得出的第三个差值数字
    let currentInput = ""; // 当前显示屏上正在拼接的字符串
    const display = document.getElementById('display');

    // ===== 核心功能函数 =====

    /**
     * 更新显示屏内容
     * @param {string|number} val - 需要显示的值
     */
    function updateDisplay(val) {
        display.innerText = val;
    }

    /**
     * 处理数字按键的输入
     * @param {string} numStr - 用户点击的数字字符
     */
    function appendNum(numStr) {
        // 防止用户在魔术表演阶段(自动打字或已出结果)干扰程序
        if (step === 3 || step === 4) return; 

        // 需求1:限制第一轮最高输入 5 位数,第二轮最高输入 6 位数
        if (step === 1 && currentInput.length >= 5) return;
        if (step === 2 && currentInput.length >= 6) return;

        // 如果当前是初始状态0,则直接替换;否则在后面追加数字
        if (currentInput === "0" || currentInput === "") {
            currentInput = numStr;
        } else {
            currentInput += numStr;
        }
        updateDisplay(currentInput);
    }

    /**
     * 处理加号 "+" 的点击事件
     */
    function handlePlus() {
        if (step === 1) {
            // 第一轮输入完毕,按下加号
            if (currentInput === "") return;
            num1 = parseInt(currentInput); // 保存第一个数字
            step = 2; // 状态切换到第二轮
            currentInput = ""; // 清空当前输入缓存
            updateDisplay("0"); // 屏幕重置为0
            
        } else if (step === 2) {
            // 第二轮输入完毕,按下加号,触发魔术核心逻辑
            if (currentInput === "") return;
            num2 = parseInt(currentInput); // 保存第二个数字
            
            // 需求2:获取当前时间并格式化
            const now = new Date();
            const month = (now.getMonth() + 1).toString(); // 月份:无需补零(1-12)
            const date = now.getDate().toString().padStart(2, '0'); // 日期:补齐2位
            const hours = now.getHours().toString().padStart(2, '0'); // 小时:补齐2位
            const minutes = now.getMinutes().toString().padStart(2, '0'); // 分钟:补齐2位
            
            // 拼接时间字符串并转换为数字 (例如: 2月17日15:00 -> "2171500" -> 2171500)
            const timeString = `${month}${date}${hours}${minutes}`;
            const timeValue = parseInt(timeString);
            
            // 魔术公式:第三个数字 = 目标时间总和 - (第一个数字 + 第二个数字)
            num3 = timeValue - (num1 + num2);
            
            step = 3; // 状态切换到第三轮(系统模拟输入)
            simulateTyping(num3.toString());
        }
    }

    /**
     * 模拟键盘自动打字效果,逐个显示第三个数字
     * @param {string} targetString - 需要自动打印的数字字符串
     */
    function simulateTyping(targetString) {
        let index = 0;
        currentInput = "";
        
        // 设置定时器,每 150 毫秒执行一次,营造一种"系统正在高速计算"的视觉效果
        const typingInterval = setInterval(() => {
            currentInput += targetString[index]; // 每次追加一个字符
            updateDisplay(currentInput);
            index++;
            
            // 当所有字符都打印完毕时,清除定时器
            if (index >= targetString.length) {
                clearInterval(typingInterval);
                // 此时模拟输入完成,等待用户按 "=" 键
            }
        }, 150); 
    }

    /**
     * 处理等号 "=" 的点击事件
     */
    function handleEqual() {
        // 只有在第三个数字模拟输入完毕后,按等号才有效
        if (step === 3) {
            // 需求3:展示最终加和结果。因为 num3 是根据差值倒推的,所以结果一定等于当前时间数值
            const finalResult = num1 + num2 + num3; 
            updateDisplay(finalResult);
            step = 4; // 流程结束,锁定按键
        }
    }

    /**
     * 清空重置计算器,恢复到初始状态
     */
    function clearCalc() {
        step = 1;
        num1 = 0;
        num2 = 0;
        num3 = 0;
        currentInput = "";
        updateDisplay("0");
    }
</script>

</body>
</html>
相关推荐
键盘鼓手苏苏4 小时前
Flutter for OpenHarmony:markdown 纯 Dart 解析引擎(将文本转化为结构化 HTML/UI) 深度解析与鸿蒙适配指南
前端·网络·算法·flutter·ui·html·harmonyos
星火开发设计1 天前
标准模板库 STL:C++ 的利器 —— 容器、算法、迭代器
java·开发语言·数据结构·c++·算法·html
Never_Satisfied1 天前
在JavaScript / HTML中,触发某个对象的click事件
开发语言·javascript·html
henry1010101 天前
通过GitHub Page服务免费部署静态Web网站
前端·html·github·html5
tod1133 天前
Redis 数据类型与 C++ 客户端实践指南(redis-plus-plus)
前端·c++·redis·bootstrap·html
henry1010103 天前
Deepseek辅助生成的HTML5网页版抄经典《弟子规》
前端·javascript·css·html·html5
想睡好3 天前
标签的ref属性
前端·javascript·html
henry1010103 天前
HTML5小游戏 - 数字消除 · 合并2048
前端·游戏·html·html5
杨超越luckly3 天前
HTML应用指南:利用GET请求获取中国邮政网点位置信息
前端·python·arcgis·html·php·数据可视化