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锄贷?一共才幾首歌译蒂,而我切了十多次才隨機到自己想要的!
有些歌明明已經(jīng)被切掉了谊却,為什么馬上又隨機到蹂随?不夠聰明誒。
那么因惭,在監(jiān)聽到用戶正在切歌時岳锁,可不可以直接跳過剛剛已經(jīng)切過的歌?
當然是可行的蹦魔。于是在RandomPicker基礎(chǔ)上實現(xiàn)了CutMode激率。進入切歌模式后,切過的歌將不會再次出現(xiàn)勿决,除非一輪已經(jīng)切完乒躺。
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);
// 指定下次隨機到的數(shù)
mRandomPicker.setNextPick(3);
//添加一個item至尾部嘉冒,并為其賦值初始比重
mRandomPicker.add(2);
源碼
GitHub: XunMengWinter/RandomPicker
下面貼出關(guān)鍵代碼:
/*執(zhí)行隨機算法*/
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;
}
}
}
// 預(yù)先算好下一次的比重
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請求讳推。