C# Guessing Game using a text file - c#

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.

Related

Is there a way to compare two strings in C# and get the differences only?

I am trying to compare two string in C# and get the differences between them i.e words which are not present in the other string ignoring cases and commas just focusing on the words. If one string contains two or multiple the and the second string has one the, it means this will be disregarded as it exists in both. Example I have two strings like below;
Cat meet's a dog
Cat meet's a dog and a bird
The difference between those two strings is and bird because it does not exist in the first one or vise versa and I want to get those two words and bird either in a List or a new string with spaces between them and in other words I want the words which are not present in the other string. Is there a way this can be done in C#?
Here's a way using LINQ. You don't need the "ToList()" part, but you mentioned that as one form of output you'd want:
string str1 = "Cat meet's a dog";
string str2 = "Cat meet's a dog and a bird";
string[] str1Words = str1.ToLower().Split(' ');
string[] str2Words = str2.ToLower().Split(' ');
var uniqueWords = str2Words.Except(str1Words).Concat(str1Words.Except(str2Words)).ToList();
// Do whatever you want with uniqueWords instead
Console.WriteLine($"output: {String.Join(" ", uniqueWords)}");
#ngdeveloper. This is my variant of your solution (had to post it in a separate answer because of the length):
private static StringsDiff Difference(string firststring, string secondstring)
{
StringsDiff _stringsDiff = new StringsDiff();
char[] _firstStringArray = firststring.ToCharArray();
char[] _secondStringArray = secondstring.ToCharArray();
int shortestLenght;
int longestLenght;
bool firstIsLongest;
if (_firstStringArray.Length > _secondStringArray.Length)
{
firstIsLongest = true;
shortestLenght = _secondStringArray.Length;
longestLenght = _firstStringArray.Length;
}
else
{
firstIsLongest = false;
shortestLenght = _firstStringArray.Length;
longestLenght = _secondStringArray.Length;
}
for (int i = 0; i < shortestLenght; i++)
{
if (!_firstStringArray[i].Equals(_secondStringArray[i]))
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
for (int i = shortestLenght; i < longestLenght; i++)
{
if (firstIsLongest)
_stringsDiff._diffList1.Add(_firstStringArray[i]);
else
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
return _stringsDiff;
}
I wrote you a simple solution, hope it will help -
The main method is called 'Difference' it receive 2 strings to compare and return an object called StringDiff.
It runs 2 loops, first comparing between the two strings char by char and then adding the rest of the longer string.
The 'StringDiff' object is a class with 2 char lists that represnt the differences of each string.
In the main method i use String.join to convert the char lists to a string and print it.
internal class Program
{
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("enter first string");
string firstString = Console.ReadLine();
Console.WriteLine("enter second string");
string secondString = Console.ReadLine();
StringsDiff _stringsDiff = Difference(firstString, secondString);
Console.WriteLine(
$"fist string difference: {string.Join("", _stringsDiff._diffList1)} / second string difference: {string.Join("", _stringsDiff._diffList2)}");
Console.WriteLine("/////////////////////////////////////");
}
}
private static StringsDiff Difference(string firststring, string secondstring)
{
StringsDiff _stringsDiff = new StringsDiff();
char[] _firstStringArray = firststring.ToCharArray();
char[] _secondStringArray = secondstring.ToCharArray();
int lenght;
if (_firstStringArray.Length > _secondStringArray.Length)
{
lenght = _secondStringArray.Length;
for (int i = 0; i < lenght; i++)
{
if (!_firstStringArray[i].Equals(_secondStringArray[i]))
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
for (int i = _secondStringArray.Length; i < _firstStringArray.Length; i++)
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
}
}
else
{
lenght = _firstStringArray.Length;
for (int i = 0; i < lenght; i++)
{
if (!_firstStringArray[i].Equals(_secondStringArray[i]))
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
for (int i = _firstStringArray.Length; i < _secondStringArray.Length; i++)
{
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
return _stringsDiff;
}
class StringsDiff
{
public List<char> _diffList1 = new List<char>();
public List<char> _diffList2 = new List<char>();
}
}
Remember to use "string.join" to connect the lists objects if you need a string.

Delete part of string value

I want to mix 2 string in 1 randomly using foreach but I don't know how I delete the part I used on the string for the foreach like:
string s = "idontknow";
string sNew = "";
foreach(char ss in s){
s = s + ss;
ss.Delete(s); //don't exist
}
Full code here i'm trying to do:
do
{
if (state == 0)
{
for (int i = 0; random.Next(1, 5) > variable.Length; i++)
{
foreach (char ch in variable)
{
fullString = fullString + ch;
}
}
state++;
}
else if (state == 1)
{
for (int i = 0; random.Next(1, 5) > numbers.Length; i++)
{
foreach (char n in numbers)
{
fullString = fullString + n;
}
}
state--;
}
} while (variable.Length != 0 && numbers.Length != 0);
I'm pretty confident, that in your first code snippet, you are creating an infinite loop, since you are appending the used char back to the string while removing it from the first position.
Regarding your specification to shuffle two stings together, this code sample might do the job:
public static string ShuffleStrings(string s1, string s2){
List<char> charPool = new();
foreach (char c in s1) {
charPool.Add(c);
}
foreach (char c in s2) {
charPool.Add(c);
}
Random rand = new();
char[] output = new char[charPool.Count];
for(int i = 0; i < output.Length; i++) {
int randomIndex = rand.Next(0, charPool.Count);
output[i] = charPool[randomIndex];
charPool.RemoveAt(randomIndex);
}
return new string(output);
}
In case you just want to shuffle one string into another string, just use an empty string as the first or second parameter.
Example:
string shuffled = ShuffleStrings("TEST", "string");
Console.WriteLine(shuffled);
// Output:
// EgsTtSnrTi
There are possibly other solutions, which are much shorter, but I think this code is pretty easy to read and understand.
Concerning the performance, the code above should works both for small stings and large strings.
Since strings are immutable, each modify-operation on any string, e.g. "te" + "st" or "test".Replace("t", ""), will allocate and create a new string in the memory, which is - in a large scale - pretty bad.
For that very reason, I initialized a char array, which will then be filled.
Alternatively, you can use:
using System.Text;
StringBuilder sb = new();
// append each randomly picked char
sb.Append(c);
// Create a string from appended chars
sb.ToString();
And if your question was just how to remove the first char of a string:
string myStr = "Test";
foreach (char c in myStr) {
// do with c whatever you want
myStr = myStr[1..]; // assign a substring exluding first char (start at index 1)
Console.WriteLine($"c = {c}; myStr = {myStr}");
}
// Output:
// c = T; myStr = est
// c = e; myStr = st
// c = s; myStr = t
// c = t; myStr =

Need to display the average letters of each word in a string and display it

Here is what I have so far, it is set up to display the total number of words, which I need to keep, or modify to keep to allow the average number of letters in each word to be displayed, please assist anyone if you can. thank you so much!:
private void btnCheck_Click(object sender, EvenArgs e)
{
string words = tbxArgument.Text.Trim();
MessageBox.Show("Number of Words: " + CountWords(words));
}
private int CountWords(string words)
{
string[] allWords = words.Split(' ');
return allWords.Length;
}
Not sure If this is what you are trying to accomplish.
But this will give you the average length of all the words.
double totalCharacters = 0;
double avgCharacters = 0;
string[] words = new string[] {"Word1","Word2","Word3" } ;
foreach (string tmpString in words)
{
totalCharacters = totalCharacters + tmpString.Length;
}
avgCharacters = totalCharacters/words.Length;
This is a method that only interate over the string, without making splits that require allocate extra memory. Just an optimization, for entertainment:
public static double GetAvgLetters(string text, out int wordsCount)
{
wordsCount = 0;
if (string.IsNullOrWhiteSpace(text))
{
return double.NaN;
}
var lettersCount = 0;
var isLetter = text[0] != ' ';
var readingLetter = isLetter;
for (int i = 0; i < text.Length; i++)
{
isLetter = text[i] != ' ';
if (isLetter != readingLetter)
{
readingLetter = isLetter;
if (readingLetter)
{
lettersCount++;
}
else
{
wordsCount++;
}
}
else if (isLetter)
{
lettersCount++;
}
}
if (isLetter == readingLetter && isLetter)
{
wordsCount++;
}
return lettersCount / (double)wordsCount;
}
I simply iterate checking the changes between blank and not blank (to count words) and, while reading letters, counting letters. At the end, if we are reading letters and last char is a letter, we must add the last word to count.

Efficiency in filling an array

I am coding an application that asks a user to enter a word, and then the program checks if there are any words contained within the larger word that are in the dictionary. For example, if the user entered "starburst", the system would output "star" and "burst".
I am creating my own dictionary of words within the program. So far I have an array, and I simply go one by one and add different words to the dictionary. Is there a more efficient way of doing this?
code posted below:
static void Main(string[] args) {
Console.WriteLine("Enter a word");
string word = Console.ReadLine();
string word2 = word;
string [] dictionary = new string[300];
dictionary[0] = "apple";
dictionary[1] = "adversary";
dictionary[2] = "apply";
dictionary[3] = "be";
dictionary[4] = "bear";
dictionary[5] = "Bare";
dictionary[6] = "car";
dictionary[7] = "care";
dictionary[8] = "cat";
dictionary[9] = "carreer";
dictionary[10] = "day";
dictionary[11] = "dare";
dictionary[12] = "date";
dictionary[13] = "do";
dictionary[14] = "double";
dictionary[15] = "ex";
dictionary[16] = "extra";
dictionary[17] = "can";
dictionary[18] = "dog";
dictionary[19] = "dont";
for (int i = 0; i < word.Length; i++)
{
for (int n = word2.Length; n < dictionary.Length; n++)
{
if (word == dictionary[n] && word != word2)
{
Console.WriteLine(word);
}
if(word2 == dictionary[n] && word != word2)
{
Console.WriteLine(word2);
}
word.Substring(1, word.Length - 1);
word2.Substring(0, word2.Length - 2);
}
}
}
Is there a more efficient way of doing this?
I assume you mean not having to manually change the array initialization code and recompile the application when you want to add a word to the dictionary.
You could do this by putting your word list in a file, and reading it with string [] dictionary = File.ReadAllLines("dictionary.txt").

Remove string from a char array

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] + " ");

Categories

Resources