播放列表随机播放

时间:2011-01-14 16:05:00

标签: java c++ list shuffle

我在java编程,但我也可以采用C ++(甚至伪)代码,没问题。这就是我的目标:

我有类似播放列表的内容,例如List<MyPlayListItem> lsMyPlaylist。现在我想给用户提供随机播放项目的机会,但随后又回到有序列表中。我的意思是,假设用户处于“随机播放模式”,播放器例如从歌曲7跳到5,然后用户关闭“随机播放模式”,因为他想要听到下一首歌曲6。你会如何处理这个问题?

我有几点想法:

  • 使用两个列表,一个原始,一个洗牌(太多存储)
  • 有一个我洗牌的int列表,然后用作索引来获取元素(可能会更好一些)
  • 使用哈希表(解决方案?我可能需要一些建议),

哦,这不是家庭作业(我希望我再次成为那个年龄:-D)。

编辑:

我刚刚完成了这样的实现:

PlayList<E> implements List {

   private List<E> lsObjs = null;
   private List<Integer> lsIdxs = null;

   boolean bShuffleMode = false;
   int Pos = 0;
}

但是现在,我想的是:

PlayListItem<E> {

   int iNextItem = 0;

}

PlayList<PlayListItem> implements List {

   private List<PlayListItem> lsObjs = null;

   boolean bShuffleMode = false;
   int Pos = 0;

}

对此不确定......仍然需要建议。如果我在列表中指定对象,我是否可以实现List?嗯...

6 个答案:

答案 0 :(得分:2)

我假设你有一个移动设备没有几个K备用。拥有两个列表不会复制列表中要大得多的元素。

将原始索引作为字段添加到MyPlayListItem。在对它们进行洗牌后,您可以使用比较器对索引进行排序,以将它们重新调整为原始顺序。注意:除非索引小于4个字节,否则将使用与具有两个列表一样多的内存。

在32位系统上,int []和List消耗的内存量几乎相同。 (约16字节差异)

答案 1 :(得分:2)

我建议您有一个主容器用于歌曲列表(库),以及每个播放列表的容器。当然,播放列表应该指向库中的元素。

在那之后,有很多方法可以改组,我喜欢的最好的方法之一就是在一个容器中有一个歌曲列表,你可以随机选择歌曲并删除选中的歌曲。所以这将是随机的,但不是重复播放。

自从我用Java编程以来已经很长时间了,所以我将给出一个有效的C ++示例。我希望它简单而自我解释:

// --*-- C++ --*--

#include <ctime>
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <vector>
#include <list>

struct Song
{
    std::string name;

    Song (const std::string & name) :
        name (name)
    {
    }

    void play ()
    {
        printf ("Playing '%s'...\n", name.c_str ());
    }
};

typedef std::vector<Song> Library;
typedef std::vector<Song *> Playlist;
typedef std::vector<size_t> SongIDSet;

int
main ()
{
    srand (time (NULL));

    Library library;

    library.push_back (Song ("Lady Gaga - Bad Romance"));
    library.push_back (Song ("Rihanna - Only Girl"));
    library.push_back (Song ("Nelly - Just a Dream"));
    library.push_back (Song ("Animal - Neon Trees"));
    library.push_back (Song ("Eminem ft. Rihanna - Love The Way You Lie"));

    Playlist playlist;

    for (Library::iterator it = library.begin (),
             end_it = library.end (); it != end_it; ++it)
    {
        printf ("Added song -> %s\n", it->name.c_str ());
        playlist.push_back (&(*it));
    }

    SongIDSet shuffle;
    for (size_t i = 0, end_i = playlist.size (); i < end_i; ++i)
    {
        shuffle.push_back (i);
    }

    size_t nowPlaying = 0;

    while (!shuffle.empty ())
    {
        size_t songIndex = 0;
            printf ("Shuffle? [Y/n] ");
        switch (fgetc (stdin))
        {
            case 'N':
            case 'n':
                songIndex = nowPlaying + 1;
                fgetc (stdin); // Skip newline.
                break;
            case 'Y':
            case 'y':
                fgetc (stdin); // Skip newline.
            default:
            {
                printf ("Shuffling...\n");
                size_t index = rand () % shuffle.size ();
                assert (index >= 0);
                assert (index < shuffle.size ());
                songIndex = shuffle[index];
                shuffle.erase (shuffle.begin () + index);
            }
        }
        assert (songIndex >= 0);
        if (songIndex < playlist.size ())
        {
            nowPlaying = songIndex;
            playlist[nowPlaying]->play ();
        }
        else
        {
            break; // Done playing.. Repeat maybe?
        }
    }
}

以下是运行/输出示例:

$ ./test 
Added song -> Lady Gaga - Bad Romance
Added song -> Rihanna - Only Girl
Added song -> Nelly - Just a Dream
Added song -> Animal - Neon Trees
Added song -> Eminem ft. Rihanna - Love The Way You Lie
Shuffle? [Y/n] 
Shuffling...
Playing 'Eminem ft. Rihanna - Love The Way You Lie'...
Shuffle? [Y/n] 
Shuffling...
Playing 'Nelly - Just a Dream'...
Shuffle? [Y/n] 
Shuffling...
Playing 'Rihanna - Only Girl'...
Shuffle? [Y/n] 
Shuffling...
Playing 'Animal - Neon Trees'...
Shuffle? [Y/n] 
Shuffling...
Playing 'Lady Gaga - Bad Romance'...
$ ./test 
Added song -> Lady Gaga - Bad Romance
Added song -> Rihanna - Only Girl
Added song -> Nelly - Just a Dream
Added song -> Animal - Neon Trees
Added song -> Eminem ft. Rihanna - Love The Way You Lie
Shuffle? [Y/n] 
S    huffling...
Playing 'Nelly - Just a Dream'...
Shuffle? [Y/n] n
Playing 'Animal - Neon Trees'...
Shuffle? [Y/n] n
Playing 'Eminem ft. Rihanna - Love The Way You Lie'...
Shuffle? [Y/n] n

答案 2 :(得分:2)

如何在MyPlayListItem上添加nextSong属性,该属性将保存对原始播放列表中下一首歌曲的引用。每当用户随机播放播放列表时,列表将被随机播放,但原始播放列表将被保留。但是,您当然需要一些东西来引用原始播放列表中的第一个MyPlayListItem

答案 3 :(得分:1)

如果记忆是你最大的限制,你可以在每首歌的结尾选择一首随机歌曲。这显然意味着你不必在再次开始列表之前播放每首歌曲。 :)

如果您需要在开始再次播放歌曲之前播放每首歌曲,请存储长度等于歌曲数量的位串。播放歌曲时,设置与该索引对应的位。如果设置了位,则不要播放歌曲,而是在该点增加索引,直到找到未设置的字符串中的某个位。如果设置了字符串中的所有位,则重置位串。

答案 4 :(得分:1)

简单的事情呢?

在列表中使用索引指针,比如一个整数。这是正在播放的当前歌曲。当播放器处于随机播放模式时,此指针将被设置为0和列表中项目数之间的随机数 - 1.当播放器处于顺序模式时,此指针只会递增。

如果你想防止重复歌曲,有两种策略。一种是使用位串,如上面建议的另一个人。另一种是使用一套。每次设置指针时,检查集合中的成员资格。如果它已经在集合中,则获取另一个索引。如果不是,那就添加它并播放歌曲。要么达到同样的效果。

当播放的歌曲与未播放的歌曲的比例变高且随机索引始终位于列表中时,您将遇到问题。

答案 5 :(得分:0)

您可以有两个项目:
1)列表中的实际项目列表
2)具有整数索引的向量

当shuffle被激活时,你会随机播放索引。关闭时,对索引进行排序。访问列表中的元素时,请使用索引。

类似的东西:

std::list< MyListElement > elements = ...;
std::vector< int > indexes = ...;

// shuffle off
sort( indexes.begin(), indexes.end() );

// get elements
elements[ indexes[ i ] ];