Reputation: 119
I am working on a simple hangman program. I have most of the code working, but I am having trouble figuring out how to get the index of multiple matching chars in a char array. For example, I have a word "sushi" converted to a char array. If the user guesses an "s" then all "s" in the char array should be shown. The way that my code is, I actually have two char arrays of the same length. The first array holds the chars of the word to guess, while the second array holds question marks. My code should iterate through the first array and return the index of each element in the array that matches the user guess. Then, the code inserts the user guess at each specified index and displays the second array for the user. Unfortunately, only the first occurrence is changed in the second array, so only the first index is returned from the match query. The problematic code is as follows:
//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: Working off of the example in the selected answer, I updated my code as:
//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);
}
Upvotes: 1
Views: 9880
Reputation: 1045
Try Regex.Matches
to build regex expression and find all matches and their positions.
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
Upvotes: 1
Reputation: 116826
You could do something like this (made generic for clarity):
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]));
}
If performance becomes an issue, you could replace the IEnumerable<T> ofAny
with a HashSet
.
Update
Just read your code more closely and realized you are indexing through guessThis
, and for each character in guessThis
, finding its index in guessThis
and checking whether it matches thisGuess
. This is unnecessary. The simplest non-generic way to find all character indices in guessThis
matching userGuess
is probably:
var matches = Enumerable.Range(0, guessThis.Length).Where(i => guessThis[i] == userGuess);
Additional note
By the way, it probably doesn't matter for your application, but some non-ASCII Unicode characters in .Net are actually represented by surrogate pairs of chars. (There are also diacritical combining characters that modify the preceding character.) In an "internationalized" hangman game you might want to handle surrogate pairs by converting them to UTF32 code points:
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++;
}
}
Upvotes: 0
Reputation: 702
Try Something like this:
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);
A simple approach
Upvotes: 0
Reputation: 127
I think the problem is with the method: var getIndex = Array.IndexOf(guessThis, c); because it return the first location. You can just use the index you have in the for loop
Upvotes: 1
Reputation: 1097
Because your:
var getIndex = Array.IndexOf(guessThis, c);
always return the first occurance of character.
Your second for loop and the getIndex is useless, a clearer code could be:
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;
}
}
Also, your code allows user to input multiple characters into the textBox1. I think in this kind of game, only one character should be guessed each time. So I suggest your confine your input.
Upvotes: 1