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
如何使用
快速開始:
// 指定列表有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請求。