一個隨機播放的算法II

一個隨機播放的算法

Idea:💡

音樂時光🎵
騎着車,戴着耳機,播放列表裏有幾首歌。
突然,很想聽《且聽風吟》,但是不想掏出手機,於是一路雙擊耳機播放鍵切歌。
emmm,下面是切過的歌:

第幾次 隨機到的音樂 停留的時間
1 Love Story 2s
2 東風破 3s
3 Refrain 1s
4 東風破 2s
5 Valder Fields 2s
6 Love Story 1s
7 My Soul 3s
8 白金ディスコ 1s
9 Refrain 3s
... ... ...
16 且聽風吟 3min

What?一共才幾首歌,而我切了十多次才隨機到自己想要的!
有些歌明明已經被切掉了,爲什麼馬上又隨機到?不夠聰明誒。

那麼,在監聽到用戶正在切歌時,可不可以直接跳過剛剛已經切過的歌?
當然是可行的。於是在RandomPicker基礎上實現了CutMode。進入切歌模式後,切過的歌將不會再次出現,除非一輪已經切完。

Demo

進入切歌模式的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請求。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章