前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个随机播放的算法II

一个随机播放的算法II

作者头像
冰之角
发布2018-09-04 15:46:48
4570
发布2018-09-04 15:46:48
举报
文章被收录于专栏:Winter漫聊技术Winter漫聊技术

一个随机播放的算法

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

如何使用

快速开始:

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

更多方法:

代码语言:javascript
复制
// 更默认的比重计算器
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

下面贴出关键代码:

代码语言:javascript
复制
    /*执行随机算法*/
    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请求。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.04.17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Idea:?
  • Demo
  • 如何使用
  • 源码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档