📖 项目简介

英语单词消消乐 是一款专为英语学习设计的互动式记忆游戏。通过经典的消消乐玩法,让用户在轻松愉快的游戏中掌握英语单词,提高词汇量和记忆效果。

🎯 项目目标

  • 让英语学习变得有趣且高效
  • 通过游戏化方式增强单词记忆
  • 提供多样化的单词库选择
  • 支持语音朗读功能,提升听说能力

✨ 核心功能特色

🎮 游戏玩法

  • 经典消消乐模式:点击英语单词和对应的中文翻译来消除
  • 智能匹配系统:自动识别英文-中文配对
  • 实时反馈:匹配成功有消失动画,失败有抖动提示
  • 进度追踪:实时显示匹配进度和得分

🗣️ 语音功能

  • 双语朗读:支持英语和中文语音朗读
  • 智能语音:根据卡片类型自动选择语言
  • 可调节语速:英语稍慢便于学习,中文正常语速
  • 语音开关:用户可自由开启/关闭语音功能

📚 单词库系统

  • 多样化主题:水果、动物、颜色、数字等多个主题
  • 易于扩展:模块化设计,可轻松添加新单词库
  • 实时切换:游戏过程中可随时切换单词库

🎨 用户体验

  • 响应式设计:完美适配手机、平板、电脑
  • 精美动画:流畅的卡片动画和交互效果
  • 直观界面:简洁美观的 UI 设计
  • 即时反馈:清晰的操作提示和状态显示

🛠️ 技术栈

  • React.js – 现代化的用户界面框架
  • Tailwind CSS – 实用优先的 CSS 框架
  • JavaScript ES6+ – 现代 JavaScript 语法
  • Web Speech API – 浏览器原生语音合成

全部源码

import { useState, useEffect } from "react";
import { wordLibraries } from "../data/wordLibraries";export default function WordsGame() {const [currentLibrary, setCurrentLibrary] = useState("fruits");const [gameWords, setGameWords] = useState([]);const [selectedCards, setSelectedCards] = useState([]);const [matchedPairs, setMatchedPairs] = useState([]);const [score, setScore] = useState(0);const [gameComplete, setGameComplete] = useState(false);const [gameStarted, setGameStarted] = useState(false);const [disappearingCards, setDisappearingCards] = useState([]);const [shakingCards, setShakingCards] = useState([]);const [speechSynthesis, setSpeechSynthesis] = useState(null);const [speechEnabled, setSpeechEnabled] = useState(true);// 初始化游戏const initializeGame = () => {const library = wordLibraries[currentLibrary];const allWords = [...library.words];// 随机选择10对单词(20张卡片)const shuffled = allWords.sort(() => Math.random() - 0.5).slice(0, 10);// 创建卡片数组,每对单词创建两张卡片const cards = [];shuffled.forEach((word, index) => {cards.push({id: `english-${index}`,type: "english",content: word.english,pairId: index,matched: false,});cards.push({id: `chinese-${index}`,type: "chinese",content: word.chinese,pairId: index,matched: false,});});// 随机打乱卡片顺序const shuffledCards = cards.sort(() => Math.random() - 0.5);setGameWords(shuffledCards);setSelectedCards([]);setMatchedPairs([]);setScore(0);setGameComplete(false);setGameStarted(true);};// 处理卡片点击const handleCardClick = (card) => {if (card.matched || selectedCards.length >= 2) return;// 朗读卡片内容speakCardContent(card);const newSelectedCards = [...selectedCards, card];setSelectedCards(newSelectedCards);if (newSelectedCards.length === 2) {const [card1, card2] = newSelectedCards;// 检查是否匹配if (card1.pairId === card2.pairId && card1.type !== card2.type) {// 匹配成功 - 添加温和的消失动画setDisappearingCards([card1.id, card2.id]);setTimeout(() => {setMatchedPairs((prev) => [...prev, card1.pairId]);setScore((prev) => prev + 10);setSelectedCards([]);setDisappearingCards([]);// 检查游戏是否完成if (matchedPairs.length + 1 === 10) {setGameComplete(true);}}, 400);} else {// 匹配失败 - 添加抖动动画和标红效果setShakingCards([card1.id, card2.id]);setTimeout(() => {setSelectedCards([]);setShakingCards([]); // 动画结束后复位}, 1000);}}};// 切换单词库const changeLibrary = (libraryKey) => {setCurrentLibrary(libraryKey);setGameStarted(false);};// 检查卡片是否被选中const isCardSelected = (card) => {return selectedCards.some((selected) => selected.id === card.id);};// 检查卡片是否已匹配const isCardMatched = (card) => {return matchedPairs.includes(card.pairId);};// 检查卡片是否正在消失const isCardDisappearing = (card) => {return disappearingCards.includes(card.id);};// 检查卡片是否正在抖动const isCardShaking = (card) => {return shakingCards.includes(card.id);};// 朗读卡片内容const speakCardContent = (card) => {if (speechEnabled && speechSynthesis && !speechSynthesis.speaking) {const utterance = new SpeechSynthesisUtterance(card.content);// 根据卡片类型设置语言if (card.type === "english") {utterance.lang = "en-US";utterance.rate = 0.8; // 稍微慢一点,便于学习} else {utterance.lang = "zh-CN";utterance.rate = 0.9;}utterance.volume = 0.8;utterance.pitch = 1.0;speechSynthesis.speak(utterance);}};// 测试语音功能const testSpeech = () => {if (speechSynthesis) {const testText = "语音功能测试";const utterance = new SpeechSynthesisUtterance(testText);utterance.lang = "zh-CN";utterance.rate = 0.9;utterance.volume = 0.8;speechSynthesis.speak(utterance);}};useEffect(() => {if (gameStarted) {initializeGame();}}, [currentLibrary]);// 初始化语音合成useEffect(() => {if ("speechSynthesis" in window) {setSpeechSynthesis(window.speechSynthesis);}}, []);return (<div className="min-h-screen bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50 py-4 px-4"><div className="max-w-6xl mx-auto">{/* 标题和单词库选择 */}<div className="flex flex-col lg:flex-row justify-between items-center mb-4 gap-4"><div className="text-center flex-1"><h1 className="text-xl md:text-2xl lg:text-3xl font-bold text-indigo-700 mb-1 animate-bounce">🎮 英语单词消消乐</h1><p className="text-xs md:text-sm lg:text-base text-indigo-600 font-medium">点击英语单词和对应的中文翻译来消除吧!</p></div>{/* 单词库选择和语音开关 */}<div className="flex flex-col sm:flex-row items-center gap-3">{/* 语音开关 */}<div className="bg-gradient-to-r from-emerald-100 to-teal-100 rounded-xl shadow-md p-2 md:p-3 border-2 border-emerald-200"><div className="flex items-center space-x-1 md:space-x-2"><span className="text-xs md:text-sm font-bold text-emerald-700">{speechEnabled ? "🔊" : "🔇"}</span><buttononClick={() => setSpeechEnabled(!speechEnabled)}className={`px-2 md:px-3 py-1 text-xs md:text-sm font-bold rounded-lg border-2 transition-all duration-200 cursor-pointer ${speechEnabled? "bg-emerald-500 text-white border-emerald-400": "bg-gray-300 text-gray-600 border-gray-400"}`}>{speechEnabled ? "语音开" : "语音关"}</button><buttononClick={testSpeech}className="px-1 md:px-2 py-1 text-xs font-bold bg-blue-500 text-white rounded border-2 border-blue-400 transition-all duration-200 cursor-pointer hover:bg-blue-600">测试</button></div></div>{/* 单词库选择 */}<div className="bg-gradient-to-r from-indigo-100 to-purple-100 rounded-xl shadow-md p-2 md:p-3 border-2 border-indigo-200"><div className="flex items-center"><span className="text-xs md:text-sm font-bold text-indigo-700 mr-1 md:mr-2">🌈</span><selectvalue={currentLibrary}onChange={(e) => changeLibrary(e.target.value)}className="px-2 md:px-3 py-1 text-xs md:text-sm font-bold text-indigo-700 bg-white rounded-lg border-2 border-indigo-200 shadow-sm focus:outline-none focus:border-purple-400 transition-all duration-200 cursor-pointer">{Object.entries(wordLibraries).map(([key, library]) => (<optionkey={key}value={key}className="text-xs md:text-sm font-bold">{library.name}</option>))}</select></div></div></div></div>{/* 游戏状态 */}<div className="bg-gradient-to-r from-emerald-100 to-teal-100 rounded-xl shadow-md p-3 mb-4 border-2 border-emerald-200"><div className="flex justify-between items-center mb-3"><div className="text-sm md:text-base font-bold text-emerald-700">🎯 {wordLibraries[currentLibrary].name}</div><div className="text-lg md:text-xl font-bold text-indigo-600">⭐ {score}</div></div>{!gameStarted ? (<buttononClick={initializeGame}className="w-full bg-gradient-to-r from-emerald-500 to-teal-600 hover:from-emerald-600 hover:to-teal-700 text-white font-bold py-2 px-4 rounded-xl text-base md:text-lg shadow-md transform hover:scale-105 transition-all duration-200 border-2 border-emerald-400">🚀 开始游戏</button>) : (<div className="text-center"><div className="text-sm md:text-base text-emerald-600 mb-2 font-bold">🎪 {matchedPairs.length} / 10</div><buttononClick={initializeGame}className="bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-600 hover:to-purple-700 text-white font-bold py-1 px-3 rounded-lg text-sm md:text-base shadow-md transform hover:scale-105 transition-all duration-200 border-2 border-indigo-400">🔄 重新开始</button></div>)}</div>{/* 游戏完成提示 */}{gameComplete && (<div className="bg-gradient-to-r from-emerald-200 to-indigo-200 border-2 border-emerald-400 text-emerald-800 px-4 py-3 rounded-xl mb-4 text-center shadow-md animate-pulse"><h3 className="text-xl md:text-2xl font-bold mb-2">🎉 恭喜!游戏完成!🎉</h3><p className="text-lg font-bold">最终得分: ⭐ {score} ⭐</p></div>)}{/* 游戏卡片区域 */}{gameStarted && (<div className="relative"><div className="grid grid-cols-4 sm:grid-cols-5 md:grid-cols-8 lg:grid-cols-10 gap-1 md:gap-2">{gameWords.map((card) => (<divkey={card.id}onClick={() => !isCardMatched(card) && handleCardClick(card)}className={`h-16 sm:h-20 md:h-24 rounded-lg md:rounded-xl shadow-md transition-all duration-300 transform${isCardMatched(card)? "opacity-0 pointer-events-none": "cursor-pointer hover:scale-105 hover:rotate-1"}${isCardDisappearing(card)? "animate-disappear pointer-events-none bg-gradient-to-br from-indigo-300 to-purple-300 border-2 border-indigo-500 shadow-lg": isCardShaking(card)? "animate-shake pointer-events-none bg-gradient-to-br from-red-200 to-pink-200 border-2 border-red-400 shadow-md": isCardSelected(card)? "bg-gradient-to-br from-indigo-200 to-purple-200 border-2 border-indigo-400 shadow-md": "bg-gradient-to-br from-slate-50 to-gray-100 border-2 border-slate-200 hover:border-indigo-400 hover:shadow-md"}`}><div className="flex items-center justify-center h-full p-1 md:p-2 w-full"><spanclassName={`text-xs md:text-sm font-bold text-center word-card-text w-full${card.type === "english"? "text-indigo-700": "text-emerald-700"}`}>{card.content}</span></div></div>))}</div></div>)}{/* 游戏说明 */}<div className="bg-gradient-to-r from-slate-100 to-gray-100 rounded-xl shadow-md p-3 mt-4 border-2 border-slate-200"><h3 className="text-lg font-bold text-slate-700 mb-3 text-center">📖 游戏规则</h3><ul className="text-slate-700 space-y-2 text-sm font-medium"><li className="flex items-center">🎯 点击英语单词和对应的中文翻译来消除</li><li className="flex items-center">👆 每次只能选择两张卡片</li><li className="flex items-center">⭐ 匹配成功得10分,匹配失败不扣分</li><li className="flex items-center">🏆 消除所有卡片即可完成游戏</li><li className="flex items-center">🔄 可以随时切换不同的单词库</li><li className="flex items-center">🔊 点击卡片时会朗读内容,可开关语音功能</li></ul></div></div></div>);
}

React 英语单词消消乐,一款专为英语学习设计的互动式记忆游戏 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿动态资讯

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/87862.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/87862.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/87862.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt:QPushButton、QRadioButton、QCheckBox

目录 一、QPushButton 1.认识QPushButton 2.设置按钮图标 3.设置按钮的快捷键 二、QRadioButton 常用的信号 按钮的分组 三、QCheckBox 一、QPushButton 1.认识QPushButton QPushButton继承自QWidget&#xff0c;所以在上一篇文章中介绍的QWidget的属性&#xff0c;理…

docker 无法拉取镜像解决方法

目录 我在omv中通过后台页面拉取alist镜像总是失败&#xff0c;原因千奇百怪 今天再战终于解决首先&#xff0c;到dockerhub找镜像和wiki进入docker账号设置 找到里面提示了登录操作和密码命令行中执行后会提示成功之后按需配置代理&#xff0c;同时检查自己的配置检查 Docker …

安卓10.0系统修改定制化_____安卓9与安卓10系统文件差异 有关定制选项修改差异

在修改安卓10的rom之前。我们需要对rom有简单的了解。区分安卓10与安卓9之间的差异。了解不同安卓版本之间系统文件的变化以及权限的区别。对于修改一些定制化选项有很大的辅助作用. 通过博文了解💝💝💝 1💝💝💝-----安卓10与安卓9之间文件实例对比 了解差异 …

HTML表单元素全面指南:从基础到实践

引言 HTML表单是网页开发中不可或缺的一部分&#xff0c;它为用户提供了与网站交互的途径。无论是简单的登录页面还是复杂的数据提交界面&#xff0c;表单元素都扮演着关键角色。本文将详细介绍各种HTML表单元素及其使用方法。 输入框(input元素) input元素是最基础也是最灵…

深度学习的核心理论与技术

理解深度学习的基本原理、核心算法和关键技术 深度学习的核心理论与技术前言一、深度学习核心理论1. 神经网络基础核心内容练习资源2. 反向传播与梯度下降核心内容练习资源3. 卷积神经网络&#xff08;CNN&#xff09;核心内容练习资源4. 循环神经网络&#xff08;RNN&#xff…

LinkedList 链表数据结构实现 (OPENPPP2)

&#x1f50d; LinkedList 链表数据结构实现 (OPENPPP2) &#x1f9f1; 1. 数据结构设计 LinkedListNode 结构 #mermaid-svg-XDJqt6cHMKxodJLG {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XDJqt6cHMKxodJLG .er…

RPC/gRPC入门学习

一、RPC 1.1 RPC概念 RPC Remote Procedure Call, 即远程过程调用&#xff0c;是一种用于构建分布式系统的理念&#xff0c;在一些资料中被称为“请求-响应”协议。两个进程可以位于同一系统中&#xff0c;也可以位于不同的系统中&#xff0c;通过网络相互连接。 RPC使程…

租车小程序电动车租赁小程序php方案

电动车租赁小程序源码&#xff0c;开发语言后端php&#xff0c;前端uniapp。四个端&#xff1a;用户端门店端分销商端小程序&#xff0c;pc管理后台。一 用户端&#xff1a;可以扫门店码&#xff0c;进入门店详情页。也可以通过地图找车。或者门店列表进入&#xff0c;或者快速…

Python数据分析基础04:预测性数据分析

相关章节&#xff1a; 《Python数据分析基础03&#xff1a;探索性数据分析》 《python数据分析基础02&#xff1a;数据可视化分析》 《Python数据分析基础01&#xff1a;描述性统计分析》 预测性数据分析&#xff08;Predictive Analytics&#xff09; 的深度解析&#xff0…

PFAE(Pyramidal Frequency Attention Extraction)通过频域注意力机制提高边界模糊、遮挡等场景的的检测能力

在伪装物体检测中&#xff0c;现有方法多依赖空间局部特征&#xff0c;难以捕捉全局信息&#xff0c;而 Transformer 类方法计算成本高昂。频率域特征因具备全局建模能力&#xff0c;可有效抑制背景噪声、提升伪装物体语义清晰度&#xff0c;但频域与空域的频繁转换会增加计算复…

AE插件安装方法

Adobe After Effects简称AE&#xff0c;是adobe公司开发的一个视频剪辑及设计软件&#xff0c;AE软件能够实现对素材的非线性编辑而完成画面的组接&#xff0c;同时还能对任何一部分进行修改&#xff0c;达到想要的结果。AE含有很多脚本、常用的表达式和插件&#xff0c;做动画…

舵轮时钟-STM32-28路PWM--ESP8266-NTP时间

1.STM32--PWM生成STM32不具备如此多的PWM&#xff0c;因此采用软件定时器的方案实现&#xff1a;使用hal库实现&#xff1b;main.c#include "main.h"#define close1 500#define open 1500#define close 2500// 定时器中断配置&#xff08;以TIM2为例&#xff09; voi…

Redis的单线程和多线程(单Worker线程)

Redis的单线程和多线程 Redis6.0之前是单线程的&#xff0c;6.0之后是多线程的&#xff0c;我们先了解6.0版本之前的单线程Redis。但其实无论6.0之前还是6.0之后&#xff0c;redis用于工作的线程也只有一个&#xff0c;所以也可以说redis一直是单线程的。 Redis单线程 Redis 6.…

OSPFv3基础

文章目录 OSPFv3基础OSPFv3的改进OSPFv2 v3相同OSPFv2 v3不同 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Datacom专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年07月07日22点31分 OSPFv3基础 OSPFv3协议号依然为89&#xff0c;在I…

前端篇——HTML知识点体系

目录 一、基础结构与文本 1. 文档基础 2. 文本元素 二、多媒体元素 1. 图像 2. 音频 3. 视频 三、列表系统 1. 无序列表 2. 有序列表 3. 定义列表 四、表格系统 1. 表格结构 2. 合并单元格 五、表单系统 1. 输入控件 2. 表单元素 3. 高级表单特性 六、布局系…

产品需求管理文档中,需求模块是怎么界定的

产品需求文档中&#xff0c;需求模块的界定方式主要包括&#xff1a;1、基于业务流程的功能划分、2、按用户角色使用场景分类、3、根据系统架构与技术边界拆解、4、对数据实体和功能点进行组合聚类、5、结合未来演进节奏设置独立迭代单元。 其中&#xff0c;“基于业务流程的功…

国内免代理免费使用Gemini大模型实战

文章目录 一、免费申请Gemini API密钥二、使用openai-gemini1、在github上找到openai-gemini2、将openai-gemini部署到Netlify3、在Cherry Studio中配置和使用gemini的模型1&#xff09;在Cherry Studio中配置gemini API2&#xff09;在Cherry Studio中使用gemini 的模型 4、在…

day46-tomcat-java业务部署

1. ✅选型1.1. &#x1f3af;中间件java web中间件说明tomcat组件&#xff0c;功能多jetty精简&#xff0c;功能少一些......weblogic使用oracle数据库配合weblogic(商业)国产&#xff1a;东方通(TongWEB)1.2. &#x1f4cc;jdkjdk选型说明jdk(oracle jdk)商业版&#xff0c;jd…

[netty5: HttpServerCodec HttpClientCodec]-源码分析

在阅读该篇文章之前&#xff0c;推荐先阅读以下内容&#xff1a; [netty5: ChannelHandler & ChannelHandlerAdapter]-源码解析[netty5: HttpObjectEncoder & HttpObjectDecoder]-源码解析 HttpServerCodec HttpServerCodec 是一个 Netty 编解码器&#xff0c;结合 …

华为OD机试 2025B卷 - 数组组成的最小数字(C++PythonJAVAJSC语言)

2025B卷目录点击查看: 华为OD机试2025B卷真题题库目录|机考题库 + 算法考点详解 2025B卷 100分题型 最新华为OD机试 真题目录:点击查看目录 华为OD面试真题精选:点击立即查看 2025华为od 机试2025B卷-华为机考OD2025年B卷 题目描述 给定一个整型数组,请从该数组中选…