ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Web-Dev-For-Beginners 打字游戏实战:用事件驱动编程构建 Sherlock Holmes 打字测速游戏

Web-Dev-For-Beginners 打字游戏实战:用事件驱动编程构建 Sherlock Holmes 打字测速游戏 Web-Dev-For-Beginners 打字游戏实战用事件驱动编程构建 Sherlock Holmes 打字测速游戏【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners事件驱动编程是每一张交互式网页背后的核心运行机制浏览器把用户的每一次点击、按键与鼠标移动封装为事件消息而开发者通过事件监听器决定如何响应。本文基于 Web-Dev-For-Beginners 课程的《Typing Game》项目从事件驱动编程的原理讲起带你用index.htmlstyle.cssscript.js三件套从零构建一个以福尔摩斯名言为素材的打字测速游戏并深入仓库的参考实现掌握随机引用生成、逐词高亮、实时错误反馈与计时统计的完整实现方案。什么是事件驱动编程让代码等待而不是执行回想你最喜欢的应用或网站是什么让它显得生动且响应迅速答案是它对你的动作做出的反应。每一次点击、输入、滑动或按键都会产生一个所谓的事件Event这正是 Web 开发真正魔法发生的地方。Web 编程之所以有趣是因为我们永远无法预知用户何时会点击按钮、何时开始输入——他可能立刻点击可能等五分钟甚至永远不点。这种不可预测性意味着我们不能像写菜谱那样自上而下地编写代码而要写耐心等待事情发生的代码。原文档用 19 世纪电报员的比喻来说明这一点电报员守在机器旁在消息穿过线路的瞬间立刻响应。在 JavaScript 中我们通过事件监听器Event Listener实现监听与响应。把事件监听器想象成代码的门铃你安装门铃——调用addEventListener()告诉它监听什么声音——传入事件名如click或input指定响铃时做什么——传入你自己的回调函数。事件监听器可以监听特定用户动作点击、按键、鼠标移动执行你编写的自定义代码立即响应用户交互以营造无缝体验并且同一个元素可以通过不同的监听器处理多个事件。注意创建事件监听器有很多方式——匿名函数、具名函数、直接设置click属性、或使用addEventListener()。本课程统一采用addEventListener() 匿名函数因为这是 Web 开发者最常用的技术且对全部事件通用——事件名可以作为参数传入灵活性最高。常见事件一览浏览器提供了数十种可监听的事件但绝大多数交互式应用只依赖少数几个核心事件。课程文档列出了如下常见事件其中click与input正是本打字游戏用到的两个事件描述常见使用场景click用户点击了某处按钮、链接、交互元素contextmenu用户点击鼠标右键自定义右键菜单select用户选中了文本文本编辑、复制操作input用户输入了文本表单校验、实时搜索理解这些事件类型的关键点在于它们由用户与页面特定元素的交互触发通过事件对象提供用户动作的详细信息支持我们构建响应式交互应用并在不同浏览器与设备上一致工作。游戏整体设计一句话说清运行流程我们将构建一个考验玩家打字速度与准确率的游戏。文档中给出了游戏的完整流程图玩家点击 Start → 随机显示一条福尔摩斯名言 → 玩家在输入框中逐字键入 → 每完成一个单词则高亮下一个单词 → 若中途打错则显示错误样式 → 全部输入完成后显示包含总耗时的祝贺消息。游戏的核心特性可以归纳为启动点击开始按钮后从引文库随机抽取一条名言并渲染追踪逐词实时追踪玩家的输入进度高亮始终高亮当前正在输入的单词引导玩家视线反馈对错误输入给出即时视觉反馈计时名言全部输入完毕后计算并展示总耗时。顺带一提今天我们使用的 QWERTY 键盘布局其实诞生于 1870 年代的打字机设计——而熟练的键盘输入能力对今天的程序员依然同样宝贵这正是本项目的现实意义所在。搭建项目三文件结构与开发环境一个整洁的文件结构能省去后续许多麻烦。项目只需三个文件这也是驱动大多数网页的经典三件套index.html—— 页面的结构与内容script.js—— 全部游戏逻辑与事件监听器style.css—— 视觉外观与样式在终端中创建项目目录并进入# Linux 或 macOS mkdir typing-game cd typing-game # Windows md typing-game cd typing-game然后打开 Visual Studio Codecode .开发过程中建议使用 VS Code 的Live Server扩展它会在本地托管应用并在每次保存文件时自动刷新浏览器。安装后按CtrlShiftPmacOS 为CmdShiftP打开命令面板输入Live Server: Open with Live Server启动。Live Server 会启动本地开发服务器通常将文件托管在localhost:5500——在浏览器中访问该地址即可看到页面。构建用户界面四个带 ID 的 DOM 元素设计 UI 就像设计飞船的控制面板——玩家需要的一切都要出现在预期位置。文档给出的 UI 元素清单如下UI 元素用途HTML 元素名言显示区展示要输入的文本p idquote消息区域展示状态与成功消息p idmessage文本输入框玩家输入名言的位置input idtyped-value开始按钮启动游戏button idstart这些元素都分配了唯一 ID以便在 JavaScript 中精确操作。创建index.html并写入以下代码!-- inside index.html -- html head titleTyping game/title link relstylesheet hrefstyle.css /head body h1Typing game!/h1 pPractice your typing skills with a quote from Sherlock Holmes. Click **start** to begin!/p p idquote/p !-- This will display our quote -- p idmessage/p !-- This will display any status messages -- div input typetext aria-labelcurrent word idtyped-value / !-- The textbox for typing -- button typebutton idstartStart/button !-- To start the game -- /div script srcscript.js/script /body /html这段结构的作用在head中链接 CSS 样式表创建清晰的标题与操作指引用带特定 ID 的占位段落承载动态内容输入框带有aria-label无障碍属性开始按钮触发游戏script放在页面末尾以获得最佳加载性能。添加 CSS高亮与错误两态反馈视觉反馈对用户界面至关重要——上世纪 80 年代的研究者就发现即时视觉反馈能显著提升用户表现并减少错误。本游戏需要让玩家立刻知道该打哪个词以及打错了没有。创建style.css/* inside style.css */ .highlight { background-color: yellow; } .error { background-color: lightcoral; border: red; }这两条规则的作用.highlight用黄色背景突出当前单词提供清晰的视觉引导.error用浅珊瑚色背景标记输入错误且不打断玩家的输入流两种对比色同时兼顾了无障碍阅读。✅ CSS 完全可自由发挥——换一种字体、给标题上色、调整元素尺寸让页面更美观。仓库中的参考实现solution/index.css就进一步扩展了样式为#quote添加了左边框、圆角与投影输入框设置了圆角与聚焦发光效果开始按钮加入了悬停抬升的transform: translateY(-2px)动画并通过media (max-width: 600px)媒体查询在移动端收窄输入框、让按钮占满整行可作为美化方向的参考。编写 JavaScript引擎的三步点火HTML 与 CSS 只是没有引擎的漂亮汽车JavaScript 才是让它真正动起来并响应玩家操作的核心。文档将 JavaScript 分为三个可独立完成的步骤步骤目的你将学到创建常量准备名言库与 DOM 引用变量管理与 DOM 选择开始逻辑事件监听器处理游戏初始化事件处理与 UI 更新输入事件监听器实时处理用户输入输入校验与动态反馈第一步创建常量像 NASA 任务控制中心发射前准备好所有监控系统一样先把资源备齐避免后续到处查找与拼写错误。需要维护的数据包括名言数组const内容不变、单词数组当前名言拆分而来、单词索引追踪正在输入第几个词、开始时间用于计算耗时。同时缓存三个 UI 元素的引用// inside script.js // all of our quotes const quotes [ When you have eliminated the impossible, whatever remains, however improbable, must be the truth., There is nothing more deceptive than an obvious fact., I ought to know by this time that when a fact appears to be opposed to a long train of deductions it invariably proves to be capable of bearing some other interpretation., I never make exceptions. An exception disproves the rule., What one man can invent another can discover., Nothing clears up a case so much as stating it to another person., Education never ends, Watson. It is a series of lessons, with the greatest for the last., ]; // store the list of words and the index of the word the player is currently typing let words []; let wordIndex 0; // the starting time let startTime Date.now(); // page elements const quoteElement document.getElementById(quote); const messageElement document.getElementById(message); const typedValueElement document.getElementById(typed-value);这段代码的设计要点名言库用const声明内容不会改变追踪变量用let声明游戏过程中会更新用document.getElementById()缓存 DOM 引用以便高效访问全部采用清晰描述性的命名。✅ 可以自由往quotes数组里添加更多名言。专业提示这些元素会被反复引用将其缓存为常量可以避免字符串字面量的拼写错误。Vue.js、React 等框架能帮你更好地集中管理代码。此外用const/let而不是var有助于提升代码可读性并获得更好的 IDE 自动补全与错误检查支持。第二步添加开始逻辑用户点击 Start 时代码需要随机选一条名言、拆分单词、重置索引、渲染 UI、清空输入框并聚焦、启动计时器。这是你写下的第一个真实事件监听器// at the end of script.js document.getElementById(start).addEventListener(click, () { // get a quote const quoteIndex Math.floor(Math.random() * quotes.length); const quote quotes[quoteIndex]; // Put the quote into an array of words words quote.split( ); // reset the word index for tracking wordIndex 0; // UI updates // Create an array of span elements so we can set a class const spanWords words.map(function(word) { return span${word} /span}); // Convert into string and set as innerHTML on quote display quoteElement.innerHTML spanWords.join(); // Highlight the first word quoteElement.childNodes[0].className highlight; // Clear any prior messages messageElement.innerText ; // Setup the textbox // Clear the textbox typedValueElement.value ; // set focus typedValueElement.focus(); // Start the timer startTime new Date().getTime(); });将这段逻辑拆开来看单词追踪准备用Math.floor()与Math.random()随机选取名言用split( )把名言拆成单词数组将wordIndex重置为 0让玩家从第一个词开始。UI 设置与显示把每个单词包进span元素以便单独设置样式join()拼接后写入innerHTML给第一个词加上highlight类实现高亮清空上一局的遗留消息。输入框准备清空输入框中的残留文本调用focus()让玩家可以立即开始输入。计时器初始化用new Date().getTime()记录当前时间戳为后续计算总耗时做准备。第三步添加输入逻辑这是整个游戏的心脏玩家每敲一个字母代码就校验一次输入、给出反馈并决定下一步。参考实现solution/index.js在代码顶部将消息文案集中管理const messages { success: (seconds) Congratulations! You finished in ${seconds.toFixed(2)} seconds., error: ⚠️ Oops! Theres a mistake., start: ⌨️ Start typing to begin the game. };而课程文档中的核心输入逻辑如下// at the end of script.js typedValueElement.addEventListener(input, () { // Get the current word const currentWord words[wordIndex]; // get the current value const typedValue typedValueElement.value; if (typedValue currentWord wordIndex words.length - 1) { // end of sentence // Display success const elapsedTime new Date().getTime() - startTime; const message CONGRATULATIONS! You finished in ${elapsedTime / 1000} seconds.; messageElement.innerText message; } else if (typedValue.endsWith( ) typedValue.trim() currentWord) { // end of word // clear the typedValueElement for the new word typedValueElement.value ; // move to the next word wordIndex; // reset the class name for all elements in quote for (const wordElement of quoteElement.childNodes) { wordElement.className ; } // highlight the new word quoteElement.childNodes[wordIndex].className highlight; } else if (currentWord.startsWith(typedValue)) { // currently correct // highlight the next word typedValueElement.className ; } else { // error state typedValueElement.className error; } });这段代码采用瀑布式判断——从最具体到最一般的条件依次检查共四种场景 名言完成场景 1当输入值完全等于当前单词且当前已是最后一个单词时用当前时间减去开始时间得到毫秒级耗时除以 1000 换算为秒显示祝贺消息与完成时间。参考实现中额外执行了typedValueElement.disabled true来禁用输入框即文档挑战章节中提到的 UI 状态管理。✅ 单词完成场景 2当输入以空格结尾endsWith( )且去除空格后与当前单词完全一致时清空输入框、wordIndex前进到下一个词、移除所有 span 的类名并给新词加上highlight类。 输入进行中场景 3当当前单词以已输入内容开头startsWith时移除错误样式允许玩家继续输入而不打断节奏。❌ 错误状态场景 4当输入与预期词首不匹配时给输入框加上error类提供即时视觉反馈帮助玩家快速发现并纠正错误。测试与调试验证五项核心行为点击 Start 并开始输入运行效果参见课程演示动画按照文档清单逐项验证点击 Start 是否显示一条随机名言输入时当前单词是否正确高亮输入错误时是否出现错误样式完成单词后高亮是否正确前移完成整条名言后是否显示带耗时的完成消息。常见调试技巧打开浏览器控制台F12查看 JavaScript 报错核对所有文件名是否完全一致区分大小写确认 Live Server 正在运行且能正确刷新多试几条名言以验证随机选取逻辑。挑战与进阶把游戏推向下一级课程为学有余力的读者准备了两档挑战。GitHub Copilot Agent 挑战——难度自适应系统扩展游戏使其根据玩家表现自动调整难度。要求包括追踪打字速度WPM与准确率在简单简单名言/中等现有名言/困难含标点的复杂名言三档间自动切换在 UI 中展示当前难度与玩家统计实现连续 3 次优秀表现后升级难度的连胜计数器用颜色与动画提供难度变化的视觉反馈并保证 ARIA 标签与错误处理的无障碍合规。高级功能挑战以表格形式列出了四项可练习的进阶能力——功能描述练习的技能输入控制完成时禁用input事件监听器点击按钮时重新启用事件管理与状态控制UI 状态管理玩家完成名言后禁用输入框DOM 属性操作模态对话框用模态窗口展示成功消息高级 UI 模式与无障碍高分系统用localStorage保存高分浏览器存储 API 与数据持久化实现提示查阅localStorage.setItem()与localStorage.getItem()实现持久化存储练习动态添加与移除事件监听器探索 HTMLdialog元素或 CSS 模态模式在禁用/启用表单控件时充分考虑无障碍体验。课后任务设计你自己的键盘游戏完成打字游戏后课程布置了综合任务见 assignment.md设计并构建一个基于键盘事件的新游戏要求包含要求说明目的事件监听器响应至少 3 种不同的键盘事件展示事件处理的理解视觉反馈对用户输入提供即时视觉反馈展示 DOM 操作的掌握游戏逻辑集成分数、关卡或进度机制练习应用状态实现用户界面清晰的指令与直观的操作锻炼 UX 设计能力可以发挥创意的方向包括节奏游戏按键跟随音乐或视觉提示、像素画创作器不同按键绘制不同颜色、单词构建器按特定顺序敲字母组词、贪吃蛇方向键控制、音乐合成器不同按键发出不同音符、分类限时输入编程术语、外语词汇、键盘鼓手按键映射不同鼓点等。建议从简单概念起步、逐步增加复杂度聚焦流畅自然的响应手感并用注释说明你的事件处理策略。结语事件驱动编程的通用价值本项目沉淀的能力远不止一个打字游戏。你掌握的包括事件驱动编程响应输入的反应式 UI、实时反馈即时的视觉与性能更新、性能测量精确的计时与计分系统、游戏状态管理控制应用流程与用户体验、交互设计打造有吸引力的体验、现代 Web API运用以及无障碍模式。这些技能可直接迁移到 Web 应用仪表盘、教育软件、文本编辑器与 IDE、浏览器游戏乃至移动端触控交互等场景。正如课程结语所言每当看到下拉菜单、边输入边校验的表单或响应点击的游戏你如今都理解了背后的魔法。【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表