播放列表随机播放开/关

发布于 2024-10-11 22:09:06 字数 975 浏览 8 评论 0原文

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

我有一个类似播放列表的东西,例如 List; 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 吗?嗯...

I am programming in java, but I could also adopt C++ (or even pseudo) code, no problem. Here is what I'm at:

I have something like a playlist such as List<MyPlayListItem> lsMyPlaylist. Now I want to give the user the opportunity to shuffle the items, but then also come back to the ordered list. I mean, let's say the user is in "shuffle mode", the player e.g. jumps from song 7 to 5, but then the user turns the "shuffle mode" off, 'cause he wants to hear song 6 next. How would you approach this problem?

I have several ideas:

  • to use two lists, one original, one shuffled (too much storage)
  • have a list of int's that I shuffle and then use as index to get the elements (a little better, maybe)
  • use a hashtable (the solution? I could need some advise on that, though)

Oh, and this is not a homework assignment (I wish I was that age again :-D).

EDIT:

I just finished an implementation like this:

PlayList<E> implements List {

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

   boolean bShuffleMode = false;
   int Pos = 0;
}

However now, I'm thinking of something like:

PlayListItem<E> {

   int iNextItem = 0;

}

PlayList<PlayListItem> implements List {

   private List<PlayListItem> lsObjs = null;

   boolean bShuffleMode = false;
   int Pos = 0;

}

Not sure about this...Could still need advice. Can I even implement List if I specify the objects in the list? Hm...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

冧九 2024-10-18 22:09:06

我假设您有一台移动设备,没有几 K 的空闲空间。有两个列表不会重复列表中的元素,列表的元素会大得多。

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

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

I assume you have a mobile device which doesn't have a couple of K to spare. Having two lists will not duplicate the elements of the list which will be far larger.

Add the orginal index as a field to the MyPlayListItem. After shuffling them you can sort them on the index with a comparator to turn them back into the original order. note: unless the index is less than 4 bytes this will use as much memory as having two lists.

On a 32-bit system, an int[] and a List consume almost the same amount of memory. (about 16 bytes difference)

我只土不豪 2024-10-18 22:09:06

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

之后,有很多随机播放的方法,我喜欢的最好的方法之一是在容器中放置一个歌曲列表,您可以在其中随机选择歌曲并删除选定的歌曲。所以它会是随机的,但不重复播放。

我已经很长时间没有用 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

I'd suggest that you have one main container for a list of songs (Library), and a container per playlist. Of course, playlist should point to elements in Library.

After that, there are many approaches to shuffling, one of the best that I like is to have a list of songs in a container where you pick songs at random and remove picked songs. So it will be random, but non-repeating playing.

It's been a long time since I programmed in Java, so I will give a working C++ example. I hope it is simple and self-explaining:

// --*-- 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?
        }
    }
}

Here is an example run/output:

$ ./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
空宴 2024-10-18 22:09:06

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

How about add nextSong property on MyPlayListItem that will hold a reference to next song in original playlist. Everytime user shuffles the playlist, the List will be shuffled but the original playlist will be kept. But of course you need something to hold a reference to the first MyPlayListItem in original playlist.

芸娘子的小脾气 2024-10-18 22:09:06

如果记忆力是您最大的限制,您可以选择随机歌曲在每首歌曲的末尾播放。这显然意味着您不一定会在重新开始列表之前播放每首歌曲。 :)

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

If memory is your biggest restriction you could just choose a random song to play at the end of each song. It obviously means you will not necessarily play every song before starting the list again. :)

If you need to play every song before starting to play songs again then store a bitstring of length equal to the number of songs. As you play songs set the bit corresponding to that index. Never play a song if it's bit is set, instead at that point increment the index until you find a bit in the string that isn't set. If all bits in the string are set then reset the bit string.

孤独患者 2024-10-18 22:09:06

简单的事情怎么样?

使用列表中的索引指针,例如整数。这是当前正在播放的歌曲。当播放器处于随机播放模式时,此指针会设置为 0 到列表中项目数 - 1 之间的随机数。当播放器处于顺序模式时,此指针会简单地递增。

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

当已播放歌曲与未播放歌曲的比例变高并且列表中始终存在随机索引时,您会遇到问题。

What about something simple?

Use an index pointer into the list, say an integer. This is the current song being played. When the player is in shuffle mode, this pointer gets set to a random number between 0 and the number of items in the list - 1. When the player is in sequential mode, this pointer is simply incremented.

If you want to prevent repetition of songs, there are two strategies. One is to use a bit string, as another person suggested above. The other would be to use a set. Each time the pointer is set, check for membership in the set. If it's in the set already, get another index. If it's not, then add it and play the song. Either will accomplish the same effect.

You will run into problems when the ratio of played songs to unplayed songs becomes high with a random index always being in the list.

凤舞天涯 2024-10-18 22:09:06

您可以拥有两件物品:
1) 列表中真实项目的列表
2) 具有整数索引的向量

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

像这样的东西:

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

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

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

You can have two items :
1) list of real items in a list
2) vector with integer indexes

When the shuffle is activated, you shuffle indexes. When it is off, sort indexes. When accessing elements in the list, use indexes.

something like this :

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

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

// get elements
elements[ indexes[ i ] ];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文