using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; namespace Hangman { /// /// C# version of the game "Hangman" from the book BASIC Computer Games. /// static class Program { static void Main() { Console.WriteLine(Tab(32) + "HANGMAN"); Console.WriteLine(Tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); MainLoop(); Console.WriteLine(); Console.WriteLine("IT'S BEEN FUN! BYE FOR NOW."); } static void MainLoop() { var words = GetWords(); var stillPlaying = true; while (stillPlaying) { if (words.Count == 0) { Console.WriteLine("YOU DID ALL THE WORDS!!"); break; } // Get a random number from 0 to the number of words we have minus one (C# arrays are zero-based). var rnd = new Random(); var randomNumber = rnd.Next(words.Count - 1); // Pick a random word and remove it from the list. var word = words[randomNumber]; words.Remove(word); GameLoop(word); // Game finished. Ask if player wants another one. Console.WriteLine("WANT ANOTHER WORD? "); var response = Console.ReadLine(); if (response == null || response.ToUpper() != "YES") { stillPlaying = false; // Exit the loop if the player didn't answer "yes". } } } static void GameLoop(string word) { var graphic = new Graphic(); var wrongGuesses = 0; var numberOfGuesses = 0; var usedLetters = new List(); // The word that the user sees. Since we just started, it's just dashes. var displayedWord = new char[word.Length]; for (var i = 0; i < word.Length; i++) { displayedWord[i] = '-'; } var stillPlaying = true; while (stillPlaying) { var guess = GetLetterFromPlayer(displayedWord, usedLetters); usedLetters.Add(guess); numberOfGuesses++; var correctLetterCount = 0; // Now we check every letter in the word to see if the player guessed any of them correctly. for(var i = 0; i < word.Length; i++) { if (word[i] == guess) { correctLetterCount++; displayedWord[i] = guess; } } if (correctLetterCount == 0) { // Wrong guess. Console.WriteLine("SORRY, THAT LETTER ISN'T IN THE WORD."); wrongGuesses++; DrawBody(graphic, wrongGuesses); if (wrongGuesses == 10) { // Player exhausted all their guesses. Finish the game loop. Console.WriteLine($"SORRY, YOU LOSE. THE WORD WAS {word}"); Console.Write("YOU MISSED THAT ONE. DO YOU "); stillPlaying = false; } } else { // Player guessed a correct letter. Let's see if there are any unguessed letters left in the word. if (displayedWord.Contains('-')) { Console.WriteLine(displayedWord); // Give the player a chance to guess the whole word. var wordGuess = GetWordFromPlayer(); if (word == wordGuess) { // Player found the word. Mark it found. Console.WriteLine("YOU FOUND THE WORD!"); stillPlaying = false; // Exit game loop. } else { // Player didn't guess the word. Continue the game loop. Console.WriteLine("WRONG. TRY ANOTHER LETTER."); } } else { // Player guessed all the letters. Console.WriteLine("YOU FOUND THE WORD!"); stillPlaying = false; // Exit game loop. } } } // End of game loop. } /// /// Display the current state of the word and all the already guessed letters, and get a new guess from the player /// /// A char array that represents the current state of the guessed word /// A list of chars that represents all the letters guessed so far /// The letter that the player has just entered as a guess private static char GetLetterFromPlayer(char[] displayedWord, List usedLetters) { while (true) // Infinite loop, unless the player enters an unused letter. { Console.WriteLine(); Console.WriteLine(displayedWord); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("HERE ARE THE LETTERS YOU USED:"); for (var i = 0; i < usedLetters.Count; i++) { Console.Write(usedLetters[i]); // If it's not the last letter, print a comma. if (i != usedLetters.Count - 1) { Console.Write(","); } } Console.WriteLine(); Console.WriteLine("WHAT IS YOUR GUESS?"); var guess = char.ToUpper(Console.ReadKey().KeyChar); Console.WriteLine(); if (usedLetters.Contains(guess)) { // After this the loop will continue. Console.WriteLine("YOU GUESSED THAT LETTER BEFORE!"); } else { // Break out of the loop by returning guessed letter. return guess; } } } /// /// Gets a word guess from the player. /// /// The guessed word. private static string GetWordFromPlayer() { while (true) // Infinite loop, unless the player enters something. { Console.WriteLine("WHAT IS YOUR GUESS FOR THE WORD? "); var guess = Console.ReadLine(); if (guess != null) { return guess.ToUpper(); } } } /// /// Draw body after wrong guess. /// /// The instance of the Graphic class being used. /// Number of wrong guesses. private static void DrawBody(Graphic graphic, int wrongGuesses) { switch (wrongGuesses) { case 1: Console.WriteLine("FIRST, WE DRAW A HEAD."); graphic.AddHead(); break; case 2: Console.WriteLine("NOW WE DRAW A BODY."); graphic.AddBody(); break; case 3: Console.WriteLine("NEXT WE DRAW AN ARM."); graphic.AddRightArm(); break; case 4: Console.WriteLine("THIS TIME IT'S THE OTHER ARM."); graphic.AddLeftArm(); break; case 5: Console.WriteLine("NOW, LET'S DRAW THE RIGHT LEG."); graphic.AddRightLeg(); break; case 6: Console.WriteLine("THIS TIME WE DRAW THE LEFT LEG."); graphic.AddLeftLeg(); break; case 7: Console.WriteLine("NOW WE PUT UP A HAND."); graphic.AddRightHand(); break; case 8: Console.WriteLine("NEXT THE OTHER HAND."); graphic.AddLeftHand(); break; case 9: Console.WriteLine("NOW WE DRAW ONE FOOT."); graphic.AddRightFoot(); break; case 10: Console.WriteLine("HERE'S THE OTHER FOOT -- YOU'RE HUNG!!"); graphic.AddLeftFoot(); break; } graphic.Print(); } /// /// Get a list of words to use in the game. /// /// List of strings. private static List GetWords() => new() { "GUM", "SIN", "FOR", "CRY", "LUG", "BYE", "FLY", "UGLY", "EACH", "FROM", "WORK", "TALK", "WITH", "SELF", "PIZZA", "THING", "FEIGN", "FIEND", "ELBOW", "FAULT", "DIRTY", "BUDGET", "SPIRIT", "QUAINT", "MAIDEN", "ESCORT", "PICKAX", "EXAMPLE", "TENSION", "QUININE", "KIDNEY", "REPLICA", "SLEEPER", "TRIANGLE", "KANGAROO", "MAHOGANY", "SERGEANT", "SEQUENCE", "MOUSTACHE", "DANGEROUS", "SCIENTIST", "DIFFERENT", "QUIESCENT", "MAGISTRATE", "ERRONEOUSLY", "LOUDSPEAKER", "PHYTOTOXIC", "MATRIMONIAL", "PARASYMPATHOMIMETIC", "THIGMOTROPISM" }; /// /// Leave a number of spaces empty. /// /// Number of spaces. /// The result string. private static string Tab(int length) => new string(' ', length); } }