Flutter实现按钮触发当日不重复的双数值列表随机数组合生成
实现方案梳理
核心逻辑拆解
整个需求的核心要覆盖三个判断分支,没有复杂的依赖:
- 自然日边界判断:基于你已经写好的「取当天0点时间戳」的逻辑,只要当前触发时间的当日0点和上一次记录的基准日期不一致,就清空所有已留存的用过的组合记录,重新开始计数
- 重复组合校验:把每次生成的两个数值用分隔符拼接成唯一的字符串标识(比如
"$num1-$num2",一定要加分隔符,避免出现1和23、12和3这类拼接后字符串完全相同的校验错误),存在哈希集合里,校验的时候O(1)速度就能判断是否已经在当天出现过 - 资源耗尽兜底:两组数全量组合一共是
100 * 30 = 3000种,当集合里存的已用组合数达到3000时,直接终止随机逻辑,给用户输出提示,避免无意义的循环
基础可运行实现
直接基于你写的基础代码补全的可落地页面逻辑,不需要额外依赖第三方库即可运行:
import 'dart:math'; import 'package:flutter/material.dart'; class RandomCombinePage extends StatefulWidget { const RandomCombinePage({super.key}); @override State<RandomCombinePage> createState() => _RandomCombinePageState(); } class _RandomCombinePageState extends State<RandomCombinePage> { final Random _random = Random(); // 存当天记录的基准日期(当日0点的时间) DateTime? _recordBaseDate; // 存当天已经用过的组合标识 final Set<String> _usedCombinations = {}; // 全量可能的组合总数 final int _totalPossibleCombos = 100 * 30; // 核心生成方法 (int, int)? generateRandomCombine() { final now = DateTime.now(); final todayStart = DateTime(now.year, now.month, now.day); // 跨天判断:首次打开/跨自然日时,重置所有记录 if (_recordBaseDate == null || _recordBaseDate != todayStart) { _recordBaseDate = todayStart; _usedCombinations.clear(); } // 边界判断:当天所有组合已抽取完毕 if (_usedCombinations.length >= _totalPossibleCombos) { return null; } // 循环生成直到拿到未重复的组合 while (true) { final num1 = _random.nextInt(100); final num2 = _random.nextInt(30); final comboKey = "$num1-$num2"; if (!_usedCombinations.contains(comboKey)) { _usedCombinations.add(comboKey); return (num1, num2); } } } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: ElevatedButton( onPressed: () { final result = generateRandomCombine(); if (result == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("今日所有可用随机组合已抽取完毕")), ); return; } // 结果可直接在页面展示或做后续逻辑处理 debugPrint("生成的组合:Num1=${result.$1}, Num2=${result.$2}"); }, child: const Text("点击生成随机组合"), ), ), ); } }
实际开发的注意事项
- 如果需要App被杀进程重启后,仍然遵守「当天不重复组合」的规则,不能仅用内存变量存已用组合和基准日期,需要把这两个数据存在本地持久化存储里(比如SharedPreferences、Hive),每次App启动时先读取存储的内容,做完跨天判断后再使用
- 如果仅需要单次打开App的会话内不重复,直接在页面状态类里存变量即可,不需要额外做持久化
效率优化参考:当当天剩余可抽取的组合数量较少时,循环随机的命中效率会下降。如果对生成速度要求高,可以在每日初始化时提前生成全量3000个组合的列表,每次生成时直接从列表中随机取一个元素、取完即从列表删除,全程不需要循环校验,即使只剩最后1个可组合,也能一步取到。
内容的提问来源于stack exchange,提问作者AzReddy
相关产品推荐
相关产品推荐

