You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.28 02:15:10