一、系统设计理念
本大乐透选号机是一款基于Web技术的轻量级应用,旨在为用户提供便捷的随机选号服务。系统采用"简洁实用"的设计哲学,具有以下核心特点:
-
完全客户端运行:无需服务器支持,所有功能在浏览器中完成
-
数据持久化:利用浏览器本地存储保存历史记录
-
响应式界面:适配各种屏幕尺寸
-
直观可视化:彩色球体展示号码,提升用户体验
二、技术架构解析
1. 前端界面实现
系统采用经典的HTML+CSS+JS三件套开发:
<div class="lottery-container">
<h2>本期推荐号码</h2>
<div class="numbers" id="currentNumbers">
<!-- 动态生成的号码球 -->
</div>
<button id="generateBtn">生成新号码</button>
</div>
2. 核心算法逻辑
随机号码生成采用Fisher-Yates算法的简化版实现:
function generateRandomNumbers(min, max, count) {
const numbers = [];
while (numbers.length < count) {
const num = Math.floor(Math.random() * (max - min + 1)) + min;
if (!numbers.includes(num)) numbers.push(num);
}
return numbers.sort((a, b) => a - b);
}
3. 数据持久化方案
利用Web Storage API实现历史记录保存:
// 保存记录
localStorage.setItem('dltHistory', JSON.stringify(history));
// 读取记录
let history = JSON.parse(localStorage.getItem('dltHistory')) || [];
三、关键功能模块
1. 号码生成引擎
-
前区号码:1-35范围内生成5个不重复随机数
-
后区号码:1-12范围内生成2个不重复随机数
-
自动排序:生成后按从小到大排列
2. 可视化展示系统
采用CSS3实现美观的号码球效果:
.number {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 5px;
font-weight: bold;
color: white;
}
.front-number { background-color: #e74c3c; }
.back-number { background-color: #3498db; }
3. 历史记录管理
-
按时间倒序排列
-
支持本地持久化存储
-
提供一键清空功能
四、系统特色功能
-
即时生成:点击按钮即可获取新号码组合
-
历史追溯:自动保存每次生成的号码
-
跨会话持久化:关闭浏览器后记录不丢失
-
响应式反馈:按钮悬停效果提升交互体验
五、技术优化方向
-
算法优化:改进随机数生成算法,提高效率
-
数据分析:加入简单统计功能,如号码出现频率
-
UI增强:添加动画效果,提升视觉体验
-
导出功能:支持将历史记录导出为文件
六、使用场景建议
-
快速选号:为没有选号思路的用户提供随机组合
-
多注生成:连续生成多组号码增加覆盖面
-
号码收藏:保存感兴趣的组合供后续参考
-
娱乐工具:纯粹体验随机选号的乐趣
结语
这款大乐透选号机展示了现代Web技术实现轻量级应用的典型范例。通过不足200行的代码,实现了完整的功能闭环,体现了"少即是多"的设计理念。开发者可以在此基础上扩展更复杂的功能,如智能分析、趋势预测等,但当前版本已经很好地满足了基本需求。
完整代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>大乐透选号机</title>
<style>
body {
font-family: 'Microsoft YaHei', sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
text-align: center;
background-color: #f5f5f5;
}
h1 {
color: #e74c3c;
}
.lottery-container {
background-color: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
}
.numbers {
display: flex;
justify-content: center;
margin: 20px 0;
flex-wrap: wrap;
}
.number {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 5px;
font-weight: bold;
color: white;
}
.front-number {
background-color: #e74c3c;
}
.back-number {
background-color: #3498db;
}
button {
background-color: #2ecc71;
color: white;
border: none;
padding: 10px 20px;
font-size: 16px;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #27ae60;
}
.history {
margin-top: 20px;
text-align: left;
}
.history-item {
background-color: white;
padding: 10px;
border-radius: 5px;
margin-bottom: 10px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.separator {
margin: 0 10px;
color: #7f8c8d;
font-weight: bold;
}
</style>
</head>
<body>
<h1>大乐透选号机</h1>
<div class="lottery-container">
<h2>本期推荐号码</h2>
<div class="numbers" id="currentNumbers">
<!-- 号码将通过JS动态生成 -->
</div>
<button id="generateBtn">生成新号码</button>
</div>
<div class="lottery-container">
<h2>历史记录</h2>
<div class="history" id="history">
<!-- 历史记录将通过JS动态生成 -->
</div>
<button id="clearHistoryBtn">清空历史</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const generateBtn = document.getElementById('generateBtn');
const clearHistoryBtn = document.getElementById('clearHistoryBtn');
const currentNumbersEl = document.getElementById('currentNumbers');
const historyEl = document.getElementById('history');
// 从本地存储加载历史记录
let history = JSON.parse(localStorage.getItem('dltHistory')) || [];
// 初始化显示
generateNumbers();
renderHistory();
// 生成号码按钮点击事件
generateBtn.addEventListener('click', function() {
generateNumbers();
});
// 清空历史按钮点击事件
clearHistoryBtn.addEventListener('click', function() {
history = [];
localStorage.setItem('dltHistory', JSON.stringify(history));
renderHistory();
});
// 生成随机号码
function generateNumbers() {
// 生成前区号码 (1-35选5个不重复)
const frontNumbers = generateRandomNumbers(1, 35, 5);
// 生成后区号码 (1-12选2个不重复)
const backNumbers = generateRandomNumbers(1, 12, 2);
// 显示当前号码
displayNumbers(frontNumbers, backNumbers, currentNumbersEl);
// 添加到历史记录
const timestamp = new Date().toLocaleString();
history.unshift({
front: frontNumbers,
back: backNumbers,
time: timestamp
});
// 保存到本地存储
localStorage.setItem('dltHistory', JSON.stringify(history));
// 更新历史显示
renderHistory();
}
// 生成指定范围内的不重复随机数
function generateRandomNumbers(min, max, count) {
const numbers = [];
while (numbers.length < count) {
const num = Math.floor(Math.random() * (max - min + 1)) + min;
if (!numbers.includes(num)) {
numbers.push(num);
}
}
// 排序
return numbers.sort((a, b) => a - b);
}
// 显示号码
function displayNumbers(front, back, container) {
container.innerHTML = '';
// 添加前区号码
front.forEach(num => {
const numEl = document.createElement('div');
numEl.className = 'number front-number';
numEl.textContent = num.toString().padStart(2, '0');
container.appendChild(numEl);
});
// 添加分隔符
const separator = document.createElement('span');
separator.className = 'separator';
separator.textContent = '+';
container.appendChild(separator);
// 添加后区号码
back.forEach(num => {
const numEl = document.createElement('div');
numEl.className = 'number back-number';
numEl.textContent = num.toString().padStart(2, '0');
container.appendChild(numEl);
});
}
// 渲染历史记录
function renderHistory() {
historyEl.innerHTML = '';
if (history.length === 0) {
historyEl.innerHTML = '<p>暂无历史记录</p>';
return;
}
history.forEach((item, index) => {
const historyItem = document.createElement('div');
historyItem.className = 'history-item';
const timeEl = document.createElement('div');
timeEl.textContent = `${index + 1}. ${item.time}`;
timeEl.style.marginBottom = '5px';
timeEl.style.color = '#7f8c8d';
const numbersContainer = document.createElement('div');
numbersContainer.className = 'numbers';
historyItem.appendChild(timeEl);
historyItem.appendChild(numbersContainer);
historyEl.appendChild(historyItem);
// 显示历史号码
displayNumbers(item.front, item.back, numbersContainer);
});
}
});
</script>
</body>
</html>