<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>英文基础互动题 App</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="max-w-2xl mx-auto py-6 px-2">
<h1 class="text-2xl font-bold text-center mb-4">英文基础互动题 App</h1>
<div id="quiz"></div>
</div>
<script>
const data = [
// 单选题
{
id: 1,
type: "mc",
question: "Which word completes the sentence? [translate:她___学生。] (She ____ a student.)",
options: ["am", "are", "is", "be"],
answer: 2,
explanation: "[translate:主语是 She(她),单数第三人称要用 is,所以答案是 is。]"
},
{
id: 2,
type: "mc",
question: "Which question is correct? [translate:哪个是正确的问句?]",
options: ["Do you speak Chinese?", "You speak Chinese?", "Are you speak Chinese?", "Are you Chinese?"],
answer: 0,
explanation: "[translate:用助动词 do/does 构成一般疑问句,'Do you speak Chinese?' 正确;其他选项语法有误或表达意思不同。]"
},
{
id: 3,
type: "mc",
question: "Choose the correct response: [translate:你好吗?]",
options: ["I'm fine.", "I'm ten.", "I'm from China.", "I'm a student."],
answer: 0,
explanation: "[translate:'How are you?' 应回应 'I'm fine.'。]"
},
{
id: 4,
type: "mc",
question: "Which word fills the blank? I ____ two pencils in my bag.",
options: ["has", "have", "am", "is"],
answer: 1,
explanation: "[translate:主语 I 用 have,I have two pencils。]"
},
{
id: 5,
type: "mc",
question: "Choose the correct word. My birthday is ____ June 1st.",
options: ["at", "on", "in", "of"],
answer: 1,
explanation: "[translate:日期前用 on。My birthday is on June 1st。]"
},
{
id: 6,
type: "mc",
question: "Select the correct answer: [translate:你需要一些水吗?]",
options: ["Do you need some water?", "Are you need any water?", "Do you need any water?", "Do you needing water?"],
answer: 2,
explanation: "[translate:一般疑问句应使用 any,且语法结构为 Do you need any water?。]"
},
{
id: 7,
type: "mc",
question: "Which matches the picture? [translate:桌子上有一本书。]",
options: ["There is a book on the table.", "There are a book on the table.", "This is a book on table.", "There is the book at the table."],
answer: 0,
explanation: "[translate:'桌子上有一本书' 应译为 There is a book on the table。]"
},
{
id: 8,
type: "mc",
question: "Find the correct word: Tom's ____ is new. [translate:汤姆的新…]",
options: ["book", "books", "the book", "of book"],
answer: 0,
explanation: "[translate:Tom's + 名词表所属关系,Tom's book 是正确的表达。]"
},
{
id: 9,
type: "mc",
question: "Choose the right phrase: [translate:请打开窗户]",
options: ["turn on the window", "open the window", "open window", "turn up the window"],
answer: 1,
explanation: "[translate:打开窗户应为 open the window。]"
},
// 完形填空题
{
id: 10,
type: "fill",
question: "I ____ hungry now.",
options: ["am", "is", "are", "be"],
answer: 0,
explanation: "[translate:主语 I 用 am。I am hungry now。]"
},
{
id: 11,
type: "fill",
question: "[translate:他们正在吃晚餐。] They ____ having dinner.",
options: ["are", "have", "is", "be"],
answer: 0,
explanation: "[translate:'They are having dinner.' 现在进行时 be 动词用 are。]"
},
{
id: 12,
type: "fill",
question: "[translate:你有钢笔吗?] ____ you have a pen?",
options: ["Do", "Does", "Is", "Are"],
answer: 0,
explanation: "[translate:一般疑问句主语 you 时用 Do。Do you have a pen?。]"
},
{
id: 13,
type: "fill",
question: "It's ____ the morning.",
options: ["at", "on", "in", "to"],
answer: 2,
explanation: "[translate:in the morning 固定搭配。]"
},
{
id: 14,
type: "fill",
question: "There ____ a dog and two cats.",
options: ["is", "are", "have", "has"],
answer: 0,
explanation: "[translate:There be 句型,主语最前面用 is。]"
},
{
id: 15,
type: "fill",
question: "How ____ you?",
options: ["are", "is", "do", "be"],
answer: 0,
explanation: "[translate:问候句型 How are you?。]"
},
{
id: 16,
type: "fill",
question: "The bridge is ____ the river.",
options: ["in", "on", "above", "under"],
answer: 2,
explanation: "[translate:桥在河的上方用 above。]"
},
{
id: 17,
type: "fill",
question: "Could you ____ me money?",
options: ["please give", "to give", "gives", "giving"],
answer: 0,
explanation: "[translate:请求中使用 Could you please give me...?。]"
},
{
id: 18,
type: "fill",
question: "[translate:这是谁的书?] Whose ____ this book?",
options: ["is", "are", "do", "does"],
answer: 0,
explanation: "[translate:Whose is this book?。]"
},
{
id: 19,
type: "fill",
question: "She ____ a teacher.",
options: ["am", "is", "are", "be"],
answer: 1,
explanation: "[translate:She 用 is。She is a teacher。]"
},
{
id: 20,
type: "fill",
question: "[translate:他们是学生。] They ____ students.",
options: ["are", "is", "am", "be"],
answer: 0,
explanation: "[translate:They 用 are。They are students。]"
},
// 配对题
{
id: 21,
type: "match",
question: "[translate:将问候语和正确回应配对]",
parts: [
{q: "How are you?", aidx: 0},
{q: "How old are you?", aidx: 1},
{q: "Where are you from?", aidx: 2},
{q: "What time is it?", aidx: 3}
],
pairs: [
"I'm fine.",
"I'm ten.",
"I'm from China.",
"It's 7 o'clock."
],
explanation: "[translate:常用问候与回应的配对练习,对应句应这样匹配。]"
},
{
id: 22,
type: "match",
question: "[translate:将问句和合适回应配对]",
parts: [
{q: "What's your name?", aidx: 0},
{q: "How's the weather?", aidx: 1},
{q: "Where is your book?", aidx: 2},
{q: "Do you like apples?", aidx: 3}
],
pairs: [
"My name is Tom.",
"It's sunny.",
"It's on the desk.",
"Yes, I do."
],
explanation: "[translate:问句与常见回应配对:如 'What's your name?' -> 'My name is Tom.'。]"
},
{
id: 23,
type: "match",
question: "[translate:请将下列问题与回答配对]",
parts: [
{q: "Can you play soccer?", aidx: 0},
{q: "Where do you live?", aidx: 1},
{q: "What do you want?", aidx: 2},
{q: "Is this your pencil?", aidx: 3}
],
pairs: [
"Yes, I can.",
"In Beijing.",
"An apple.",
"Yes, it is."
],
explanation: "[translate:动词 can/is/do 等不同问句的回应搭配。]"
},
// 更多题(单选/填空题)
{
id: 24,
type: "mc",
question: "Choose the right answer: [translate:你多大了?]",
options: ["I'm fine.", "I'm ten.", "No, I don't.", "Yes, I do."],
answer: 1,
explanation: "[translate:问年龄应答 I'm ten.。]"
},
{
id: 25,
type: "fill",
question: "[translate:我们有一些糖果。] We ____ some candies.",
options: ["have", "has", "are", "is"],
answer: 0,
explanation: "[translate:主语为 we,复数用 have。We have some candies。]"
},
{
id: 26,
type: "mc",
question: "What does 'sunny' mean? [translate:'sunny' 是什么意思?]",
options: ["下雨的", "晴朗的", "阴天的", "多云的"],
answer: 1,
explanation: "[translate:'sunny' 表示晴朗的。]"
},
{
id: 27,
type: "fill",
question: "[translate:今天天气晴朗。] It's ____ today.",
options: ["rainy", "snowy", "sunny", "windy"],
answer: 2,
explanation: "[translate:晴朗用 sunny。]"
},
{
id: 28,
type: "mc",
question: "Which is correct? [translate:哪个表达正确?]",
options: ["I'm a students.", "I'm a student.", "I a student.", "I student."],
answer: 1,
explanation: "[translate:正确表达为 I'm a student。]"
},
{
id: 29,
type: "fill",
question: "The book is ____ the table.",
options: ["on", "in", "at", "of"],
answer: 0,
explanation: "[translate:表示“在桌子上”用 on。]"
},
{
id: 30,
type: "fill",
question: "[translate:我们现在在家。] We are ____ home now.",
options: ["at", "to", "on", "in"],
answer: 0,
explanation: "[translate:at home 固定搭配。]"
},
{
id: 31,
type: "mc",
question: "Which is the plural form? [translate:哪个是复数形式?]",
options: ["apple", "apples", "a apple", "is apple"],
answer: 1,
explanation: "[translate:apples 是 apple 的复数形式。]"
},
{
id: 32,
type: "fill",
question: "We ____ from China.",
options: ["am", "are", "is", "has"],
answer: 1,
explanation: "[translate:We 用 are。]"
},
{
id: 33,
type: "mc",
question: "Select the right question: [translate:你叫什么名字?]",
options: ["What's your name?", "Where is your name?", "Who you are?", "How old are you?"],
answer: 0,
explanation: "[translate:询问姓名用 What's your name?。]"
},
{
id: 34,
type: "fill",
question: "[translate:我喜欢苹果。] I ____ apples.",
options: ["like", "likes", "am like", "am likes"],
answer: 0,
explanation: "[translate:主语 I 用 like。I like apples。]"
}
];
// Fisher-Yates shuffle for options
function shuffle(arr) {
let a = arr.slice();
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
function renderQuiz() {
const container = document.getElementById('quiz');
data.forEach((q, idx) => {
let html = '';
// 卡片
html += `<div class="bg-white rounded-lg shadow p-4 flex flex-col" id="q${q.id}">
<div class="flex items-center mb-2">
<span class="font-bold text-blue-600 mr-2">第${idx + 1}题</span>
<span class="text-gray-700 flex-1">${q.question.replace(/\[translate:([^]+?)\]/g, '$1')}</span>
</div>`;
if(q.type === "mc" || q.type === "fill") {
let opts = shuffle(q.options.map((o, i) => ({ i, txt: o })));
html += `<div class="space-y-2 mt-2">`;
opts.forEach(opt => {
html += `
<label class="flex items-center space-x-2">
<input type="radio" name="ans${q.id}" value="${opt.i}" class="form-radio text-blue-500" />
<span>${opt.txt}</span>
</label>`;
});
html += `</div>`;
}
if(q.type === "match") {
// Match题需动态配对
html += `<div class="grid grid-cols-1 md:grid-cols-2 gap-2 mt-2">`;
q.parts.forEach((part, i) => {
html += `
<div>
<span>${part.q}</span>
<select class="border rounded ml-2 px-2 py-1" id="match${q.id}_${i}">
<option value="">请选择</option>
${q.pairs.map((t, j) => `<option value="${j}">${t}</option>`).join("")}
</select>
</div>`;
});
html += `</div>`;
}
html += `
<button class="bg-blue-500 text-white rounded px-4 py-1 mt-4 hover:bg-blue-600 transition" onclick="checkAns(${q.id})">查看正解</button>
<div class="mt-2 hidden" id="exp${q.id}">
<div class="text-green-700 font-semibold">正确答案:</div>
<div>
${
q.type === "match" ?
q.parts.map((p, j) => {
return `${q.parts[j].q} → ${q.pairs[q.parts[j].aidx]}<br/>`;
}).join("")
: q.options
? `${q.options[q.answer]}`
: ""
}
</div>
<div class="mt-2 text-sm text-gray-700">${q.explanation.replace(/\[translate:([^]+?)\]/g, '$1')}</div>
<button class="text-blue-600 mt-2 underline text-sm" onclick="readAloud('${q.type==='match'
? (q.parts.map((p, j)=>q.pairs[q.parts[j].aidx]).join('; ')).replace(/'/g,"\\'")
: (q.options ? q.options[q.answer]: '').replace(/'/g,"\\'")}')">语音朗读答案</button>
</div>
</div>`;
container.insertAdjacentHTML('beforeend', html);
});
}
function checkAns(qid) {
const q = data.find(x => x.id === qid);
let correct = false;
if(q.type === "mc" || q.type === "fill") {
const radios = document.getElementsByName('ans'+qid);
let val = -1;
radios.forEach(r => { if(r.checked) val = parseInt(r.value); });
correct = val === q.answer;
}
else if(q.type === "match") {
correct = true;
for(let i=0;i<q.parts.length;i++){
const sel = document.getElementById(`match${qid}_${i}`);
if(parseInt(sel.value) !== q.parts[i].aidx) correct = false;
}
}
const exp = document.getElementById('exp'+qid);
exp.classList.remove('hidden');
exp.classList.add(correct ? 'border-green-400' : 'border-red-400');
}
function readAloud(text) {
if (!window.speechSynthesis) {
alert('设备不支持语音朗读');
return;
}
const utter = new window.SpeechSynthesisUtterance(text);
utter.lang = 'en-US';
window.speechSynthesis.speak(utter);
}
window.onload = renderQuiz;
</script>
</body>
</html>