网站服务器端存储每日答题记录及避免近期重复方案咨询
我正在开发一款小型每日网页游戏,当前使用基于日期作为种子的pRNG(伪随机数生成器)从候选答案数据库中生成每日答案。我希望存储过去30-60天的答案记录,以便修改随机答案生成逻辑,避免近期出现重复答案。
现有生成每日答案的代码如下:
function splitmix32(a) { return function() { a |= 0; a = a + 0x9e3779b9 | 0; var t = a ^ a >>> 16; t = Math.imul(t, 0x21f0aaad); t = t ^ t >>> 15; t = Math.imul(t, 0x735a2d97); return ((t = t ^ t >>> 15) >>> 0) / 4294967296; } } function generateAnsOfTheDay(){ let now = new Date(); let epochDays = Math.floor(now/8.64e7); console.log("Epoch Day: " + epochDays); let randomNumber = splitmix32(epochDays)(); //check number of digits in the float randomNumber var length = (randomNumber + '').replace('.', '').length; //multiply float randomNumber by 10^x where x is the number of digits minus one, this converts the number to a integer randomNumber = randomNumber*Math.pow(10, length-1) console.log(randomNumber) let ansNumber= randomNumber%ansList.length console.log(ansNumber) console.log(ansList[ansNumber].ansName); return Math.floor(ansNumber); }
目前功能正常,但存在重复答案问题(已确认重复频率较高)。请问存储过去X天答案的最佳方式是什么?我能轻松调整生成逻辑避免重复,但不清楚如何在服务器端实现每日新增最新答案并移除最旧答案的功能。
一、过去X天答案的存储方案
1. 轻量场景:JSON文件存储
如果游戏用户量小、服务器资源有限,直接用JSON文件存储是最简便的选择。可以设计成数组结构,每个元素包含日期标识和对应答案索引:
[ {"epochDay": 19850, "ansIndex": 42}, {"epochDay": 19851, "ansIndex": 17}, ... ]
这种方式读写简单,适合小规模应用,但并发写入时需要加锁或用队列处理,避免文件冲突。
2. 稳定场景:小型数据库存储
如果用户量稍大,推荐用SQLite、MySQL这类数据库,建一张极简的表:
CREATE TABLE daily_answers ( epoch_day INTEGER PRIMARY KEY, ans_index INTEGER NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
用epoch_day作为主键可避免重复存储同一天的答案,查询和维护更可靠,适合长期运行的服务。
二、服务器端自动维护逻辑实现
不管用哪种存储方式,核心逻辑都是每日生成新答案后,自动移除超出X天的旧记录,具体步骤如下:
1. 生成前检查是否已存在当日答案
每次运行生成逻辑时,先根据当前epochDays查询存储记录:
- 如果已有记录,直接返回对应答案索引,避免重复生成
- 如果没有记录,再执行随机生成逻辑(需排除过去X天的答案索引)
2. 生成并存储新答案
生成符合要求的答案索引后,将epochDays和索引存入存储介质。
3. 清理过期记录
存储新答案后,计算过期阈值(当前epochDays - X),删除所有小于该阈值的记录:
- JSON文件:读取数组后过滤掉过期元素,再写回文件
- 数据库:执行删除语句
DELETE FROM daily_answers WHERE epoch_day < ?
4. 触发方式选择
- 定时触发:用服务器定时工具(如Linux的cron、Windows任务计划),每天凌晨固定时间执行生成+清理逻辑
- 懒加载触发:当有用户访问时,先检查当日是否已有答案,没有则生成并清理过期记录,适合低访问量场景,无需维护定时任务
三、优化原生成逻辑避免重复
修改generateAnsOfTheDay函数,加入排除近期答案的逻辑,同时简化原代码中冗余的字符串处理步骤:
async function generateAnsOfTheDay(excludedIndexes) { let now = new Date(); let epochDays = Math.floor(now/8.64e7); // 生成随机数直到找到不在排除列表中的索引 let ansNumber; const rng = splitmix32(epochDays); do { let randomNumber = rng(); // 直接用随机数乘列表长度取整,替代原字符串转整数的冗余逻辑 ansNumber = Math.floor(randomNumber * ansList.length); } while (excludedIndexes.includes(ansNumber)); console.log(ansList[ansNumber].ansName); return ansNumber; }
调用时先从存储中取出过去X天的ans_index列表作为excludedIndexes传入即可。
内容的提问来源于stack exchange,提问作者Jadon Latta

