Files
cpp-courseware/2.Course/1.深入浅出程序设计竞赛(基础篇)/1.语言入门/第4章 循环结构程序设计/3.多重循环/content/C++ 嵌套循环单步可视化操作.html
T

277 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>C++ 嵌套循环单步可视化</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f4f7f6;
color: #333;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
display: flex;
gap: 20px;
background: white;
padding: 20px;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
width: 1000px; /* 稍微增加了总宽度 */
max-width: 95%;
}
/* 左侧代码区 */
.code-panel {
flex: 1.3; /* 给代码区分配更多空间 */
background: #1e1e1e;
color: #d4d4d4;
padding: 20px;
border-radius: 8px;
font-family: 'Courier New', Courier, monospace;
font-size: 16px;
line-height: 1.6;
overflow-x: auto; /* 内容超出时显示水平滚动条 */
}
.code-line {
padding: 2px 10px;
border-radius: 4px;
margin: 2px 0;
border-left: 4px solid transparent;
transition: all 0.3s;
white-space: pre; /* 关键修改:强制不换行,保持代码在一行显示 */
}
.code-line.active {
background-color: #063f4c;
border-left: 4px solid #4fc1ff;
color: #fff;
}
.keyword { color: #569cd6; }
.type { color: #4ec9b0; }
.string { color: #ce9178; }
/* 右侧面板 */
.side-panel {
flex: 1;
display: flex;
flex-direction: column;
gap: 15px;
}
/* 状态与控制台 */
.panel-box {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 15px;
flex: 1;
}
.panel-title {
font-size: 14px;
font-weight: bold;
color: #6c757d;
margin-bottom: 10px;
text-transform: uppercase;
letter-spacing: 1px;
}
.vars {
font-size: 24px;
font-family: monospace;
font-weight: bold;
}
.vars span {
color: #e83e8c;
background: #fdf3f7;
padding: 2px 8px;
border-radius: 4px;
}
.status-msg {
margin-top: 10px;
font-size: 14px;
color: #0056b3;
background: #cce5ff;
padding: 8px;
border-radius: 4px;
line-height: 1.5;
}
.console-output {
background: #000;
color: #0f0;
font-family: 'Courier New', Courier, monospace;
padding: 10px;
border-radius: 4px;
height: 120px;
white-space: pre-wrap;
overflow-y: auto;
}
/* 控制按钮 */
.controls {
display: flex;
gap: 10px;
justify-content: center;
margin-top: 10px;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
border: none;
border-radius: 6px;
font-weight: bold;
transition: 0.2s;
}
.btn-prev { background: #6c757d; color: white; }
.btn-prev:hover { background: #5a6268; }
.btn-next { background: #007bff; color: white; }
.btn-next:hover { background: #0056b3; }
.btn-reset { background: #dc3545; color: white; }
.btn-reset:hover { background: #c82333; }
button:disabled { background: #cccccc; cursor: not-allowed; }
</style>
</head>
<body>
<div class="container">
<!-- 代码区 -->
<div class="code-panel">
<div id="line-1" class="code-line"><span class="keyword">for</span> (<span class="type">int</span> i = 1; i <= 3; i++) {</div>
<div id="line-2" class="code-line"> <span class="keyword">for</span> (<span class="type">int</span> j = 1; j <= 2; j++) {</div>
<div id="line-3" class="code-line"> cout << <span class="string">"("</span> << i << <span class="string">", "</span> << j << <span class="string">") "</span>;</div>
<div id="line-4" class="code-line"> }</div>
<div id="line-5" class="code-line"> cout << endl;</div>
<div id="line-6" class="code-line">}</div>
</div>
<!-- 状态与控制区 -->
<div class="side-panel">
<div class="panel-box">
<div class="panel-title">内存中的变量状态</div>
<div class="vars">
i = <span id="var-i">?</span><br><br>
j = <span id="var-j">?</span>
</div>
<div class="status-msg" id="status-msg">点击“下一步”开始执行程序</div>
</div>
<div class="panel-box">
<div class="panel-title">控制台输出 (Console)</div>
<div class="console-output" id="console"></div>
</div>
<div class="controls">
<button class="btn-prev" id="btn-prev" onclick="prevStep()" disabled>上一步</button>
<button class="btn-next" id="btn-next" onclick="nextStep()">下一步</button>
<button class="btn-reset" onclick="reset()">重置</button>
</div>
</div>
</div>
<script>
// 预定义所有执行步骤的状态机
const steps = [
{ line: null, i: '?', j: '?', out: '', msg: '程序准备就绪,等待外层循环启动。' },
// i = 1
{ line: 1, i: 1, j: '?', out: '', msg: '进入外层循环。初始化 i = 1。' },
{ line: 2, i: 1, j: 1, out: '', msg: '外层触发内层!创建全新变量 j,初始化 j = 1。' },
{ line: 3, i: 1, j: 1, out: '(1, 1) ', msg: '打印当前 i 和 j 的值。' },
{ line: 4, i: 1, j: 1, out: '(1, 1) ', msg: '内层循环一轮结束,准备 j++ 回到行2判断。' },
{ line: 2, i: 1, j: 2, out: '(1, 1) ', msg: 'j 增加到 2,满足 j<=2,继续内层。' },
{ line: 3, i: 1, j: 2, out: '(1, 1) (1, 2) ', msg: '打印当前 i 和 j 的值。' },
{ line: 4, i: 1, j: 2, out: '(1, 1) (1, 2) ', msg: '内层循环一轮结束,准备 j++。' },
{ line: 2, i: 1, j: 3, out: '(1, 1) (1, 2) ', msg: 'j 增加到 3,不满足 j<=2,内层循环终止!' },
{ line: 5, i: 1, j: '销毁 (死亡)', out: '(1, 1) (1, 2) \n', msg: '退出内层大括号,j 被彻底销毁!执行换行。' },
{ line: 6, i: 1, j: '销毁 (死亡)', out: '(1, 1) (1, 2) \n', msg: '外层第一轮结束,准备 i++ 回到行1判断。' },
// i = 2
{ line: 1, i: 2, j: '销毁 (死亡)', out: '(1, 1) (1, 2) \n', msg: 'i 增加到 2,满足 i<=3,进入外层第二轮。' },
{ line: 2, i: 2, j: 1, out: '(1, 1) (1, 2) \n', msg: '再次遇到内层循环,重新孕育一个全新的 j = 1!' },
{ line: 3, i: 2, j: 1, out: '(1, 1) (1, 2) \n(2, 1) ', msg: '打印当前 i 和 j 的值。' },
{ line: 4, i: 2, j: 1, out: '(1, 1) (1, 2) \n(2, 1) ', msg: '内层循环一轮结束,准备 j++。' },
{ line: 2, i: 2, j: 2, out: '(1, 1) (1, 2) \n(2, 1) ', msg: 'j 增加到 2,满足 j<=2。' },
{ line: 3, i: 2, j: 2, out: '(1, 1) (1, 2) \n(2, 1) (2, 2) ', msg: '打印当前 i 和 j 的值。' },
{ line: 4, i: 2, j: 2, out: '(1, 1) (1, 2) \n(2, 1) (2, 2) ', msg: '内层循环一轮结束,准备 j++。' },
{ line: 2, i: 2, j: 3, out: '(1, 1) (1, 2) \n(2, 1) (2, 2) ', msg: 'j 增加到 3,不满足 j<=2,内层循环终止!' },
{ line: 5, i: 2, j: '销毁 (死亡)', out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n', msg: '退出内层,j 再次被彻底销毁!执行换行。' },
{ line: 6, i: 2, j: '销毁 (死亡)', out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n', msg: '外层第二轮结束,准备 i++ 回到行1判断。' },
// i = 3
{ line: 1, i: 3, j: '销毁 (死亡)', out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n', msg: 'i 增加到 3,满足 i<=3,进入外层最后一轮。' },
{ line: 2, i: 3, j: 1, out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n', msg: '第三次触发内层循环,重新初始化新 j = 1。' },
{ line: 3, i: 3, j: 1, out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n(3, 1) ', msg: '打印当前 i 和 j 的值。' },
{ line: 4, i: 3, j: 1, out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n(3, 1) ', msg: '内层循环一轮结束。' },
{ line: 2, i: 3, j: 2, out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n(3, 1) ', msg: 'j 增加到 2,满足 j<=2。' },
{ line: 3, i: 3, j: 2, out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n(3, 1) (3, 2) ', msg: '打印最后的值。' },
{ line: 4, i: 3, j: 2, out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n(3, 1) (3, 2) ', msg: '内层循环一轮结束。' },
{ line: 2, i: 3, j: 3, out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n(3, 1) (3, 2) ', msg: 'j 增加到 3,内层循环最后一次终止!' },
{ line: 5, i: 3, j: '销毁 (死亡)', out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n(3, 1) (3, 2) \n', msg: 'j 被销毁。执行最后一次换行。' },
{ line: 6, i: 3, j: '销毁 (死亡)', out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n(3, 1) (3, 2) \n', msg: '外层循环体全部执行完毕。' },
// 结束
{ line: 1, i: 4, j: '销毁 (死亡)', out: '(1, 1) (1, 2) \n(2, 1) (2, 2) \n(3, 1) (3, 2) \n', msg: 'i 增加到 4,不满足 i<=3。外层循环结束!程序完成。' }
];
let currentStep = 0;
function renderState() {
const state = steps[currentStep];
// 1. 清除所有高亮,设置当前高亮
document.querySelectorAll('.code-line').forEach(el => el.classList.remove('active'));
if (state.line !== null) {
document.getElementById('line-' + state.line).classList.add('active');
}
// 2. 更新变量面板,带有颜色区分销毁状态
document.getElementById('var-i').innerText = state.i;
const varJ = document.getElementById('var-j');
varJ.innerText = state.j;
if (state.j === '销毁 (死亡)') {
varJ.style.color = '#dc3545';
varJ.style.background = '#f8d7da';
} else {
varJ.style.color = '#e83e8c';
varJ.style.background = '#fdf3f7';
}
// 3. 更新控制台和提示信息
document.getElementById('console').innerText = state.out;
document.getElementById('status-msg').innerText = state.msg;
// 4. 更新按钮状态
document.getElementById('btn-prev').disabled = currentStep === 0;
document.getElementById('btn-next').disabled = currentStep === steps.length - 1;
// 控制台自动滚动到底部
const consoleEl = document.getElementById('console');
consoleEl.scrollTop = consoleEl.scrollHeight;
}
function nextStep() {
if (currentStep < steps.length - 1) {
currentStep++;
renderState();
}
}
function prevStep() {
if (currentStep > 0) {
currentStep--;
renderState();
}
}
function reset() {
currentStep = 0;
renderState();
}
// 初始化渲染
renderState();
</script>
</body>
</html>