乐于分享
好东西不私藏

利用AI生成网页——以分离定律为例

利用AI生成网页——以分离定律为例
界面:
演示效果
已关注
关注
重播 分享
我用的是deepseek,本来是想让它生成分离定律中等位基因分离的动态过程,但是效果一直不好,可能需要用擅长生成图片、动画的AI软件会好些,懒得去弄了,直接让deepseek模拟后代情况。
生成过程:先赋予专业身份,让它分析什么是分离定律,实质是什么,然后再根据以上分析让它生成网页代码模拟单杂合子自交的结果。要写清楚里面要有哪一些控件,功能是什么,再根据它生成的网页提出意见,反复修改。多修改几次就得到这个了。对效果满意的话,可以直接复制到记事本当中,并把txt后缀改成html,双击就可以运行了,就算在没有网络的教室也可以打开。
这个网页当中设置了后代个数默认800,也可以手动输入,设置了保存每一次生成的记录,方便后续查看数据,设置了各基因型、显隐性的统计方便看出1:2:1或者3:1,最后设置了重置键,可以一键归零,从头开始。
代码由AI生成,具体如下:

<!DOCTYPE html>

<html lang="zh">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>分离定律 · 多轮模拟记录</title>

    <style>

        * {

            box-sizing: border-box;

            font-family: system-ui, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;

        }

        body {

            background: linear-gradient(145deg, #f0f7e8 0%, #e1efe0 100%);

            min-height: 100vh;

            margin: 0;

            display: flex;

            justify-content: center;

            align-items: center;

            padding: 16px;

        }

        .card {

            max-width: 1100px;

            width: 100%;

            background: rgba(255, 255, 255, 0.85);

            backdrop-filter: blur(6px);

            background-color: #fefefee0;

            border-radius: 42px;

            box-shadow: 0 25px 40px -12px rgba(40, 70, 40, 0.4), inset 0 1px 3px #ffffffcc;

            padding: 30px 30px 40px;

            border: 1px solid #d0e0c0;

        }

        h1 {

            margin: 0 0 8px 0;

            font-weight: 600;

            font-size: 2.2rem;

            color: #1f4f2b;

            display: flex;

            align-items: center;

            gap: 12px;

            flex-wrap: wrap;

        }

        h1 small {

            font-size: 1rem;

            font-weight: 400;

            background: #d4e6cf;

            color: #1f4f2b;

            padding: 6px 15px;

            border-radius: 40px;

        }

        .subhead {

            color: #2d5a3a;

            border-left: 6px solid #76b583;

            padding-left: 20px;

            margin: 8px 0 25px 0;

            font-size: 1.1rem;

            font-weight: 350;

            background: #ecf6e9;

            border-radius: 0 40px 40px 0;

            line-height: 1.6;

            width: fit-content;

            padding: 12px 25px;

        }

        .law-badge {

            background: #2d5a3a;

            color: #f9fff5;

            padding: 4px 18px;

            border-radius: 28px;

            font-weight: 500;

            font-size: 0.85rem;

            display: inline-block;

            margin-bottom: 20px;

            letter-spacing: 0.5px;

        }

        .parents-panel {

            background: #e5f0df;

            border-radius: 36px;

            padding: 22px 28px;

            margin-bottom: 30px;

            display: flex;

            flex-wrap: wrap;

            justify-content: space-around;

            align-items: center;

            box-shadow: inset 0 2px 5px #b5c9ac, 0 10px 15px -8px #8faa84;

        }

        .parent {

            text-align: center;

            min-width: 150px;

        }

        .parent .genotype {

            font-size: 2.4rem;

            font-weight: 700;

            background: #ffffffc9;

            display: inline-block;

            padding: 10px 30px;

            border-radius: 60px;

            box-shadow: 0 6px 0 #8ba381;

            color: #17331e;

            letter-spacing: 4px;

            border: 2px solid #afc8a5;

            margin: 10px 0 5px;

        }

        .parent .label {

            font-weight: 600;

            color: #1f4f2b;

            background: #cbe3c2;

            padding: 6px 18px;

            border-radius: 30px;

            font-size: 1rem;

            display: inline-block;

        }

        /* 减数分裂可视化区域 */

        .meiosis-process {

            background: #e0efd8;

            border-radius: 50px;

            padding: 25px 25px 20px;

            margin: 15px 0 30px;

            box-shadow: inset 0 1px 8px #b0cdae, 0 10px 12px -8px #6e8f66;

        }

        .meiosis-title {

            font-weight: 600;

            color: #1f4f2b;

            font-size: 1.25rem;

            margin: 0 0 20px 10px;

            display: flex;

            align-items: center;

            gap: 10px;

        }

        .meiosis-title span {

            background: #3b6e49;

            color: white;

            padding: 5px 15px;

            border-radius: 30px;

            font-size: 0.9rem;

        }

        .split-panel {

            display: flex;

            justify-content: space-around;

            flex-wrap: wrap;

            gap: 25px;

        }

        .parent-meiosis {

            flex: 1 1 250px;

            background: #f1faecc0;

            border-radius: 40px;

            padding: 15px 15px 20px;

            border: 3px solid #c1ddb5;

            box-shadow: 0 4px 0 #8bb17e;

        }

        .parent-meiosis .parent-title {

            font-size: 1.3rem;

            font-weight: 600;

            color: #1f4f2b;

            text-align: center;

            background: #d0e7c4;

            border-radius: 30px;

            padding: 8px;

            margin-top: -5px;

        }

        .somatic-cell {

            display: flex;

            justify-content: center;

            align-items: center;

            gap: 5px;

            margin: 18px 0 5px;

        }

        .chromosome-pair {

            background: #fff5d9;

            border-radius: 40px;

            padding: 12px 25px;

            border: 3px solid #b5945a;

            display: inline-flex;

            gap: 20px;

            box-shadow: 0 4px 0 #9e7f48;

        }

        .chromosome {

            font-size: 2.2rem;

            font-weight: 700;

            background: #ffffff;

            width: 70px;

            height: 70px;

            display: flex;

            align-items: center;

            justify-content: center;

            border-radius: 50%;

            border: 3px solid #6d8c60;

            color: #1b4b1b;

            box-shadow: 0 3px 0 #4a6940;

        }

        .arrow-down {

            font-size: 2rem;

            color: #527a4c;

            margin: 5px 0;

            text-align: center;

        }

        .gametes-result {

            display: flex;

            justify-content: center;

            gap: 35px;

            margin: 10px 0 5px;

        }

        .gamete-item {

            text-align: center;

        }

        .gamete-circle {

            width: 65px;

            height: 65px;

            background: #ffffff;

            border-radius: 50%;

            display: flex;

            align-items: center;

            justify-content: center;

            font-size: 2rem;

            font-weight: 700;

            border: 3px solid #3f6645;

            box-shadow: 0 5px 0 #2b4d2b;

            color: #1d4f1d;

            margin-bottom: 6px;

        }

        .gamete-label {

            background: #2d5a3a;

            color: white;

            padding: 4px 12px;

            border-radius: 30px;

            font-size: 0.9rem;

            font-weight: 500;

        }

        .process-note {

            text-align: center;

            color: #2d5a3a;

            font-weight: 500;

            margin-top: 20px;

            background: #c6e0bb;

            padding: 10px;

            border-radius: 40px;

            font-size: 1rem;

        }

        .process-note i {

            font-style: normal;

            background: #f9fff5;

            padding: 3px 10px;

            border-radius: 30px;

            margin: 0 4px;

        }

        .control-area {

            background: #ffffffd6;

            border-radius: 60px;

            padding: 18px 30px;

            margin: 25px 0 30px;

            display: flex;

            flex-wrap: wrap;

            align-items: center;

            justify-content: center;

            gap: 25px;

            border: 2px dashed #98b38b;

        }

        .input-group {

            display: flex;

            align-items: center;

            gap: 12px;

            background: #ecf6e9;

            padding: 8px 20px;

            border-radius: 40px;

        }

        .input-group label {

            font-weight: 600;

            color: #1f4f2b;

        }

        .input-group input {

            width: 100px;

            padding: 10px 15px;

            border: 2px solid #b1cfaa;

            border-radius: 40px;

            font-size: 1.1rem;

            font-weight: 600;

            text-align: center;

            background: white;

            outline: none;

            transition: 0.2s;

        }

        .input-group input:focus {

            border-color: #2f7d4a;

            box-shadow: 0 0 0 3px #b3dfb3;

        }

        .simulate-btn {

            background: #2b7342;

            border: none;

            color: white;

            font-size: 1.5rem;

            font-weight: 600;

            padding: 16px 45px;

            border-radius: 60px;

            cursor: pointer;

            box-shadow: 0 10px 0 #124d24, 0 6px 18px #1d512d80;

            transition: 0.07s linear;

            border: 2px solid #9fcc9a;

            letter-spacing: 1px;

            display: inline-flex;

            align-items: center;

            gap: 8px;

        }

        .simulate-btn:active {

            transform: translateY(7px);

            box-shadow: 0 3px 0 #124d24, 0 6px 18px #1d512d80;

        }

        .reset-btn {

            background: #b0b0b0;

            border: none;

            color: white;

            font-size: 1.3rem;

            font-weight: 600;

            padding: 12px 30px;

            border-radius: 60px;

            cursor: pointer;

            box-shadow: 0 6px 0 #6e6e6e, 0 6px 18px #5d5d5d80;

            transition: 0.07s linear;

            border: 2px solid #d0d0d0;

            display: inline-flex;

            align-items: center;

            gap: 6px;

        }

        .reset-btn:active {

            transform: translateY(4px);

            box-shadow: 0 2px 0 #6e6e6e, 0 6px 18px #5d5d5d80;

        }

        .results {

            background: #f6fff0;

            border-radius: 40px;

            padding: 20px 20px 30px;

            border: 3px solid #bfdbaf;

        }

        .results h3 {

            color: #1d4f2a;

            margin: 0 0 8px 20px;

            font-size: 1.6rem;

            font-weight: 500;

        }

        .barchart-container {

            display: flex;

            justify-content: space-around;

            align-items: flex-end;

            gap: 30px;

            padding: 20px 10px;

            min-height: 250px;

        }

        .bar-item {

            flex: 1;

            display: flex;

            flex-direction: column;

            align-items: center;

            text-align: center;

            max-width: 150px;

        }

        .bar-label {

            font-weight: 700;

            font-size: 1.4rem;

            margin-top: 10px;

            background: #ddecd4;

            width: 100%;

            padding: 8px 0;

            border-radius: 40px;

            color: #17331e;

        }

        .bar-outer {

            height: 200px;

            width: 100%;

            display: flex;

            flex-direction: column-reverse;

            border-radius: 30px 30px 15px 15px;

            background: #e3eedb;

            border: 3px solid #a0bb95;

            overflow: hidden;

            margin-bottom: 8px;

            box-shadow: inset 0 2px 6px #8f8f8f33;

        }

        .bar-inner {

            width: 100%;

            transition: height 0.3s ease;

            border-radius: 12px 12px 0 0;

        }

        .bar-inner.AA { background: #5fa7d1; }

        .bar-inner.Aa { background: #6fbf73; }

        .bar-inner.aa { background: #e8a35e; }

        .count-info {

            font-size: 1.1rem;

            font-weight: 600;

            color: #1e3d24;

            margin-top: 5px;

        }

        .percent-info {

            font-size: 1rem;

            background: #d0e0c0;

            padding: 3px 15px;

            border-radius: 50px;

            color: #1b4f1b;

            font-weight: 600;

            margin-top: 5px;

        }

        .phenotype-row {

            display: flex;

            justify-content: space-around;

            margin: 25px 10px 10px;

            background: #deedd4;

            border-radius: 100px;

            padding: 18px 20px;

        }

        .phenotype-block {

            display: flex;

            align-items: center;

            gap: 18px;

            flex-wrap: wrap;

            justify-content: center;

        }

        .phenotype-dot {

            width: 32px;

            height: 32px;

            border-radius: 50%;

            background: #d9b650;

        }

        .phenotype-dot.dominant { background: #5180b0; }

        .phenotype-dot.recessive { background: #c07a4a; }

        .phenotype-value {

            font-size: 1.5rem;

            font-weight: 700;

            color: #1e3f1e;

        }

        /* 新增:历史记录表格(多轮模拟总体结果) */

        .history-area {

            margin-top: 30px;

            background: #eaf3e3;

            border-radius: 40px;

            padding: 18px 20px;

            border: 3px solid #b1cfaa;

        }

        .history-header {

            display: flex;

            justify-content: space-between;

            align-items: center;

            margin-bottom: 15px;

            flex-wrap: wrap;

            gap: 15px;

        }

        .history-header h4 {

            margin: 0;

            font-size: 1.4rem;

            color: #1f4f2b;

            font-weight: 600;

        }

        .history-table-wrapper {

            max-height: 250px;

            overflow-y: auto;

            border-radius: 30px;

            background: #ffffffc9;

            padding: 5px;

            box-shadow: inset 0 2px 6px #bacdb0;

        }

        table {

            width: 100%;

            border-collapse: collapse;

            text-align: center;

            font-size: 0.95rem;

        }

        th {

            background: #2d5a3a;

            color: white;

            padding: 12px 5px;

            font-weight: 500;

            position: sticky;

            top: 0;

        }

        td {

            padding: 10px 5px;

            border-bottom: 1px solid #c8ddbc;

        }

        .history-note {

            margin-top: 10px;

            font-size: 0.95rem;

            color: #3b6e49;

            text-align: center;

        }

        .footnote {

            margin-top: 20px;

            text-align: center;

            color: #406d48;

            font-style: italic;

            font-weight: 500;

            background: #dcedd1;

            padding: 12px;

            border-radius: 60px;

        }

        hr {

            border: 2px solid #c0dbc0;

            border-radius: 5px;

            margin: 25px 0 15px;

        }

        .button-group {

            display: flex;

            gap: 20px;

            flex-wrap: wrap;

            justify-content: center;

        }

    </style>

</head>

<body>

<div class="card">

    <h1>

        🌱 分离定律 · 多轮模拟记录

        <small>Aa × Aa</small>

    </h1>

    <div class="subhead">

        ⚡ 体细胞中成对基因(Aa)在减数分裂时分离 → 配子只含一个等位基因(A或a) → 受精随机结合

    </div>

    <!-- 亲本展示(体细胞) -->

    <div class="parents-panel">

        <div class="parent">

            <span class="label">父本体细胞 ♂</span>

            <div class="genotype">Aa</div>

        </div>

        <div style="font-size: 3rem; color: #3b6e49;">⨯</div>

        <div class="parent">

            <span class="label">母本体细胞 ♀</span>

            <div class="genotype">Aa</div>

        </div>

    </div>

    <!-- 减数分裂过程(体细胞→配子) -->

    <div class="meiosis-process">

        <div class="meiosis-title">

            🧬 减数分裂 · 等位基因分离

            <span>同源染色体分开</span>

        </div>

        <div class="split-panel">

            <!-- 父本减数分裂 -->

            <div class="parent-meiosis">

                <div class="parent-title">父本 ♂ 减数分裂</div>

                <div class="somatic-cell">

                    <div class="chromosome-pair">

                        <div class="chromosome">A</div>

                        <div class="chromosome">a</div>

                    </div>

                </div>

                <div class="arrow-down">⬇ 分离 ⬇</div>

                <div class="gametes-result">

                    <div class="gamete-item">

                        <div class="gamete-circle">A</div>

                        <div class="gamete-label">配子 50%</div>

                    </div>

                    <div class="gamete-item">

                        <div class="gamete-circle">a</div>

                        <div class="gamete-label">配子 50%</div>

                    </div>

                </div>

            </div>

            <!-- 母本减数分裂 -->

            <div class="parent-meiosis">

                <div class="parent-title">母本 ♀ 减数分裂</div>

                <div class="somatic-cell">

                    <div class="chromosome-pair">

                        <div class="chromosome">A</div>

                        <div class="chromosome">a</div>

                    </div>

                </div>

                <div class="arrow-down">⬇ 分离 ⬇</div>

                <div class="gametes-result">

                    <div class="gamete-item">

                        <div class="gamete-circle">A</div>

                        <div class="gamete-label">配子 50%</div>

                    </div>

                    <div class="gamete-item">

                        <div class="gamete-circle">a</div>

                        <div class="gamete-label">配子 50%</div>

                    </div>

                </div>

            </div>

        </div>

        <div class="process-note">

            <i>等位基因随同源染色体分离而分开</i> → 每个配子获得一个等位基因(A 或 a),概率相等

        </div>

    </div>

    <!-- 控制区域:模拟受精 + 重置 -->

    <div class="control-area">

        <div class="input-group">

            <label for="offspringCount">🌱 每轮子代数量</label>

            <input type="number" id="offspringCount" min="10" max="10000" value="800" step="10">

        </div>

        <div class="button-group">

            <button class="simulate-btn" id="simulateBtn">

                <span>▶</span> 开始一轮模拟

            </button>

            <button class="reset-btn" id="resetBtn">

                <span>⟲</span> 重置所有记录

            </button>

        </div>

    </div>

    <!-- 当前结果图表 -->

    <div class="results">

        <h3>📊 本轮子代基因型分布</h3>

        <div class="barchart-container" id="barContainer">

            <div class="bar-item">

                <div class="bar-outer" id="barAAOuter">

                    <div class="bar-inner AA" id="barAA" style="height: 0%;"></div>

                </div>

                <div class="bar-label">AA</div>

                <div class="count-info" id="countAA">0</div>

                <div class="percent-info" id="percAA">0.0%</div>

            </div>

            <div class="bar-item">

                <div class="bar-outer" id="barAaOuter">

                    <div class="bar-inner Aa" id="barAa" style="height: 0%;"></div>

                </div>

                <div class="bar-label">Aa</div>

                <div class="count-info" id="countAa">0</div>

                <div class="percent-info" id="percAa">0.0%</div>

            </div>

            <div class="bar-item">

                <div class="bar-outer" id="baRaaOuter">

                    <div class="bar-inner aa" id="barAa_aa" style="height: 0%;"></div>

                </div>

                <div class="bar-label">aa</div>

                <div class="count-info" id="countaa">0</div>

                <div class="percent-info" id="percaa">0.0%</div>

            </div>

        </div>

        <!-- 表现型总结 -->

        <div class="phenotype-row">

            <div class="phenotype-block">

                <span class="phenotype-dot dominant"></span>

                <span style="font-weight:600;">高茎 (显性 A_ ) :</span>

                <span class="phenotype-value" id="dominantCount">0</span>

                <span style="font-size:1.2rem;font-weight:500;" id="dominantPerc">(0.0%)</span>

            </div>

            <div class="phenotype-block">

                <span class="phenotype-dot recessive"></span>

                <span style="font-weight:600;">矮茎 (隐性 aa) :</span>

                <span class="phenotype-value" id="recessiveCount">0</span>

                <span style="font-size:1.2rem;font-weight:500;" id="recessivePerc">(0.0%)</span>

            </div>

        </div>

    </div>

    <!-- 新增:多轮模拟历史记录 -->

    <div class="history-area">

        <div class="history-header">

            <h4>📋 历次模拟总体结果</h4>

            <span style="font-size:0.9rem; color:#2d5a3a;">每次点击“开始一轮模拟”都会新增一行记录</span>

        </div>

        <div class="history-table-wrapper">

            <table id="historyTable">

                <thead>

                    <tr>

                        <th>轮次</th>

                        <th>样本量(N)</th>

                        <th>AA</th>

                        <th>Aa</th>

                        <th>aa</th>

                        <th>AA%</th>

                        <th>Aa%</th>

                        <th>aa%</th>

                        <th>显性%</th>

                    </tr>

                </thead>

                <tbody id="historyBody">

                    <!-- 动态生成 -->

                </tbody>

            </table>

        </div>

        <div class="history-note" id="historyNote">暂无历史记录,点击按钮开始模拟</div>

    </div>

    <hr>

    <div style="text-align: right; color: #3f6b48; padding-right: 10px;">

        <span class="law-badge">分离定律 · 孟德尔第一定律</span>

    </div>

</div>

<script>

    (function() {

        // DOM 元素

        const simulateBtn = document.getElementById('simulateBtn');

        const resetBtn = document.getElementById('resetBtn');

        const countInput = document.getElementById('offspringCount');

        // 当前统计显示

        const countAA = document.getElementById('countAA');

        const countAa = document.getElementById('countAa');

        const countaa = document.getElementById('countaa');

        const percAA = document.getElementById('percAA');

        const percAa = document.getElementById('percAa');

        const percaa = document.getElementById('percaa');

        // 柱状图

        const barAA = document.getElementById('barAA');

        const barAa = document.getElementById('barAa');

        const baraa = document.getElementById('barAa_aa');

        // 表现型

        const dominantCountSpan = document.getElementById('dominantCount');

        const recessiveCountSpan = document.getElementById('recessiveCount');

        const dominantPercSpan = document.getElementById('dominantPerc');

        const recessivePercSpan = document.getElementById('recessivePerc');

        // 历史记录表格

        const historyBody = document.getElementById('historyBody');

        const historyNote = document.getElementById('historyNote');

        // 存储历史数据,每个元素包含轮次、总数、AA、Aa、aa

        let historyData = [];

        let roundCounter = 0; // 记录模拟轮次

        // 更新当前统计和柱状图

        function updateCurrentResults(counts) {

            const { AA, Aa, aa } = counts;

            const total = AA + Aa + aa;

            if (total === 0) {

                barAA.style.height = '0%';

                barAa.style.height = '0%';

                baraa.style.height = '0%';

                countAA.innerText = '0';

                countAa.innerText = '0';

                countaa.innerText = '0';

                percAA.innerText = '0.0%';

                percAa.innerText = '0.0%';

                percaa.innerText = '0.0%';

                dominantCountSpan.innerText = '0';

                recessiveCountSpan.innerText = '0';

                dominantPercSpan.innerText = '(0.0%)';

                recessivePercSpan.innerText = '(0.0%)';

                return;

            }

            const percAAVal = (AA / total * 100).toFixed(1);

            const percAaVal = (Aa / total * 100).toFixed(1);

            const percaaVal = (aa / total * 100).toFixed(1);

            barAA.style.height = percAAVal + '%';

            barAa.style.height = percAaVal + '%';

            baraa.style.height = percaaVal + '%';

            countAA.innerText = AA;

            countAa.innerText = Aa;

            countaa.innerText = aa;

            percAA.innerText = percAAVal + '%';

            percAa.innerText = percAaVal + '%';

            percaa.innerText = percaaVal + '%';

            const dominant = AA + Aa;

            const recessive = aa;

            const percDom = (dominant / total * 100).toFixed(1);

            const percRec = (recessive / total * 100).toFixed(1);

            dominantCountSpan.innerText = dominant;

            recessiveCountSpan.innerText = recessive;

            dominantPercSpan.innerText = `(${percDom}%)`;

            recessivePercSpan.innerText = `(${percRec}%)`;

        }

        // 更新历史记录表格

        function updateHistoryTable() {

            historyBody.innerHTML = '';

            if (historyData.length === 0) {

                historyNote.style.display = 'block';

                return;

            }

            historyNote.style.display = 'none';

            // 按轮次正序显示(最新的在后面)

            historyData.forEach(rec => {

                const row = document.createElement('tr');

                // 轮次

                const tdRound = document.createElement('td'); tdRound.textContent = rec.round; row.appendChild(tdRound);

                // 样本量

                const tdN = document.createElement('td'); tdN.textContent = rec.total; row.appendChild(tdN);

                // AA, Aa, aa 数量

                const tdAA = document.createElement('td'); tdAA.textContent = rec.AA; row.appendChild(tdAA);

                const tdAa = document.createElement('td'); tdAa.textContent = rec.Aa; row.appendChild(tdAa);

                const tdaa = document.createElement('td'); tdaa.textContent = rec.aa; row.appendChild(tdaa);

                // 百分比 (保留1位小数)

                const percAA = (rec.AA / rec.total * 100).toFixed(1);

                const percAa = (rec.Aa / rec.total * 100).toFixed(1);

                const percaa = (rec.aa / rec.total * 100).toFixed(1);

                const percDom = ((rec.AA + rec.Aa) / rec.total * 100).toFixed(1);

                const tdPercAA = document.createElement('td'); tdPercAA.textContent = percAA + '%'; row.appendChild(tdPercAA);

                const tdPercAa = document.createElement('td'); tdPercAa.textContent = percAa + '%'; row.appendChild(tdPercAa);

                const tdPercaa = document.createElement('td'); tdPercaa.textContent = percaa + '%'; row.appendChild(tdPercaa);

                const tdPercDom = document.createElement('td'); tdPercDom.textContent = percDom + '%'; row.appendChild(tdPercDom);

                historyBody.appendChild(row);

            });

        }

        // 模拟一轮,返回 counts 对象

        function simulateRound(offspringCount) {

            let AA = 0, Aa = 0, aa = 0;

            for (let i = 0; i < offspringCount; i++) {

                const paternal = Math.random() < 0.5 ? 'A' : 'a';

                const maternal = Math.random() < 0.5 ? 'A' : 'a';

                if (paternal === 'A' && maternal === 'A') AA++;

                else if (paternal === 'a' && maternal === 'a') aa++;

                else Aa++;

            }

            return { AA, Aa, aa };

        }

        // 处理模拟按钮点击

        function onSimulate() {

            let number = parseInt(countInput.value, 10);

            if (isNaN(number) || number < 1) {

                number = 100;

                countInput.value = 100;

            } else if (number > 20000) {

                number = 20000;

                countInput.value = 20000;

            }

            const counts = simulateRound(number);

            // 更新当前图表

            updateCurrentResults(counts);

            // 添加到历史记录

            roundCounter++;

            const total = counts.AA + counts.Aa + counts.aa;

            historyData.push({

                round: roundCounter,

                total: total,

                AA: counts.AA,

                Aa: counts.Aa,

                aa: counts.aa

            });

            updateHistoryTable();

        }

        // 重置所有

        function resetAll() {

            // 清空当前图表

            updateCurrentResults({ AA: 0, Aa: 0, aa: 0 });

            // 清空历史数据

            historyData = [];

            roundCounter = 0;

            updateHistoryTable();

            // 输入框保留原值,不清空

        }

        // 绑定事件

        simulateBtn.addEventListener('click', onSimulate);

        resetBtn.addEventListener('click', resetAll);

        // 输入框回车触发模拟

        countInput.addEventListener('keypress', (e) => {

            if (e.key === 'Enter') {

                onSimulate();

            }

        });

        // 输入框失焦时校正

        countInput.addEventListener('blur', () => {

            let val = parseInt(countInput.value, 10);

            if (isNaN(val) || val < 1) {

                countInput.value = 100;

            } else if (val > 20000) {

                countInput.value = 20000;

            }

        });

        // 初始状态为空(不自动模拟)

        resetAll();

    })();

</script>

</body>

</html>