Need to create an array to reveal correct letters - c#

Code works the way I want it to. I am having trouble making an array to replace the *s in Console.WriteLine("The word is *******."); .... The array has to reveal the correct letters in their correct place and I am hopelessly lost.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int correctcounter = 0;
int wrongcounter = 0;
char l1 = 'j';
char l2 = 'o';
char l3 = 'h';
char l4 = 'n';
char l5 = 's';
char[] correctletters = { 'j', 'o', 'h', 'n', 's', 'o', 'n' };
char[] guessedletters = new char[10];
Console.WriteLine("Welcome to the Hangman Game!");
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("You have 10 tries to guess the word right.");
Console.WriteLine();
Console.WriteLine();
for (int i = 0; i < 10; i++)
{
Console.WriteLine("The word is *******.");
Console.WriteLine();
Console.WriteLine("Guessed letters: [{0}]", string.Join(",", guessedletters));
Console.WriteLine();
Console.WriteLine("Your total wrong guesses:{0}.", wrongcounter);
Console.WriteLine();
Console.WriteLine("Please enter a letter");
Console.WriteLine();
guessedletters[i] = Convert.ToChar(Console.ReadLine());
if (guessedletters[i] == l1 || guessedletters[i] == l2 || guessedletters[i] == l3 || guessedletters[i] == l4 || guessedletters[i] == l5)
{
Console.WriteLine();
Console.WriteLine("You guessed correctly!");
correctletters[i] = guessedletters[i];
correctcounter++;
}
else
{
Console.WriteLine();
Console.WriteLine("You guessed incorrectly");
wrongcounter++;
}
if (correctcounter == 5)
{
Console.WriteLine();
Console.WriteLine("You guessed the word, [{0}]. You WIN!", string.Join("",correctletters));
break;
}
if (wrongcounter == 10)
{
Console.WriteLine();
Console.WriteLine("You LOSE! The word was [{0}]. You LOSE!", string.Join("", correctletters));
break;
}
}
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Please hit enter to end the program");
Console.ReadLine();
}
}
}

Okay, let's try to do that slowly, with structures you already know of.
So, to achieve our goal, we will work with an other array, which will hold the word to reveal to the user. We'll call it 'wordToReveal':
char[] wordToReveal = {'*', '*', '*', '*', '*', '*', '*'};
When the user finds a correct letter, we will fill it with the correct letters.
If we move to the first if, we can see you already tried to alter the correctLetters with the guessedLetters:
correctletters[i] = guessedletters[i];
However, what this code is doing is wrong. You are using the index i (which is the turn #) to change the correct letter to what the user guessed. So if we're at the 3rd turn, the user input 'j', you'll end-up with your correct word looking like this : johjson.
Instead of this, we will loop through your current 'correctLetters' and change the "word to reveal" to show the real letters. To loop, we're using an other for loop, with a variable called j (because i is already taken!). This variable will go from 0 up to the end of the array.
In that loop, we'll check if the letter at the index j have been guessed by the user. If it is the case, we'll overwrite the * by the correct letter:
for (int j = 0; j < correctletters.Length; j++)
{
if (guessedletters.Contains(correctletters[j]))
{
wordToReveal[j] = correctletters[j];
}
}
Finally, we need to display the word. To do that, we'll replace your string "The word is *******." with our new word to reveal :
Console.WriteLine("The word is " + string.Concat(wordToReveal) + ".");
By the way, string.Concat is exactly like the string.Join you were using. The difference is that you do not have to specify an empty string as a delimiter, it joins the array together by itself.
The final code looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int correctcounter = 0;
int wrongcounter = 0;
char l1 = 'j';
char l2 = 'o';
char l3 = 'h';
char l4 = 'n';
char l5 = 's';
char[] correctletters = { 'j', 'o', 'h', 'n', 's', 'o', 'n' };
char[] wordToReveal = {'*', '*', '*', '*', '*', '*', '*'};
char[] guessedletters = new char[10];
Console.WriteLine("Welcome to the Hangman Game!");
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("You have 10 tries to guess the word right.");
Console.WriteLine();
Console.WriteLine();
for (int i = 0; i < 10; i++)
{
Console.WriteLine("The word is " + string.Concat(wordToReveal) + ".");
Console.WriteLine();
Console.WriteLine("Guessed letters: [{0}]", string.Join(",", guessedletters));
Console.WriteLine();
Console.WriteLine("Your total wrong guesses:{0}.", wrongcounter);
Console.WriteLine();
Console.WriteLine("Please enter a letter");
Console.WriteLine();
guessedletters[i] = Convert.ToChar(Console.ReadLine());
if (guessedletters[i] == l1 || guessedletters[i] == l2 || guessedletters[i] == l3 || guessedletters[i] == l4 || guessedletters[i] == l5)
{
Console.WriteLine();
Console.WriteLine("You guessed correctly!");
for (int j = 0; j < correctletters.Length; j++)
{
if (guessedletters.Contains(correctletters[j]))
{
wordToReveal[j] = correctletters[j];
}
}
correctcounter++;
}
else
{
Console.WriteLine();
Console.WriteLine("You guessed incorrectly");
wrongcounter++;
}
if (correctcounter == 5)
{
Console.WriteLine();
Console.WriteLine("You guessed the word, [{0}]. You WIN!", string.Concat(correctletters));
break;
}
if (wrongcounter == 10)
{
Console.WriteLine();
Console.WriteLine("You LOSE! The word was [{0}]. You LOSE!", string.Concat(correctletters));
break;
}
}
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Please hit enter to end the program");
Console.ReadLine();
}
}
}
You can see we declared the new array with the other, changed the Console.Write and added the new loop in the first if.
There's a lot of other ways to achieve it, but I hope this was clear enough for you.

This is one way:
var secretWord = "shmurple"; // the secret word
var mask = new String('*', secretWord.Length); // the mask
When revealing a letter:
var sb = new StringBuilder(mask); // to be able to alter at index
sb[2] = secretWord[2];
mask = sb.ToString();
Example:
var secretWord = "shmurple";
var mask = new String('*', secretWord.Length);
var sb = new StringBuilder(mask);
sb[2] = secretWord[2];
mask = sb.ToString();
Console.WriteLine(String.Format("The word is {0}.", mask)); // **m*****
This is one way... but there are lots more. I gave this a one-minute consideration, so you might find a more efficient way.
Alternatively, secretWord could be a char array, so that you don't have to worry about the whole StringBuilder business. Everything else works the same way.
EDIT:
I see your new code.... Just create a mask array (same length as the secret word) and when you're revealing a letter, replace it with the char from the correct array:
char[] secret = { 'j', 'o', 'h', 'n', 's', 'o', 'n' };
char[] solution = Enumerable.Repeat('*', secret.Length).ToArray(); // mask
solution[2] = secret[2]; // example
Console.WriteLine(solution); // **h****
That way, all your indexes match and your life is a lot simpler. If you need to reveal all matches, just use a loop.

Related

Counter goes down by 4 at the time instead of one (C#)

I am new at C# and after learning the basics I've decided that I wanna make a Hangman game. The problem is that a counter that normally counts down from 8 by 1 each time I miss a letter is counting down by 4 and I have no idea why.
static void Main(string[] args)
{
int Chances= 8;
bool key = false;
int N= 10;
char[] Word = { 'P', 'R', 'O', 'G', 'R', 'A', 'M' };
Console.WriteLine("The word is:_ _ _ _ _ _ _");
Console.Write("Please input a letter:");
while (key == false)
{
char letter = Convert.ToChar(Console.Read());
N = Numberofletter(letter);
Console.WriteLine(N);
while (N == 0 && Chances > 0)
{
Chances--;
Console.WriteLine("The letter is incorrect you have " + K + " tries Remaining");
letter = Convert.ToChar(Console.Read());
};
if (Chances == 0)
{
Console.WriteLine("Gameover");
return;
}
static int Numberofletter(char letter)
{
int N = 0;
char[] Word = { 'P', 'R', 'O', 'G', 'R', 'A', 'M' };
if (Word[0] == letter)
{ N = 1; }
else if (Word[1] == letter)
{ N = 2; }
else if (Word[2] == letter)
{ N = 3; }
else if (Word[3] == letter)
{ N = 4; }
else if (Word[5] == letter)
{ N = 6; }
else if (Word[6] == letter)
{ N = 7; }
else { N = 0; }
return N;
}
The problem is in your while loop.
You enter the loop with N = position of the guessed letter = 0.
INSIDE the loop, you ask for another letter, but NEVER calculate its position.
So even if the letter is in the word, you've never re-assigned the value of N. This means the loop will keep running and decrementing chances until chances < 0;
Simply add
N = Numberofletter(letter);
after you read in the next letter.
I don't know if anyone else will have the same problem as me but I will post my mistake here so at least I hope it will not be repeated
instead of letter=Convert.ToChar(Console.Read());
you should use letter=Convert.ToChar(Console.ReadLine());
i don't know why was that the problem but it happend try it out randomly and it worked

Checking to see the char equivalent of my int value

Okay i might not have explained it to the best of my ability but i'm a beginner and i would like to make a piece of code that does this :
you have a string and you need to find each vowel in it and multiply each vowel's position in the string by its position in the alphabet and add all the sums together
example : steve: has 2 vowels the first e's position is 3 and its position in the alphabet is 5. and the second's position in the alphabet and the string is 5
so the sum is 5*3 + 5*5 = 40
this is what i did . idk what to do now or how to approach it
var vowels = new char[] {'a', 'e', 'i', 'o', 'u', 'y', 'A','E','I', 'O', 'U','Y'};
var chars = new List<char>();
List<int> indexes = new List<int>();
Console.WriteLine("Write something : ");
var input = Console.ReadLine();
int index;
foreach (var vowel in vowels)
{
if (input.Contains(vowel))
{
index = input.IndexOf(vowel);
indexes.Add(index + 1);
chars.Add(vowel);
}
}
Consider this approach:
using System;
using System.Linq;
using System.Collections.Generic;
namespace Whatever
{
class Program
{
static void Main(string[] args)
{
var vowels = new Dictionary<string, int>(5, StringComparer.OrdinalIgnoreCase) { { "a", 1 }, { "e", 5 }, { "i", 9 }, { "o", 15 }, { "u", 21 } };
Console.WriteLine("Write something : ");
var input = Console.ReadLine();
var sum = input.Select((value, index) => new { value, index })
.Sum(x =>
{
vowels.TryGetValue(x.value.ToString(), out var multiplier);
return (x.index + 1) * multiplier;
});
Console.ReadLine();
}
}
}
The Select projects the original string as an anonymous type with the char and its index included.
The Sum checks if the string is a vowel - and if it is it multiplies the position (index + 1) by the position in the alphabet (from vowels).
vowels is case insensitive so that "A" and "a" are treated the same.
If the compiler complains about the out var then use:
int multiplier = 0;
vowels.TryGetValue(x.value.ToString(), out multiplier);
return (x.index + 1) * multiplier;
instead.
i figured it out right here
for (int i = 0; i < indexes.Count; i++)
{
sumofone += indexes[i] * (char.ToUpper(chars[i]) - 64);
}
You can do this (Reference is from here):
var vowels = new char[] { 'a', 'e', 'i', 'o', 'u' };
Console.WriteLine("Write something : ");
var input = Console.ReadLine().ToLower();
int total = 0;
for (int temp = 1; temp <= input.Length; temp++)
{
if (vowels.Contains(input[temp - 1]))
{
total += temp * (char.ToUpper(input[temp -1]) - 64);
}
}
Console.WriteLine("The length is " + total);

Hangman Console Application

I am currently working on a small project where I am creating a hangman game as a console application. Currently, I am having problems because I want to create an array for the word that is to be guessed. This word is not random and will always be the same. In this case, it is "miller". I want to create an array for "miller" and have a loop to display each letter in the word character array. When the letter is guessed correctly, I want to display the correct letter and if not display the special character "*" in its stead. So, for instance, the word is "miller" and would be first displayed as "******". When the user guessed a letter correctly, one special character would become the correctly guessed letter. So, say the user guesses "i"...the displayed word would then be "*i****". Say he guesses "l" next...the displayed word would then be "*ill**". How would I go about doing this? This is my code so far... I've created already attempted to create an array for this. Sorry if this seems trivial, but I am new to programming and just need some guidance and help.
TLDR;
I need help with this code. I am trying to make an array containing 'miller' and I want to be able to call on that array when the user guesses a letter correct changing the display of a special character "*" to whatever the letter he guesses correctly is. I am told going about a for loop is the best route for this, but I'm kind of lost. Help?
static void Main(string[] args)
{
char[] guessed = new char[26];
char[] word = "miller".ToCharArray();
char guess;
int score = 0, index = 0;
Console.WriteLine("******");
for (int i = 0; i < 10; i++)
{
Console.Write("Please enter a letter to guess: ");
guess = char.Parse(Console.ReadLine());
if (guess == l1 || guess == l2 || guess == l3 || guess == l4 || guess == l5 || guess == l6)
{
Console.WriteLine("Your guess is correct.");
guessed[index] = guess;
index++;
}
else
{
Console.WriteLine("Your guess is incorrect.");
score++;
}
}
Console.WriteLine("Your score is " + score);
Console.ReadLine();
}
}
}
I don't know if this is what you were looking for, maybe you should be more specific next time... but I tried to create a solution for your problem.
static void Main(string[] args)
{
char[] guessed = new char[26];
char[] testword = "******".ToCharArray();
char[] word = "miller".ToCharArray();
char[] copy = word;
char guess;
int score = 0, index = 0;
Console.WriteLine(testword);
for (int i = 0; i < 10; i++)
{
Console.Write("Please enter a letter to guess: ");
guess = char.Parse(Console.ReadLine());
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.");
score++;
}
else
{
right = false;
}
Console.WriteLine(testword);
}
Console.WriteLine("Your score is " + score);
Console.ReadLine();
}
Include using System.Linq; in your file and here is your for loop.
for (int 1 = 0; i < 10; i++)
{
Console.Write("Please enter a letter to guess: ");
char guess = char.Parse(Console.ReadLine());
if(word.Contains(guess))//checks if the word is is the array word
{
//the guess was correct.
Console.WriteLine("Your guess is correct.");
guessed[index] = guess;
index++;
}
else
{
//the guess was wrong.
console.WriteLine("Your guess is incorrect.");
....
}
}
Hope this helps.
It looks like you're fairly close to there. The two things I'm uncertain about is the if statement "guess == l1 || guess == l2" etc etc...This can be handled with:
if(word.Contains(guess))
Second, you will need another for loop to go through the correctly guessed letters and place them.
for loop to fill in letters instead of asterisks:
put it at the beginning of for (int i = 10...)
for (int j = 0; j < word.Length; j++)
{
if (guessed.Contains(word[j]))
{
Console.Write(word[j]);
}
else
{
Console.Write("*");
}
}

I want to search integers from string and store them in array

I'm building a console based lottery game where user enters his/her choice of numbers. I need to check that the numbers are between 1-39 and user has entered exactly 7 valid numbers. I'd like to do this in a way where user writes them in one line of string in console and the program finds any white space, comma or other non-digit characters and ignores them. The remaining lottery numbers should be stored in integer array which doesn't include any duplicates.
My current version is quite horrible since it gets errors very easily if user writes e.g. 2 spaces between numbers.
Console.WriteLine("Choose 7 numbers (1-39) by pressing ENTER after every number:");
string userRow = Console.ReadLine();
int[] userLottery = new int[7];
for(int i = 0; i < userLottery.Length; i++)
{
userLottery = userRow.Split(',', '.', ' ').Select(x => int.Parse(x)).ToArray();
if(userLottery[i] > 7)
{
Array.Resize(ref userLottery, 7);
}
}
I'd like to replace my current way in more convenient way where amount of user errors won't affect the program. If the user writes more than one space the error occures.
I have tried to build regular expression to handle these situations but I can't use it to store them in to array.
string userChoice = Console.ReadLine();
MatchCollection userNumbers = Regex.Matches(userChoice, #"\d+");
int[] userRow;
for(int i = 0; i < userNumbers.Count; i++)
{
userRow[i] = userNumbers[i].Value;
}
That says string can't be converted to int[]...
You could use this LINQ query using String.Split with RemoveEmptyEntries and int.tryParse:
int num = 0;
int[] userLottery = userRow.Trim()
.Split(new[] { '.', ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Where(s => int.TryParse(s.Trim(), out num) && num > 0 && num < 40)
.Select(s => num)
.Distinct()
.ToArray();
if(userLottery.Length != 7)
Console.WriteLine("Enter 7 valid numbers between 1 and 39");
else
Console.WriteLine("You have chosen following numbers: " + string.Join(",", userLottery));
Enumerable.Distinct removes duplicates as requested.
Your code doesn't match the instruction to the user. The following does what you tell the user:
Console.WriteLine("Choose 7 numbers (1-39) by pressing ENTER after every number:");
int[] userLottery = new int[7];
int i = 0;
while (i < 7)
{
Console.Write("Your choice #{0}: ", i+1);
string userRow = Console.ReadLine();
int userNumber;
if (!Int32.TryParse(userRow, out userNumber) || userNumber < 1 || userNumber > 39)
{
Console.WriteLine("Invalid number! Please try again!");
}
else
{
userLottery[i++] = userNumber;
}
}
Use Regex.Split() for this to handle multiple white spaces.
string[] numbers = Regex.Split(userRow, #"\s+");
\s+ means one or more white spaces. You can use [ ]+ only for space if you want.
You can just parse it with RegEx first and then it should work.
using System.Text.RegularExpressions;
Console.WriteLine("Choose 7 numbers (1-39) by pressing ENTER after every number:");
string userRow = Console.ReadLine();
int[] userLottery = new int[7];
string[] userEnter = Regex.Split(userRow, " ");
int n = 0;
int k = 0;
for (int i = 0; i < userEnter.Length; i++)
{
bool isNumeric = int.TryParse(userEnter[i], out n);
if(isNumeric == true)
{
userLottery[k] = int.Parse(userEnter[i]);
k++;
}
}
Use the following code
Console.WriteLine("Choose 7 numbers (1-39) by pressing ENTER after every number:");
string data = Console.ReadLine();
int[] userLottery = new int[7];
int i = 0;
StringBuilder num = new StringBuilder();
foreach (char item in data)
{
if (!Char.IsDigit(item))
{
if (num.Length == 0)
continue;
userLottery[i] = int.Parse(num.ToString());
i++;
num.Clear();
continue;
}
num.Append(item);
}
if(num.Length > 0)
userLottery[i] = int.Parse(num.ToString());

Reduce lines of code with switch statement

I am teaching myself C# and one of the current chapters challenges asks me to prompt the user for a string, write back the string, count the number of characters, the instances of the letter 'e' and finally the instances of all vowels. It gave a hint to use switch but I couldn't figure out how to do it. I did get it to work by doing it manually, but I don't think that's the point. :) How could I use a switch statement to reduce the number of typed lines?
Console.WriteLine("Please type a sentence and hit enter: ");
string myString = Console.ReadLine();
int letterCount = myString.Split('e').Length - 1;
Console.Clear();
Console.WriteLine("Thank you. The sentence you entered was: \n\"{0}\"", myString);
Console.WriteLine("This sentence is {0} characters long.", myString.Length);
Console.WriteLine("It contains {0} instances of the letter \'e\'.", letterCount);
int vowelCount = 0;
int letterALower = myString.Split('a').Length - 1;
vowelCount += letterALower;
int letterELower = myString.Split('e').Length - 1;
vowelCount += letterELower;
int letterILower = myString.Split('i').Length - 1;
vowelCount += letterILower;
int letterOLower = myString.Split('o').Length - 1;
vowelCount += letterOLower;
int letterULower = myString.Split('u').Length - 1;
vowelCount += letterULower;
int letterAUpper = myString.Split('A').Length - 1;
vowelCount += letterAUpper;
int letterEUpper = myString.Split('E').Length - 1;
vowelCount += letterEUpper;
int letterIUpper = myString.Split('I').Length - 1;
vowelCount += letterIUpper;
int letterOUpper = myString.Split('O').Length - 1;
vowelCount += letterOUpper;
int letterUUpper = myString.Split('U').Length - 1;
vowelCount += letterUUpper;
Console.WriteLine("There are {0} vowels used.", vowelCount);
Console.ReadLine();
I know this isn't a good answer to the question, but I couldn't resist a one liner!
inputString.ToLower().Count(s=>"aeiou".Contains(s)); //count the vowels
Here's a simple solution:
string str = Console.ReadLine();
string low_str = str.ToLower();
Console.Clear();
Console.WriteLine("Thank you. The sentence you entered was: \n\"{0}\"", str);
Console.WriteLine("This sentence is {0} characters long.", str.Length);
int vowelCount = 0;
int eCount = 0;
for (int i = 0; i < low_str.Length; i++)
{
switch(low_str[i])
{
case 'e': eCount ++; vowelCount++; break;
case 'a': vowelCount++; break;
case 'o': vowelCount++; break;
case 'i': vowelCount++; break;
case 'u': vowelCount++; break;
case 'y': vowelCount++; break;
}
}
Console.WriteLine("It contains {0} instances of the letter \'e\'.", eCount);
Console.WriteLine("There are {0} vowels used.", vowelCount);
Console.ReadLine();
Notice that this could be done in an even fewer lines using this method (not the best way, but let's not go too deep into the framework details :) ):
int eCount = low_str.split(new char[]{'e'}) - 1;
int vowelCount = low_str.split(new char[]{'a','e','o','i','u','y'}) - 1;
Something like this (pseudo code, not actual C#)?
foreach (c in mySentence)
{
c = LowerCase(c);
switch (c) {
case 'a' :
case 'e' :
case 'i' :
case 'o' :
case 'u' :
nVowels ++;
break;
case ' ' :
case '\t' :
nBlanks++;
break;
default :
nChars++
break;
}
Here's a bit more info:
http://msdn.microsoft.com/en-us/library/06tc147t%28v=vs.80%29.aspx
I personally would do it with foreach and an array or vowels. This way it's easy to expand, like this:
Char[] vowels = {'e', 'a', 'o', 'i', 'u', 'y'};
string str = Console.ReadLine();
string low_str = str.ToLower();
Console.Clear();
Console.WriteLine("Thank you. The sentence you entered was: \n\"{0}\"", str);
Console.WriteLine("This sentence is {0} characters long.", str.Length);
int vowelCount = 0;
int eCount = 0;
foreach (char chara in low_str)
{
foreach (char vowel in vowels)
if (vowel == chara)
vowelCount++;
if (chara == 'e')
eCount++;
}
Console.WriteLine("It contains {0} instances of the letter \'e\'.", eCount);
Console.WriteLine("There are {0} vowels used.", vowelCount);
Console.ReadLine();

Categories

Resources