Hangman in C# Looping Issue - c#

So i got The following Code Here... I have to provide 5 User provided words, randomize on the 5 and give any one of them up for a guess, the tries = word length + 2. The main problem i Am having is looping the entire check to fill in the 2nd, 3rd guess etc. The 1st guess is fine. How would i go about looping and keeping the characters which were guessed right while still keeping the ones that were not guessed as a "_" character.
Example - Word was "Heaven" - User Enters "e" - Produces - _ e _ _ e _ No Spaces.
The tries would then be equal to 6(Word Length) + 2 = 8 Tries
int tries = 0;
Random rand = new Random();
int randomword = rand.Next(1, 5);
string word = "";
Console.WriteLine("Please Enter 5 Words into the System");
Console.WriteLine();
for (int i = 0; i < 5; i++)
{
words.Add(Console.ReadLine());
Console.Clear();
}
Console.WriteLine("For Display Purposes. Here are Your 5 Words");
Console.WriteLine("===========================================");
Console.WriteLine();
foreach (var item in words)
{
Console.WriteLine(item);
}
Console.WriteLine();
Console.WriteLine("Now Guess The word given Below");
Console.WriteLine();
switch (randomword)
{
case 1:
//Gets the List index 0 - 1st word in the list
word = words[0];
tries = word.Length;
break;
case 2:
word = words[1];
tries = word.Length;
break;
case 3:
word = words[2];
tries = word.Length;
break;
case 4:
word = words[3];
tries = word.Length;
break;
case 5:
word = words[4];
tries = word.Length;
break;
default:
break;
}
//Default + addition to the Length
tries += 2;
Console.WriteLine();
Console.WriteLine("You Have {0} + tries",tries );
//Works for the 1st Guess
do
{
char guess = char.Parse(Console.ReadLine());
if (word.Contains(guess))
{
foreach (char item in word)
{
if (item == guess)
{
Console.Write(item);
}
else
{
Console.Write("_");
}
}
}
Console.WriteLine();
}
//If my word contains A "_" i will keep looping
while (word.Contains("_"));
Console.ReadKey();

Your main problem is that you're only keeping track of the current guess, not all the previous ones. You can use a HashSet to keep track of your previous guesses. So define a variable HashSet<char> guessedLetters before your do loop, and then as the 2nd line in your loop after you parse "guess" do guessedLetters.Add(guess). Then substitute if(item==guess) with if(guessedLetters.Contains(item)). Viola, only three lines code change!
Finally your exit condition can be while (word.Any(c=>!guessedChars.Contains(c)) && --tries != 0);.

How about:
static void Main(string[] args)
{
string[] words = new string[] { "Apple", "Banana", "Pear", "Pineapple", "Melon"};
Random random = new Random();
string wordToGuess = words[random.Next(5)].ToLower();
char[] currentLetters = new char[wordToGuess.Length];
for (int i = 0; i < currentLetters.Length; i++) currentLetters[i] = '_';
int numTries = currentLetters.Length + 1;
bool hasWon = false;
do
{
string input = Console.ReadLine().ToLower();
if (input.Length == 1) //guess a letter
{
char inputChar = input[0];
for (int i = 0; i < currentLetters.Length; i++)
{
if (wordToGuess[i] == inputChar)
{
currentLetters[i] = inputChar;
}
}
if (!currentLetters.Contains('_'))
{
hasWon = true;
}
else
{
Console.WriteLine(new string(currentLetters));
}
}
else
{
if (input == wordToGuess)
{
hasWon = true;
}
else
{
Console.WriteLine("Incorrect!");
Console.WriteLine(new string(currentLetters));
}
}
numTries--;
} while (new string(currentLetters) != wordToGuess && numTries > 0 && !hasWon);
if (hasWon)
{
Console.WriteLine("Congratulations, you guessed correctly.");
}
else
{
Console.WriteLine("Too bad! Out of tries");
}
}

you need to store the guessing result and check that for your loop (change your do while loop to as below):
string resultword = word;
do
{
char guess = char.Parse(Console.ReadLine());
if (word.Contains(guess))
{
resultword = resultword.Replace(guess, ' ');
for (int i = 0; i < resultword.Count(); i++)
{
if (resultword[i] == ' ')
{
Console.Write(word[i]);
}
else
{
Console.Write("_");
}
}
}
Console.WriteLine();
}
while (tries-- != 0 && resultword.Trim() != string.Empty);

How about, using your existing code;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
internal class Program
{
private static void Main(string[] args)
{
List<string> words = new List<string>();
int tries = 0;
Random rand = new Random();
var currentLetters = new List<char>();
int randomword = rand.Next(1, 5);
string word = "";
Console.WriteLine("Please Enter 5 Words into the System");
Console.WriteLine();
for (int i = 0; i < 5; i++)
{
words.Add(Console.ReadLine());
Console.Clear();
}
Console.WriteLine("For Display Purposes. Here are Your 5 Words");
Console.WriteLine("===========================================");
Console.WriteLine();
foreach (var item in words)
{
Console.WriteLine(item);
}
Console.WriteLine();
Console.WriteLine("Now Guess The word given Below");
Console.WriteLine();
switch (randomword)
{
case 1:
//Gets the List index 0 - 1st word in the list
word = words[0];
tries = word.Length;
break;
case 2:
word = words[1];
tries = word.Length;
break;
case 3:
word = words[2];
tries = word.Length;
break;
case 4:
word = words[3];
tries = word.Length;
break;
case 5:
word = words[4];
tries = word.Length;
break;
default:
break;
}
//Default + addition to the Length
tries += 2;
Console.WriteLine();
Console.WriteLine("You Have {0} + tries", tries);
//Works for the 1st Guess
do
{
char guess = char.Parse(Console.ReadLine());
if (!currentLetters.Contains(guess))
{
currentLetters.Add(guess);
foreach (var l in word.ToCharArray().Intersect(currentLetters).ToArray())
{
word = word.Replace(l, '_');
}
}
Console.WriteLine(word);
} //If my word contains A "_" i will keep looping
while (word.Contains("_"));
Console.ReadKey();
}
}
}

Working example:
List<string> words = new List<string>();
int tries = 0;
Random rand = new Random();
int randomword = rand.Next(1, 5);
string word = "";
Console.WriteLine("Please Enter 5 Words into the System");
Console.WriteLine();
for (int i = 0; i < 5; i++)
{
words.Add(Console.ReadLine());
Console.Clear();
}
Console.WriteLine("For Display Purposes. Here are Your 5 Words");
Console.WriteLine("===========================================");
Console.WriteLine();
foreach (var item in words)
{
Console.WriteLine(item);
}
Console.WriteLine();
Console.WriteLine("Now Guess The word given Below");
Console.WriteLine();
switch (randomword)
{
case 1:
//Gets the List index 0 - 1st word in the list
word = words[0];
tries = word.Length;
break;
case 2:
word = words[1];
tries = word.Length;
break;
case 3:
word = words[2];
tries = word.Length;
break;
case 4:
word = words[3];
tries = word.Length;
break;
case 5:
word = words[4];
tries = word.Length;
break;
default:
break;
}
//Default + addition to the Length
tries += 2;
Console.WriteLine();
Console.WriteLine("You Have {0} + tries", tries);
List<char> guesses = new List<char>();
string guessedWord = "";
for(int i=0;i<word.Length;i++)
{
guessedWord += "_";
}
//Works for the 1st Guess
do
{
char guess = char.Parse(Console.ReadLine());
if (word.Contains(guess))
{
guesses.Add(guess);
}
foreach (char storedGuess in guesses)
{
if(word.Contains(storedGuess))
{
int index = word.IndexOf(storedGuess);
while(index > -1)
{
StringBuilder sb = new StringBuilder(guessedWord);
sb[index] = storedGuess;
guessedWord = sb.ToString();
index = word.IndexOf(storedGuess, index+1);
}
}
}
Console.WriteLine(guessedWord);
}
while (guessedWord.Contains("_"));
Console.ReadKey();

You mention the number of tries, but you never use it in the code after it is used. Presumably, you want to do the following:
Pick a random word (in your case, you are picking one of the five words supplied by the user)
Set the number of guesses (tries?) equal to the length of the word plus 2. If they guess a letter that is present, then it is free. If the letter is not present, then they lose one of their guesses.
Before each guess, display the word with all the unguessed letters replaced by "_".
When the user guesses a letter that is present, replace the "_" in the displayed word by the letter.
Here is some sample code that should work (untested):
string displayword = String.Copy(word);
for (int j = 0; j < displayword.length; j++) displayword[j]='_';
do {
// Display the word so far.
Console.WriteLine("Word is {0}", displayword);
// Get a guess from the user
char guess = char.Parse(Console.ReadLine());
if (word.Contains(guess)) {
for (j=0; j<word.length; j++) {
if (word[j] == guess) displayword[j]=guess;
}
} else {
// Decrease the tries.
tries--;
}
} while (displayword.Contains("_") && (tries > 0));

You need to distinguish the input word from the result so-far. Initialize the result with underscores, and then add the letters to the result as people guess them. It's a little easier if you make result a char array instead of a string.
var result = new string('_', word.Length).ToCharArray();
do
{
char guess = char.Parse(Console.ReadLine());
for (var i = 0; i < word.Length; ++i)
{
if(word[i] == guess)
{
result[i] = guess;
}
}
Console.WriteLine(new string(result));
}
//If my word contains A "_" i will keep looping
while (result.Contains('_') && --tries != 0);

Related

losing streak loop in hangman C#

I'm trying to make a Hangman game in C#. It has a 5 tries limit, then the user will get a "you lose" message. If the user gets a letter wrong, it was supposed to get them a "wrong letter -- try again"
class Program
{
static void Main(string[] args)
{
string word;
int correct = 0;
int errors = 0;
Console.WriteLine("Enter a word");
word = Console.ReadLine();
char[] letters = word.ToCharArray();
char[] hanged = word.ToCharArray();
char digits;
for (int i = 0; i < word.Length; i++)
{
if (letters[i] == ' ')
{
hanged[i] = ' ';
}
else
{
hanged[i] = '_';
}
}
Console.Clear();
do
{
Console.Write(" ________\n" +
"| |\n" +
"| |\n" +
"|\n" +
"|\n" +
"|\n" +
"|\n" +
"|\n" +
"|\n\n");
Console.SetCursorPosition(2, Console.CursorTop - 2);
for (int i = 0; i < word.Length; i++)
{
Console.Write(hanged[i] + " ");
}
Console.WriteLine("\n\n\nEnter a letter");
digits = Convert.ToChar(Console.Read());
for (int i = 0; i < word.Length; i++)
{
if (digits == hanged[i])
{
Console.WriteLine("\nletter already in there -- press enter");
Console.ReadKey();
}
else if (digits == letters[i])
{
hanged[i] = digits;
correct++;
}
else if (digits != letters[i])
{
Console.WriteLine("\nwrong letter -- try again");
errors++;
Console.ReadKey();
}
if (errors == 5)
{
Console.WriteLine("\nYou lose");
Console.ReadKey();
break;
} else if (correct == word.Length)
{
Console.WriteLine("\nYou win");
Console.ReadKey();
break;
}
}
Console.Clear();
} while (correct < word.Length);
Console.ReadKey();
}
}
However, my program is stuck in a loop when counting the losses. The code thats messing it up is this section
else if (digits != letters[i])
{
Console.WriteLine("\nwrong letter -- try again");
errors++;
Console.ReadKey();
}
When I delete this section and run the code, in case of a wrong letter it just runs over it infinitely and the player will get infinite chances to try when they were supposed to have only 5 chances. How can I fix this?
The problem is that the 2nd loop for (int i = 0; i < word.Length; i++) that is responsible for finding a letter should not perform other logic in there. E.g., if the user types a letter matching the third position, then this will count 2 errors before counting one correct letter and also do extra console input and output.
I suggest using Array.IndexOf to get the index of a letter. This returns -1 if it is not found. Also, I found that the different kinds of Console.ReadXY can interfere with each other. E.g. calling Console.Read() and pressing a letter plus Enter makes the next Console.ReadLine() just return without waiting for user input.
My attempt (content of static void Main(string[] args)):
string word;
int correct = 0;
int errors = 0;
Console.WriteLine("Enter a word");
word = Console.ReadLine();
char[] letters = word.ToCharArray();
char[] hanged = word.ToCharArray();
char digits;
for (int i = 0; i < word.Length; i++) {
if (letters[i] == ' ') {
hanged[i] = ' ';
} else {
hanged[i] = '_';
}
}
Console.Clear();
do {
Console.Write(" ________\n" +
"| |\n" +
"| |\n" +
"|\n" +
"|\n" +
"|\n" +
"|\n" +
"|\n" +
"|\n\n");
Console.SetCursorPosition(2, Console.CursorTop - 2);
for (int i = 0; i < word.Length; i++) {
Console.Write(hanged[i] + " ");
}
Console.Write("\n\n\nEnter a letter: ");
ConsoleKeyInfo key = Console.ReadKey();
digits = key.KeyChar;
int hangedIndex = Array.IndexOf(hanged, digits);
int lettersIndex = Array.IndexOf(letters, digits);
if (hangedIndex >= 0) {
Console.WriteLine("\nletter already in there -- press enter");
Console.ReadLine();
} else if (lettersIndex >= 0) {
hanged[lettersIndex] = digits;
correct++;
} else {
Console.Write("\nwrong letter -- try again (press enter) ");
Console.ReadLine();
errors++;
}
if (errors == 5) {
Console.WriteLine("\nYou lose");
break;
} else if (correct == word.Length) {
Console.WriteLine("\nYou win");
break;
}
Console.Clear();
} while (correct < word.Length);
Console.ReadKey();

Input from user to array and Display in Console in C#

I am a Beginner in C# and I was wondering what I got wrong with this code.
I want the user to input the amount of numbers
Then an array with that amount gets created
Then finally I want to display all the numbers in the array.
The Code:
using System;
using System.Threading;
using System.Collections.Generic;
namespace Console_Project_alpha
{
class Program
{
static void Main(string[] args)
{
Console.Write("Enter the amount of numbers: ");
int amount = Convert.ToInt32(Console.ReadLine());
int[] numbers = new int[amount];
string nth = "";
for( int i = 1; i <= amount ; i++)
{
if(i == 1)
{
nth = i + "st";
}
else if( i == 2)
{
nth = i + "nd";
}
else if( i == 3)
{
nth = i + "rd";
}else{
nth = i + "th";
}
Console.Write("\nEnter " + nth + " Number:");
int num = Convert.ToInt32(Console.ReadLine());
for(int j = 0; j <= numbers.Length; j++)
{
numbers[j] = num;
}
}
System.Console.WriteLine(numbers);
}
}
}
Any help is highly appreciated. Thanks in advance
In your code you all time overwriting the same value to all index in
array.
If you want to display values from array in console just iterate after array
Properly worked example based on your code:
class Program
{
static void Main(string[] args)
{
Console.Write("Enter the amount of numbers: ");
int amount = Convert.ToInt32(Console.ReadLine());
int[] numbers = new int[amount];
string nth = "";
int index = 0;
for (int i = 1; i <= amount; i++)
{
if (i == 1)
{
nth = i + "st";
}
else if (i == 2)
{
nth = i + "nd";
}
else if (i == 3)
{
nth = i + "rd";
}
else
{
nth = i + "th";
}
Console.Write("\nEnter " + nth + " Number:");
int num = Convert.ToInt32(Console.ReadLine());
numbers[index] = num;
index++;
}
for (int i = 0; i <= numbers.Length - 1; i++)
{
Console.WriteLine(numbers[i]);
}
Console.ReadLine();
}
}

Console not printing lines and/or words

I have a simple code just to have fun, it was supposed to print the entire alphabet, each letter separated from each other with 100 empty lines... But this is not printing any line....
Note: Before I used code similar to this and it worked (obviously the other was real code and didn't have the 100 lines thingy)
"alfabeto" = "alphabet" (Portuguese word, I was not going to translate 26 lines if I could just say this)
namespace Alfabeto_das_100_linhas
{
class Inicial
{
static void Main(string[] args)
{
string[] alfabeto = new string[26];
alfabeto[0] = "A";
alfabeto[1] = "B";
alfabeto[2] = "C";
alfabeto[3] = "D";
alfabeto[4] = "E";
alfabeto[5] = "F";
alfabeto[6] = "G";
alfabeto[7] = "H";
alfabeto[8] = "I";
alfabeto[9] = "J";
alfabeto[10] = "K";
alfabeto[11] = "L";
alfabeto[12] = "M";
alfabeto[13] = "N";
alfabeto[14] = "O";
alfabeto[15] = "P";
alfabeto[16] = "Q";
alfabeto[17] = "R";
alfabeto[18] = "S";
alfabeto[19] = "T";
alfabeto[20] = "U";
alfabeto[21] = "V";
alfabeto[22] = "W";
alfabeto[23] = "X";
alfabeto[24] = "Y";
alfabeto[25] = "Z";
for (int i = 0; i <= alfabeto.Length; i++)
{
Console.WriteLine(alfabeto[i]);
for(int iii = 0; i != 100; iii++)
{
Console.Write("\n");
}
Console.WriteLine();
}
Console.Read();
}
}
}
Your inner loop is wrong:
for(int iii = 0; i != 100; iii++)
{
Console.Write("\n");
}
Depending on the the value of i this will either do nothing or loop forever.
It should be:
for(int iii = 0; iii < 100; iii++)
{
Console.Write(Environment.NewLine);
}
In addition to fixing your loop counter, you were outputting the string \n rather than the newline character. You could also just use WriteLine with an empty string.
Now I look again, I see that your outer loop is also wrong. It should be:
for (int i = 0; i < alfabeto.Length; i++)
If you loop to the count equal to the length you'll exceed the length of the array - a 26 element array has indices 0 to 25.
If you're not sure what the inner loop is doing I'd reduce the end test to something more manageable (5 for example) so you can see exactly how many lines are being inserted between each of your letters. You could also output the loop counter (as a debug measure) as an extra check
Also notice that you have 101 line, not 100. Should be:
for (int i = 0; i < alfabeto.Length; i++)
{
Console.WriteLine(alfabeto[i]);
for (int iii = 0; iii < 100; iii++)
{
Console.WriteLine();
}
}
Console.Read();
Or you can simplify:
string s = new string('\n', 100);
for (char ch = 'A'; ch <= 'Z'; ch++)
{
Console.WriteLine(ch);
Console.Write(s);
}
Console.Read();

C# Need inputs in different lines

I am trying to create a program that is will take letters as input only and not duplicated. I am getting error when i put one letter in an input.
This is what i need to do, I need to get the user input in each line (like a enter, b enter, etc), if there is a duplication value i need a error message and continues with the input, and if there is incorrect value i get another error stating such. I cannot use LINQ, Hashset, nor list, it has to be arrays.
static void Main(string[] args)
{
char[] Array = new char[5];
Console.WriteLine("Please Enter 5 Letters B/W a through j only: ");
string letters = "abcdefghij";
char[] read = Console.ReadLine().ToLower().ToCharArray();
//loop through array
for (int i = 0; i < 5; i++)
{
if (letters.Contains(read[i]) && !Array.Contains(read[i]))
{
Array[i] = read[i];
}
else
{
Console.WriteLine("You have entered an incorrect value");
}
}
Console.WriteLine("You have Entered the following Inputs: ");
for (int i = 0; i < Array.Length; i++)
{
Console.WriteLine(Array[i]);
}
Console.ReadKey();
}
I think this more or less does what you want:
var max = 5;
var array = new char[max];
var letters = "abcdefghij";
var count = 0;
while (count < 5)
{
Console.WriteLine("Please Enter {0} Letters B/W a through j only: ", max);
var key = Console.ReadKey();
var read = key.KeyChar
if (!letters.Contains(read))
{
Console.WriteLine("You have entered an incorrect value");
continue;
}
var found = false;
for (int i = 0; i < count; i++)
{
if (array[i] == read)
{
found = true;
}
}
if (found)
{
Console.WriteLine("You have entered an duplicate value");
continue;
}
array[count++] = read;
}
Console.WriteLine("You have Entered the following Inputs: ");
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine(array[i]);
}
Console.ReadKey();
If you want the user to enter the values individually then you would need to request each character in a loop.
Something like:
static void Main(string[] args)
{
const string validValues = "abcdefghij";
var enteredCharacters = new char[5];
for (int i = 0; i < enteredCharacters.Length; i++)
{
Console.WriteLine("Please enter a unique character between a and j");
var input = Console.ReadLine();
if (input.Length == 0)
{
Console.WriteLine("You did not enter a value.");
return;
}
if (input.Length > 1)
{
Console.WriteLine("You have entered more than 1 character");
return;
}
var character = input[0];
if (!validValues.Contains(character))
{
Console.WriteLine("You have entered an invalid character");
return;
}
if (enteredValues.Contains(character))
{
Console.WriteLine("You have already entered this character");
return;
}
enteredCharacters[i] = character;
}
// process numbers.
}
this is you problem
for (int i = 0; i < 5; i++)
this is your fix:
static void Main(string[] args)
{
char[] Array = new char[5];
Console.WriteLine("Please Enter 5 Letters B/W a through j only: ");
string letters = "abcdefghij";
char[] read = Console.ReadLine().ToLower().ToCharArray();
//loop through array
for (int i = 0; i < read.Length; i++)
{
if (letters.Contains(read[i]) && !Array.Contains(read[i]))
{
Array[i] = read[i];
}
else
{
Console.WriteLine("You have entered an incorrect value");
}
}
Console.WriteLine("You have Entered the following Inputs: ");
for (int i = 0; i < Array.Length; i++)
{
Console.WriteLine(Array[i]);
}
Console.ReadKey();
}

drawing a simple hangman design linked to my incorrect guesses in c#

I wish to display a simple hangman design using characters from the keyboard based on the incorrect answers that a user inputs. These incorrect answers will draw a new piece to the hangman each time although i am unsure how to do this. I have made my program function to cycle through 10 guesses before displaying the right answer and looping back to a new word.
The question i am asking is i do not know how to make a visual representation of a hangman in c# and how to link this to my existing code to only draw specific parts of the hangman based on the incorrect guesses. How do i do this?
The code is below.
namespace ConsoleApplication9
{
class Program
{
static string RandomWord()
{
Random rnd = new Random();
int response = rnd.Next(1, 4);
string randWord = "";
switch (response)
{
case 1:
randWord = "dog";
break;
case 2:
randWord = "robot";
break;
case 3:
randWord = "fish";
break;
case 4:
randWord = "continue";
break;
}
return randWord;
}
static void Main(string[] args)
{
string value = "";
int count = 0;
int gameLoop = 0;
string inData;
Console.WriteLine("Welcome to Hangman here is the first word");
do
{
count = 0;
value = RandomWord();
char[] newValue = new char[value.Length];
for (int i = 0; i < newValue.Length; i++)
{
newValue[i] = '_';
}
for (int i = 0; i < newValue.Length; i++)
{
Console.Write(newValue[i] + " ");
}
do
{
count++;
Console.Write("\n\nPlease enter your guess : ");
char input = (Console.ReadLine().ToCharArray()[0]);
for (int i = 0; i < value.Length; i++)
{
if (value[i] == input)
{
newValue[i] = input;
}
}
for (int x = 0; x < newValue.Length; x++)
{
Console.Write(newValue[x] + " ");
}
string s = (value);
string t = new string(newValue);
int c = string.Compare(s, t);
if (c == 0)
{
count = 10;
Console.WriteLine("\n\nCongratulations you guessed the word {0}", value);
}
} while (count < 10);
string Wrong = (value);
string Wrong2 = new string(newValue);
int gameOver = string.Compare(Wrong, Wrong2);
if (gameOver != 0)
{
Console.WriteLine("\n\nGame Over! the correct word was {0}", value);
}
Console.WriteLine("Would you like to go again? if so press 1 or 0 to exit");
inData = Console.ReadLine();
gameLoop = Convert.ToInt32(inData);
}
while (gameLoop == 1);
}
}
}
I am not quite sure how you plan to draw the hangman using ASCII art, but you could create a string array containing the 10 "pictures" as strings and then showing the corresponding one when appropriate.
You can create an array like so:
var pictures = new[]{":-)", ":-|", ":-(", "x.x", etc. };
and then
count++;
// display it here
Console.WriteLine(pictures[count]);
Console.Write("\n\nPlease enter your guess : ");

Categories

Resources