【随机获取数组数据,连续获取不重复且不连续】

文章讲述了如何在抽奖系统中随机获取数组数据,避免重复且保证不连续,通过代码示例展示了使用`CopyOnWriteArrayList`和轮询方法,以及考虑彩票概率的解决方案。
摘要由CSDN通过智能技术生成

随机获取数组中数据,连续获取不重复且不连续

随机获取数组中数据,连续获取不重复且不连续,应尽可能多次请求返回不一样数据。

关于讨论抽奖问题,做一个记录。

常用操作方式是使用Random的nextInt方法,获取随机数发放。但可能存在几点问题。(欢迎补充)


  1. 当数组中数据较少时,会多次返回相同数据,体验较差。
  2. 可能会存在连续两次返回相同数据,误以为并未随机展示。
  3. 奖品等级因根据级别不同,命中率应不相同。

常用办法解决以上问题(欢迎补充)


  1. 使用轮询方法
  2. 随机打乱并获取首位数据。
  3. 记录抽取与未抽取数据数据分别处理

当前处理方式

后续有其他方法再补充,当前仅记录简单思路,具体业务具体分析。

  1. 数据顺序不固定,且不连续
  2. Random

方法一:代码如下

@SpringBootTest
public class RandomTest {
    private final CopyOnWriteArrayList<String> dataList = new CopyOnWriteArrayList<>();
    private final CopyOnWriteArrayList<String> usedList = new CopyOnWriteArrayList<>();

    public void addListAll(List<String> list) {
        if (dataList.equals(list)) {
            return;
        }
        dataList.clear();
        dataList.addAll(list);
    }

    /**
     * 获取
     */
    public synchronized String getRandomElement() {
        if (dataList.isEmpty()) {
            // 如果列表中的元素已经用尽,可以选择重新填充或者返回空值
            return null;
        }

        Collections.shuffle(dataList); // 随机打乱列表顺序
        String element = dataList.remove(0); // 移除并返回第一个元素
        usedList.add(element);

        if (dataList.isEmpty()) {
            // 如果列表中的元素已经用尽,将已使用的元素重新放回列表以实现循环使用
            dataList.addAll(usedList);
            usedList.clear();
        }

        return element;
    }

    @Test
    public void testRandom() {
        ArrayList<String> strings = new ArrayList<>() {{
            add("foo");
            add("bar");
            add("baz");
            add("boo");
        }};
        addListAll(strings);
        for (int i = 0; i < 6; i++) {
            String randomElement = getRandomElement();
            System.out.println("randomElement:"+randomElement);
        }
    }
  } 

方法二:代码如下

@SpringBootTest
public class RandomTest {
    
    private List<String> itemList;
    private Set<String> drawnItems;
    private Random random;

    public RandomTest(List<String> itemList) {
        this.itemList = new ArrayList<>(itemList);
        this.drawnItems = new HashSet<>();
        this.random = new Random();
    }
    public String drawItemForUser() {
        if (itemList.isEmpty()) {
            // 处理抽奖结束的逻辑,可以重新填充List或者采取其他处理方式
            return "抽奖已结束";
        }

        String selectedItem = drawUniqueItem();
        // 将抽取的元素添加到已抽取的集合中
        drawnItems.add(selectedItem);

        return selectedItem;
    }

    private String drawUniqueItem() {
        int randomIndex = random.nextInt(itemList.size());
        String selectedItem = itemList.get(randomIndex);

        // 检查是否已经被抽取过
        while (drawnItems.contains(selectedItem)) {
            randomIndex = random.nextInt(itemList.size());
            selectedItem = itemList.get(randomIndex);
        }

        return selectedItem;
    }

    public static void main(String[] args) {
        List<String> items = new ArrayList<>();
        items.add("奖品1");
        items.add("奖品2");
        items.add("奖品3");
        items.add("奖品4");
        items.add("奖品5");
        items.add("奖品6");
        items.add("奖品7");

        RandomTest lottery = new RandomTest(items);

        // 模拟一个用户连续抽取四次
        for (int i = 1; i <= 10; i++) {
            String result = lottery.drawItemForUser();
            System.out.println("用户" + i + "抽到了:" + result);
        }
    }
}

加入彩票概率:代码如下

public class Lottery {

    private List<String> itemList;
    private Set<String> lastDrawnItems;  // 用于记录上一次抽取的元素
    private Random random;

    public Lottery(List<String> itemList) {
        this.itemList = new ArrayList<>(itemList);
        this.lastDrawnItems = new HashSet<>();
        this.random = new Random();
    }

    public String drawItemForUser() {
        if (itemList.isEmpty()) {
            // 处理抽奖结束的逻辑,可以重新填充List或者采取其他处理方式
            return "抽奖已结束";
        }

        String selectedItem;

        // 如果lastDrawnItems为空(第一次抽取)或者已经连续两次抽取相同元素,则重新抽取
        do {
            selectedItem = drawUniqueItem();
        } while (lastDrawnItems.contains(selectedItem));

        // 更新lastDrawnItems
        lastDrawnItems.clear();
        lastDrawnItems.add(selectedItem);

        // 如果所有元素都已经被抽取,那么一等奖有可能被抽取
        if (itemList.isEmpty()) {
            // 这里可以根据需要调整一等奖的概率
            if (random.nextDouble() < 0.1) {  // 例如,10%的概率抽中一等奖
                return "一等奖";
            }
        }

        return selectedItem;
    }

    private String drawUniqueItem() {
        int randomIndex = random.nextInt(itemList.size());
        return itemList.remove(randomIndex);
    }

    public static void main(String[] args) {
        List<String> items = new ArrayList<>();
        items.add("奖品1");
        items.add("奖品2");
        items.add("奖品3");
        items.add("奖品4");

        Lottery lottery = new Lottery(items);

        // 模拟一个用户连续抽取四次
        for (int i = 1; i <= 6; i++) {
            String result = lottery.drawItemForUser();
            System.out.println("用户" + i + "抽到了:" + result);
        }
    }
}


后续有问题和处理再补充

Unity中的随机重复通常是指在编程中生成一系列随机且不重复数据集合。这在游戏开发中经常需要,比如随机选择不同的敌人、道具或者关卡等。在Unity中实现随机重复的一个常见方法是使用列表(List)或数组(Array)来存储数据,然后通过随机选择和移除元素的方式来确保元素的唯一性。 以下是实现随机重复的一个简单步骤: 1. 创建一个列表并初始化包含所有可能的元素。 2. 使用随机随机选择列表中的一个元素。 3. 从列表中移除这个元素,确保它不会被再次选择。 4. 重复步骤2和3直到列表为空。 Unity中可以使用`System.Random`类来生成随机,或者使用`Random.Range`等内置函来辅助生成随机。 示例代码(假设我们随机选择一个不重复字): ```csharp using System; using System.Collections.Generic; public class RandomUniqueSelector { private List<int> pool; private Random random; public RandomUniqueSelector(int min, int max) { pool = new List<int>(); random = new Random(); for (int i = min; i <= max; i++) { pool.Add(i); } } public int GetRandomUnique() { if (pool.Count == 0) return -1; // 没有元素可选时返回-1或其他错误码 int index = random.Next(pool.Count); int value = pool[index]; pool.RemoveAt(index); return value; } } ``` 使用该类时,只需要创建一个`RandomUniqueSelector`实例,并不断地调用`GetRandomUnique`方法来获取随机且不重复字。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值