如何从字符串数组中只选择一次随机字符串

时间:2014-03-01 23:10:10

标签: c# arrays string random combinations

我正在尝试用C#制作Hangman,并且在游戏开始时你需要一个词来猜测,所以游戏不会无聊你可以得到很多单词(一次只有一个)。但是当你开始一个新游戏时,你不会得到你已经猜到的一个词。所以我必须选择一个我尚未选择的随机字符串。

我尝试过多种方法来解决这个问题,但没有一种方法能够成功。

方法#1:

这里我运行NewWord函数,然后在numberOfTries中添加1。

string[] wordArr = { "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL", "STUDIO" };
int numberOfTries = 0;
int randomNumber = -1;


protected string NewWord()
{
    if (!(numberOfTries >= wordArr.Length))
    {
        randomNumber = RandomNumberFromTo(0, (wordArr.Length - numberOfTries));

        ChangeWord(((wordArr.Length - numberOfTries)-1), randomNumber);

        return wordArr[(randomNumberl)];
    }
    else
    {
        return "There are no more new words!! :(";
    }
}


private int RandomNumberFromTo(int NumberA, int NumberB)
{
    System.Threading.Thread.Sleep(2);
    Random minRandomGenerator = new Random();
    System.Threading.Thread.Sleep(3);
    return minRandomGenerator.Next(NumberA, NumberB);
}



protected void ChangeWord (int NumberA, int NumberB)
{
    string cashe1 = wordArr[NumberA];
    wordArr[NumberA] = wordArr[NumberB];
    wordArr[NumberB] = cashe1;
    return;
}

方法#2我在StackOverflow上找到了它,但它没有用。

这里我还运行NewWord函数,然后在numberOfTries中添加1。

string[] wordArr = { "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL", "STUDIO" };       
int numberOfTries = 0;
Random random = new Random();
protected string NyttOrd()
{
    if (!(numberOfTries >= wordArr.Length))
    {
        var names = new List<string> { "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL", "STUDIO" };

        System.Threading.Thread.Sleep(3);
        int index = random.Next(names.Count);
        var name = names[index];
        names.RemoveAt(index);
        return name;
    }
    else
    {
        return "There are no more new words!! :(";
    }
}

我还尝试了一个版本,其中我有两个不同的数组,一个是Int-Array,另一个是String-Array。这真的很乱,没用。

我也是C#的新手我只知道基础知识,比如+ - / *,转换,函数和数组。

6 个答案:

答案 0 :(得分:2)

从概念上讲,您要么跟踪已经使用过的字符串,要么在使用它们时从可选字符串列表中删除字符串。

要实现第一种方法,您可以保留已经使用的字符串的散列表,并在拉出新字符串时 - 查看它是否存在于散列表中(如果是,请选择另一个,直到“新鲜” “挑选字符串。”

要实现第二种方法,只需在选择时删除从列表中选取的字符串。

答案 1 :(得分:2)

如果你改变你的单词数组:

var r = new Random();
var shuffledWords = wordArr.OrderBy(_ => r.Next());

然后将你的单词推入堆栈:

var wordStack = new Stack<string>(shuffledWords);

现在你有了一个结构,可以使用Pop Stack<T>方法从集合中随机删除它,同时从集合中移除它(比从前面删除项目要高效得多)在List<T>的中间,虽然你的收藏很小,但这并不重要。)

var someWord = wordStack.Pop();

答案 2 :(得分:0)

static readonly List<string> Words = new List<string>(wordArr);
static readonly Random Rnd = new Random();

public string Next()
{
    if(Words.Count < 1)
        return "There are no more new words!! :(";

    var index = Rnd.Next(0, Words.Length);
    var result = Words[index];
    Words.RemoveAt(index);

    return result;
}

答案 3 :(得分:0)

使用KeyValuePair

键将是你的词,值将是它被使用了多少次,然后只取最少使用的词并增加它的计数器。

List<KeyValuePair<string, int>>

答案 4 :(得分:0)

既然你说过你是编程新手,我会快速解释一下关键线:

.Except()将您的数组与另一个数组进行比较,并仅返回唯一元素。 .OrderBy(x =&gt; rn.Next())将以随机顺序返回数组。 .FirstOrDefault()将从数组中获取第一个条目,如果数组为空,则返回null。

public void GenerateWord()
{
    Random rn = new Random();
    string[] attemptedWords = LoadUsedWords();
    string[] wordArr = { "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL", "STUDIO" };
    string word = wordArr.Except(attemptedWords).OrderBy(x => rn.Next()).FirstOrDefault();
    if (string.IsNullOrEmpty(word))
    {
        Console.WriteLine("Oh no");
    }
    else
    {
        Console.WriteLine(word);
    }
}

public string[] LoadUsedWords()
{
    return new string[] { "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL" };
}

答案 5 :(得分:0)

您应该将WordArr列为清单。它可以更轻松地满足您的需求。

这是一种随机化列表的简便方法:

List<string> wordArr = new List<string>()
{
    "PROGRAMMERING", "CSHARP", "STOL", "ELEV", "VISUAL", "STUDIO"
};
Random random = new Random();
wordArr = wordArr.OrderBy(x => random.Next()).ToList();

然后只需要总是拿下列表中的第一个单词,这样就可以简单地删除你使用的每个单词:

wordArr.RemoveAt(0);

wordArr为空时,您就完成了。