How to update an array that's linked to a List<string>

Viewed 175

So I'm working on this project and I'm really new to programming. I'm trying to make a Hangman game using C# and I'm a little stuck. I can display everything just fine to the console but when it comes to guessing the word, which is CRYPTOZOOLOGY, I can't get the underscores to change to the correct letter if the user's guess is actually within the word. So right now if the user guesses 'C' then the game will keep asking the user to choose a letter. This is not what I want. What I'm trying to get to is once the user guesses the correct letter I want the underscores to update to reveal the correct letter and the 'Used Letters: ' to reflect the letter that have been used in total. I believe my issue might be a hierarchy problem but I've been working on this for a couple of hours and at this point I'm pretty frustrated. I wish I could make this question more simple to answer but I don't feel like I have much of a choice. My code is listed below. Thanks.

Update: I added a while loop so the code can be run from the top once everything is done in the body. I've cleared the console after the user makes a selection. My issue now is outputting the letter in the correct spot where the underscore is.

Update: I was able to add the letter 'C' to the beginning of the underscores. Now if I type in 'R' the used Letters list will show the letters I've used but even if it's the right letter it won't update the underscores.

        public void GameDisplay(int randomNumber, Dictionary<string, string> randomKeyValue)
        {
            bool gameRunning = true;
            if (randomNumber == 0)
            {
                // Displaying the title
                Console.WriteLine("===================================");
                Console.WriteLine("              HANGMAN          ");
                Console.WriteLine("===================================");

                while (gameRunning)
                {

                    // Pulling the definition based on the Key of the word Dictionary
                    string randomDefinition = randomKeyValue["CRYPTOZOOLOGY"];

                    string associatedWord = "CRYPTOZOOLOGY";


                    string[] arrWord = { "C", "R", "Y", "P", "T", "O", "Z", "O", "O", "L", "O", "G", "Y" };

                    Console.WriteLine("\r\nDefinition: {0}\r\n", randomDefinition);


                       for (int i = 0; i < arrWord.Length; i++)
                    {
                     
                        if (_guesses.Contains(arrWord[i])) 
                        {
                            Console.Write("{0} ", _guesses[i]);

                        }

                        else
                        {
                            Console.Write("__ ");
                        }
                    }



                    Console.WriteLine("\r\n\r\n------------------------------------\r\n");


                    Console.WriteLine("Used Letters: ");

                    foreach (string miss in _misses)
                    {
                        Console.Write("{0} ", miss);
                    }



                    Console.WriteLine("\r\n========================================\r\n");


                    bool winning = false;


                    if (winning == false)
                    {

                        while (!winning)
                        {
                            GuessAgain(_guesses, _misses, arrWord, associatedWord);
                            AllMisses(_guesses);
                            Console.Clear();
                            winning = true;
                        }

                        /*Console.WriteLine("You won!");
                        _guesses.Clear();
                        winning = false;
                        */
                    }
                    else if (_guesses.Contains("C") && _guesses.Contains("R") && _guesses.Contains("Y") && _guesses.Contains("P") && _guesses.Contains("T") && _guesses.Contains("O") && _guesses.Contains("Z") && _guesses.Contains("L") && _guesses.Contains("G") && _guesses.Contains("Y"))
                    {

                        while (!winning)
                        {
                            GuessAgain(_guesses, _misses, arrWord, associatedWord);
                            AllMisses(_guesses);
                            Console.Clear();
                            winning = true;
                        }

                        // Console.WriteLine("Game over...");

                    }


                }

                Console.ReadLine();
            }
            
            // INSTRUCTIONS
            // display each letter in the word and replace with an underscore if its not within guesses


            // While the user has not won or misses 6 times
            // Call a method to display the misses
            // Call a method to allow the player to guess and make sure to validate against repeats

            // Display win/lose hangman message

        }


        public static bool AllMisses(List<string> misses)
        {
            bool winning = false;

            if (misses.Count == 6)
            {
                winning = true;
            }

            return winning;
        }

        public static void GuessAgain(List<string> guesses, List<string> misses, string[] arrWord, string actualWord)
        {

              Console.WriteLine("Choose a letter:");

            string userGuess = Console.ReadLine();
            string userGuessCaps = userGuess.ToUpper();

            while (string.IsNullOrWhiteSpace(userGuess))
            {
                Console.WriteLine("Please do not leave this blank.");
                Console.WriteLine("Choose a letter.");
                userGuess = Console.ReadLine();
            }

            for (int i = 0; i < arrWord.Length; i++)
            {
                if (userGuessCaps == arrWord[i] )
                {
                    guesses.Add(userGuessCaps);
                    break;
                }
                else if (userGuessCaps != arrWord[i]) 
                {
                    misses.Add(userGuessCaps);
                    AllMisses(misses);
                    break;

                }
            }
        }
    }
2 Answers

Following is a working solution.

public static void Main(string[] args)
{

    string associatedWord = "CRYPTOZOOLOGY";
    List<string> arrWord = new List<string>() { "C", "R", "Y", "P", "T", "O", "Z", "O", "O", "L", "O", "G", "Y" };

    List<string> _guesses = new List<string>();
    List<string> _misses = new List<string>();
    bool winning = false;

    while (!winning)
    {

        Console.Clear();

        // Displaying the title
        Console.WriteLine("===================================");
        Console.WriteLine("              HANGMAN          ");
        Console.WriteLine("===================================");

        // Iterate through each letter in arrWord and display Correct Guesses or __ for not discovered letters
        foreach (string letter in arrWord)
        {
            // Print either the correctly guessed letter or __ for not guessed yet.
            if (_guesses.Contains(letter))
                Console.Write(" " + letter + " ");
            else
                Console.Write("__ ");
        }
                
        // Print all the letters that have been missed.
        Console.WriteLine("\r\n\r\n------------------------------------\r\n");
        Console.WriteLine("Used Letters: " + string.Join(" ", _misses));
        Console.WriteLine("\r\n========================================\r\n");
            
        // Run the method to guess the letter.
        GuessAgain(_guesses, _misses, arrWord, associatedWord);

        // If misses == 6 or if you guessed all the letters, exit.
        winning = AllMisses(_misses) || arrWord.Where(x => _guesses.Contains(x)).Count() == arrWord.Count();
    }

    if (arrWord.Where(x => !_guesses.Contains(x)).Count() > 0)
        Console.WriteLine("LOST");
    else
        Console.WriteLine("WON");
}

public static bool AllMisses(List<string> misses)
{
    // No need to use extra variables to see if the misses count has reached 6
    return misses.Count == 6;
}

public static void GuessAgain(List<string> guesses, List<string> misses, List<string> arrWord, string actualWord)
{
    Console.WriteLine("Choose a letter:");

    string userGuess = Console.ReadLine().ToUpper(); // Change user's input to upper case

    while (string.IsNullOrWhiteSpace(userGuess))
    {
        Console.WriteLine("Please do not leave this blank.");
        Console.WriteLine("Choose a letter.");
        userGuess = Console.ReadLine().ToUpper(); // Change user's input to upper case
    }

    // Only add the letter to "ONE" of the lists. either it was a guess or a miss. Your code adds 12 letters at a time.. not what you want.
    // You can also add checks to see if the letter has already been guessed before or not.
    if (arrWord.Contains(userGuess))
        guesses.Add(userGuess);

    else
        misses.Add(userGuess);
}

Things I found with your code that needed a bit of a change

  1. Use List for arrWord... Makes things easier with Linq queries.
  2. One loop to go over the entire Code... you can make a method of it as well, but multiple while loops and for loops were found to be unneeded.
  3. See the comments in the code for changes

enter image description here

I like Hangman! Thanks for the "homework".

Here's another approach:

static void Main(string[] args)
{
    string word = "CRYPTOZOOLOGY";

    bool result = PlayHangman(word);
    Console.WriteLine();
    if (result)
    {
        
        Console.WriteLine("You guessed my word: " + word);
    }
    else
    {
        Console.WriteLine("You ran out of tries!");
        Console.WriteLine("The word was: " + word);
    }

    Console.Write("Press Enter to Quit");
    Console.ReadLine();
}

static bool PlayHangman(string word, int maxMisses = 6)
{
    int misses = 0;
    string wordToGuess = word.ToUpper();
    StringBuilder currentWord = new StringBuilder(new string('_', wordToGuess.Length));
    string validLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    string availableLetters = validLetters;
    while (currentWord.ToString() != wordToGuess && misses < maxMisses)
    {
        Console.WriteLine();
        Console.WriteLine("Guesses Left: " + (maxMisses - misses));
        Console.WriteLine("Word: " + currentWord.ToString());
        Console.WriteLine("Available Letters: " + availableLetters);
        Console.Write("Your guess: "); ;
        string guess = Console.ReadLine().Trim().ToUpper();
        if (guess.Length == 1 && validLetters.Contains(guess))
        {
            if (availableLetters.Contains(guess))
            {
                int letterFound = 0;
                for (int i = 0; i < wordToGuess.Length; i++)
                {
                    if(wordToGuess.Substring(i,1) == guess)
                    {
                        currentWord[i] = guess.ToCharArray()[0];
                        letterFound++;
                    }
                }
                availableLetters = availableLetters.Replace(guess, "");
                if (letterFound == 0)
                {
                    Console.WriteLine(guess + " was not in the word!");
                    misses++;
                }
                else
                {
                    Console.WriteLine(guess + " was found " + letterFound + " time" + (letterFound>1 ? "s" : "") + "!");
                }
            }
            else
            {
                Console.WriteLine("You already tried that letter!");
            }
        }
        else
        {
            Console.WriteLine("Invalid Input. Please try again.");
        }
    }
    return (misses < maxMisses);
}
Related