2

私はJavaでプログラミングしていますが、C ++(または疑似)コードを採用することもできます。問題ありません。これが私がいるところです:

のようなプレイリストのようなものがありList<MyPlayListItem> lsMyPlaylistます。ここで、ユーザーにアイテムをシャッフルする機会を与えたいと思いますが、その後、注文リストに戻ります。つまり、ユーザーが「シャッフルモード」になっているとしましょう。たとえば、プレーヤーは曲7から5にジャンプしますが、次に曲6を聞きたいので、ユーザーは「シャッフルモード」をオフにします。この問題にどのようにアプローチしますか?

私にはいくつかのアイデアがあります:

  • 2つのリストを使用するには、1つはオリジナル、もう1つはシャッフル(ストレージが多すぎる)
  • シャッフルしてから要素を取得するためのインデックスとして使用する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;

}

これについてはよくわかりません...まだアドバイスが必要な場合があります。リスト内のオブジェクトを指定した場合でも、リストを実装できますか?うーん...

4

6 に答える 6

2

曲のリスト (ライブラリ) 用のメイン コンテナーを 1 つと、プレイリストごとにコンテナーを 1 つ用意することをお勧めします。もちろん、プレイリストはライブラリ内の要素を指す必要があります。

その後、シャッフルには多くのアプローチがありますが、私が気に入っている最良の方法の 1 つは、ランダムに曲を選択して選択した曲を削除するコンテナーに曲のリストを用意することです。したがって、ランダムですが、繰り返し再生されません。

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
于 2011-01-14T16:44:00.983 に答える
2

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.

于 2011-01-15T04:06:40.380 に答える
2

数 K も余裕のないモバイル デバイスをお持ちだと思います。2 つのリストを使用しても、リストの要素が重複することはなく、はるかに大きくなります。

元のインデックスをフィールドとして MyPlayListItem に追加します。それらをシャッフルした後、コンパレータを使用してインデックスで並べ替えて、元の順序に戻すことができます。注: インデックスが 4 バイト未満でない限り、これは 2 つのリストを持つのと同じくらい多くのメモリを使用します。

32 ビット システムでは、int[] と List はほぼ同じ量のメモリを消費します。(約16バイトの差)

于 2011-01-14T16:11:33.293 に答える
1

シンプルなものはどうですか?

リストへのインデックス ポインタ、たとえば整数を使用します。現在再生中の曲です。プレーヤーがシャッフル モードの場合、このポインターは 0 からリスト内の項目数 - 1 までの乱数に設定されます。プレーヤーがシーケンシャル モードの場合、このポインターは単純にインクリメントされます。

曲の重複を防ぎたい場合、2 つの戦略があります。1 つは、別の人が上で提案したように、ビット文字列を使用することです。もう1つはセットを使用することです。ポインターが設定されるたびに、セット内のメンバーシップを確認します。すでにセットにある場合は、別のインデックスを取得します。そうでない場合は、追加して曲を再生します。どちらでも同じ効果が得られます。

再生済みの曲と未再生の曲の比率が高くなり、ランダムなインデックスが常にリストにある場合、問題が発生します。

于 2011-01-14T16:36:18.430 に答える
1

メモリが最大の制限である場合は、各曲の最後に再生する曲をランダムに選択できます。これは明らかに、リストを再開する前に必ずしもすべての曲を再生するとは限らないことを意味します。:)

曲の再生を再開する前にすべての曲を再生する必要がある場合は、曲の数に等しい長さのビット文字列を格納します。曲を再生すると、そのインデックスに対応するビットが設定されます。ビットが設定されている場合は曲を再生しないでください。代わりに、その時点で、設定されていないビットが文字列に見つかるまでインデックスを増やします。文字列内のすべてのビットが設定されている場合は、ビット文字列をリセットします。

于 2011-01-14T16:22:14.053 に答える
0

2 つの項目を持つことができます:
1) リスト内の実際の項目のリスト
2) 整数インデックスを持つベクトル

シャッフルを有効にすると、インデックスがシャッフルされます。オフの場合、インデックスをソートします。リスト内の要素にアクセスするときは、インデックスを使用します。

このようなもの :

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

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

// get elements
elements[ indexes[ i ] ];
于 2011-01-14T16:23:26.377 に答える