Как выбрать случайную строку из массива строк только один раз

Я пытаюсь сделать Hangman на С#, и в начале игры вам понадобится слово, чтобы догадаться, и поэтому игра не будет скучной, вы можете получить много слов (только по одному). Но когда вы начинаете новую игру, вы не получите ни слова, которое вы уже догадались. Поэтому я должен выбрать случайную строку, которую я уже выбрал.

Я попробовал несколько методов для решения этой проблемы, но ни один из них не прошел.

Способ №1:

Здесь я запускаю функцию NewWord, а затем добавляю 1 к numberOfTries.

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, а затем добавляю 1 к numberOfTries.

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!! :(";
 }
}
</string>

Я также попробовал версию, в которой у меня было два разных массива: один - Int-Array, а второй - String-Array. Это было действительно грязно и не сработало.

Я также очень новичок в С#, я знаю только основы, такие как + -/*, convert, functions и массивы.

6 ответов

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;
}
</string></string>


Если вы перетасовываете свой массив слов:

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

затем вставьте свои слова в стек:

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

теперь у вас есть структура, которая передаст вам случайное слово из коллекции, одновременно удалив его из коллекции, используя метод Pop из Stack (значительно более эффективно, чем удаление элементов из передней/средней List, хотя ваша коллекция настолько мала, это не имеет большого значения).

var someWord = wordStack.Pop();


Концептуально вы либо отслеживаете строки, которые вы уже использовали, либо удаляете строки из списка необязательных строк по мере их использования.

Чтобы реализовать первый метод, вы можете сохранить хеш-таблицу строк, которые вы уже использовали, и когда вытягиваете новую строку - посмотрите, присутствует ли она в хэш-таблице (и если да, выберите другую, пока не появится "свежая" строка выбрал).

Чтобы реализовать второй метод, просто удалите строки, которые вы выбрали из списка, когда вы их выбираете.


Используйте ************.

Ключ будет вашим словом, значение будет сколько раз его использовать, затем просто возьмите наименее используемое слово и увеличите его счетчик.

List<************<string, int="">>
</************<string,>


Вы должны представить WordArr как список. Это проще для работы с учетом ваших потребностей.

Здесь простой способ рандомизировать ваш список:

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

Затем просто выберите первое слово в списке, чтобы просто удалить каждое слово, которое вы используете следующим образом:

wordArr.RemoveAt(0);

Когда wordArr пуст, вы закончите.


Поскольку вы сказали, что новичок в программировании, я быстро объясню ключевую строку:

.Except() сравнивает ваш массив с другим массивом и возвращает только уникальные элементы. .OrderBy(x => 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" };
}

licensed under cc by-sa 3.0 with attribution.