本网站采用加密安全的随机数生成算法,确保每次抽取结果完全随机、公平公正。
我们使用浏览器内置的 crypto.getRandomValues() API,这是基于硬件熵源的
密码学安全随机数生成器,保证了结果的不可预测性。
// 使用加密安全的随机数生成器(借鉴 wheelofnames.com)
function getSecureRandom() {
if (window.crypto && window.crypto.getRandomValues) {
const array = new Uint32Array(1);
window.crypto.getRandomValues(array);
return array[0] / (0xFFFFFFFF + 1);
}
return Math.random();
}
说明:crypto.getRandomValues() 使用浏览器提供的加密安全随机数生成器,
基于硬件熵源(如鼠标移动、键盘输入延迟、系统时钟等)生成真正不可预测的随机数。
通过将随机数除以最大值,确保每个学生被选中的概率完全相等。
完全随机模式,每次抽取都是独立事件,每个学生被选中的概率完全相等。这是最公平的随机算法,适合需要绝对公平的场景。
// 独立随机算法
function selectStudent() {
// 完全随机选择,每个学生概率相等
return Math.floor(getSecureRandom() * students.length);
}
智能分配模式,尽可能保证所有学生都会被抽到,且不会连续抽取同一个人。系统会记录每个学生的被抽中次数,优先选择被抽中次数较少的学生。
// 雨露均沾算法
function selectStudent() {
// 排除上次被抽中的学生
const availableStudents = students
.map((student, index) => ({
student, index,
count: studentPickCounts[student] || 0
}))
.filter(item => item.index !== lastPickedIndex);
// 找到被抽中次数最少的学生
const minCount = Math.min(...availableStudents.map(item => item.count));
const candidates = availableStudents.filter(item => item.count === minCount);
// 从候选者中随机选择一个
const selected = candidates[Math.floor(getSecureRandom() * candidates.length)];
// 更新计数
studentPickCounts[selected.student] = (studentPickCounts[selected.student] || 0) + 1;
lastPickedIndex = selected.index;
return selected.index;
}
平衡随机模式,在保证随机性的同时,适度考虑历史记录。既保持随机性,又避免某些学生长期不被抽中。使用加权随机算法,被抽中次数越少的学生权重越高。
// 均衡模式算法
function selectStudent() {
// 计算每个学生的权重
const weights = students.map((student, index) => {
const count = studentPickCounts[student] || 0;
// 如果上次被抽中,权重降低(避免连续抽取)
const penalty = (index === lastPickedIndex) ? 0.3 : 1.0;
// 被抽中次数越少,权重越高(使用倒数)
return (1 / (count + 1)) * penalty;
});
// 计算总权重
const totalWeight = weights.reduce((sum, w) => sum + w, 0);
// 加权随机选择
let random = getSecureRandom() * totalWeight;
let selectedIndex = 0;
for (let i = 0; i < weights.length; i++) {
random -= weights[i];
if (random <= 0) {
selectedIndex = i;
break;
}
}
// 更新计数
studentPickCounts[students[selectedIndex]] =
(studentPickCounts[students[selectedIndex]] || 0) + 1;
lastPickedIndex = selectedIndex;
return selectedIndex;
}
注意:本系统不使用标准的 Math.random(),
而是采用更高安全级别的加密随机数生成器,确保结果的真实随机性。
所有算法都基于 getSecureRandom() 函数,保证了底层随机数的安全性。