随机播放音乐 伪随机

发布于:2025-03-06 ⋅ 阅读:(7) ⋅ 点赞:(0)

import java.util.*;


/**
 * https://cloud.tencent.com.cn/developer/news/1045747
 * 伪随机播放音乐
 */
public class MusicPlayer {
    private List<String> allSongs; // 所有歌曲列表
    private List<String> playedSongs; // 已经播放过的歌曲列表
    private Map<String, Integer> songPreferences; // 歌曲偏好权重

    public MusicPlayer(List<String> allSongs) {
        this.allSongs = allSongs;
        this.playedSongs = new ArrayList<>();
        this.songPreferences = new HashMap<>();
        // 初始化所有歌曲的偏好权重为1
        for (String song : allSongs) {
            songPreferences.put(song, 1);
        }
    }

    // 根据偏好权重随机选择下一首歌曲
    public String getNextSong() {
        List<String> availableSongs = new ArrayList<>(allSongs);
        availableSongs.removeAll(playedSongs);

        if (availableSongs.isEmpty()) {
            // 如果所有歌曲都播放过了,重置播放列表
            playedSongs.clear();
            availableSongs = new ArrayList<>(allSongs);
        }

        // 计算总权重
        int totalWeight = availableSongs.stream().mapToInt(song -> songPreferences.get(song)).sum();

        // 生成一个随机数
        Random random = new Random();
        int randomWeight = random.nextInt(totalWeight);

        // 根据权重选择歌曲
        int cumulativeWeight = 0;
        for (String song : availableSongs) {
            cumulativeWeight += songPreferences.get(song);
            if (randomWeight < cumulativeWeight) {
                playedSongs.add(song);
                return song;
            }
        }

        return null; // 正常情况下不会执行到这里
    }

    // 更新歌曲偏好权重
    public void updatePreference(String song, int weight) {
        if (songPreferences.containsKey(song)) {
            songPreferences.put(song, songPreferences.get(song) + weight);
        }
    }

    public static void main(String[] args) {
        List<String> songs = Arrays.asList("Song1", "Song2", "Song3", "Song4", "Song5");
        MusicPlayer player = new MusicPlayer(songs);

        // 模拟用户偏好,增加某些歌曲的权重
        player.updatePreference("Song1", 3);
        player.updatePreference("Song3", 2);

        // 模拟播放10首歌曲
        for (int i = 0; i < 10; i++) {
            System.out.println("Now playing: " + player.getNextSong());
        }
    }
}

你是否曾想过音乐播放器的随机播放的歌曲真的是完全随机的吗?不,它们在骗你!

我们来介绍一下伪随机和真随机。

伪随机算法是最常见的一种,它会从播放列表中随机选择一首歌曲播放,然后根据一些规则来决定下一首播放的歌曲。例如,它可能会排除已经播放过的歌曲,以避免重复播放。另外,一些播放器还可能会根据歌曲的类型、时长、评分等因素来决定下一首播放的歌曲。

而真随机算法则会完全随机选择一首歌曲播放,没有任何规则和预测。但这种算法并不常见,因为它可能会导致某些歌曲被播放多次,而有些歌曲则几乎不会被播放。

如果,要表达的更清楚一些的话,如下:

真随机,它就像抓阄一样,没有列表的概念,也没有上一首和下一首的概念,它会随机到不同的音乐。而伪随机,是被算法所操纵的随机,算法在你选择随机播放时,一个完整的播放歌单或许就形成了。

那么如何判断是真随机还是伪随机呢?其实只要按上一首就知道了。如果切换到是你刚才听过的那一首,那就是伪随机。如果是每次都在切换不同的歌,那么就是真随机。

说到这里,大概有一个概念了,那就是大部分的音乐软件会推崇伪随机算法。为什么?

原因就是,用户选择随机播放就是为了满足自己无法下决定但又想要获得新鲜感的心理,这时就应该尽可能的避免重复和单调。如果是真随机算法的话,那么可能导致某些歌曲被播放多次,而有些歌曲则几乎不会被播放。

但这不是主要的,如果随机播放的歌是用户讨厌的呢?或者无论怎么随机播放,歌都不是用户不喜欢的,那用户会开始讨厌这个平台,平台的用户留存变少,转去其他平台。

打个比方,用户喜欢听古风歌曲,那么在它听歌时,前一首是古风,后一首就变成了嘻哈摇滚风,本来想着没准第三首就好了,结果第三首是纯音乐,换你你能接受吗?

用户的整体听歌体验都变得割裂了,于是用户转战其他平台,自己的平台用户大量流失。

那么,为了提高用户对于平台的粘滞力,伪随机是最好的选择。于是平台会干预随机列表,算法根据你平时的习惯,不断地推送那些你喜欢听的歌,迎合你的喜好。

而且,这还能让用户不需要自己搜就能找到想听的歌曲,甚至可以找到好多自己想听却忘记名字的歌了。


网站公告

今日签到

点亮在社区的每一天
去签到