Добавлен: 09.01.2024
Просмотров: 108
Скачиваний: 3
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
МИНОБРНАУКИ РОССИИ
Федеральное государственное бюджетное образовательное учреждение высшего образования
НИЖЕГОРОДСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ
УНИВЕРСИТЕТ им. Р.Е.АЛЕКСЕЕВА
Институт радиоэлектроники и информационных технологий
Кафедра информатики и систем управления
Курсовая работа
Игра «Точки и квадраты»
по дисциплине
Алгоритмы и структуры данных
РУКОВОДИТЕЛЬ:
________________ Капранов С. Н.
СТУДЕНТ:
________________ Сухоруков В.А.
19-ИВТ-3
Работа защищена «___» ____________
С оценкой ________________________
Нижний Новгород 2020
Оглавление
Правила игры 3
Инструкция пользователя 4
Инструкция программиста 5
Оценочная функция 6
Описание оценочной функции 6
Пример расчёта оценочной функции 6
Программная реализация оценочной функции 7
Алгоритм минимакса 8
Описание вычислений 8
Пример расчёта 9
Программная реализация 10
Функция альфа бета отсечения 11
Описание функции альфа бета отсечения 11
Программная реализация 12
Код Tree.h 16
Код основного файла 18
Функция game_is_over() 18
Функция check_cell() 19
Функция is_square_up () 22
Функция is_square_down () 23
Функция is_square_right () 24
Функция is_square_left () 25
Функция is_square () 26
Функция generation_move() 28
Функция make_tree() 31
Функция get_assessement() 33
Функция alpha_betta() 34
Функция choose_best_move() 36
Функция Print_field() 37
Функция create_root() 38
Функция re_create_root() 39
Функция read_human_move() 40
Функция game() 42
Функция get_result() 43
Функция main() 44
Результаты работы программы 45
Ввод некорректных данных 45
Корректная работа программы 46
Правила игры
Игровое поле представляет из себя n рядов по n точек. Играющие соединяют соседние по вертикали или горизонтали точки отрезками. Ходы делаются по очереди, но если игрок замкнул своим ходом один или два единичных квадратика, то он закрашивает эти квадраты своим цветом, и он обязан продолжать делать ходы, пока не сделает ход, не замыкающий квадратик, или до конца игры. Когда проведены все отрезки
, подсчитываются квадратики, которые замкнул каждый игрок. Выигрывает тот, кто занял больше точек.
Инструкция пользователя
Программа разработана для игры в «Точки и квадраты». Исходное поле представляет собой поле точек, в крайних двух противоположных углах располагаются точки компьютера и Ваша: в левом нижем компьютера, в правом верхнем Ваша.
Цель игры заключается в захвате незанятых точек. Побеждает тот, кто соберёт больше.
Если игрок собирает квадрат, то его противник пропускает ход.
Соединять можно любую занятую Вами точку с точкой, не принадлежащей противнику и расположенной рядом с данной (сверху, снизу, справа или слева).
Координаты точки – 2 значения от 0 до 9.
Инструкция программиста
Файл Tree.h содержит структуру узла дерева и функции для работы с ней. Поля структуры:
struct Tree_node {
Tree_node* child[N]; //Массив указателей на сыновей
Tree_node* parent; //Указатель на родителя
Tree_node* next_brother; //Указатель на следующего брата
int field [10][10] ; //Состояние поля игры
int connections[10][10][4]; //Массив клеток, соединённых с данной
int count_connections[10][10];//Количество клеток, соединённых с данной
int count_child; //Количество сыновей
int number; //Номер узла
int height; //Высота узла
int assessment; //Оценка текущего состояния игры
int alpha; //Параметр для альфа-бета отсечения
int betta; //Параметр для альфа-бета отсечения
int count_check_child; //Количество просмотренных сыновей при
//поиске лучшего хода
bool is_check; //Был ли полностью рассмотрен узел т.е.
//рассмотрены все его сыновья
bool is_square; //Показывает был ли образован квадрат на
//этом ходу
};
Функции:
-
Tree_node* newNode //Позволяет создавать узел с переданными
//параметрами
-
void push(]); //Позволяет добавлять сына узлу с
//переданными номером
-
void deletion(); //Позволяет освободить динамическую
//память выделенную под дерево
Код основного файла содержит функции логики игры:
-
bool game_is_over(); //Проверяет завершенность игры -
bool check_cell(); //Проверяет можно ли занять клетку -
void is_square(); //Проверяет был ли образован квадрат
//на данном ходу
-
void generation_move(); //Генерирует ход -
void make_tree(); //Строит дерево возможных ходов -
void get_assessment(); //Оценочная функция -
void alpha_betta(); //Алгоритм альфа бета отсечения -
void choose_best_move(); //Выбирает лучший ход -
void Print_field(); //Выводит поле игры -
Tree_node* creat_root(); //Создаёт начальный корень дерева -
Tree_node * re_create_root();//Создаёт корень дерева -
void read_human_move(); //Считывает ход игрока -
Tree_node* game(); //Осуществляет игровой процесс -
void get_result(); //Анализ результатов игры
Оценочная функция
Описание оценочной функции
Каждая точка на игровом поле имеет свою стоимость, её значение может быть отрицательным или положительным, в зависимости от принадлежности игроку. Если точка принадлежит компьютеру, то её стоимость положительная, если человеку – отрицательная. Если точка не принадлежит игроку, то её стоимость равна нулю. Результат оценочной функции – сумма стоимостей каждой точки.
Стоимость точки определяется её связями с соседними "союзными " точками: модуль значения стоимости точки равен количеству её связей.
П ример: Красная точка принадлежит компьютеру и имеет 2 связи с соседними точками. Её стоимость – 2.
Пример расчёта оценочной функции
-
Рассчитываем стоимость каждой клетки. -
Вычисляем значение оценочной функции.
F=2+2+3+3+3+4+3+1+2+3+2-2-3-3-1-3-4-2-2-2=6
Программная реализация оценочной функции
/*Оценочная функция
Параметры:
1)Указатель на узел дерева, поля которого:
-
int field[10][10]- текущее состояние поля -
int count_connections[10][10]- количество связей клетки -
assessment - оценка поля
Принцип работы:
1)Просматриваются значения клеток текущего поля
2)Если значение клетки равно 1, то она принадлежит компьютеру. К результату прибавляется количество связей этой клетки
3)Если значение клетки равно 2, то она принадлежит человеку. К результату вычитается количество связей этой клетки
*/
void get_assessment(Tree_node* PNode) {
int res = 0;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (PNode->field[i][j] == 1) {
res = res + PNode->count_connections[i][j];
}
if (PNode->field[i][j] == 2) {
res = res - PNode->count_connections[i][j];
}
}
}
PNode->assessment = res;
}
Алгоритм минимакса
Описание вычислений
Алгоритм Минимакса — правило принятия решений, используемое в теории игр, теории принятия решений, исследовании операций, статистике и философии для минимизации возможных потерь их тех
, которые лицу, принимающему решение, нельзя предотвратить при развитии событий по наихудшему сценарию.
Строится дерево ходов (решений) заданной глубины. После постройки дерева получаем результаты оценочной функции для каждого листа (состояния поля) и начинаем двигаться вверх, к корню дерева. На уровне MIN выбирается минимальное значение дочерних узлов и транслируется на данный уровень, а на уровне MAX максимальное значение дочерних узлов. Последними операциями выбора и трансляции получаем значение для корня дерева. Как только получено значение корня дерева делаем ход согласно той ветви, которая привела к данному результату. Если к одинаковому значению корня приводят несколько ветвей дерева, то направления движения выбирается произвольно.
Пример расчёта
Рассмотрим состояние поля, представленное на скриншоте 1. Ход делает компьютер (MAX – красные точки).
Скриншот 1
Для данного состояния возможно построение следующего дерева минимакса.
Замечание: Последний уровень у всех вершин одинаковый, для отсутствия нагромождения он построено только для одной вершины.
В дереве красным цветом отмечены ходы компьютер, синим ходы игрока.
Программная реализация
/*Функция минимакса
Параметры:
1)Указатель на узел дерева
Принцип работы:
1)Если узел является листом, то высчитываем его оценку
2)Если проверены не все сыновья узла, то применяем функция к непроверенным сыновьям
4)Вычисляем значение проверенных сыновей
5)Если проверены все сыновья, то узел проверен
6)Если узел не корень:
6.1) Если родитель находится на чётном уровне (минимума) и его значение больше оценки текущего узла, то заменяем оценку
6.2) Если родитель находится на нечётном уровне (максимума и его значение меньше оценки текущего узла, то заменяем оценку
*/
void Min_max(Tree_node* PNode) {
if (PNode->height == 3) {
get_assessment(PNode);
}
if (PNode->count_check_child != PNode->count_child) {
for (int i = PNode->count_check_child;
i
{
Min_max(PNode->child[i]);
}
}
for (int i = 0; i < PNode->count_child; i++) {
if (PNode->child[i]->is_check == true) {
PNode->count_check_child++;
}
}
if (PNode->count_check_child == PNode->count_check_child) {
PNode->is_check = true;
}
if (PNode->height != 1) {
if (PNode->parent->height % 2 == 0) {
if (PNode->parent-> assessment > PNode->assessment)
PNode->parent-> assessment = PNode->assessment;
}
if (PNode->parent->height % 2 == 1) {
if (PNode->parent-> assessment < PNode->assessment) {
PNode->parent-> assessment = PNode->assessment;
}
}
if (PNode->next_brother != nullptr) {
PNode = PNode->next_brother;
}
else {
PNode = PNode->parent;
}
}
}
1 2 3 4 5 6 7 8 9 10