<think>我们要求删除结算统计按钮,改为在左侧实时显示统计列表。
因此,我们需要:
1. 移除结算统计按钮(settleBtn)
2. 在页面左侧添加一个固定列表,实时显示每首歌的统计信息(歌曲编号、出现次数、喜欢次数、不喜欢次数、当前概率)
3. 每次用户操作(喜欢/不喜欢)后更新这个列表
我们将对HTML结构进行调整:
- 将整个布局改为左右两栏:左侧为实时统计列表,右侧为歌曲显示和操作区。
- 移除原来的结算按钮和相关代码。
注意:由于概率计算需要归一化,我们每次更新时都需要重新计算当前的实际概率(归一化到100%)。
步骤:
1. 修改HTML结构,添加左侧统计列表的容器(例如一个固定宽度的div)
2. 创建表格(或列表结构)来展示统计数据,并给这个表格一个ID以便用JS更新
3. 编写一个更新统计列表的函数,在每次歌曲显示或用户操作后调用
4. 初始化时显示统计列表,并设置定时更新或事件驱动更新(我们选择事件驱动:每次操作后更新)
另外,为了避免频繁操作DOM影响性能,我们可以只更新变化的数据行,但考虑到歌曲数量固定为10首,每次全量更新也可以接受。
我们将移除结算按钮的事件监听,并删除结算按钮本身。
此外,由于布局变化,需要调整CSS以实现左右分栏。
代码修改如下:
</think>以下是删除结算统计功能并改为左侧实时显示列表的完整代码:
```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>歌曲偏好测试</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Microsoft YaHei', sans-serif;
display: flex;
min-height: 100vh;
background-color: #f8f9fa;
color: #333;
}
.stats-panel {
width: 300px;
background-color: #ffffff;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
padding: 20px;
overflow-y: auto;
height: 100vh;
position: fixed;
left: 0;
top: 0;
z-index: 1000;
}
.stats-panel h2 {
text-align: center;
margin-bottom: 20px;
color: #2c3e50;
padding-bottom: 10px;
border-bottom: 2px solid #3498db;
}
.stats-list {
list-style: none;
}
.stats-list li {
padding: 12px 15px;
margin-bottom: 10px;
border-radius: 8px;
background: #f8f9fa;
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
transition: all 0.3s ease;
}
.stats-list li:hover {
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.stats-list li:first-child {
background-color: #e3f2fd;
font-weight: bold;
}
.stats-list li.current {
background-color: #e1f5fe;
border-left: 4px solid #3498db;
}
.stat-row {
display: flex;
justify-content: space-between;
padding: 3px 0;
}
.stat-label {
font-weight: bold;
color: #7f8c8d;
}
.stat-value {
font-weight: 500;
}
.probability-bar {
height: 10px;
background-color: #e0e0e0;
border-radius: 5px;
margin: 8px 0;
overflow: hidden;
}
.probability-fill {
height: 100%;
background: linear-gradient(90deg, #3498db, #2ecc71);
border-radius: 5px;
transition: width 0.5s ease;
}
.negative .probability-fill {
background: linear-gradient(90deg, #e74c3c, #f39c12);
}
.content-panel {
flex: 1;
margin-left: 300px;
display: flex;
flex-direction: column;
align-items: center;
padding: 40px 20px;
background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
}
.header {
text-align: center;
margin-bottom: 30px;
}
.header h1 {
font-size: 36px;
color: #2c3e50;
margin-bottom: 15px;
}
.header p {
color: #7f8c8d;
max-width: 600px;
line-height: 1.6;
}
#songDisplay {
font-size: 120px;
margin: 30px 0;
color: #2c3e50;
text-shadow: 3px 3px 10px rgba(0,0,0,0.1);
transition: all 0.3s;
padding: 20px;
border-radius: 15px;
background: rgba(255,255,255,0.8);
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.controls {
display: flex;
gap: 20px;
margin: 20px 0 40px;
}
button {
padding: 15px 35px;
font-size: 18px;
border: none;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s;
font-weight: bold;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
display: flex;
align-items: center;
justify-content: center;
}
button:active {
transform: translateY(3px);
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
#likeBtn {
background: linear-gradient(135deg, #2ecc71, #27ae60);
color: white;
}
#dislikeBtn {
background: linear-gradient(135deg, #e74c3c, #c0392b);
color: white;
}
#resetBtn {
background: linear-gradient(135deg, #3498db, #2980b9);
color: white;
padding: 12px 25px;
}
.current-stats {
background: white;
border-radius: 15px;
padding: 25px;
width: 450px;
box-shadow: 0 10px 30px rgba(0,0,0,0.08);
margin-top: 20px;
}
.current-stats h3 {
text-align: center;
margin-bottom: 20px;
color: #3498db;
}
.progress-container {
margin: 15px 0;
}
.progress-row {
display: flex;
align-items: center;
margin-bottom: 12px;
}
.progress-label {
width: 100px;
font-weight: bold;
color: #7f8c8d;
}
.progress-bar-container {
flex: 1;
height: 20px;
background-color: #e0e0e0;
border-radius: 10px;
overflow: hidden;
}
.progress-bar {
height: 100%;
border-radius: 10px;
transition: width 0.3s;
}
.like-progress {
background: linear-gradient(90deg, #2ecc71, #27ae60);
}
.dislike-progress {
background: linear-gradient(90deg, #e74c3c, #c0392b);
}
.progress-value {
width: 60px;
text-align: right;
font-weight: bold;
}
.feedback {
font-size: 28px;
font-weight: bold;
height: 50px;
margin: 20px 0;
opacity: 0;
text-align: center;
transition: opacity 0.5s;
}
.highlight {
animation: highlight 0.6s ease;
}
@keyframes highlight {
0% { transform: scale(1); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
.probability-change {
position: absolute;
font-size: 18px;
font-weight: bold;
opacity: 0;
animation: floatUp 1.5s forwards;
text-shadow: 0 2px 3px rgba(0,0,0,0.2);
}
@keyframes floatUp {
0% { transform: translateY(0); opacity: 1; }
100% { transform: translateY(-60px); opacity: 0; }
}
.instructions {
background: rgba(255,255,255,0.9);
border-radius: 10px;
padding: 15px 25px;
margin-top: 20px;
box-shadow: 0 5px 15px rgba(0,0,0,0.05);
max-width: 600px;
}
.instructions p {
color: #7f8c8d;
margin: 8px 0;
text-align: center;
}
.key {
display: inline-block;
padding: 2px 10px;
background: #2c3e50;
color: white;
border-radius: 5px;
font-weight: bold;
margin: 0 3px;
}
</style>
</head>
<body>
<!-- 左侧实时统计列表 -->
<div class="stats-panel">
<h2>歌曲统计列表</h2>
<ul class="stats-list" id="statsList">
<li class="header-row">
<div class="stat-row">
<span>歌曲</span>
<span>出现次数</span>
<span>喜欢次数</span>
<span>不喜欢次数</span>
<span>概率</span>
</div>
</li>
<!-- 列表项将通过JS动态生成 -->
</ul>
</div>
<!-- 右侧主内容区 -->
<div class="content-panel">
<div class="header">
<h1>歌曲偏好测试</h1>
<p>测试你对不同歌曲的偏好,系统会根据你的选择动态调整歌曲出现概率</p>
</div>
<div id="songDisplay">?</div>
<div class="feedback" id="feedback"></div>
<div class="controls">
<button id="likeBtn">喜欢 (A)</button>
<button id="dislikeBtn">不喜欢 (D)</button>
<button id="resetBtn">重置游戏</button>
</div>
<div class="current-stats">
<h3>当前歌曲统计</h3>
<div class="progress-container">
<div class="progress-row">
<div class="progress-label">歌曲编号</div>
<div class="progress-value" id="currentSong">-</div>
</div>
<div class="progress-row">
<div class="progress-label">出现次数</div>
<div class="progress-value" id="appearanceCount">0</div>
</div>
<div class="progress-row">
<div class="progress-label">喜欢进度</div>
<div class="progress-bar-container">
<div class="progress-bar like-progress" id="likeProgress" style="width: 0%"></div>
</div>
<div class="progress-value"><span id="currentLikes">0</span>/10</div>
</div>
<div class="progress-row">
<div class="progress-label">不喜欢进度</div>
<div class="progress-bar-container">
<div class="progress-bar dislike-progress" id="dislikeProgress" style="width: 0%"></div>
</div>
<div class="progress-value"><span id="currentDislikes">0</span>/10</div>
</div>
</div>
</div>
<div class="instructions">
<p>按 <span class="key">A</span> 键或"喜欢"按钮表示喜欢当前歌曲(增加出现概率)</p>
<p>按 <span class="key">D</span> 键或"不喜欢"按钮表示不喜欢当前歌曲(减少出现概率)</p>
<p>每喜欢同一首歌10次,该歌曲出现概率<span style="color:#27ae60;font-weight:bold">增加0.5%</span></p>
<p>每不喜欢同一首歌10次,该歌曲出现概率<span style="color:#e74c3c;font-weight:bold">减少0.5%</span></p>
</div>
</div>
<script>
// 初始化游戏数据
const songs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let baseProbabilities = new Array(10).fill(0.1); // 基础概率
let extraProbabilities = new Array(10).fill(0); // 额外增加概率
let appearanceCounts = new Array(10).fill(0); // 出现次数统计
let likeCounts = new Array(10).fill(0); // 喜欢次数统计
let dislikeCounts = new Array(10).fill(0); // 不喜欢次数统计
let totalChoices = 0; // 总选择次数
// DOM元素
const songDisplay = document.getElementById('songDisplay');
const likeBtn = document.getElementById('likeBtn');
const dislikeBtn = document.getElementById('dislikeBtn');
const resetBtn = document.getElementById('resetBtn');
const statsList = document.getElementById('statsList');
const currentSongSpan = document.getElementById('currentSong');
const currentLikesSpan = document.getElementById('currentLikes');
const currentDislikesSpan = document.getElementById('currentDislikes');
const appearanceCountSpan = document.getElementById('appearanceCount');
const likeProgress = document.getElementById('likeProgress');
const dislikeProgress = document.getElementById('dislikeProgress');
const feedback = document.getElementById('feedback');
// 初始化统计列表
function initStatsList() {
// 清空列表(保留标题行)
while (statsList.children.length > 1) {
statsList.removeChild(statsList.lastChild);
}
// 添加歌曲统计项
songs.forEach((song, index) => {
const li = document.createElement('li');
li.id = `song-${song}`;
li.innerHTML = `
<div class="stat-row">
<span class="stat-label">${song}</span>
<span class="stat-value" id="appCount-${song}">0</span>
<span class="stat-value" id="likeCount-${song}">0</span>
<span class="stat-value" id="dislikeCount-${song}">0</span>
<span class="stat-value" id="probValue-${song}">10.00%</span>
</div>
<div class="probability-bar">
<div class="probability-fill" id="probBar-${song}" style="width: 10%"></div>
</div>
`;
statsList.appendChild(li);
});
}
// 更新统计列表
function updateStatsList() {
// 计算当前总概率
const totalProbability = baseProbabilities.reduce(
(sum, base, i) => sum + base + extraProbabilities[i], 0
);
// 更新每首歌曲的统计信息
songs.forEach((song, index) => {
// 计算当前实际概率
let currentProb = ((baseProbabilities[index] + extraProbabilities[index])
/ totalProbability * 100);
currentProb = Math.max(0, Math.min(100, currentProb));
// 更新DOM
document.getElementById(`appCount-${song}`).textContent = appearanceCounts[index];
document.getElementById(`likeCount-${song}`).textContent = likeCounts[index];
document.getElementById(`dislikeCount-${song}`).textContent = dislikeCounts[index];
document.getElementById(`probValue-${song}`).textContent = currentProb.toFixed(2) + '%';
document.getElementById(`probBar-${song}`).style.width = `${currentProb}%`;
// 为当前歌曲添加高亮样式
const songItem = document.getElementById(`song-${song}`);
if (parseInt(currentSongSpan.textContent) === song) {
songItem.classList.add('current');
// 概率为负值时添加特殊样式
if (extraProbabilities[index] < 0) {
songItem.classList.add('negative');
} else {
songItem.classList.remove('negative');
}
} else {
songItem.classList.remove('current');
}
});
}
// 显示随机歌曲
function showRandomSong() {
// 计算当前实际概率
const currentProbabilities = baseProbabilities.map(
(base, index) => base + extraProbabilities[index]
);
// 确保概率不为负值
currentProbabilities.forEach((prob, index) => {
if (prob < 0) {
extraProbabilities[index] = -baseProbabilities[index];
}
});
// 随机选择歌曲
const rand = Math.random();
let cumulative = 0;
let selectedIndex = 0;
for (let i = 0; i < songs.length; i++) {
cumulative += currentProbabilities[i];
if (rand <= cumulative) {
selectedIndex = i;
break;
}
}
// 更新显示和统计数据
const song = songs[selectedIndex];
songDisplay.textContent = song;
currentSongSpan.textContent = song;
appearanceCountSpan.textContent = appearanceCounts[selectedIndex];
currentLikesSpan.textContent = likeCounts[selectedIndex];
currentDislikesSpan.textContent = dislikeCounts[selectedIndex];
likeProgress.style.width = `${(likeCounts[selectedIndex] % 10) * 10}%`;
dislikeProgress.style.width = `${(dislikeCounts[selectedIndex] % 10) * 10}%`;
appearanceCounts[selectedIndex]++;
// 更新统计列表
updateStatsList();
return selectedIndex;
}
// 显示反馈信息
function showFeedback(message, color) {
feedback.textContent = message;
feedback.style.color = color;
feedback.style.opacity = 1;
setTimeout(() => {
feedback.style.opacity = 0;
}, 1500);
}
// 显示概率变化动画
function showProbabilityChange(amount, element, isPositive) {
const changeElement = document.createElement('div');
changeElement.className = 'probability-change';