Палач — GDI проблема

#c# #.net

#c# #.net

Вопрос:

Я в небольшом затруднении. Я начал разработку игры Hangman с графическим интерфейсом, для развлечения. Однако я столкнулся с несколькими проблемами.

Слово, которое требуется угадать, было преобразовано в массив символов. Однако, когда пользователь вводит символ, чтобы угадать слово, методы CheckLetter (), похоже, не работают, хотя он вызывает правильно. Поскольку буквы не отображаются нарисованными на экране, когда они были угаданы правильно.

Я был бы признателен, если бы вы могли направить в правильном направлении…

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace HangmanV1._0
{
    public partial class Main : Form
    {
        private Graphics g;

        //Stores words characters
        private char[] WordCharactes;

        //Cloned array size of word characters, though data only appears in the elements
        //when characters are matched succesfully
        private char[] GuessedLetters;

        public Main()
        {
            InitializeComponent();
        }

        public void GetWord(string Word, int NumberOfCharacters)
        {
            //Declares new char array
             WordCharactes = new char[NumberOfCharacters];
             GuessedLetters = new char[NumberOfCharacters];

            //Converts word to char array
             WordCharactes = Word.ToCharArray();
        }

        private void btnPlay_Click(object sender, EventArgs e)
        {
            //invokes the method by passing the word required to be guessed, specified by the user
            GetWord(tbWordToGuess.Text, tbWordToGuess.Text.Length);
            grbNewGame.Visible = false;

            //Draw hangman game board
            DrawWord(g);
        }

        public void DrawWord(Graphics e)
        {
            //Line Coordinates 
            int LinePointX = 50;
            int LinePointY = 80;
            int LetterPoint = 50;

            for (int i = 0; i < WordCharactes.Length; i  )
            {
                //Draws dashed unser letters, highlights how many letters to guess
                e.DrawLine(new Pen(Color.Black, 5), new PointF(LinePointX, 300), new PointF(LinePointY, 300));


                //Draws letters that have been correctly guessed
                e.DrawString(GuessedLetters[i].ToString(), new Font("Arial", 18), Brushes.Black, new PointF(LetterPoint, 270));

                //Steadily increments line 
                LetterPoint  = 40;
                LinePointX  = 40;
                LinePointY  = 40;
            }
        }

        public void CheckLetter(char Letter)
        {
            this.Refresh(); //<-- Edit: adding this solved my problem

            //Compares letters
            for (int i = 0; i < WordCharactes.Length; i  )
            {
                if (WordCharactes[i] == Letter)
                {
                    GuessedLetters[i] = WordCharactes[i];
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            g = this.CreateGraphics();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Exits enviroment
            Environment.Exit(0);
        }

        private void btnInputLetter_Click(object sender, EventArgs e)
        {
            //Invokes the checkletter method to compare inputted char to that of the word
            CheckLetter(char.Parse(tbGuessedLetter.Text));

            //Redraws 
            DrawWord(g);
        }
    }
}
  

Ответ №1:

Правильный способ рисования в форме (или любом другом элементе управления) — сделать ее недействительной, вызвав

 Invalidate();
  

вы бы сделали это вместо DrawWord (g) в btnInputLetter_Click

Затем система вызовет событие рисования формы. У этого события есть аргумент, который содержит графический объект, который следует использовать для рисования.

Все это в итоге привело бы к чему-то вроде этого:

 private void Form1_Paint(object sender, PaintEventArgs e)
{
    DrawWord(e.Graphics);
}

private void btnInputLetter_Click(object sender, EventArgs e)
{
    //Invokes the checkletter method to compare inputted char to that of the word
    CheckLetter(char.Parse(tbGuessedLetter.Text));

    //Redraws 
    Invalidate();
}
  

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

1. Это вызвало бы проблему (исключение нулевой ссылки) в методе DrawWord(), поскольку ссылка на объекты WordCharacters[] не создается, пока пользователь не введет слово.

2. Это должно быть легко решено с помощью «if (WordCharacters != null)» в цикле for.

Ответ №2:

Разве вы не можете просто использовать строку.Содержит метод, позволяющий проверить, существует ли буква?

 public bool CheckLetter(char letter)
{
   return word.Contains(letter);
}
  

Затем вы можете использовать результат этого для манипулирования имеющимися у вас словами.

Ответ №3:

Ваш метод контрольного списка является обратным, он должен быть:

 GuessedLetters[i] = WordCharactes[i];
  

не:

 WordCharactes[i] = GuessedLetters[i];
  

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

1. Спасибо, хотя проблема по-прежнему не позволяет отобразить соответствующий символ на экране…

2. Вы отлаживали контрольный список и методы DrawWord? Соответствует ли содержимое угаданных писем тому, что вы ожидаете?

3. Да, спасибо за информацию, проблему удалось решить.

Ответ №4:

Проблема в том, что вы не обновляете свою логику рисования в событии рисования вашей формы / элемента управления. Добавьте событие для этого, затем обработайте весь ваш чертеж там. Для обновления вызовите функцию Invalidate() формы / элемента управления.