Как отобразить или скрыть буквы в строке — игра Hangman

#c#

#c#

Вопрос:

Я новичок в C #, и я изучаю его в течение последних нескольких недель, в основном выполняя задания и задачи, чтобы улучшить свои знания. Я наткнулся на создание консольного приложения «Hangman», и я близок к его завершению. На самом деле, я могу сказать, что я сделал это, но я хотел бы кое-что улучшить и узнать одну новую вещь.

Это пример моего вопроса, если вы не можете его понять, извините, английский не мой основной язык. Вы знаете, как, когда вы играете в hangman, как только вы угадываете правильную букву, эта буква «показывает себя» на своей позиции в слове.

 etc. word Head

you guess "e" and it prints _e__
you guess "d" and it prints _e_d
you guess "H" and it prints He_d
you guess "a" and it prints Head
  

Вот мой код :

 using System;

namespace Hangman
{
    class Program
    {
        static void Main(string[] args)
        {
            Random random = new Random();

            string word1;
            Console.Write("Please enter a random word: ");
            word1 = Console.ReadLine();
            word1.ToLower();
            Console.Clear();

            int i = 0;
            int j = 0;
            do
            {
                string guess;
                Console.Write("Please enter a letter: ");
                guess = Console.ReadLine();

                if (guess == ""  
                    "")
                {
                    i  = 1;
                    Console.WriteLine($"Not allowed. You have {word1.Length - i} tries left.n");
                    
                }


                else if(word1.Contains(guess) == true)
                {
                    Console.WriteLine("You guessed correctly !n");
                    j  = 1;
                }

                else
                {
                    i  = 1;
                    Console.WriteLine($"You guessed wrongly ! You have {word1.Length - i} tries leftn");
                    
                }

                /* If you guessed all the letters correctly this will print that you won */
                if (j == word1.Length)
                {
                    Console.Clear();
                    Console.WriteLine($"You won ! The guessing word was {word1}.n");
                }
                /* If you tried too many times it will end your program and you will lose.
                 * If you guessed all letters in a word correctly you win and the game is done. */

                if(i == word1.Length)
                {
                    Console.Clear();
                    Console.WriteLine($"You lost ! The guessing word was {word1}.n");
                }

            } while (i != word1.Length amp; j != word1.Length);
        }
    }
}
  

Комментарии:

1. позиционировать курсор

2. Я действительно не вижу способа сделать это с помощью метода, который вы опубликовали. Не могли бы вы немного объяснить?

3. Вы можете напечатать символ в указанной позиции, о чем просил заголовок вашего вопроса, нет?

Ответ №1:

В вашем коде есть несколько ошибок, если хотите —

Если вы вводите слово head и продолжаете угадывать h , вы выигрываете.

Когда вы вводите свое предположение, вы можете фактически ввести строку, а не только один символ.

Также код не учитывает возможность ввода нескольких символов. Например, если слово alexleo — и я предполагаю l — это даст мне только одно совпадение.

Что нам нужно сделать, так это отслеживать статус каждой буквы в слове, то есть угадана буква или нет.

На каждой итерации:

  1. Пользователь угадывает букву —
  2. Если буква содержится в слове — меняем статус на угадано.
  3. Если буква уже угадана, мы предупреждаем пользователя.
  4. Если буква не содержится в слове — увеличиваем наш флаг totalGuessCounts на 1.
  5. Мы оставляем отзыв пользователю и показываем то, что было угадано до сих пор.

Цикл завершается, когда мы либо выигрываем, либо у пользователя заканчиваются догадки.

Во-первых, я определил свой класс настройки букв

 public class LetterSetting
{
    public char Letter { get; set; }
    public bool HasBeenGuessed { get; set; }

    public LetterSetting(char letter, bool hasBeenGuessed)
    {
        this.Letter = letter;
        this.HasBeenGuessed = hasBeenGuessed;
    }
}
  

Затем я определил класс hangman word — здесь мы отслеживаем угаданную букву, логику, чтобы увидеть, выиграли ли мы, и отображение того, что у нас есть на данный момент.

    static class HangmanWord
    {
        static List<LetterSetting> LettersStatus = new List<LetterSetting>();

        public static void Initialise(string word)
        {
            foreach (char letter in word)
            {
                LettersStatus.Add(new LetterSetting(letter, false));
            }
        }

        public static bool SetGuessStatus(char letter)
        {
            List<LetterSetting> tempLettersStatus = new List<LetterSetting>();

            foreach (LetterSetting item in LettersStatus)
            {
                if (item.Letter == letter amp;amp; item.HasBeenGuessed)
                {
                    return false;
                }

                tempLettersStatus.Add(item.Letter == letter ? new LetterSetting(letter, true) : item);
            }

            LettersStatus = tempLettersStatus;

            return true;
        }

        public static void Display()
        {
            StringBuilder hangManWord = new StringBuilder();

            foreach (var item in LettersStatus)
            {
                hangManWord.Append(!item.HasBeenGuessed ? '_' : item.Letter);
            }
            Console.SetCursorPosition(50, 1);
            Console.Write(hangManWord.ToString());
            Console.SetCursorPosition(0,1);
        }

        public static bool HaveWeWon()
        {
            return !LettersStatus.Any(letter => letter.HasBeenGuessed == false);
        }
    }
  

Ваш основной класс просто инкапсулирует для извлечения слова и игрового цикла:

 class Program
    {
        static void Main(string[] args)
        {
            int totalGuessCounts = 0;
            int maxNumberOfGuess = 0;

            Console.Write("Please enter a random word: ");
            string word = Console.ReadLine()?.ToLower();

            while (word != null amp;amp; word.Contains(" ") || string.IsNullOrWhiteSpace(word))
            {
                Console.Clear();
                Console.WriteLine("Word must not contain spaces or be nothing ");
                Console.Write("Please enter a random word: ");
                word = Console.ReadLine()?.ToLower();
            }

            maxNumberOfGuess = word.Length;

            HangmanWord.Initialise(word);
            Console.Clear();

            HangmanWord.Display();

            do
            {
                Console.Write("Please enter a letter: ");
                char guess = Console.ReadKey().KeyChar;

                Console.WriteLine("n");
                Console.Clear();

                if (!char.IsLetterOrDigit(guess))
                {
                    continue;
                }

                if (word.Contains(guess))
                {
                    Console.WriteLine(HangmanWord.SetGuessStatus(guess)
                        ? "You guessed correctly!"
                        : "You already guessed that letter.");
                }

                else
                {
                    totalGuessCounts  ;
                    Console.WriteLine($"You guessed wrongly ! You have {word.Length - totalGuessCounts} tries leftn");
                }

                if (HangmanWord.HaveWeWon())
                {
                    Console.WriteLine($"You won ! The guessing word was {word}.n");
                    break;
                }

                if (totalGuessCounts == maxNumberOfGuess)
                {
                    Console.WriteLine($"You lost ! The guessing word was {word}.n");
                }

                HangmanWord.Display();

            } while (totalGuessCounts != word.Length);
        }
    }
  

Вот несколько результатов:
введите описание изображения здесь
введите описание изображения здесь

вы можете изменить макет обратной связи — на свой вкус — добавить словарь слов, чтобы вам не приходилось вводить слово самостоятельно — нарисуйте палача, пока пользователь угадывает — В идеале вы можете перенести всю логику в класс HangmanWord — то есть для неудачи, успеха и полной обратной связи.

Комментарии:

1. Спасибо! Весь этот новый код немного сложен для понимания, но я постараюсь понять, что он делает и как он работает.

2. Хорошо, никаких проблем — вот консольное приложение, которое все вместе может помочь вам понять — codeshare.io/5Mrrwn если вам нужна дополнительная информация, дайте мне знать.

3. забыл упомянуть codeshare.io/5Mrrwn истекает через 24 часа

Ответ №2:

Я закодировал что-то вроде этого. Это мое предложение для решения этой проблемы, но помните, что оно, вероятно, не самое лучшее. Вы можете попробовать оптимизировать его.

 bool[] guessed = new bool[wordToGuess.Length];
int index = 0;
while ((index = wordToGuess.IndexOf(guess, index, wordToGuess.Length - index)) != -1)
{
    guessed[index] = true;
    index  ;
}

for(int i = 0; i < wordToGuess.Length; i  )
{
    if(guessed[i])
        Console.Write(wordToGuess[i]);
    else
        Console.Write('_');
}
  

Я использовал String.Метод indexOf(String, Int32, Int32) для этой цели.

Комментарии:

1. Спасибо. Я пытался оптимизировать для себя, но у меня это не работает.