<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>高中生物：细胞结构 连线小游戏</title>
<style>
*{box-sizing:border-box;font-family:"Microsoft Yahei",sans-serif;}
body{background:#f0f8ff;padding:20px;margin:0;}
h1{text-align:center;color:#2c5c97;}
.box{max-width:1000px;margin:0 auto;background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 10px #0002;}
.game-wrap{display:flex;justify-content:space-between;margin-top:30px;position:relative;min-height:420px;}
.col{width:35%;}
.item{padding:14px;background:#e6f2ff;margin:12px 0;border-radius:8px;cursor:pointer;border:2px solid transparent;transition:0.2s;}
.item:hover{background:#d0e6ff;}
.item.active{border:2px solid #2c5c97;background:#b8ddff;}
.item.right{background:#bcf2bc;border-color:#28a745;color:#085010;}
.item.wrong{background:#ffd6d6;border-color:#dc3545;color:#740c15;}
#canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;}
.btns{text-align:center;margin-top:20px;}
button{padding:10px 22px;font-size:16px;border:none;border-radius:6px;margin:0 8px;cursor:pointer;}
#check{background:#2c5c97;color:white;}
#reset{background:#6c757d;color:white;}
#result{text-align:center;font-size:20px;margin:16px;font-weight:bold;}
.info{background:#eef6ff;padding:12px;border-radius:8px;margin-bottom:15px;color:#204060;}
</style>
</head>
<body>
<div class="box">
  <h1>🧬 细胞结构 · 连线配对游戏</h1>
  <div class="info">
    游戏说明：点击左侧【结构名称】，再点击右侧【对应功能】进行配对；完成后点击「检查答案」。<br>
    知识点：高中生物 动植物细胞细胞器
  </div>
  <div id="result"></div>

  <div class="game-wrap">
    <canvas id="canvas"></canvas>
    <!-- 左栏：结构名称 -->
    <div class="col left-col">
      <div class="item" data-id="1">细胞膜</div>
      <div class="item" data-id="2">细胞核</div>
      <div class="item" data-id="3">线粒体</div>
      <div class="item" data-id="4">叶绿体</div>
      <div class="item" data-id="5">核糖体</div>
      <div class="item" data-id="6">内质网</div>
      <div class="item" data-id="7">高尔基体</div>
      <div class="item" data-id="8">液泡</div>
      <div class="item" data-id="9">溶酶体</div>
      <div class="item" data-id="10">中心体</div>
    </div>
    <!-- 右栏：功能（打乱顺序） -->
    <div class="col right-col">
      <div class="item" data-id="3">有氧呼吸主要场所，细胞动力车间</div>
      <div class="item" data-id="7">对蛋白质加工、分类、包装；植物形成细胞壁</div>
      <div class="item" data-id="1">控制物质进出细胞，选择透过性膜</div>
      <div class="item" data-id="4">光合作用场所，只存在植物绿色细胞</div>
      <div class="item" data-id="10">与动物/低等植物细胞有丝分裂有关</div>
      <div class="item" data-id="2">遗传信息库，细胞代谢和遗传控制中心</div>
      <div class="item" data-id="5">合成蛋白质的场所，无膜结构</div>
      <div class="item" data-id="8">植物细胞，内含细胞液，维持细胞形态</div>
      <div class="item" data-id="6">蛋白质合成加工、脂质合成车间</div>
      <div class="item" data-id="9">含多种水解酶，分解衰老细胞器</div>
    </div>
  </div>

  <div class="btns">
    <button id="check">✅ 检查答案</button>
    <button id="reset">🔄 重置游戏</button>
  </div>
</div>

<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const gameWrap = document.querySelector('.game-wrap');

// 配对标准答案
const answerMap = {
  1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,10:10
};

let selectedLeft = null;
let pairs = {}; // 保存配对 {leftId:rightId}
let leftItems = document.querySelectorAll('.left-col .item');
let rightItems = document.querySelectorAll('.right-col .item');

// 画布自适应
function resizeCanvas(){
  canvas.width = gameWrap.offsetWidth;
  canvas.height = gameWrap.offsetHeight;
  drawLines();
}
window.addEventListener('resize',resizeCanvas);

// 绘制连线
function drawLines(){
  ctx.clearRect(0,0,canvas.width,canvas.height);
  for(let lid in pairs){
    const rid = pairs[lid];
    const lDom = document.querySelector(`.left-col .item[data-id="${lid}"]`);
    const rDom = document.querySelector(`.right-col .item[data-id="${rid}"]`);
    if(!lDom || !rDom) continue;
    const lRect = lDom.getBoundingClientRect();
    const rRect = rDom.getBoundingClientRect();
    const wrapRect = gameWrap.getBoundingClientRect();
    const x1 = lRect.right - wrapRect.left;
    const y1 = lRect.top + lRect.height/2 - wrapRect.top;
    const x2 = rRect.left - wrapRect.left;
    const y2 = rRect.top + rRect.height/2 - wrapRect.top;

    ctx.beginPath();
    ctx.moveTo(x1,y1);
    ctx.lineTo(x2,y2);
    ctx.lineWidth=3;
    ctx.strokeStyle="#2c5c97";
    ctx.stroke();
  }
}

// 左侧点击
leftItems.forEach(item=>{
  item.onclick = ()=>{
    clearActive();
    selectedLeft = item.dataset.id;
    item.classList.add('active');
  }
})
// 右侧点击
rightItems.forEach(item=>{
  item.onclick = ()=>{
    if(!selectedLeft) return;
    // 如果这个右边已经被配对，先删掉旧配对
    for(let k in pairs){
      if(pairs[k] === item.dataset.id) delete pairs[k];
    }
    pairs[selectedLeft] = item.dataset.id;
    clearActive();
    selectedLeft=null;
    drawLines();
  }
})

function clearActive(){
  document.querySelectorAll('.item').forEach(i=>i.classList.remove('active'));
}

// 检查答案
document.getElementById('check').onclick = function(){
  let score=0, total=Object.keys(answerMap).length;
  document.querySelectorAll('.item').forEach(i=>i.classList.remove('right','wrong'));

  for(let lid in pairs){
    const rid = pairs[lid];
    const lDom = document.querySelector(`.left-col .item[data-id="${lid}"]`);
    const rDom = document.querySelector(`.right-col .item[data-id="${rid}"]`);
    if(answerMap[lid]==rid){
      score++;
      lDom.classList.add('right');
      rDom.classList.add('right');
    }else{
      lDom.classList.add('wrong');
      rDom.classList.add('wrong');
    }
  }
  document.getElementById('result').innerText = `得分：${score}/${total} ${score===total?"🎉全部答对！":"继续加油！"}`;
}

// 重置
document.getElementById('reset').onclick = function(){
  pairs={};
  selectedLeft=null;
  document.querySelectorAll('.item').forEach(i=>i.classList.remove('active','right','wrong'));
  ctx.clearRect(0,0,canvas.width,canvas.height);
  document.getElementById('result').innerText="";
}

resizeCanvas();
</script>
</body>
</html>