Как получить индекс всех соответствующих символов в массиве символов?

1

Я работаю над простой программой палача. У меня большая часть кода работает, но мне трудно понять, как получить индекс нескольких совпадающих символов в массиве 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);
            }
Теги:
arrays
foreach
indexing
visual-studio-2010

5 ответов

1
Лучший ответ

Попробуйте 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

  • 0
    @melnikovl Спасибо за пример! К сожалению, ссылка отображается на другом языке, но я смог выяснить, что означает это выражение, и как правильно его реализовать.
  • 0
    @JustinDay, я редактировал ссылку MSDN
Показать ещё 1 комментарий
1

Я думаю, проблема связана с методом: var getIndex = Array.IndexOf(guessThis, c); потому что он возвращает первое место. Вы можете просто использовать индекс, который у вас есть в цикле for

  • 0
    Да, именно в этом и заключается проблема. Я догадался, что это то, что происходит. Спасибо за подтверждение.
1

Потому что ваш:

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. Я думаю, что в этой игре каждый раз следует угадывать только одного персонажа. Поэтому я предлагаю вам ограничить ваш вклад.

  • 0
    Этот код на самом деле не работает. Есть пара проблем. Во-первых, вы не можете использовать [i] в userGuess [i], потому что userGuess - это символ, а не массив. Вторая проблема заключается в том, что если вы удалите цикл foreach, то «c» станет недопустимой переменной, потому что это не declard, поэтому вы не можете сравнить userGuess с «c». Если вы оставите внутри цикл foreach и удалите [i], код скомпилируется, но он просто заменяет все символы в массиве displayAnswer на догадку пользователя. Кроме того, у меня уже есть реализованный код, который ограничивает пользователя одним символом и только буквами.
0

Попробуйте что-то вроде этого:

        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);

Простой подход

  • 0
    Текст, который отображается по умолчанию в метке ответа, представляет собой вопросительные знаки, содержащиеся в массиве displayAnswer. Таким образом, ничего, что пользовательские вводы на самом деле не будут совпадать. Я понимаю, что это не ясно из-за ограниченного кода, который я разместил. В противном случае это может сработать.
  • 0
    Мысль работает так: пользователь: S, метка: s? S ??
Показать ещё 1 комментарий
0

Вы могли бы сделать что-то вроде этого (сделать общий для ясности):

    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++;
        }
    }
  • 0
    @Justin Day - обновленный ответ.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню