我试图通过更改索引来随机更改数组的元素。没关系。现在的问题是,由于随机总是随机的,我可以得到两个相同的结果。
例如: 星期一: 歌1 歌2 歌3 星期二: 歌2 歌1 歌3 星期三: 歌1 歌2 歌3
等等..。
和名单
星期一
和
星期三
在这种情况下是一样的。我需要控制它,但是正如您在代码中所看到的,一旦我从一天中得到列表,我就会打印出来。我想把它放在一个数组或元组上,并检查这个元组是否存在,但我认为太复杂了。我想也许我可以做我自己的随机函数。不过,我也不确定这个解决方案。我有什么办法解决这个问题吗?谢谢!
下面是我到目前为止掌握的代码:
static string[] songs = new string[] { "song1", "song2", "song3" };
static string[] days = new string[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
private static Random random = new Random();
/* Random number between lower and higher, inclusive */
public static int rand(int lower, int higher)
{
int r = lower + (int)(random.Next(0, 2) * (higher - lower));
return r;
}
/* pick M elements from original array. Clone original array so that
7 * we don’t destroy the input. */
public static string[] pickMRandomly()
{
string[] subset = new string[songs.Length];
string[] array = (string[])songs.Clone();
for (int j = 0; j < songs.Length; j++)
{
int index = rand(j, array.Length - 1);
subset[j] = array[index];
array[index] = array[j]; // array[j] is now “dead”
}
return subset;
}
public static void playListCreation()
{
for (int j = 0; j < days.Length; j++)
{
var result =pickMRandomly();
System.Console.WriteLine(days[j]);
foreach (var i in result)
{
System.Console.WriteLine(i + " ");
}
System.Console.WriteLine("/n");
}
}
}发布于 2016-06-19 11:19:28
如果我对你的理解是正确的,你不只是想要每天的歌曲的随机排列,你要的是每天独特的(随机的)歌曲安排。
我唯一能保证这一点的方法就是找出所有可能的歌曲组合,并随机排序--然后每天从列表中挑选一个不同的组合。
using System;
using System.Collections.Generic;
using System.Linq;
namespace StackOverflowAnswer
{
class Program
{
static string[] songs = new string[] { "song1", "song2", "song3" };
static string[] days = new string[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
static void Main(string[] args)
{
var rnd = new Random();
var allCombinationsInRandomOrder = GetCombinations(songs, songs.Length)
.Select(combination => new { Combination = combination, Order = rnd.Next() })
.OrderBy(entry => entry.Order)
.Select(entry => entry.Combination);
var dayIndex = 0;
foreach (var combination in allCombinationsInRandomOrder)
{
var day = days[dayIndex];
Console.WriteLine(day);
Console.WriteLine(string.Join(", ", combination));
dayIndex++;
if (dayIndex >= days.Length)
break;
}
Console.ReadLine();
}
private static IEnumerable<IEnumerable<string>> GetCombinations(IEnumerable<string> songs, int numberOfSongsInGeneratedLists)
{
if (songs == null)
throw new ArgumentNullException(nameof(songs));
if (numberOfSongsInGeneratedLists <= 0)
throw new ArgumentOutOfRangeException(nameof(numberOfSongsInGeneratedLists));
if (numberOfSongsInGeneratedLists > songs.Count())
throw new ArgumentOutOfRangeException("can't ask for more songs in the returned combinations that are provided", nameof(numberOfSongsInGeneratedLists));
if (numberOfSongsInGeneratedLists == 1)
{
foreach (var song in songs)
yield return new[] { song };
yield break;
}
foreach (var combinationWithOneSongTooFew in GetCombinations(songs, numberOfSongsInGeneratedLists - 1))
{
foreach (var song in songs.Where(song => !combinationWithOneSongTooFew.Contains(song)))
yield return combinationWithOneSongTooFew.Concat(new[] { song });
}
}
}
}发布于 2016-06-19 11:18:48
据我所知,您想要创建一个随机播放列表,如果这个播放列表是以前创建的,那么您希望生成另一个播放列表(直到它是唯一的)。您可以这样做的一种方法是向HashSet中添加某种类型的散列,并查看它以前是否已经生成。例如,
bool HashSet<int> playlistHashes = new HashSet<int>();
private bool CheckIfUnique(string[] playlist)
{
//HashSet returns false if the hash already exists
//(i.e. playlist already likely to have been created)
return playlistHashes.Add(string.Join("",playlist).GetHashCode());
}然后,一旦生成了播放列表,就可以调用该方法,并查看它是否返回false。如果它返回false,则以前已经创建了播放列表顺序,因此您可以再次生成。使用上述技术意味着song1, song2, song3与song3, song2, song1不同,因此顺序非常重要。
正如我对这个问题的评论中提到的,如果你用3首歌测试,每周只有6个不同的排列和7天,所以你会得到一个副本。
附带注意,GetHashCode可以抛出“假阳性”,但这取决于您确定它有多大的可能性,以及它的影响是否真的有任何意义,因为新的播放列表是生成的。好线程获得更多信息,here。如果GetHashCode在这里还不够的话,有很多哈希技术可以降低碰撞的几率。
发布于 2016-06-20 03:09:37
考虑到您手头有3 Songs,并且希望为一周中的每一天(7天)分配独特的组合。这是不可能的,因为你只能做六个独特的组合与这三个。所以肯定有一个重复的序列。如果将另一首歌曲(让它是24 )添加到这个集合中,您将得到"song4"唯一的歌曲序列。我已经包括了一个片段,帮助您获得这些独特的歌曲序列组合。
string[] songs = new string[] { "song1", "song2", "song3", "song4" };
int numberOfSongs = songs.Count();
var collection = songs.Select(x => x.ToString()); ;
for (int i = 1; i < numberOfSongs; i++)
{
collection = collection.SelectMany(x => songs, (x, y) => x + "," + y);
}
List<string> SongCollections = new List<string>();
SongCollections.AddRange(collection.Where(x => x.Split(',')
.Distinct()
.Count() == numberOfSongs)
.ToList());现在,SongCollections将包含24独特的4歌曲序列。(如果您选择3首歌曲,那么您将得到6独特的序列)。您可以从这些集合中随机选择序列,并根据您的意愿将其分配给天数。
现在,让我使用一个Dictionary<string, int> dayCollectionMap将一个集合映射到一天(注意:,这里我使用了一个4歌曲集合,因为对于7 days来说,3是不够的)。考虑下面的片段:
Dictionary<string, int> dayCollectionMap = new Dictionary<string, int>();
string[] days = new string[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
Random randomCollection = new Random();
foreach (string day in days)
{
int currentRandom = randomCollection.Next(0, SongCollections.Count());
if (!dayCollectionMap.Any(x => x.Value == currentRandom))
{
dayCollectionMap.Add(day, currentRandom);
}
else
{
// The collection is already taken/ Add another random sequence
while (true)
{
currentRandom = randomCollection.Next(0, SongCollections.Count());
if (!dayCollectionMap.Any(x => x.Value == currentRandom))
{
dayCollectionMap.Add(day, currentRandom);
break;
}
}
}
}以便您可以使用以下代码为Wednesday选择歌曲集合
var songCollectionForWed = SongCollections[dayCollectionMap["Wednesday"]];https://stackoverflow.com/questions/37906373
复制相似问题