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

Flutter实现无重复随机抽取4个名字的技术咨询

Flutter实现从名字列表中随机抽取4个不重复项

你当前的代码每次独立调用random.nextInt(names.length)随机取名字,导致重复概率很高。要实现无重复抽取,核心是每次抽取后排除已选中的项,同时处理名字数量不足的边界情况。

修改方案

替换原有的showAlertDialog方法,以下是完整修改后的代码:

import 'package:flutter/material.dart';
import 'dart:math';

class RandomName extends StatefulWidget {
  static const id = 'RandomName';
  const RandomName({super.key});

  @override
  State<RandomName> createState() => _RandomNameState();
}

class _RandomNameState extends State<RandomName> {
  List<String> names = [];
  Random random = Random();
  TextEditingController nameController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[900],
      appBar: AppBar(),
      body: Column(
        children: [
          Expanded(
              child: ListView.builder(
                  itemCount: names.length,
                  itemBuilder: ((context, index) {
                    return Dismissible(
                      key: UniqueKey(),
                      onDismissed: (direction) {
                        setState(() {
                          names.removeAt(index);
                        });
                      },
                      child: ListTile(
                        title: Text(names[index]),
                      ),
                    );
                  }))),
          Expanded(
            child: Padding(
              padding: EdgeInsets.all(20.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.end,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  Text(
                    "add new",
                    style: TextStyle(
                        color: Colors.grey.shade500,
                        fontWeight: FontWeight.w600),
                  ),
                  Row(
                    children: <Widget>[
                      Expanded(
                        child: TextField(
                          autocorrect: false,
                          autofocus: true,
                          maxLines: 1,
                          cursorColor: Colors.grey.shade500,
                          cursorWidth: 1.5,
                          textInputAction: TextInputAction.done,
                          keyboardAppearance: Brightness.dark,
                          style: TextStyle(
                              fontSize: 20, color: Colors.grey.shade500),
                          textAlign: TextAlign.center,
                          keyboardType: TextInputType.name,
                          controller: nameController,
                          decoration: const InputDecoration(
                            border: InputBorder.none,
                            contentPadding:
                                EdgeInsets.only(top: 10, bottom: 10),
                            isDense: true,
                          ),
                        ),
                      ),
                      ElevatedButton(
                        child: Text('Add'),
                        onPressed: () {
                          addToList();
                          nameController.clear();
                        },
                      )
                    ],
                  ),
                  Builder(
                      builder: (context) => ElevatedButton(
                          child: Text('Get Random Name'),
                          onPressed: () {
                            showAlertDialog(context);
                          }))
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  Future<void> showAlertDialog(BuildContext context) {
    return showDialog<void>(
      context: context,
      builder: (BuildContext context) {
        // 处理名字数量不足4个的情况
        if (names.length < 4) {
          return AlertDialog(
            backgroundColor: Colors.grey.shade900,
            content: const Text(
              "至少需要添加4个名字才能抽取!",
              style: TextStyle(color: Colors.white),
              textAlign: TextAlign.center,
            ),
            actions: [
              TextButton(
                onPressed: () => Navigator.pop(context),
                child: const Text("确定"),
              )
            ],
          );
        }

        // 创建原列表的副本,避免修改原数据
        List<String> tempNames = List.from(names);
        List<String> selectedNames = [];

        // 循环抽取4个不重复名字
        for (int i = 0; i < 4; i++) {
          int randomIndex = random.nextInt(tempNames.length);
          selectedNames.add(tempNames[randomIndex]);
          tempNames.removeAt(randomIndex); // 移除已选中项,防止重复
        }

        return AlertDialog(
          content: Container(
            margin: const EdgeInsets.all(8),
            padding: const EdgeInsets.all(5),
            width: MediaQuery.of(context).size.width / 1.3,
            height: MediaQuery.of(context).size.height / 3.5,
            color: Colors.grey.shade900,
            alignment: Alignment.center,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: selectedNames.map((name) {
                return Text(
                  name,
                  textAlign: TextAlign.center,
                  style: const TextStyle(fontSize: 15, color: Colors.white),
                );
              }).toList(),
            ),
          ),
          backgroundColor: Colors.grey.shade900,
        );
      },
    );
  }

  void addToList() {
    if (nameController.text.isNotEmpty) {
      setState(() {
        names.add(nameController.text);
      });
    }
  }
}

关键修改点

  • 边界处理:先判断名字列表长度,不足4个时弹出提示,避免索引越界错误
  • 无重复抽取:创建原列表的临时副本,每次抽取后移除已选中的名字,确保后续不会重复选中
  • 代码优化:用map方法动态生成展示名字的Text组件,替代重复的代码片段

内容的提问来源于stack exchange,提问作者JabiR Alzahrani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 14:45:24