React 英语单词消消乐一款专为英语学习设计的互动式记忆游戏
📖 项目简介
英语单词消消乐 是一款专为英语学习设计的互动式记忆游戏。通过经典的消消乐玩法,让用户在轻松愉快的游戏中掌握英语单词,提高词汇量和记忆效果。
🎯 项目目标
- 让英语学习变得有趣且高效
- 通过游戏化方式增强单词记忆
- 提供多样化的单词库选择
- 支持语音朗读功能,提升听说能力
✨ 核心功能特色
🎮 游戏玩法
- 经典消消乐模式:点击英语单词和对应的中文翻译来消除
- 智能匹配系统:自动识别英文-中文配对
- 实时反馈:匹配成功有消失动画,失败有抖动提示
- 进度追踪:实时显示匹配进度和得分
🗣️ 语音功能
- 双语朗读:支持英语和中文语音朗读
- 智能语音:根据卡片类型自动选择语言
- 可调节语速:英语稍慢便于学习,中文正常语速
- 语音开关:用户可自由开启/关闭语音功能
📚 单词库系统
- 多样化主题:水果、动物、颜色、数字等多个主题
- 易于扩展:模块化设计,可轻松添加新单词库
- 实时切换:游戏过程中可随时切换单词库
🎨 用户体验
- 响应式设计:完美适配手机、平板、电脑
- 精美动画:流畅的卡片动画和交互效果
- 直观界面:简洁美观的 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 英语单词消消乐,一款专为英语学习设计的互动式记忆游戏 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿动态资讯