Я работаю над простой программой палача. У меня большая часть кода работает, но мне трудно понять, как получить индекс нескольких совпадающих символов в массиве char. Например, у меня есть слово "суши", преобразованное в массив символов. Если пользователь угадывает "s", тогда все "s" в массиве char должны быть показаны. Как мой код, у меня на самом деле есть два массива символов одинаковой длины. Первый массив содержит символы слова для угадывания, тогда как второй массив содержит вопросительные знаки. Мой код должен проходить через первый массив и возвращать индекс каждого элемента в массиве, который соответствует догадке пользователя. Затем код вставляет пользователя в каждый указанный индекс и отображает второй массив для пользователя. К сожалению, во втором массиве изменяется только первое вхождение, поэтому из запроса соответствия возвращается только первый индекс. Проблемный код выглядит следующим образом:
//check if char array contains the user input
if (guessThis.Contains(Convert.ToChar(textBox1.Text)))
{
//save user input as char
char userGuess = Convert.ToChar(textBox1.Text);
//iterate through first char array
for (int i = 0; i < guessThis.Length - 1; i++ )
{
//check each element in the array
//probably don't need both for and foreach loops
foreach (char c in guessThis)
{
//get index of any element that contains the userinput
var getIndex = Array.IndexOf(guessThis, c);
//check if the element matches the user guess
if (c == userGuess)
{
//insert the userguess into the index
displayAnswer[getIndex] = userGuess;
}
}
}
//update the display label
answerLabel.Text = new string(displayAnswer);
SOLVED: отключение примера в выбранном ответе, я обновил свой код как:
//check if char array contains the user input
if (guessThis.Contains(Convert.ToChar(textBox1.Text)))
{
//save user input as char
char userGuess = Convert.ToChar(textBox1.Text);
string maybeThis = textBox1.Text;
string tryThis = new string(guessThis);
foreach (Match m in Regex.Matches(tryThis, maybeThis))
{
displayAnswer[m.Index] = userGuess;
}
answerLabel.Text = new string(displayAnswer);
}
Попробуйте Regex.Matches
чтобы создать выражение регулярного выражения и найти все совпадения и их позиции.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = "a*";
string input = "abaabb";
foreach (Match m in Regex.Matches(input, pattern))
Console.WriteLine("'{0}' found at index {1}.",
m.Value, m.Index);
}
}
// The example displays the following output:
// 'a' found at index 0.
// '' found at index 1.
// 'aa' found at index 2.
// '' found at index 4.
// '' found at index 5.
// '' found at index 6.'
http://msdn.microsoft.com/en-gb/library/system.text.regularexpressions.regex.matches(v=vs.110).aspx
Я думаю, проблема связана с методом: var getIndex = Array.IndexOf(guessThis, c); потому что он возвращает первое место. Вы можете просто использовать индекс, который у вас есть в цикле for
Потому что ваш:
var getIndex = Array.IndexOf(guessThis, c);
всегда возвращают первое появление символа.
Ваш второй цикл for и getIndex бесполезен, более понятный код может быть:
for (int i = 0; i < guessThis.Length - 1; i++ )
{
//check if the element matches the user guess
if (c == userGuess[i])
{
//insert the userguess into the index
displayAnswer[i] = userGuess;
}
}
Кроме того, ваш код позволяет пользователю вводить несколько символов в textBox1. Я думаю, что в этой игре каждый раз следует угадывать только одного персонажа. Поэтому я предлагаю вам ограничить ваш вклад.
Попробуйте что-то вроде этого:
char userGuess = Convert.ToChar(textBox1.Text);
char[] displayAnswer = answerLabel.Text.ToCharArray();
for (int n = 0; n < displayAnswer.Length; n++)
{
if (guessThis[n] == userGuess)
{
displayAnswer[n] = userGuess;
}
}
answerLabel.Text = new string(displayAnswer);
Простой подход
Вы могли бы сделать что-то вроде этого (сделать общий для ясности):
public static IEnumerable<int> AllIndexesOfAny<T>(this IList<T> list, IEnumerable<T> ofAny)
{
return Enumerable.Range(0, list.Count).Where(i => ofAny.Contains(list[i]));
}
Если производительность становится проблемой, вы можете заменить IEnumerable<T> ofAny
на HashSet
.
Обновить
Просто внимательно прочитайте свой код и guessThis
, что вы индексируете через guessThis
, и для каждого символа в guessThis
, находя его индекс в guessThis
и проверяя, соответствует ли он thisGuess
. Это не нужно. Простейший не общий способ найти все индексы персонажей в guessThis
соответствующие userGuess
, вероятно:
var matches = Enumerable.Range(0, guessThis.Length).Where(i => guessThis[i] == userGuess);
Дополнительное примечание
Кстати, это, вероятно, не имеет значения для вашего приложения, но некоторые символы Unicode, отличные от ASCII в.Net, фактически представлены суррогатными парами символов. (Есть также диакритические комбинации символов, которые изменяют предыдущий символ.) В "интернационализированной" игре палача вы можете обрабатывать суррогатные пары, преобразовывая их в кодовые точки UTF32:
public static IEnumerable<KeyValuePair<int, int>> Utf32IndexedCodePoints(this string s, int index)
{
for (int length = s.Length; index < length; index++)
{
yield return new KeyValuePair<int, int>(index, char.ConvertToUtf32(s, index));
if (char.IsSurrogatePair(s, index))
index++;
}
}