МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ КУРГАНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ Кафедра автоматизации производственных процессов Тема курсовой работы «Разработка программы на языке С++» Курсовая работа Расчётно-пояснительная записка. Дисциплина: Программирование и алгоритмизация Студент Вагин П.А. Группа ИТ-1540122 Руководитель Сахаринова В.О. Оценка____________________ Дата Защиты_______________ Курган 2023 г. СОДЕРЖАНИЕ ВВЕДЕНИЕ................................................................................................................. 3 1. Постановка задачи.................................................................................................. 5 2. Описание программы............................................................................................. 6 2.1. Правила игры................................................................................................. 6 2.2. Интерфейс программы.................................................................................. 6 2.3. Общий принцип работы программы............................................................ 8 2.4. Блок-схема алгоритма игры......................................................................... 10 3. Контрольный пример............................................................................................ 11 ЗАКЛЮЧЕНИЕ......................................................................................................... 14 СПИСОК ЛИТЕРАТУРЫ........................................................................................ 15 ПРИЛОЖЕНИЕ А – листинг программы................................................................ 16 2 ВВЕДЕНИЕ Данная курсовая работа выполнена на языке программирования высокого уровня С++ с использованием компилятора Microsoft Visual Studio 2019. Язык программирования С++ достаточно актуален в последнее время. С помощью него можно решать всевозможные задачи, ставящиеся перед современным программистом: написание системных программ, разработка полноценных Windows-приложений, объектное моделирование. С++ является языком программирования общего назначения. Он известен эффективностью, универсальностью, экономичностью. Использование данного языка в качестве инструментального позволяет получать быстрые и компактные программы в объеме, достаточном для их работы в большом количестве. Для удобства работы в программе применяются основные средства и объекты языка С++. С целью определения собственных типов данных и простой манипуляции ими в курсовой работе используются классы. Классы позволяют отделить детали, касающиеся реализации нового типа, от определения интерфейса и операций, предоставляемых пользователю. Перечисления (enum): определяет несколько именованных констант. Также используются переменные – изменяемые величины и константы – неизменяемые величины, типы данных – величина, которая определяет внутреннее представление данных в памяти компьютера, множество значений, которые могут принимать величины этого типа, операции и функции, которые можно применять к величинам этого типа. В программе используются следующие библиотеки: 1. Iostream – заголовочный файл с классами, функциями и переменными для организации ввода- вывода в языке программирования С++. Он включен в стандартную библиотеку С++; 2. StartForm.h – заголовочный файл, в котором находится форма для работы с главным меню; 3 3. GameForm.h – заголовочный файл, в котором находится форма для работы с игровым полем; 4. GameMap.h – заголовочный файл с классами, методами и переменными для работы с игровой картой; 5. Gamer.h – заголовочный файл с классами, методами и переменными для работы с игроком; 6. Windows.h - подключает использования функционала для предоставляемой операционной системой. Цель курсового проекта – закрепление и углубление знаний, полученных при изучении курса «Алгоритмические языки» посредством разработки игры «Крестики - нолики» на Windows Forms C++. 4 1. Постановка задачи Для успешного выполнения курсового проекта и результативной реализации программы были поставлены следующие задачи: 1. Построить схему алгоритма решения задачи; 2. Изучить необходимые средства языка для выполнения программы; 3. Разработать программу: 3.1 Реализовать графический интерфейс; 3.2 Реализовать возможность выбора игрового режима; 3.3 Реализовать возможность выбора размера игрового поля; 3.4 Реализовать функцию, которая не позволяет пользователю сделать ход на ячейку, которая занята; 4. Провести всевозможные испытания и отладку; 5. Проанализировать результаты; 6. Оформить пояснительную записку. 5 2. Описание программы 2.1. Правила игры Правила игры состоят в том, что необходимо выстроить линию из 3-х (или более) крестиков (ноликов) в любом направлении и каким угодно способом (по горизонтали, вертикали или диагонали). Соответственно, ваш противник должен выстроить подобную линию быстрее вас или не давать вам построить такую линию. Игра начинается с того, что в любом месте игрового поля ставится крестик, ваш противник ставит нолик, и так до тех пор, пока не будет выстроена линия. В данной программе чтобы выиграть, необходимо первым составить линию. 2.2. Интерфейс программы Для запуска программы сделайте двойной щелчок по ярлыку TicTacToeGame.exe. На экране. появится основное окно программы, имеющее следующий вид (Рис. 2.2.1.): Рис. 2.2.1. Главное меню На окне размещено несколько кнопок – Начать игру и Выход, а также кнопки выбора режима игры, размерность игрового поля и длина комбинации для победы. Для начала новой игры необходимо выбрать игровой режим, а затем кликнуть по кнопке «Начать игру». Для выхода из программы нужно нажать кнопку «Выход» или нажать на крестик. 6 После всех действий появится игровое поле. Игровое поле представлено на Рис. 2.2.2. В данной программе первый ход всегда предоставляется Player1. Это и означает начало игры. Рис. 2.2.2. Игровое поле При победе одного из игроков появляется сообщение (Рис. 2.2.3.) «Launch a new game?». Если нажать кнопку «Yes», то начнется новая игра, а если «No», то сообщение исчезает. Рис. 2.2.3. Сообщение о перезапуске игры В игре возможны несколько исходов: a) победа Player1, проигрыш Player2; b) победа Player2, проигрыш Player1; c) победа Player, проигрыш Computer; d) победа Computer, проигрыш Player; e) ничья. 7 Каждый исход оповещается соответствующим сообщением. Сообщение об одном из исходов представлено на Рис. 2.2.4. Рис. 2.2.4. Исход игры «ничья» 2.3. Общий принцип работы программы В С++ при написании программы на Windows Forms есть четкое разделение файлов: заголовочные файлы (с разрешением «.h») и исполняемые (с разрешением «.cpp»). В файлах с разрешением «.h» инициализированы обработчики нажатия на кнопки. В файлах с разрешением «.cpp» реализованы эти обработчики. В программе созданы 2 класса: Gamer.h и GameMap.h. Это так называемые сущности для игрока и для карты соответственно. В файле Gamer.h инициализированы всевозможные статусы игрока и класс Gamer, в котором находятся поля и методы класса. Поля имеют закрытый спецификатор доступа, и там описаны статус игрока (status) и то, чем игрок ходит в данный момент (mark). Методы класса, такие как: SetField – задать поля, GetMark – вернуть текущую метку и GetStatus – вернуть статус, имеют открытый спецификатор доступа. В GameMap.h подключены необходимые библиотеки, такие как: <vector> – контейнерный класс, который предоставляет информацию как обычный одномерный массив, и <algorithm>. В классе GameMap находятся поля, которые также имеют закрытый спецификатор доступа, и в них расположены: int** map – матрица, для предоставления карты в виде двумерного массива, Vector2 size – вектор для того, чтобы указать размерность этой матрицы и int length – необходимая длина для 8 выигрышной последовательности. В методах, имеющих открытый спецификатор доступа, в первую очередь описаны GameMap() – конструктор, создающий объект класса, и GameMap() – деструктор, удаляющий объект класса, SetPosition – позволяет задать позицию, IsEmpty – проверить свободную ячейку, SetMap - получить некоторые значения текущей карты, GetValue – получить значения, GetLenght – получить некоторую длину выигрышной последовательности, GetSize – получить размер текущей карты, CheckingWin – проверить, выиграл ктото из игроков или нет, CanMove – проверить наличие свободных ходов. Решения всех методов реализованы в файлах Gamer.cpp и GameMap.cpp соответственно. Для реализации интерфейсной части программы были выбраны основные компоненты: 1. Label – предназначен для отображения текстовой информации; 2. MenuStrip – этот компонент создает главное меню приложения, с помощью которого управляют всей работой приложения и его частей; 3. ListBox – представляет собой список, в котором можно выбрать нужный элемент; 4. NumericUpDown – представляет пользователю выбор числа из определенного диапазона; 5. Button – один из элементов интерфейса пользователя компьютерной программы, «нажатие (клик)» на которую приводит к некоторому действию, заложенному в программе; 6. StatusStrip – используется для отображения какого-нибудь информационного текста, отражающего состояние приложения или результат действий пользователя; 7. DataGridView – стандартный GUI компонент для отображения и редактирования таблиц. 9 2.4. Блок-схема алгоритма игры Блок-схема – совокупность символов, соответствующих этапам работы алгоритма и соединяющих их линий. В данной схеме используются основные блоки: блок начало/конец, блок вычислительных операций, логический блок, ввод/вывод данных, вывод информации на печать. На Рис. 2.4.1. представлена блок-схема алгоритма работы игры «Крестикинолики». Рис. 2.4.1. Блок-схема алгоритма игры «Крестики-нолики» 10 3. Контрольный пример Для начала запустим файл TicTacToeGame.exe. Появится окно меню (Рис. 3.1.), в котором будет предложено выбрать режим игры, размерность поля и длину комбинации для выигрыша Рис. 3.1. Главное меню Проведем несколько тестовых запусков: Режим игры PvE: результат победы Player представлен на рисунке 3.2., результат победы Computer представлен на рисунке 3.3., результат исхода «ничья» представлен на рисунке 3.4. Рис. 3.2. Победа Player 11 . Рис. 3.3. Победа Computer Рис. 3.4. Ничья Режим игры PvP: результат победы Player1 представлен на Рис. 3.5., результат победы Player2 представлен на Рис. 3.6. Рис. 3.5. Победа Player1 12 Рис. 3.6. Победа Player2 Режим игры на увеличенном размере поля (6х6) с длиной комбинации в 4 клетки представлен на Рис. 3.7. Рис. 3.7. Игра 6х6 Ситуация, когда игрок пытается занять позицию, на которой уже сделан ход представлена на Рис. 3.8. Рис. 3.8. Попытка сделать ход на позицию, занятую другим игроком 13 ЗАКЛЮЧЕНИЕ В курсовом проекта была разработана игра «Крестики - нолики». В процессе выполнения были изучены новые возможности языка С++. В том числе была изучена графическая подсистема Microsoft Visual Studio 2019. Все ранее поставленные задачи были успешно выполнены. В программе реализован базовый алгоритм игры, который имеет простой интерфейс, позволяющий максимально упростить работу с ней для любого пользователя. Тестовые запуски с последующей отладкой помогли добиться того, что программа работает корректно. На практике удалось применить все знания, полученные в процессе изучения курса «Алгоритмические языки». 14 СПИСОК ЛИТЕРАТУРЫ 1. Ашарина, И.В. Основы программирования на языках С и С++: Курс лекций для высших учебных заведений / И.В. Ашарина. — М.: Гор. линия-Телеком, 2018. — 208 c. 2. Баженова, И.Ю. Языки программирования: Учебник для студентов учреждений высш. проф. образования / И.Ю. Баженова; Под ред. В.А. Сухомлин. — М.: ИЦ Академия, 2018. — 368 c. 3. Базовый курс C++ (MIPT, ILab). Lecture 1. Scent of C++./ Электронный ресурс / Режим доступа: https://www.youtube.com/watch?v=Bym7UMqpVEY, свободный 4. Современный С++: новые возможности и лучшие методологии / Электронный ресурс / Режим доступа: https://www.youtube.com/watch?v=tSANTMpT9o, свободный 5. Страуструп Б. Язык программирования C++: Пер. с англ. – 3-е спец. изд. – М.: Бином, 2003. – 1104 с. 6. Троелсен, Э. Язык программирования С# 5.0 и платформа .NET 4.5 / Э. Троелсен; Пер. с англ. Ю.Н. Артеменко. — М.: Вильямс, 2016. — 1312 c. 7. Уолтер Сэвитч. С++ в примерах /Пер. с англ. – М.: ЭКОМ, 1997. – 736 с 8. Эккель Б., Эллисон Ч. Философия C++. Практическое программирование: Пер. с англ. – СПб.: Питер, 2004. – 608 с. 15 ПРИЛОЖЕНИЕ А ЛИСТИНГ ПРОГРАММЫ GameForm.cpp: #include "GameForm.h" #include "StartForm.h" enum GameMode { PvP = 0, //игрок против игрока PvE //игрок против AI } gameMode; //общие данные GameMap map; Gamer player1; Gamer player2; GamerStatus currentPlayer; Vector2 selectedCellPlayer; //флажки bool canPlay; bool endGame; bool sound; //данные для AI std::vector<Vector2> allMoves;//все возможные ходы int currentMoves;//текущий ход, с которого начинать System::Void TicTacToegame::GameForm::GameForm_Load(System::Object^ sender, System::EventArgs^ e) { //инициализируем параметры if (selectedGameMode == 0) { gameMode = PvP; } else { gameMode = PvE; } NewGame(); } System::Void TicTacToegame::GameForm::новаяИграToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { if (MessageBox::Show("Continue?", "Attention!", MessageBoxButtons::YesNo) == Windows::Forms::DialogResult::Yes) { NewGame(); } } System::Void TicTacToegame::GameForm::вернутьсяToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { if (MessageBox::Show("Continue?", "Attention!", MessageBoxButtons::YesNo) == Windows::Forms::DialogResult::Yes) { StartForm^ form = gcnew StartForm(); form->Show(); this->Hide(); } } 16 ПРИЛОЖЕНИЕ А System::Void TicTacToegame::GameForm::оПрограммеToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { MessageBox::Show("The program implements a Tic-Tac-Toe game of the standard type for two players and against the computer. The game was implemented in order to complete the course work. Teacher: Gorlov Alexey Petrovich. Performed by: art. gr. O-21-IB-2-ozi-B Korotkova K.V."); } System::Void TicTacToegame::GameForm::выходToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { if (MessageBox::Show("Continue?", "Attention", MessageBoxButtons::YesNo) == Windows::Forms::DialogResult::Yes) { Application::Exit(); } } System::Void TicTacToegame::GameForm::dataGridView_CellContentClick(System::Object^ sender, System::Windows::Forms::DataGridViewCellEventArgs^ e) { auto senderGrid = (DataGridView^)sender;//преобразуем полученный объект в таблицу //запоминаем индексы выбранной ячейки selectedCellPlayer.x = e->RowIndex; selectedCellPlayer.y = e->ColumnIndex; //делаем ход SetPositionPlayer(selectedCellPlayer); } void TicTacToegame::GameForm::GameLogic() { //проверяем режим игры if (gameMode == PvE) { //если очередь AI if (currentPlayer == Computer) { //делаем ход StepAI(); } Update(); } } void TicTacToegame::GameForm::Update() { if (endGame) return; //проверяем состояние игрового поля int state_game = map.CheckingWin(); if (state_game == 1) { if (gameMode == PvP) { MessageBox::Show("Congratulations to Player1 on his victory!!!", "Win!"); } else { MessageBox::Show("Congratulations to Player on his victory!!!", "Win!"); } UpdateGameGrid(); 17 ПРИЛОЖЕНИЕ А endGame = true; } else if (state_game == 2) { if (gameMode == PvP) { MessageBox::Show("Congratulations to Player2 on his victory!!!", "Win!"); } else { MessageBox::Show("Congratulations to Computer on his victory!!!", "Win!"); } UpdateGameGrid(); endGame = true; } else if (state_game == 3) { MessageBox::Show("Friendship won!!!", "Draw!"); UpdateGameGrid(); endGame = true; } if (endGame) { if (MessageBox::Show("Launch a new game???", "Attention!", MessageBoxButtons::YesNo) == Windows::Forms::DialogResult::Yes) { NewGame(); } return; } if (gameMode == PvE) { if (currentPlayer == Computer) { status->Text = "Player's move!"; currentPlayer = Player; return; } else { status->Text = "Computer move!"; currentPlayer = Computer; GameLogic(); UpdateGameGrid(); return; } } else { if (currentPlayer == Player1) { status->Text = "Motion: 0!"; currentPlayer = Player2; } else { status->Text = "Motion: X!"; currentPlayer = Player1; } } GameLogic(); UpdateGameGrid(); } void TicTacToegame::GameForm::NewGame() { 18 ПРИЛОЖЕНИЕ А //инициализация данных map.SetMap(rows, columns, length); rand = gcnew Random(); endGame = false; CreateGameGrid(map.GetSize()); //создаем игровое поле //инициализируем все возможные ходы для AI currentMoves = 0; allMoves.clear(); Vector2 buf; for (int i = 0; i < map.GetSize().x; i++) { for (int j = 0; j < map.GetSize().x; j++) { buf.x = i; buf.y = j; allMoves.push_back(buf); } } //перемешиваем все возможные ходы //несколько раз int num_mixing = rand->Next(1, 10); for (int i = 0; i < num_mixing; i++) std::random_shuffle(allMoves.begin(), allMoves.end()); //проверяем очередность и режимы игры int state_gamer = rand->Next(1, 3); if (state_gamer == 1) { if (gameMode == PvE) { player1.SetField(Player, 1); player2.SetField(Computer, 2); status->Text = "Motion: Player!"; currentPlayer = Player; } else { player1.SetField(Player1, 1); player2.SetField(Player2, 2); status->Text = "Motion: X!"; currentPlayer = Player1; } } else if (state_gamer == 2) { if (gameMode == PvE) { player1.SetField(Player, 1); player2.SetField(Computer, 2); status->Text = "Motion: Computer!"; currentPlayer = Computer; GameLogic(); UpdateGameGrid(); } else { player1.SetField(Player1, 1); player2.SetField(Player2, 2); status->Text = "Motion: 0!"; 19 ПРИЛОЖЕНИЕ А currentPlayer = Player2; } } else { MessageBox::Show("Initial Player generation error!", "Error!"); return; } } void TicTacToegame::GameForm::StepAI() { //проверяем есть ли еще ходы if (currentMoves < allMoves.size()) { //проверяем текущий код if (map.IsEmpty(allMoves[currentMoves])) { //если свободно, делаем ход map.SetPosition(allMoves[currentMoves], player2.GetMark()); currentMoves++; } else { //если занята, перемещаемся на следующий ход //и вызываем рекурсивно данную функцию currentMoves++; StepAI(); } } } void TicTacToegame::GameForm::UpdateGameGrid() { for (int i = 0; i < map.GetSize().x; i++) { for (int j = 0; j < map.GetSize().y; j++) { if (!map.IsEmpty(i, j)) { if (map.GetValue(i, j) == 1) { dataGridView->Rows[i]->Cells[j]->Value = "X"; } else { dataGridView->Rows[i]->Cells[j]->Value = "0"; } } } } } void TicTacToegame::GameForm::CreateGameGrid(Vector2 size) { //очищаем таблицу dataGridView->Rows->Clear(); dataGridView->Columns->Clear(); //задаем стиль System::Drawing::Font^ font = gcnew System::Drawing::Font("Microsoft Sans Serif", 14); dataGridView->DefaultCellStyle->Font = font; dataGridView->ColumnHeadersDefaultCellStyle->Font = font; dataGridView->RowHeadersDefaultCellStyle->Font = font; //создаем столбцы for (int i = 0; i < size.x; i++) DataGridViewButtonColumn^ column->HeaderCell->Value column->Name = "column" + column->Width = 50; { column = gcnew DataGridViewButtonColumn(); = Convert::ToString(i + 1); i; 20 ПРИЛОЖЕНИЕ А dataGridView->Columns->Add(column); } //создаем строки for (int i = 0; i < size.y; i++) { dataGridView->Rows->Add(); dataGridView->Rows[i]->HeaderCell->Value = Convert::ToString(i + 1); dataGridView->Rows[i]->Height = 50; } } System::Void TicTacToegame::GameForm::SetPositionPlayer(Vector2 cell) { //проверяем режим игры if (gameMode == PvE) { //проверяем очередность игрока if (currentPlayer == Player) { //делаем ход if (!map.SetPosition(cell, player1.GetMark())) { MessageBox::Show("This position is occupied!", "Attention!"); return; } } else { MessageBox::Show("It's not your turn yet!", "Attention!"); return; } } else { //проверяем очередность игрока if (currentPlayer == Player1) { //делаем ход if (!map.SetPosition(cell, player1.GetMark())) { MessageBox::Show("This position is occupied!", "Attention!"); return; } } else { //делаем ход if (!map.SetPosition(cell, player2.GetMark())) { MessageBox::Show("This position is occupied!", "Attention!"); return; } } } Update(); } StartForm.cpp: #include "StartForm.h" #include "GameForm.h" using namespace System; using namespace System::Windows::Forms; [STAThreadAttribute] void main(array<String^>^ args) { Application::EnableVisualStyles(); Application::SetCompatibleTextRenderingDefault(false); 21 ПРИЛОЖЕНИЕ А TicTacToegame::StartForm form; Application::Run(% form); } System::Void TicTacToegame::StartForm::оПрограммеToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { MessageBox::Show("The program implements a Tic - Tac - Toe game of the standard type for two playersand against the computer.The game was implemented in order to complete the course work.Teacher: Gorlov Alexey Petrovich.Performed by : art.gr.O - 21 - IB - 2 - ozi - B Korotkova K.V."); } System::Void TicTacToegame::StartForm::выходToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { Application::Exit(); } System::Void TicTacToegame::StartForm::buttonStartGame_Click(System::Object^ sender, System::EventArgs^ e) { int indexGameMode = listBoxGameMode->SelectedIndex; if (indexGameMode == -1) { MessageBox::Show("Play!"); return; } int size; size = Convert::ToInt32(numericUpDownSizeMap->Value); numericUpDownLenght->Maximum = size; int length = Convert::ToInt32(numericUpDownLenght->Value); GameForm^ form = gcnew GameForm(); form->rows = size; form->columns = size; form->length = length; form->selectedGameMode = indexGameMode; form->Show(); this->Hide(); } GameMap.h: #pragma once #include <vector> #include <algorithm> struct Vector2 { int x, y; }; class GameMap { //поля класса private: int** map; Vector2 size; 22 ПРИЛОЖЕНИЕ А int length;//необходимая длина выигрышной последовательности //методы класса public: GameMap();//конструктор (создает пустой объект класса) GameMap(Vector2, int);//конструктор (создает объект класса с заданными параметрами) GameMap(int, int, int);//конструткор (создает объект класса с заданными параметрами) ~GameMap();//деструктор (удаляет необходимые данные относительно текущего класса) bool SetPosition(Vector2, int); //задание позиции bool IsEmpty(Vector2); //проверка на свободную ячейку bool IsEmpty(int, int); //проверка на свободную ячейку void SetMap(Vector2, int); //получить некоторые значения текущей карты void SetMap(int, int, int); //получить некоторые значения текущей карты int GetValue(Vector2); //получить значения int GetValue(int, int); //получить значения int GetLength() { return length; }; //получить длину для выигрышной последовательности Vector2 GetSize() { return size; }; //получить размер текущей карты int CheckList(std::vector<int> a); int CheckingWin(); //проверить выигрыш bool CanMove(); //проверить свободные ходы Vector2 GetCenter(); //проверка для центра }; GameMap.cpp: #include "GameMap.h" GameMap::GameMap() { size.x = 0; size.y = 0; length = 0; map = new int* [size.x]; for (int i = 0; i < size.x; i++) { map[i] = new int[size.y]; } } GameMap::GameMap(Vector2 _size, int l) { //инициализируем игровую карту size = _size; length = l; //выделяем память для нашей карты map = new int* [size.x]; for (int i = 0; i < size.x; i++) { map[i] = new int[size.y]; } //Обнуляем for (int i = 0; i < size.x; i++) { for (int j = 0; j < size.y; j++) { map[i][j] = 0; } 23 ПРИЛОЖЕНИЕ А } } GameMap::GameMap(int i, int j, int l) { //инициализируме игровую карту size.x = i; size.y = j; length = l; map = new int* [size.x]; for (i = 0; i < size.x; i++) { map[i] = new int[size.y]; } //обнуляем for (i = 0; i < size.x; i++) { for (j = 0; j < size.y; j++) { map[i][j] = 0; } } } GameMap::~GameMap() { //Очищаем матрицу for (int i = 0; i < size.x; i++) { delete[] map[i]; } delete[] map; } bool GameMap::SetPosition(Vector2 cell, int c) { if (IsEmpty(cell)) { map[cell.x][cell.y] = c; return true; } else { return false; } } bool GameMap::IsEmpty(Vector2 cell) { if (map[cell.x][cell.y] == 0) return true; else return false; } bool GameMap::IsEmpty(int i, int j) { if (map[i][j] == 0) return true; else return false; } void GameMap::SetMap(Vector2 _size, int l) { //инициализируем игровую карту size = _size; 24 ПРИЛОЖЕНИЕ А length = l; map = new int* [size.x]; for (int i = 0; i < size.x; i++) { map[i] = new int[size.y]; } //обнуляем for (int i = 0; i < size.x; i++) { for (int j = 0; j < size.y; j++) { map[i][j] = 0; } } } void GameMap::SetMap(int i, int j, int l) { //инициализируем size.x = i; size.y = j; length = l; map = new int* [size.x]; for (int i = 0; i < size.x; i++) { map[i] = new int[size.y]; } //обнуляем for (int i = 0; i < size.x; i++) { for (int j = 0; j < size.y; j++) { map[i][j] = 0; } } } int GameMap::GetValue(Vector2 cell) { return map[cell.x][cell.y]; } int GameMap::GetValue(int i, int j) { return map[i][j]; } int GameMap::CheckList(std::vector<int> a) { if (a.size() < length) return 0; //флажки победы игроков bool winPl1 = false; bool winPl2 = false; int count1 = 0, count2 = 0; //проверяем набранные очки for (int i = 0; i < a.size(); i++) { for (int j = i; j < i + length; j++) { if (j < a.size()) { if (a[j] == 1) { count1++; 25 ПРИЛОЖЕНИЕ А } } else break; } if (count1 >= length) { winPl1 = true; break; } count1 = 0; } for (int i = 0; i < a.size(); i++) { for (int j = i; j < i + length; j++) { if (j < a.size()) { if (a[j] == 2) { count2++; } } else break; } if (count2 >= length) { winPl2 = true; break; } count2 = 0; } //выводим результат if (winPl1 && winPl2) { return 3;//ничья } else if (!winPl1 && winPl2) { return 2;//победа 2 } else if (winPl1 && !winPl2) { return 1;//победа 1 } else return 0; } int GameMap::CheckingWin() { //проходим по карте в поиске последовательностей заданной длины int stateWin = 0; std::vector<int> check; /* [][][] [][][] [][][] */ //1. Проверяем все горизонтали for (int i = 0; i < size.x; i++) { for (int j = 0; j < size.y; j++) { check.push_back(map[i][j]); } 26 ПРИЛОЖЕНИЕ А //Проверяем stateWin = CheckList(check); check.clear(); if (stateWin == 3) { return 3;//ничья } else if (stateWin == 2) { return 2;//победа 2 } else if (stateWin == 1) { return 1;//победа 1 } } //2. Проверяем все вертикали for (int i = 0; i < size.x; i++) { for (int j = 0; j < size.y; j++) { check.push_back(map[j][i]); } //проверяем stateWin = CheckList(check); check.clear(); if (stateWin == 3) { return 3;//ничья } else if (stateWin == 2) { return 2;//победа 2 } else if (stateWin == 1) { return 1;//победа 1 } } //3. Проверяем все левые диагонали //Главная диагональ и над ней for (int i = 0; i < size.x; ++i) { for (int j = 0; i + j < size.y; ++j) { check.push_back(map[i + j][j]); } //проверяем stateWin = CheckList(check); check.clear(); if (stateWin == 3) { return 3;//ничья } else if (stateWin == 2) { return 2;//победа 2 } else if (stateWin == 1) { return 1;//победа 1 } } //Под главной диагональю for (int i = 1; i < size.x; ++i) { for (int j = 0; i + j < size.y; ++j) { 27 ПРИЛОЖЕНИЕ А check.push_back(map[i + j][j]); } //проверяем stateWin = CheckList(check); check.clear(); if (stateWin == 3) { return 3;//ничья } else if (stateWin == 2) { return 2;//победа 2 } else if (stateWin == 1) { return 1;//победа 1 } } //4. Проверяем все правые диагонали //Побочная диагональ и над ней for (int j = size.y; j > 0; --j) { for (int i = 0; i < size.x; ++i) { if (size.x - j - i >= 0) { check.push_back(map[i][size.x - j - i]); } } //проверяем stateWin = CheckList(check); check.clear(); if (stateWin == 3) { return 3;//ничья } else if (stateWin == 2) { return 2;//победа 2 } else if (stateWin == 1) { return 1;//победа 1 } } //Под побочной диагональю for (int j = 0; j < size.y; ++j) { for (int i = 0; i < size.x; ++i) { if (size.x + j - i < size.x) { check.push_back(map[i][size.x + j - i]); } } //проверяем stateWin = CheckList(check); check.clear(); if (stateWin == 3) { return 3;//ничья } else if (stateWin == 2) { return 2;//победа 2 } else if (stateWin == 1) { return 1;//победа 1 28 ПРИЛОЖЕНИЕ А } } if (CanMove()) return 0; //нет победителя else return 3; } bool GameMap::CanMove() { for (int i = 0; i < size.x; i++) { for (int j = 0; j < size.y; j++) { if (map[i][j] == 0) { return true; } } } return false; } Vector2 GameMap::GetCenter() { Vector2 center; int x; if (size.x % 2 != 0) { x = (size.x - 1) / 2; } else { x = (size.x / 2) - 1; } center.x = x; center.y = x; return center; } Gamer.h: #pragma once enum GamerStatus { //перечисляем все возможные статусы игрока Computer = 0, Player, Player1, Player2 }; class Gamer { //поля класса private: GamerStatus status; int mark; //методы класса public: Gamer() {} //конструктор ~Gamer() {} //деструктор void SetField(GamerStatus mode, int m); //задаем поля 29 ПРИЛОЖЕНИЕ А int GetMark() { return mark; }; //вернуть то, кто сейчас ходит GamerStatus GetStatus() { return status; } //вернуть статус }; Gamer.cpp: #include "Gamer.h" void Gamer::SetField(GamerStatus mode, int m) { if (mode == 0) status = Computer; else if (mode == 1) status = Player; if (mode == 2) status = Player1; else status = Player2; mark = m; } 30