I am making a hangman in C# by my own and so far i am doing good. The game works but the letters organize depending on the users input and i want to erase the " _ " from the character everytime the word is found and is on the text.
This is how it looks on the game :
As you can see , the "_" only disapears for the first letter but not for the others and if the users put the correct answer correctly but radomly some words stick together in many cases and do not stay on their places. This my code for the game:
string word;
char letter_inserted;
int correctanswer, incorrectanswer;
int counter = 0;
correctanswer = 5;
Console.WriteLine("welcome to the game of hangman");
Console.Write("First player please introduce the secret word: ");
word = Console.ReadLine();
Char[] sentenceChar = word.ToCharArray();
Console.WriteLine("Second player you can already play.");
foreach( char letter in senteceChar)
{
Console.Write(" _ ");
}
Console.WriteLine("\n");
Console.WriteLine("{0} correcct answers are allowed. \n",correctanswers); //lives
Char[] correctletter = new Char[5];
for (int i = 1; i > 0; i++)
{
Console.Write("\n\nWhat letter you want to play : ");
letter_inserted = Convert.ToChar(Console.ReadLine());
for (int j = 0; j < sentenceChar.Length; j++)
{
if (sentenceChar[j] != letter_inserted)
{
incorrectanswer = correctanswer - 1; //lives
Console.Write(correctletter[j] + " _ ");
}
if (sentenceChar[j] == letter_inserted)
{
correctletter[j] += sentnceChar[j]; //inserting the correct word
Console.Write(correctletter[j]);
}
}
}
Console.ReadKey();
}
I would use a different approach for this. Create two arrays, one for the solution:
var solution = new char[] {'H', 'A', 'N', 'G', 'M', 'A', 'N'};
And one for the current hint. At the beginning, you'd initialize this to:
var hint = new char[] {'_', '_', '_', '_', '_', '_', '_'};
When a letter is guessed, you can loop through solution and each time solution[i] is equal to the guessed letter, replace the corrosponding index in hint:
for(int i = 0; i < solution.Length; i++)
{
if(solution[i] == guess)
hint[i] = guess;
}
At the end of this loop, just re-write hint onto the screen, which will always contain the current hint.
A few things you'll want to do:
Have a Boolean within your loop to track if solution contained any instances of the letter. If not, at the end of the loop you'd subtract a life. You can also do this very easily using solution.Contains(guess) as well.
Perhaps create a List<char> to track already attempted guesses. If this list already contains the entered letter, you can display "You already guessed that!", otherwise add the guess to the list.
This answer is meant as a hint to get you going in the right direction, rather than a complete solution. However, feel free to ask if any part of it is unclear.
I will start with your first sentence - I am making a hangman in C# by my own and so far i am doing good. In fact as you can see in the comments there are a lot of things that you would want to consider before going to this exact problem but since you ask how to deal with the extra _ I'll jump to that.
And a method :
public static void printWord(char[] correctletters)
{
for (int j = 0; j < correctletters.Length; j++)
{
Console.Write(correctletters[j]);
}
}
And then rewrite your code like this:
namespace Hangman
{
class Program
{
static void Main(string[] args)
{
string word;
char letter_inserterd;
int correctanswer = 5;
int counter = 0;
Console.WriteLine("welcome to the game of hangman");
Console.Write("First player enter the secret word: ");
word = Console.ReadLine();
Char[] sentenceChar = word.ToCharArray();
Console.WriteLine("Second player you can already play.");
foreach( char letter in sentenceChar)
{
Console.Write(" _ ");
}
Console.WriteLine("\n");
Console.WriteLine("{0} correct answers are allowed. \n",correctanswer); //lives
Char[] correctletter = new Char[sentenceChar.Length];
for (int i = 0; i <sentenceChar.Length; i++)
{
correctletter[i] = '_';
}
while (correctanswer > 0)
{
Console.Write("\n\nWhat letter you want to play : ");
letter_inserted = Convert.ToChar(Console.ReadLine());
bool ContainsWord = false;
for (int j = 0; j < sentenceChar.Length; j++)
{
if (sentnceChar[j] == letter_inserted)
{
correctletter[j] = letter_inserted; //inserting the correct word
ContainsWord = true;
}
}
if (!ContainsWord)
{
correctanswer -= 1;
}
printWord(correctletter);
}
Console.ReadKey();
}
public static void printWord(char[] correctletter)
{
for (int j = 0; j < correctletter.Length; j++)
{
Console.Write(correctletter[j]);
}
}
}
}
P.S if you want to make it a little more clear in printWord method change the Console.Write line like this: Console.Write(letracorrecta[j] + " ");
Related
My apologies if I didn't explain it clear the first time. I have edited my explanation further in bold below.
In the program below user enters a word and then enters a letter which the user would like to replace with any character. For instance, user enter's a word "Hello" and the replacement letter is "l" with "$". So "Hello" will become "He$$o". First, the goal is to find the location of "l" (example - 2,3) and then replace the element in that specific location.
I started by finding the location of "l" and storing it in a findIndex array. Every time I run the program I get "22222" stored in findIndex[] array. At this point, I am not even sure if I am even applying the right logic. Any advice will be appreciated! Please don't use LINQ.
public static void RemoveSpecifiedCharacters()
{
Console.WriteLine("\nWrite a word/sentence: ");
string myString = Console.ReadLine();
Console.Write("Type the character you would like to replace: ");
string myCharacter = Console.ReadLine();
int[] findIndex = new int[myString.Length];
for (int i = 0; i < myString.Length; i++)
{
findIndex[i] = myString.IndexOf(myCharacter, 0);
}
for (int i = 0; i < findIndex.Length; i++)
{
Console.Write(findIndex[i]);
}
}
This is probably what you want :
public static void RemoveSpecifiedCharacters()
{
Console.WriteLine("\nWrite a word/sentence: ");
string myString = Console.ReadLine();
Console.Write("Type the character you would like to replace: ");
string myCharacter = Console.ReadLine();
List<int> findIndex = new List<int>();
int offs = 0;
while (offs < myString.Length)
{
offs = myString.IndexOf(myCharacter, offs);;
if (offs == -1)
break;
findIndex.Add(offs);
offs++;
}
for (int i = 0; i < findIndex.Count; i++)
{
Console.Write(findIndex[i]);
}
}
Set an initial offset to the start of the string, try to find index of required character if not found exit, otherwise store the location & increment the offset so the next loop starts after the found position. Then keep looping.
As you do not know how many characters will be found, then a list is better than an array to store the results. It can always be converted to an array with .ToArray() afterwards.
Below should serve the purpose :
var str = "Hello";
var replaced = str.Replace('l', '$');
Even though it's easier to use String.Replace, I just want to give you an explanation why you are getting [2,2,2,2,2] array.
Firstly, IndexOf method returns index of character's first occurence, starting from 0.
Secondly, you are using method overload IndexOf(myCharacter, 0) which "says" that character search should be done always from the start of the string.
To circumvent the issue, you should use IndexOf(myCharacter, i, 1) instead to set the search to start from i-th character, not the start of string.
I guess a simple solution would be to split the string into a character array and then do the comparison?
For example something like:
Console.WriteLine("\nWrite a word/sentence: ");
char[] myString = Console.ReadLine().ToCharArray();
Console.Write("Type the character you would like to replace: ");
char myCharacter = Console.ReadLine().ToCharArray()[0];
int[] findIndex = new int[myString.Length];
int indexCount = 0;
for (int i = 0; i < myString.Length; i++)
{
if (myString[i] == myCharacter)
findIndex[indexCount++] = i;
}
for (int i = 0; i < indexCount; i++)
{
Console.Write(findIndex[i]);
}
I need some help with a C# program that i am creating. So in this scenario i am inputting duplicate values into the program. For Example, a,b,b,c,c.
The exercise is that if there are any duplicated letters inputted (no numbers) i should get an error stating "Duplicate Value. Please Try Again!" and will not accept the duplicate value, and should show the values as a,b,c,d,e.
class Program
{
static void Main(string[] args)
{
char[] arr = new char[5];
//User input
Console.WriteLine("Please Enter 5 Letters only: ");
for (int i = 0; i < arr.Length; i++)
{
arr[i] = Convert.ToChar(Console.ReadLine());
}
//display
for(int i = 0; i<arr.Length; i++)
{
Console.WriteLine("You have entered the following inputs: ");
Console.WriteLine(arrArray[i]);
}
}
}
Choose right data structure at beginning, use HashSet instead of array since the operations are mainly looking up & inserting.
Using a hashtable (Generic Dictionary) is an efficient way to determine if an entered character has already been encountered.
Also, the Char.IsLetter method in the .NET framework is a great way to check for bad data.
static void Main(string[] args) {
Dictionary<char, bool> charsEntered = new Dictionary<char, bool>();
Console.WriteLine("Please enter 5 characters, each on a separate line.");
while (charsEntered.Count() < 5) {
Console.WriteLine("Enter a character:");
char[] resultChars = Console.ReadLine().ToCharArray();
if(resultChars.Length != 1 || !Char.IsLetter(resultChars[0])) {
Console.WriteLine("Bad Entry. Try again.");
} else {
char charEntered = resultChars[0];
if (charsEntered.ContainsKey(charEntered))
Console.WriteLine("Character already encountered. Try again.");
else
charsEntered[charEntered] = true;
}
}
Console.WriteLine("The following inputs were entered:");
Console.WriteLine(String.Join(", ", charsEntered.Keys));
Console.ReadLine();
}
Use Any linq expression to validate duplicates. char.TryParse will validates input and returns true when succeeded.
public static void Main()
{
char[] arr = new char[5];
//User input
Console.WriteLine("Please Enter 5 Letters only: ");
for (int i = 0; i < arr.Length; i++)
{
char input;
if(char.TryParse(Console.ReadLine(), out input) && !arr.Any(c=>c == input))
{
arr[i] = input;
}
else
{
Console.WriteLine( "Error : Either invalid input or a duplicate entry.");
i--;
}
}
Console.WriteLine("You have entered the following inputs: ");
//display
for(int i = 0; i<arr.Length; i++)
{
Console.WriteLine(arr[i]);
}
}
Working Code
Elaborating on Shelvin's answer of using HashSet
HashSet<char> chars = new HashSet<char>();
//User input
Console.WriteLine("Please Enter 5 Letters only: ");
for (int i = 0; i < 5; )
{
char c = Convert.ToChar(Console.ReadLine());
if(!("abcdefghijklmnopqrstuvwxyz".Contains(c.ToString().ToLower())))
{
Console.WriteLine("Please enter an alphabet");
continue;
}
else if (!chars.Contains(c))
{
chars.Add(c);
i++;
}
else
{
Console.WriteLine("Duplicate value please try again");
continue;
}
}
//display
Console.WriteLine("You have entered the following inputs: ");
foreach(char c in chars)
Console.WriteLine(c.ToString());
Console.Read();
Keep it simple, and although a HashSet is nice semantically, it's not needed for 5 elements (it's actually slower than a List in that case). Worse, it requires a parallel structure to track the characters (assuming you care about order).
Clearly none of these considerations matter for such a small example but it's good to learn them up front and don't always jump to big-O notation when actually measured performance and memory consumption should be your guide for most practical applications.
Instead you can simply do:-
List<char> chars = new List<char>(5);
while (chars.Count < 5)
{
char c = Console.ReadKey().KeyChar;
if (!char.IsLetter(c)) continue;
if (chars.Contains(char)) continue;
chars.Add(char);
}
Plus whatever error messages you want to add.
I'm trying to create a word guessing game that uses a dictionary text file. The game is supposed to take input from the user on how long the word should be before asking them to guess the word. If the user fails to guess after 3 times then it reveals the answer. I used a list on recommendation from a friend to read from the dictionary as it is quite large.
My question is, how can I read the list to choose a word for the guessing game?
{
static int letterLength, LettersLeft, wrongGuess;
public static void Main(string[] args)
{
string input = System.IO.File.ReadAllText("dictionary.txt");
string[] terms = input.Split();
List<string> list = new List<string>();
for (int num = 0; num < terms.Length; num++)
list.Add(terms[num]);
int wordToGuess = GetLengthOfWordToGuess();
List<string> fixedlist = new List<string>();
for (int num = 0; num < list.Count; num++)
{
string tempword = list[num];
if (tempword.Length == wordToGuess)
fixedlist.Add(tempword);
}
for (int num = 0; num < fixedlist.Count; num++)
Console.WriteLine(fixedlist[num]);
Console.WriteLine("Welcome to the guessing game");
letterLength = GetLengthOfWordToGuess();
Console.Clear();
//Not Working from here on.
string wordGuess = GetWordToGuess();
char[] maskedWord = GetHiddenLetters(wordGuess, '-');
LettersLeft = wordGuess.Length;
char userGuess;
wrongGuess = 3;
while (wrongGuess > 0 && LettersLeft > 0)
{
DispayCharacters(maskedWord);
Console.WriteLine("Enter a Letter");
userGuess = char.Parse(Console.ReadLine());
maskedWord = CheckGuess(userGuess, wordGuess, maskedWord);
}
Console.WriteLine("Well done! Thanks for Playing.");
Console.ReadLine();
}
static string GetWordToGuess()
{
Random word = new Random();
int wordNumber = word.Next(0, 9);
string[] words = { "" };
string selectWord = words[wordNumber];
return selectWord;
}
static char [] GetHiddenLetters(string word, char mask)
{
char[] hidden = new char[word.Length];
for (int i = 0; i < word.Length; i++)
{
hidden[i] = mask;
}
return hidden;
}
static void DispayCharacters(char [] characters)
{
foreach(char letter in characters)
{
Console.Write(letter);
Console.WriteLine();
}
}
static int GetLengthOfWordToGuess()
{
Console.WriteLine("Input length of word to guess");
int selectWord = int.Parse(Console.ReadLine());
return selectWord;
}
static char [] CheckGuess (char letterToCheck, string word, char [] characters)
{
bool wrong = true;
if(wrongGuess > 0)
{
for (int i = 0; i < word.Length; i++)
{
if (word[i] == letterToCheck)
{
characters[i] = word[i];
LettersLeft--;
wrong = false;
}
}
}
}
}
One major problem I see up front is that your GetWordToGuess function is not functional and probably throws an IndexOutOfRangeException.
The reason for that is that you are instantiating the words array as an array with a single empty string in it, but you are then referencing an index between 0 and 9, which will not exist in that array unless the random number generated is 0.
To solve this you should pass the fixedlist List you already created and use that instead of the words array. You should make sure to generate a random number between 0 and fixedlist.Count-1 so that you don't hit that same out of range exception. Therefore that function should look something like this:
static string GetWordToGuess(List<string> fixedlist)
{
Random word = new Random();
int wordNumber = word.Next(0, 9);
string[] words = { "" };
string selectWord = words[wordNumber];
return selectWord;
}
Also, as it stands right now, your included code doesn't compile because the CheckGuess function doesn't return a char[] as it says it should. I believe what you meant to do was have a return characters; line at the end (this was probably just a copy paste issue when you put your code in your question, but I thought I'd mention it just in case).
As a side note there are a number of small issues with your code like declaring things you don't use, but since they don't break your program I didn't want to go through and fix them.
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.
int LetterCount = 0;
string strText = "Debugging";
string letter;
for (int i = 0; i <strText.Length; i++)
{
letter = strText.Substring(0, 9);
if(letter == "g")
{
LetterCount++;
textBox1.Text = "g appears " + LetterCount + " times";
}
}
So, I'm doing this tutorial thing, and I've been stuck on this exercise for like 4 hours. And I can't figure out what's wrong with my For Loop.
The point of the exercise is to make my program thing tell me how many g's are in the word debugging. But you probably figured that out. Anyway, I'm not even sure that I have the right code for telling me that, because I think that I need to change the second part of the For Loop (the i < ) part.
But my problem is that it isn't registering the "if letter == "g" " at all. Because according to my locals window it says that letter=Debugging, which would make me think that g should be registering on my program 24 times, I think (because str.length is 9 letters long?) But it's registering as 0 no matter what I do.
You are extracting a string of 9 characters. It will never be equal to "g" (which only has one). Here's how I'd do it.
int count = 0;
foreach (char c in strText)
{
if (c == 'g')
count++;
}
Using the for loop:
for (int i = 0; i < strText.Length; i++)
{
if (strText[i] == 'g')
count++;
}
Take a look at the documentation for string.Substring(x, y).
Basically:
letter = strText.Substring(0, 9);
Isn't giving you a letter. Each time through it's giving you all 9 characters of the string strText. You might want to consider using the variable i for one of the values you pass to Substring.
(I've deliberately not given you the entire answer as you seem to want to understand, so, if the pointers I've given don't get you there, let me know and I'll expand my answer =)
Try this:
for (int i = 0; i <strText.Length; i++)
{
if(strText[i] == 'g')
{
LetterCount++;
}
}
textBox1.Text = "g appears " + LetterCount + " times";
The issue is that you are looking at the entire string when you compare to "g". By specifying an index you are telling it to look at a specific character in the string. Also, I removed your substring because it did not appear to be doing anything.
You're not using i at all in your for loop.
Do you mean
letter = strText.Substring(i, 1);
?
Well, you are taking substring that is long 9 charachters and comparing it to "g". It won't be equal.
You should try:
letter = strText.Substring(i,1);
Because String.Substring(int, int) takes two arguments: the offset and amount to take.
In your case, letter = strText.Substring(0, 9); will simply assign letter's value to "Debugging". If you want to check each letter individually, you need to write letter = strText.Substring(i, 1).
You're probably looking for something like this:
int LetterCount = 0;
string strText = "Debugging";
string letter;
for (int i = 0; i <strText.Length; i++)
{
letter = strText.Substring(i, 1);
if(letter == "g")
{
LetterCount++;
textBox1.Text = "g appears " + LetterCount + " times";
}
}
letter = strText.Substring(0, 9);
at this point, 'letter' has the value "Debugging" since you're taking the entire string.
Try letter = strText[i] so you isolate the single letter.
What #Rob said.
Try something like this:
int gCount = 0;
string s = "Debugging";
for ( int i = 0; i <strText.Length; i++)
{
if ( s[i] == 'g' ) ++gCount ;
}
textBox1.Text = "g appears " + gCount+ " times";
namespace runtime
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int lettercount = 0;
string strText = "Debugging";
string letter;
for (int i = 0; i < strText.Length; i++)
{
letter = strText.Substring(i,1);
if (letter == "g")
{
lettercount++;
}
}
textBox1.Text = "g appear " + lettercount + " times";
}
}
}