一个随机播放的算法II

一个随机播放的算法

Idea:💡

音乐时光🎵
骑着车,戴着耳机,播放列表里有几首歌。
突然,很想听《且听风吟》,但是不想掏出手机,于是一路双击耳机播放键切歌。
emmm,下面是切过的歌:

第几次随机到的音乐停留的时间
1Love Story2s
2东风破3s
3Refrain1s
4东风破2s
5Valder Fields2s
6Love Story1s
7My Soul3s
8白金ディスコ1s
9Refrain3s
16且听风吟3min

What?一共才几首歌,而我切了十多次才随机到自己想要的!
有些歌明明已经被切掉了,为什么马上又随机到?不够聪明诶。

那么,在监听到用户正在切歌时,可不可以直接跳过刚刚已经切过的歌?
当然是可行的。于是在RandomPicker基础上实现了CutMode。进入切歌模式后,切过的歌将不会再次出现,除非一轮已经切完。

Demo

《一个随机播放的算法II》 进入切歌模式的RandomPicker

如何使用

快速开始:

// 指定列表有n首歌,初始比重为1.
mRandomPicker = new RandomPicker(n, 1); 
// 进入切歌模式。
mRandomPicker.enterCutMode();
// 随机获取下一首
int nextPos = mRandomPicker.next();
...
// 退出切歌模式
mRandomPicker.exitCutMode();

更多方法:

// 更默认的比重计算器
mRandomPicker.setCalculator(new Calculator() {
@Override
public int calculateNextWeight(int currentWeight, int originWeight) {
    return (currentWeight + 1) * originWeight;
    }
 });
// 改变某个item的初始比重
mRandomPicker.changeOriginWeight(0, 3);
// 指定下次随机到的数
mRandomPicker.setNextPick(3);
//添加一个item至尾部,并为其赋值初始比重
mRandomPicker.add(2);

源码

GitHub: XunMengWinter/RandomPicker

下面贴出关键代码:

    /*执行随机算法*/
    private int randomPick() {
        // 若列表长度小于2,则下一次位置必为0.
        if (mCurrentWeightList.size() < 2) {
            return 0;
        }

        int nextPos = 0;
        // 算出下一次选中的位置
        if (mNextPickPosition != null) {
            nextPos = mNextPickPosition;
            mNextPickPosition = null;
        } else {
            int allWeight = 0;
            for (int i = 0; i < mCurrentWeightList.size(); i++) {
                allWeight += mCurrentWeightList.get(i);
            }

            if (allWeight <= 0) {
                //TODO avoid this situation.
                allWeight = Integer.MAX_VALUE;
                //Log.e(TAG, "...");
            }

            int nextPosInWeight = mRandom.nextInt(allWeight);
            int currentWeight = 0;
            for (int i = 0; i < mCurrentWeightList.size(); i++) {
                currentWeight += mCurrentWeightList.get(i);
                if (currentWeight > nextPosInWeight) {
                    nextPos = i;
                    break;
                }
            }
        }

        // 预先算好下一次的比重
        for (int i = 0; i < mCurrentWeightList.size(); i++) {
            if (isCutMode()) {
                if (mCutOutSet.contains(i)) {
                    continue;
                }
            }
            int weight = calculateWeight(mCurrentWeightList.get(i), mOriginWeightList.get(i));
            mCurrentWeightList.set(i, weight);
        }
        if (isRepeatable)
            mCurrentWeightList.set(nextPos, calculateWeight(0, mOriginWeightList.get(nextPos)));
        else
            mCurrentWeightList.set(nextPos, 0);

        if (isCutMode()) {
            mCurrentWeightList.set(nextPos, 0);
            mCutOutSet.add(nextPos);
            if (mCutOutSet.size() >= getSize())
                mCutOutSet.clear();
        }
        return nextPos;
    }

p.s. 如果你有更好的建议,请留言或者在GitHub fork并提交pull请求。

    原文作者:DreamWinter
    原文地址: https://www.jianshu.com/p/eee5cbf839d8
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞