П'ятниця, 19.04.2024
Творча лабораторія

Навчальні посібники та робочі зошити з інформатики - якісно і дешево


Меню сайту
Реклама
Категорії каталогу
MS Visual C++ 2005 Express Edition [3]
Середовища програмування [8]
Особливості встановлення та використання різних середовищ програмування
MS Visual Basic 6 [1]
Microsoft Visual Basic
C# [8]
Програмування мовою C#
C++ [3]
Паскаль [5]
ЛОГО [1]
Олімпіадне програмування [0]
Python [1]
Головна » Статті » Програмування » C#

Проект "Хрестики-нулики" (С#)

Нові статті

[19.02.2020] [C#]
Задача про розрізання квадрата (ООП, C#)
[09.02.2020] [Python]
Задача про розрізання квадрата (ООП, Python)
[06.02.2020] [Паскаль]
Задача про розрізання квадрата (ООП, Free Pascal)

Пилипчук О.П., вчитель інформатики Гаврилівської ЗОШ Теофіпольського району Хмельницької області

Проект "Хрестики-нулики" (С#)

Завдання. Розробити програму для гри з комп’ютером у хрестики-нулики.

Детальний опис функціонування проекту

  1. Зовнішній вигляд вікна програми показаний на малюнках:
     

    На початку гри

    У процесі гри

  2. Після запуску людина розпочинає гру клацанням однієї з ігрових кнопок.
  3. Людина грає хрестиками, а комп’ютер – нуликами.
  4. Комп’ютер коректно відповідає на ходи людини.
  5. На клацання кнопки з позначкою комп’ютер не реагує.
  6. У випадку виграшу одного з партнерів:
  • невикористані кнопки блокуються, тобто перестають реагувати на клацання;
  • у відповідному написі відображається поновлене значення лічильника перемог для гравця;
  • після клацання кнопки «Почати» ігрове поле очищається і програма стає готова для нової гри.

Звантажити діючу програму

План розробки

  1. Розробити клас GameButton – нащадок класу Button.
  2. Розробити клас Pole – компонент користувача, який, зокрема, генерує подію «Хтось виграв».
  3. На формі розмістити компонент Pole та інші компоненти і забезпечити їх взаємодію.

    Приклад програмного коду

    1.    Клас GameButton – ігрова кнопка.

    Розпочнемо з розробки компоненту GameButton (ігрова кнопка), 9 екземплярів якого складатимуть поле для гри. Клас GameButton буде спадкоємцем класу Button (кнопка), тому що саме компонент Button має потрібний для нас базовий набір властивостей, методів та подій:

            class GameButton : Button
        {

    Поле Text буде використовуватись для виведення на кнопку позначки «Х» або «0». Додамо три поля логічного типу, значення яких описуватимуть стан кнопки: IsClear, IsCross, IsZero. Їх призначення зрозуміле з таблиці:


    Поле
    Про що сигналізує?
    Примітка
    True
    False
    IsClear
    Кнопка «чиста»
    На кнопці є позначка
    Потрібне для прийняття рішення, чи має кнопка реагувати на клацання
    IsCross
    На кнопці є хрестик
    На кнопці не хрестик
    Потрібне для аналізу стану ігрового поля після ходу гравця та для вибору найкращого ходу комп’ютером
    IsZero
    На кнопці є нулик
    На кнопці не нулик

    public bool IsClear, //прапорець «Кнопка чиста»
        IsCross, //прапорець «Кнопка з хрестиком»
        IsZero;  //прапорець «Кнопка з нуликом»

    Новостворена кнопка не повинна містити позначки (Text="";). Також при створенні кнопки треба налаштувати деякі її властивості (розмір шрифту, значення згаданих логічних полів). Тому створимо для неї конструктор такого вигляду:

    public GameButton()  //конструктор
    {
        Text="";
        Font = new Font(Font.Name, 30, Font.Style);
        IsClear=true;
        IsCross=IsZero=false;
    }

    Метод SetCross компоненту GameButton призначений для того, щоб у процесі гри поставити на кнопці позначкук-хрестик. При цьому відповідно мають змінитися поля IsClear, IsCross, IsZero:

            public void SetCross()//Метод «Поставити хрестик»
            {
                Text="X";
                IsCross=true; IsClear=IsZero=false;
            }

    Аналогічно напишемо й метод SetNull для встановлення нулика:

            public void SetNull()//Метод «Поставити нулик»
            {
                Text="O";
                IsClear=IsCross=false; IsZero=true;
            }

    Для початку нової гри потрібно буде стирати позначки з кнопок, тому додамо метод SetClear:

            public void SetClear()//Метод «Зробити чистою»
            {
                Text="";
                IsClear=true; IsCross=IsZero=false;
            }
        }

    2.    Клас Pole – ігрове поле з 9 кнопок.

    public partial class Pole : UserControl
    {
            GameButton[,] P = new GameButton [3,3];   //Ігрове поле з кнопок
            public event FinishEventHandlerOnFinish; //Подія "Хтось виграв"
            bool active=true;    //Прапорець "Чи реагувати на кнопки?"
            int Moves=0;    //Лічильник ходів на випадок "нічиєї"
           
            public Pole()
            {
            InitializeComponent();
            this.ClientSizeChanged +=new EventHandler(PoleClientSizeChanged);

                //Створення кнопок
                for (int r=0; r<3; r++)
                    for (int c=0; c<3; c++)
                {
                    P[r,c]=new GameButton ();
                    P[r,c].Parent = this;
                    P[r,c].Click += new EventHandler(GameButtonClick);
                }
            }

            void Control() //перевірка, чи раптом хтось не виграв. Якщо виграв
            //- генерується подія OnFinish і передається символ-переможець
            {
    if ( P[0,0].IsCross && P[0,1].IsCross && P[0,2].IsCross || P[1,0].IsCross && P[1,1].IsCross && P[1,2].IsCross ||    P[2,0].IsCross && P[2,1].IsCross && P[2,2].IsCross ||   P[0,0].IsCross && P[1,0].IsCross && P[2,0].IsCross ||    P[0,1].IsCross && P[1,1].IsCross && P[2,1].IsCross ||    P[0,2].IsCross && P[1,2].IsCross && P[2,2].IsCross ||    P[0,0].IsCross && P[1,1].IsCross && P[2,2].IsCross ||    P[0,2].IsCross && P[1,1].IsCross && P[2,0].IsCross)
    {active=false;
        if (OnFinish != null) OnFinish ('X');
    }
    if ( P[0,0].IsZero && P[0,1].IsZero && P[0,2].IsZero || P[1,0].IsZero && P[1,1].IsZero && P[1,2].IsZero || P[2,0].IsZero && P[2,1].IsZero && P[2,2].IsZero || P[0,0].IsZero && P[1,0].IsZero && P[2,0].IsZero || P[0,1].IsZero && P[1,1].IsZero && P[2,1].IsZero || P[0,2].IsZero && P[1,2].IsZero && P[2,2].IsZero || P[0,0].IsZero && P[1,1].IsZero && P[2,2].IsZero || P[0,2].IsZero && P[1,1].IsZero && P[2,0].IsZero)
    {active=false;
        if (OnFinish != null) OnFinish ('O');}
    }
           
    void PoleClientSizeChanged(object sender, EventArgs e)
            {
            //Підгонка розмірів та розміщення кнопок на полі
                for (int r=0; r<3; r++)
                    for (int c=0; c<3; c++)
                {
                    P[r,c].Width = ClientRectangle.Width/3;
                    P[r,c].Height = ClientRectangle.Height/3;
                    P[r,c].Left = c*P[r,c].Width;
                    P[r,c].Top = r*P[r,c].Height;
                }
            }

    public void Clear() //Підготовка до нової партії
    {
        for (int r=0; r<3; r++)
            for (int c=0; c<3; c++)
                P[r,c].SetClear();
        active=true; Moves=0;
    }

    void GameButtonClick(object sender, EventArgs e)
    {
        if ((sender as GameButton).IsClear)
        if (active) //Якщо партія не закінчена
        {
            (sender as GameButton).SetCross(); //ставимо на
                                    //кнопці хрестик
                Control(); //Перевірити, чи не переміг
                            //той, хто клацав
                if (++Moves>8) active=false;//Якщо останній
                                //хід - блокуємо поле
                if (active)     //Якщо потрібна відповідь
                            //комп'ютера
                { int kh=0, nr=0, ns=0;
                    //Пошук виграшного ходу для нуликів
              for (int r=0; r<3; r++)
                for (int s=0; s<3; s++)
                    if (P[r,s].IsClear)
                    { //перевірка у стовпці
                    if (kh!=2)
                    { kh=0; for (int rr=0; rr<3; rr++)
                            if (P[rr,s].IsZero)
                            { kh++;
    if (kh==2) { ns=s; nr=r; }
                                }
                        }
                                //перевірка у рядку
                    if (kh!=2)
                    { kh=0;
                    for (int ss=0; ss<3; ss++)
                        if (P[r,ss].IsZero)
                         { kh++;
    if (kh==2) { ns=s; nr=r; }
                                }
                    }
                            //перевірка у діагоналі 1
                    if ((kh!=2) && (r==s))
                    { kh=0;
                    for (int ss=0; ss<3; ss++)
                        if (P[ss,ss].IsZero)
                                { kh++;
    if (kh==2) { ns=s; nr=r; }
                                }
                    }
                            //перевірка у діагоналі 2
                      if ((kh!=2) && (r==2-s))
                    { kh=0;
                      for (int ss=0; ss<3; ss++)
                          if (P[ss,2-ss].IsZero)
                { kh++;
    if (kh==2) { ns=s; nr=r; }
                                }
                    }
                    }
    if (kh!=2) //Якщо нулики не виграють цим ходом, то
    //пошук виграшного ходу хрестиків, щоб не програти
                        for (int r=0; r<3; r++)
                        for (int s=0; s<3; s++)
                            if (P[r,s].IsClear)
                            { //перевірка у стовпці
                            if (kh!=2)
                            { kh=0;
                            for (int rr=0; rr<3; rr++)
                                if (P[rr,s].IsCross)
                                { kh++;
    if (kh==2) { ns=s; nr=r; }
                                    }
                            }
                                //перевірка у рядку
                          if (kh!=2)
                         { kh=0;
                         for (int ss=0; ss<3; ss++)
                             if (P[r,ss].IsCross)
                             { kh++;
    if (kh==2) { ns=s; nr=r; }
                                    }
                          }
                            //перевірка у діагоналі 1
                          if ((kh!=2) && (r==s))
                         { kh=0;
                                for (int ss=0; ss<3; ss++)
                              if (P[ss,ss].IsCross)
                              { kh++;
    if (kh==2) { ns=s; nr=r;}
                                    }
                          }
                            //перевірка у діагоналі 2
                          if ((kh!=2) && (r==2-s))
                          { kh=0;
    for (int ss=0; ss<3; ss++)
                              if (P[ss,2-ss].IsCross)
                              { kh++;
    if (kh==2) { ns=s; nr=r; }
                                    }
                          }
                        }
            if (kh!=2)  //якщо немає виграшного ходу і
                            //загрози програшу – випадковий хід
                    {
              Random RN = new Random();
                    do    {nr = RN.Next(3); ns = RN.Next(3);}
                               while (!P[nr,ns].IsClear);
                        }
                        P[nr,ns].SetNull(); Moves++;
                        Control(); return;
                    }
            }
        }//Кінець GameButtonClick
    }//Кінець Pole

    3.    Програмний код головної форми програми (на доповнення до згенерованого автоматично)

        int CrossCount=0, ZeroCount=0; //Лічильники перемог
           
            public MainForm()
            {
                InitializeComponent();

                //додаємо обробник для події OnFinish
                pole1.OnFinish += new FinishEventHandler (Finish);
            }
           
            void Finish (char Winner)
            {
                switch (Winner)
                {case 'X': CrossCount++; labelMan.Text = Convert.ToString (CrossCount); break;
                case 'O': ZeroCount++; labelComp.Text = Convert.ToString (ZeroCount); break;
                }
            }
           
            void Button1Click(object sender, EventArgs e)
            {
                pole1.Clear();
            }
        }

    Завдання для вдосконалення проекту

    1. Ім'я та результат того, хто має більше перемог, виділяти червоним жирним.
    2. Зробити хрестики зеленими, а нулики червоними.
    3. Після початку партії кнопка "Почати" стає недоступною до кінця партії.
    4. Коли перемагає людина, напис "Почати" на кнопці змінюється на "Вітаю!" (червоним кольором), а після клацання - знову стає "Почати" (чорним кольором).
    5. Підраховувати і виводити кількість нічиїх.
    6. При клацанні кнопки, що вже позначена генерувати якийсь звук.
    7. Забезпечити введення імені людини-гравця та відображення його замість слова «ЛЮДИНА».
    8. Забезпечити три рівні "майстерності" гри комп'ютера:
      -    початківець (ходить випадково),
      -    кандидат (не пропускає своїх виграшних ходів)
      -    експерт (не пропускає своїх виграшних ходів і, по можливості, заважає виграти людині).
    9. Підсвічувати лінію знаків, яка призвела до перемоги.
    10. Замість символів «Х» та «О» виводити на кнопці графічні зображення хрестика та нулика.
    11. Забезпечити людині можливість вибору, чим грати (хрестиками чи нуликами).
    12. Забезпечити можливість вибору, хто ходитиме першим (у всіх партіях): комп’ютер чи людина.
    13. Забезпечити можливість вибору, хто ходитиме першим: у першій партії і при нічиїй – комп’ютер чи людина, а в наступних – переможець попередньої партії, чи переможений.

    Завдання для самостійної розробки

    Розробити програму, що імітує головоломку «15».



    Интернет реклама
    Категорія: C# | Додав: teachlab (05.05.2011)
    Переглядів: 3365 | Рейтинг: 0.0/0
    Всього коментарів: 0
    Додавати коментарі можуть тільки зареєстровані користувачі.
    [ Реєстрація | Вхід ]
    Форма входу
    Пошук
    Друзі сайту

    Підтримка

    Система Orphus

    Маєте свій сайт?
    Заробіть на ньому грошей!


    Не маєте власного сайту?
    Заробіть на обміні файлами!
    Статистика
    Copyright Пилипчук О.П. © 2024
    div id=