Hej, does anyone know how i can make my method for guessing letters remember
the guesses before? Currently it turns all the "right" guesses into the last right letter guessed :(
public void myGuess(char letter)
{
string wordToGuess = label4.Text;
string wordToShow = label5.Text;
for (int i = 0; i < wordToGuess.Length; i++)
{
if (wordToGuess[i] == letter || wordToGuess[i] == wordToShow[i])
wordToShow = wordToShow.Remove(i, 1).Insert(i, Char.ToString(letter));
}
label5.Text = wordToShow;
if (wordToGuess == wordToShow)
this.Close();
Form Win = new Win();
Win.Show();
}
Have a global list of char and add to it after every guess
List<char> guesses = new List<char>();
Then in your method just add to it
guesses.Add(letter);
and then you can check using this
if (guesses.Contains(letter))
{
//DoSomething
}
The problem is with your loop.
Your test checks if the character equals either the guessed letter or the letter at the same position in the already guessed words.
If the test succeeds you then effectively replace the value with the guessed letter.
You need to either remove the second part of the test:
if (wordToGuess[i] == letter)
wordToShow = wordToShow.Remove(i, 1).Insert(i, Char.ToString(letter));
or change the replacement
if (wordToGuess[i] == letter || wordToGuess[i] == wordToShow[i])
wordToShow = wordToShow.Remove(i, 1).Insert(i, Char.ToString(wordToShow[i]));
Also instead of removing/inserting if you change the wordToShow to a char array first you can then just directly change it's value and convert back to a string when finished, this makes the code a little easier to read. It may also be better performance than all the insert/removes.
var newWord = wordToShow.ToCharArray();
for (var i = 0; i<wordToGuess.Length; i++) {
if (wordToGuess[i] == letter) {
newWord[i] = letter;
}
}
wordToGuess = new string(newWord);
Related
string sentence = "This is a goodday";
string word = "good";
I know this can be done with .Contains() method. I was asked in an interview how to do it without contains method.
how to do it in english.
pick the first letter of word.
walk down sentence a character at a time till you find that letter
now look at the next letters in sentence to see if they are the rest of that word
yes - done
no - keep going
the thing to use is that word[x] is the x-1th character of word, so you just need 2 indexes and a loop or 2
Q: Check if a word exists in another string in c# without using any inbuilt function
A: Tricky
It depends on how detailed that "any inbuilt function" really is.
In general the algorithm is simple:
Loop through the string you're searching in
for each position, see if you've found the word
you do this by looping through all the characters in what we're looking for
and compare each character from the first string with one from the second
if they all matched, we've found a match
but then ... "without using any inbuilt function".
I assume this would mean, do not use the obvious ones, such as Contains, IndexOf, a regular expression, all those things.
But taken to the extreme, does that mean I cannot even know how long the strings are? Is s.Length a built-in function? And thus not allowed?
public bool Contains(string value, string whatWereLookingFor)
{
return IndexOf(value, whatWereLookingFor) >= 0;
}
public int Length(string s)
{
int result = 0;
for (int i = 0; i <= 2147483647; i++)
{
try
{
char c = s[i];
}
catch (IndexOutOfRangeException)
{
break;
}
result = i + 1;
}
return result;
}
public int IndexOf(string value, string whatWereLookingFor)
{
int iMax = Length(value);
int whatMax = Length(whatWereLookingFor);
for (int i = 0; i <= iMax - whatMax; i++)
{
bool isMatch = true;
for (int j = 0; j < whatMax; j++)
{
if (value[i + j] != whatWereLookingFor[j])
{
isMatch = false;
break;
}
}
if (isMatch)
return i;
}
return -1;
}
How about using a for loop?
Loop through the sentence checking for the first character of the work. Once you find that check for the next character of the word until you find the whole word (done - word exists in sentence) or a different character so you start again looking for the first character of the word until you run out of characters.
As the comments say, it would have been nicer to let us know what you answered.
try this:
static bool checkString(string inputString="",string word="")
{
bool returV=false;
if(inputString =="" || word=="")
return false;
int intexcS=0;
Dictionary<int,string> d = new Dictionary<int, string>();
foreach (char cW in word)
{
foreach (char cS in inputString)
{
if(cW==cS){
if(!d.ContainsKey(intexcS) && d.Count<word.Length){
d.Add(intexcS,cW.ToString());
}
}
intexcS++;
}
intexcS=0;
}
int i=0;
foreach(var iitem in d) { if(iitem.Value!=word[i].ToString()) returV=false; else returV=true; i++; }
return returV;
}
I am trying to create a hangman game that picks a random word from a text file and then displays the word as asterisks and has the user guess the letters of the word. If the user guesses correct then the letter gets uncovered and they keep guessing until they uncover the word. It will then display the number of misses and ask if the user wants to try to guess another word.
The problem I am having is when you try to guess the first letter in any word and guess it correctly it still says its incorrect and doesn't uncover the word.The other letters uncover but you then keep guessing forever because the first letter of the word can't be uncovered. I am not sure how to fix this
static void Main(string[] args)
{
char[] guessed = new char[26];
char guess = ' ';
char playAgain= ' ';
int amountMissed = 0, index = 0;
do
{
// initilization of word and testword so that we could generate a testword with the same length as original
char[] word = RandomLine().Trim().ToCharArray();
char[] testword = new string('*', word.Length).ToCharArray();
char[] copy = word;
Console.WriteLine(testword);
Console.WriteLine("I have picked a random word on animals");
Console.WriteLine("Your task is to guess the correct word");
while (!testword.SequenceEqual(word))
{
try
{
Console.Write("Please enter a letter to guess: ");
guess = char.Parse(Console.ReadLine());
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
bool right = false;
for (int j = 0; j < copy.Length; j++)
{
if (copy[j] == guess)
{
Console.WriteLine("Your guess is correct.");
testword[j] = guess;
guessed[index] = guess;
index++;
right = true;
}
}
if (right != true)
{
Console.WriteLine("Your guess is incorrect.");
amountMissed++;
}
else
{
right = false;
}
Console.WriteLine(testword);
}
Console.WriteLine($"The word is {copy}. You missed {amountMissed} times.");
try
{
Console.WriteLine("Do you want to guess another word? Enter y or n: ");
playAgain = char.Parse(Console.ReadLine());
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
} while (playAgain == 'y' || playAgain == 'Y');
Console.WriteLine("Good-Bye and thanks for playing my Hangman game.");
}
public static string RandomLine()
{
// store text file in an array and return a random value
string[] lines = File.ReadAllLines("D:\\CPSC1012 ADV PORTFOLIO\\Advanced Portfolio\\Advanced1.csv");
Random rand = new Random();
return lines[rand.Next(lines.Length)];
}
}
That code works fine for me once I modify RandomLine() to just return zebra (since I don't have access to your words file).
So the first thing I would check is that your animal names are actually all lower case in that file. I note that, if I have it return Zebra instead, it exhibits the behaviour you describe when I try to guess the lower case z.
If that is the case, you just need to make your comparisons case-insensitive, something like modifying RandomLine() to ensure the word is all lower case:
return lines[rand.Next(lines.Length)].ToLower();
and this to ensure your guess is lower case:
guess = char.Parse(Console.ReadLine().ToLower());
Im trying to make a user enter a char and check if they entered that char before. and if that happens ask him to enter another char that he hasn't used before. My knowledge is limited to if statements and loops so I would appreciate it if the solution is something that i can understand.
When i enter any letter e.g E it would throw it into the guessed array, if i enter E again, it throws into the guessed array again instead of asking the user to change the letter.
string check= "";
char wguess ='';
char[] wguess = new char[26];
do
{
check = Console.ReadLine();
if (check!="")
{
wguess = char.ToUpper(Convert.ToChar(check));
for (int i = 0; i <= 25; i++)
{
if (wguess == guessed[i])
{
Console.Write(wguess);
Console.WriteLine(guessed[i]);
Console.WriteLine("Please choose a letter you haven't used yet.");
}
else
{
Console.Write(wguess);
Console.WriteLine(guessed[i]);
temp = wguess;
guessed[i] = wguess;
wguess = ' ';
}
}
}
else
{
Console.WriteLine("Please Enter a letter.");
}
} while (check=="");
Output1 = Guessed Letters: E
Output2 = Guessed Letters: EE
You can use the Contains method, like this:
If(guessed.Contains(wguess)
{
//Whatever happens when the character already has been entered
}
else
{
//Whatever happens when the character has not been guessed
}
Change the code like the following:
do{
check = char.ToUpper(Convert.ToChar(Console.ReadKey()));
if (!guessed.Contains(check))
{
// This is new, not in the guessed
}
else
{
// Already entered
}
} while (check==' ');
I´m having a string with allowed chars. I´d like that user is only able to use this chars.
My idea was to loop through the unser inputs string and compare char for char. But the problem which I have is when the first char in string allowed is "A" and the first in the users input "B" is, it gives me an error...
Totally confused right now
string allowed = "abc";
string read= Console.ReadLine();
for (int i = 0; i < allowed.Length; i++ )
{
if (allowed[i] == read[i])
{
Console.WriteLine("Okay");
}
else
{
Console.WriteLine("Invalid char on" +index);
}
}
If you wanna check if the user input has any of not allowed characters you need a nested loop, because you wanna compare each char in the user input against the chars in the allowed:
foreach(var r in read)
{
bool isValid = false;
foreach(var c in allowed)
{
// if we found a valid char set isValid to true
if(c == r)
isValid = true;
}
// if it's still false then the current char
// doesn't match any of the allowed chars
// so it's invalid
if(!isValid)
{
Console.WriteLine("the string has invalid char(s)");
break;
}
}
Or, to simplify this you can use LINQ:
bool isInvalid = read.Any(c => !allowed.Contains(c));
If you want to know which chars are invalid, you can use Except method:
var invalidChars = read.Except(allowed);
foreach(var c in invalidChars)
{
Console.WriteLine(c);
}
You either need to search the char of user input within the allowed characters or you could use a regular expression.
Search approach:
private string allowed = "abc";
private string userInput = "some string entered";
bool stringIsValid = false;
for (int i = 0; i < userInput.Length; i++)
{
if (!allowed.IndexOf(userInput[i]))
{
stringIsValid = false;
break; // You can stop the loop upon the first occurance of an invalid char
}
}
Regular expression approach:
private string allowed = "abc";
private string userInput = "some string entered";
bool stringIsValid = Regex.IsMatch(allowed, userInput);
Please note that the regular expression approach is more flexible. If you learn about regular expressions, you will find it very powerful.
You need another loop in your first one:
string allowed = "abc";
string read= Console.ReadLine();
for (int i = 0; i < read.Length; i++ )
{
bool isValid = false;
for (int j = 0; j < allowed.Length; j++)
{
if (read[i] == allowed[j])
{
isValid = true;
break;
}
}
if (isValid)
{
Console.WriteLine("Okay");
}else{
Console.WriteLine("Invalid char on" +index);
}
}
Right now, what you're saying is "every character in read must be exactly the same as in allowed".
What you're trying to say (I think) is "every character in read must be present somewhere in allowed" – that's what the second loop does. It looks for the character in allowed and if it finds it, sets isValid to true. Otherwise the character wasn't found and it's incorrect.
As other answers here state, you can use LINQ or (preferrably) regular expressions (regex) for things like this. I assume this is homework, or you're new to C# or programming, so I provided a basic answer to (hopefully) help you understand what's not working currently with your code.
If this should indeed be a homerwok or studying-related question, then let me recommend you put that in your question next time, for it's not forbidden to ask about homework.
The "real world" solutions we would use are of no help to you if you're trying to figure out the basics, so if we know it's about learning stuff then we'll provide answers that are more useful for you.
When using a collection to store not allowed items (instead of a plain string) it opens a whole new spectrum of LINQ expressions you can use:
public static void Main(string[] args)
{
var allowed = new List<string> { "a", "b", "c" };
var read = Console.ReadLine().Select(c => c.ToString()).ToList();
if (read.All(allowed.Contains))
{
Console.WriteLine("Okay");
}
else
{
var firstNotAllowed = read.First(a => !allowed.Contains(a));
var firstIndex = read.FindIndex(a => !allowed.Contains(a));
Console.WriteLine("Invalid char: {0}, at index: {1}", firstNotAllowed, firstIndex);
}
}
Okay so I'm making an auto typer and I want the user to be able to enter the keys {}()^+ and have the application out put. I know that you need to format the symbols like SendKeys.Send({^}); but I cant get this to work. Heres what I have so far for my Timer Tick. Also, I have global int blockCount, which tells the program to move on to the next character in the blockText string.
It returns "Group delimiters are not balanced."
private void timer3_Tick(object sender, EventArgs e)
{
string blockText = richTextBox1.Text;
int blockLength = richTextBox1.TextLength;
btrand = RandomNumber(75, 200); //I have a method to make a rand num
timer3.Interval = btrand;
char[] specialChars = { '{', '}', '(', ')', '+','^' };
foreach (char letter in blockText)
{
for (int i = 0; i < specialChars.Length; i++)
{
if (letter == specialChars[i])
{
SendKeys.Send("{" + specialChars[i] + "}");
blockText.Remove(blockText.IndexOf(specialChars[i].ToString()));
}
else
{
SendKeys.Send(letter.ToString());
}
}
}
blockCount++;
if (blockCount >= blockLength)
{
blockCount = 0;
}
}
Ok, quick analysis, so forgive me if I miss something.
You're doing a foreach using blockText as your collection, and manipulating it if a special char is found. This can be messy; I would think on another way to implement this.
You're looping through all special chars, and for each interaction that you can't identify a match you're sending the current letter. That means you're re-sending all non-special characters for the number of elements in the specialChars array minus one. I don't think that's what you've intended to do.
I would suggest an implementation like this:
foreach (char letter in blockText)
{
bool _specialCharFound = false;
for (int i = 0; i < specialChars.Length; i++)
{
if (letter == specialChars[i])
{
_specialCharFound = true;
break;
}
}
if (_specialCharFound)
SendKeys.Send("{" + letter.ToString() + "}");
else
SendKeys.Send(letter.ToString());
}
There are more optimized ways to implement, but I would choose this one out of clarity of purpose and similarity to your original code.