宠物网站模板,wordpress导航条加搜索,给别人做网站挣钱么,陕西建设工程合同备案网站目录 1 为什么要开发单词消消乐2 需要具备什么功能3 采用什么技术方案实现4 逻辑设计4.1 数据结构设计4.2 游戏的核心逻辑4.3 数据设计 5 代码详解5.1 导入依赖5.2 定义函数组件5.3 数据初始化5.4 状态定义5.5 打乱解释的逻辑5.6 定义选择单词的函数5.7 定义选择解释的函数5.8 … 目录 1 为什么要开发单词消消乐2 需要具备什么功能3 采用什么技术方案实现4 逻辑设计4.1 数据结构设计4.2 游戏的核心逻辑4.3 数据设计 5 代码详解5.1 导入依赖5.2 定义函数组件5.3 数据初始化5.4 状态定义5.5 打乱解释的逻辑5.6 定义选择单词的函数5.7 定义选择解释的函数5.8 界面渲染 6 如何使用这个代码总结 周末线上观看了腾讯TVP技术分享交流产品经理现场演示了使用新的云开发Copilot写一个抽奖的功能。看完后大受启发于是我也现学现卖做一个类似的组件。 单词消消乐小游戏教程 1 为什么要开发单词消消乐
在在线英语单词的APP或者小程序中有很多学习单词的场景。教培机构为了让学员体会到学习的乐趣通常会引入游戏的元素。那么单词消消乐就是一种趣味性的工具。
低龄孩子在消消乐的过程中既记住了单词又有耐心把学习进行完毕。
2 需要具备什么功能
屏幕左侧显示一组英文单词右侧显示一组中文解释。玩家需要点击英文单词和其对应的中文解释如果配对正确单词和解释会从屏幕中消失。当所有单词和解释都匹配完成后显示“游戏结束”并提供重新开始的选项。
3 采用什么技术方案实现
单词消消乐总体算是复杂逻辑了如果我们使用基本的组件比如普通容器、文本、按钮这些搭建。不是说不可以但是问题是要考虑副作用的问题。
微搭总体是使用react组件设计的简单场景没问题但是复杂场景尤其在用户快速点击的时候就会有奇奇怪怪的问题。比如我的单词明明选中了要消掉但是还留着。这种就大大影响用户的体验了。
过去这种我们只能是将就用但是新版本提供了AI代码块的组件支持你用React的语法实现自己想要的功能就比较方便了。
4 逻辑设计
要想设计一款比较好玩的游戏逻辑是非常重要的逻辑想明白了代码只是逻辑的实现罢了。有的人就感觉技术非常高级技术本身是为业务服务的企业最终是通过技术来实现自己的商业目标。
TVP的一位嘉宾的观点我非常认同系统的价值在于给企业带没带来效率的提升成本的降低给没给用户的体验带来提升。那我们在做程序设计的时候也需要把用户体验放在首位进行考虑。
4.1 数据结构设计
游戏的核心是管理一组单词和对应的解释因此我们用数组来存储这些数据。
每个单词和解释用一个对象表示包含两个属性
word英文单词。definition对应的中文解释。
实际的数据结构是长这样的
[{ word: apple, definition: 苹果 },{ word: banana, definition: 香蕉 }
]
4.2 游戏的核心逻辑
1.初始化游戏
提供一组单词和解释。打乱右侧的中文解释顺序增加挑战性。
2.点击事件
玩家点击一个英文单词后再点击一个中文解释。判断二者是否匹配匹配成功将这对单词和解释从屏幕移除。匹配失败重置选择提示玩家重新尝试。
3.游戏结束:
当所有单词都匹配完成显示“重新开始”的按钮。
4.重新开始
恢复初始状态重新打乱解释。
4.3 数据设计
我们的组件需要设计一些数据来跟踪用户的点击我们考虑如下数据
pairs剩余的单词和解释。shuffledDefinitions打乱后的解释。selectedWord 和 selectedDefinition当前被选中的单词和解释。matchedPairs已匹配成功的单词和解释。
5 代码详解
完整代码如下
import React, { useState, useEffect } from react;
import { Button, CardContent, CardTitle } from /components/ui;// 打乱数组顺序的函数
const shuffle (array) {return array.sort(() Math.random() - 0.5);
};export default function WordMatchGame() {const initialPairs $w.page.dataset.state.wordsconst [pairs, setPairs] useState(initialPairs); // 存储单词和解释的数组const [shuffledDefinitions, setShuffledDefinitions] useState([]); // 存储打乱后的中文解释const [selectedWord, setSelectedWord] useState(null); // 当前选中的单词const [selectedDefinition, setSelectedDefinition] useState(null); // 当前选中的解释const [matchedPairs, setMatchedPairs] useState([]); // 匹配成功的单词和解释// 打乱解释的顺序useEffect(() {const shuffled shuffle(pairs.map(pair pair.definition)); // 仅打乱中文解释setShuffledDefinitions(shuffled);}, [pairs]); // 当 pairs 改变时重新打乱解释// 选择单词const selectWord (word) {if (matchedPairs.some(pair pair.word word)) return; // 如果该单词已匹配成功则不能再次选择console.log(选择单词: ${word}); // 输出选中的单词setSelectedWord(word);};// 选择解释const selectDefinition (definition) {console.log(选择解释: ${definition}); // 输出选中的解释setSelectedDefinition(definition);// 找到选中的单词的正确解释const correctDefinition pairs.find(pair pair.word selectedWord)?.definition;if (correctDefinition correctDefinition definition) {// 如果匹配成功消除配对的单词和解释console.log(匹配成功); // 输出匹配成功的日志setMatchedPairs(prev [...prev, { word: selectedWord, definition }]);// 移除已匹配的单词和解释setPairs(prevPairs prevPairs.filter(pair pair.word ! selectedWord pair.definition ! definition));// 重置选中的单词和解释setSelectedWord(null);setSelectedDefinition(null);} else {console.log(匹配失败); // 输出匹配失败的日志// 如果匹配失败重置选中的单词和解释setTimeout(() {setSelectedWord(null);setSelectedDefinition(null);}, 500); // 延迟恢复避免闪烁}};// 渲染单词和解释列const renderColumn (column, isWordColumn) {return column.map((item, index) {// 根据是否选中单词来改变样式const isSelected isWordColumn ? selectedWord item.word : selectedDefinition item;const selectedClass isSelected ? bg-green-300 : ; // 选中时背景为绿色return (divkey{index}className{cursor-pointer p-2 mb-2 bg-white rounded-lg shadow-md ${isWordColumn ? text-left : text-right} ${selectedClass}}onClick{() isWordColumn ? selectWord(item.word) : selectDefinition(item)}{isWordColumn ? item.word : item}/div);});};// 判断是否所有的单词和解释都已匹配成功const isGameOver pairs.length 0;// 重新开始游戏const restartGame () {setPairs(initialPairs); // 重置 pairs 数组setMatchedPairs([]); // 清空匹配记录setShuffledDefinitions(shuffle(initialPairs.map(pair pair.definition))); // 重新打乱解释顺序setSelectedWord(null); // 清空选中的单词setSelectedDefinition(null); // 清空选中的解释};return (div classNameflex flex-col items-center justify-center min-h-screen bg-gradient-to-r from-green-400 via-blue-500 to-purple-500 relativediv classNametext-white text-4xl font-extrabold mb-8单词对对碰游戏/div{/* 游戏列 */}div classNameflex justify-center space-x-12div classNameflex flex-col space-y-2CardTitle classNametext-white font-bold text-xl mb-4英文单词/CardTitle{pairs.map((pair, index) (divkey{index}className{cursor-pointer p-2 mb-2 bg-white rounded-lg shadow-md text-left ${selectedWord pair.word ? bg-green-300 : }}onClick{() selectWord(pair.word)}{pair.word}/div))}/divdiv classNameflex flex-col space-y-2CardTitle classNametext-white font-bold text-xl mb-4中文解释/CardTitle{renderColumn(shuffledDefinitions, false)} {/* 渲染打乱后的中文解释列 */}/div/div{/* 匹配成功的信息 */}{matchedPairs.length 0 (div classNamemt-6 text-white text-xlCardContentCardTitle已匹配:/CardTitleul{matchedPairs.map((pair, index) (li key{index}{pair.word} - {pair.definition}/li))}/ul/CardContent/div)}{/* 重新开始按钮 */}{isGameOver (Button onClick{restartGame} classNamemt-6 bg-green-500 text-white px-6 py-2 rounded-md shadow-lg重新开始/Button)}/div);
}
5.1 导入依赖
import React, { useState, useEffect } from react;
import { Button, CardContent, CardTitle } from /components/ui;
一开头有两条导入语句这部分相当于是要引入已经封装好的第三方库。
先导入了React框架
React 是一个前端框架用来构建用户界面。每个 React 组件需要 React 提供的一些功能比如状态管理useState、生命周期管理useEffect等。
这个就相当于我们可以直接用方法名调用它封装好的方法但是也必须要强制符合他的方法定义的要求不能自由发挥。开源的东西看似好用其实是引入了复杂性遇到问题就比较费时间。
之后导入了导入 useState 和 useEffect
useState用来定义和管理组件的状态。useEffect用来定义组件的副作用逻辑比如初始化数据、监听事件等。
导入 UI 组件
Button、CardContent、CardTitle 是从一个自定义的 UI 库中引入的现成组件用来实现按钮、卡片标题等界面元素。
5.2 定义函数组件
export default function WordMatchGame() {这是一个 React 函数组件在 React 中所有的界面逻辑都定义在组件里。WordMatchGame 是这个组件的名字表示这是一个“单词配对游戏”的组件。
export default 的作用它表示将 WordMatchGame 组件作为模块导出方便其他地方引入使用。
5.3 数据初始化
const initialPairs $w.page.dataset.state.words;这一行是做什么的
定义了一个变量 initialPairs它存储了游戏初始的单词和解释配对数据。
数据来源是 $w.page.dataset.state.words表示从页面的数据集里获取单词和解释。
在JSX组件中是可以引用我们微搭中定义的各种自定义变量的在代码区我们可以创建一个数组变量用来初始化数据 默认值是
[{word: apple,definition: 苹果},{word: dog,definition: 狗},{word: car,definition: 汽车},{word: sun,definition: 太阳},{word: tree,definition: 树},{word: house,definition: 房子}
]5.4 状态定义
const [pairs, setPairs] useState(initialPairs);
const [shuffledDefinitions, setShuffledDefinitions] useState([]);
const [selectedWord, setSelectedWord] useState(null);
const [selectedDefinition, setSelectedDefinition] useState(null);
const [matchedPairs, setMatchedPairs] useState([]);
使用 React 的 useState 定义了 5 个状态分别是
pairs游戏的核心数据单词和解释配对。shuffledDefinitions打乱后的中文解释用来显示在界面上。selectedWord当前选中的英文单词。selectedDefinition当前选中的中文解释。matchedPairs匹配成功的单词和解释。
每个状态都有两个变量pairs 是状态的值setPairs 是修改状态的函数。
用中括号定义是React强制的语法React 提供了一个叫做 useState 的 Hook用来定义和管理组件的状态。
语法说明
const [状态变量, 修改状态的函数] useState(初始值);状态变量存储数据的地方如 pairs。修改状态的函数用来更新状态React 会自动重新渲染界面如 setPairs。初始值状态的初始数据比如 initialPairs。
5.5 打乱解释的逻辑
useEffect(() {const shuffled shuffle(pairs.map(pair pair.definition));setShuffledDefinitions(shuffled);
}, [pairs]);
useEffect 的作用这个函数在组件渲染后运行。它监听 pairs 的变化只要 pairs 更新就会重新执行里面的代码。
具体逻辑pairs.map(pair pair.definition) 提取所有中文解释。调用 shuffle 函数打乱解释的顺序。将打乱后的结果保存到状态 shuffledDefinitions。
设计这个的初衷是如果不把解释打乱用户就知道你的答案是一一对应的也就失去了学习的意义。
5.6 定义选择单词的函数
const selectWord (word) {if (matchedPairs.some(pair pair.word word)) return;setSelectedWord(word);
};
这段代码是干什么的
定义了一个函数 selectWord用来处理“点击单词”的操作。如果这个单词已经匹配成功在 matchedPairs 里直接返回。否则将当前选中的单词存储到 selectedWord 状态。
5.7 定义选择解释的函数
const selectDefinition (definition) {setSelectedDefinition(definition);const correctDefinition pairs.find(pair pair.word selectedWord)?.definition;if (correctDefinition correctDefinition definition) {setMatchedPairs(prev [...prev, { word: selectedWord, definition }]);setPairs(prev prev.filter(pair pair.word ! selectedWord));} else {setTimeout(() {setSelectedWord(null);setSelectedDefinition(null);}, 500);}
};
这段代码是干什么的
定义了一个函数 selectDefinition用来处理“点击解释”的操作。将当前选中的解释存储到 selectedDefinition 状态。查找当前选中的单词的正确解释correctDefinition。判断是否匹配成功成功更新匹配记录并从未匹配的单词中移除该配对。失败延迟清空选中的单词和解释。
5.8 界面渲染
return (div classNameflex flex-col items-center justify-center min-h-screen bg-gradient-to-r from-green-400 via-blue-500 to-purple-500 relativediv classNametext-white text-4xl font-extrabold mb-8单词对对碰游戏/div{/* 游戏列 */}div classNameflex justify-center space-x-12div classNameflex flex-col space-y-2CardTitle classNametext-white font-bold text-xl mb-4英文单词/CardTitle{pairs.map((pair, index) (divkey{index}className{cursor-pointer p-2 mb-2 bg-white rounded-lg shadow-md text-left ${selectedWord pair.word ? bg-green-300 : }}onClick{() selectWord(pair.word)}{pair.word}/div))}/divdiv classNameflex flex-col space-y-2CardTitle classNametext-white font-bold text-xl mb-4中文解释/CardTitle{renderColumn(shuffledDefinitions, false)} {/* 渲染打乱后的中文解释列 */}/div/div{/* 匹配成功的信息 */}{matchedPairs.length 0 (div classNamemt-6 text-white text-xlCardContentCardTitle已匹配:/CardTitleul{matchedPairs.map((pair, index) (li key{index}{pair.word} - {pair.definition}/li))}/ul/CardContent/div)}{/* 重新开始按钮 */}{isGameOver (Button onClick{restartGame} classNamemt-6 bg-green-500 text-white px-6 py-2 rounded-md shadow-lg重新开始/Button)}/div);这里其实就需要懂HTML和CSS了这里的CSS是引入了Tailwind CSS我发现微搭的技术栈里这个是可以使用的用样式库自带的样式搭建界面还是非常快的
这里唯一需要注意的就是{}的使用他的作用类似于表达式凡是你要用表达式的就得用{}包裹起来
6 如何使用这个代码
上边代码要想看的懂需要你学习React、HTML、CSS、JavaScript学习过程还是比较艰辛的。但是代码的一个最大的特点是可以拷贝粘贴我们使用我们的cv大法看如何使用。
在应用中创建一个页面
输入页面的名称 加入我们的AI代码块组件 点击编辑JSX代码 将教程的完整代码贴入编辑器中 在代码区创建一个数组变量words 然后设置默认值
[{word: apple,definition: 苹果},{word: dog,definition: 狗},{word: car,definition: 汽车},{word: sun,definition: 太阳},{word: tree,definition: 树},{word: house,definition: 房子}
]我们的效果就有了 点击预览就大功告成啦
总结
我们本篇介绍了微搭的新能力AI组件的具体用法。结合一个实战案例单词消消乐详细讲解了游戏的功能设计、逻辑设计以及代码逻辑。对于复杂需求借助纯代码也是一种可行解。但是纯代码技术难度高调错复杂未来也许AI的能力提高之后这部分就不是太复杂的一件事。