
ТП_23_ИСТ_1_1_Какушкина_Ольга_Витальевна_KР_01ОФ
.docxМИНОБРНАУКИ РОССИИ
Ф
едеральное
государственное бюджетное образовательное
учреждение высшего образования
НИЖЕГОРОДСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ
УНИВЕРСИТЕТ им. Р.Е.АЛЕКСЕЕВА
Институт радиоэлектроники и информационных технологий
Кафедра информатики и систем управления
Программа играющая в «ГЕКСАГОН»
(наименование темы проекта или работы)
Курсовая работа (1-ый этап)
по дисциплине
Алгоритмы и структуры данных
(наименование дисциплины)
РУКОВОДИТЕЛЬ:
________________ Капранов С. Н.
(подпись) (фамилия, и.,о.)
СТУДЕНТ:
________________ Какушкина О. В.
(подпись) (фамилия, и.,о.)
23-ИСТ-1-1
(шифр группы)
Работа защищена «___» ____________
С оценкой ________________________
Нижний Новгород 2025
Текст задачи:
Взятие обязательно. Побитые шашки снимаются только после завершения хода.
Захват соседних клеток:
Если игрок ставит свою шашку на клетку или перемещает её, он может захватить соседние клетки противника.
Захват происходит, если клетка противника находится в непосредственной близости (соседние клетки) от новой позиции шашки игрока.
Захваченные клетки переходят под контроль игрока, сделавшего ход.
Направления захвата:
В Гексагоне используется шестигранная сетка, поэтому у каждой клетки есть 6 соседей (по одному в каждом направлении).
Направления задаются следующим образом:
Слева.
Углом вверх вправо.
Вправо.
Справа.
Углом вверх влево.
Вверх.
Условия захвата:
Она находится в пределах игрового поля.
Она принадлежит противнику (не пустая и не принадлежит текущему игроку).
Она является соседней для новой позиции шашки игрока.
Запрет на самозахват:
Игрок не может захватывать свои собственные клетки.
Выигрыш партии
Партия считается выигранной в следующих случаях:
Один из игроков контролирует больше клеток, чем противник, когда все клетки на поле заполнены.
Один из игроков заявляет о сдаче.
Один из игроков просрочил время (если используется контроль времени).
Шашки и клетки одного из игроков обездвижены (он не имеет возможности сделать ход, когда пришла его очередь).
Ничья
Партия считается закончившейся вничью в следующих случаях:
Один из игроков предлагает ничью, а другой её принимает.
При невозможности выигрыша ни одного из игроков (например, если у обоих игроков одинаковое количество клеток).
Если три раза повторяется одна и та же позиция.
Если в течение 15 ходов игроки делали ходы, не приводящие к изменению соотношения сил (например, не было захватов и перемещений, меняющих баланс).
Факторы, учитываемые в оценочной функции
Количество занятых клеток:
Каждая клетка, занятая игроком 1 (PLAYER1), добавляет +1 к оценке.
Каждая клетка, занятая игроком 2 (PLAYER2), вычитает -1 из оценки.
Это базовый фактор, который отражает текущее соотношение сил на поле.
Контроль центральных клеток:
Центральные клетки имеют стратегическое значение, так как они обеспечивают больше возможностей для захвата и контроля.
Если клетка игрока находится в центральной зоне, добавляется бонус +3 (значение CENTRAL_CELL_BONUS).
Центральные клетки определены в массиве:
cpp
Copy
std::vector<std::pair<int, int>> centralCells = {
{NUM_ROWS / 2, NUM_COLS / 2},
{NUM_ROWS / 2 - 1, NUM_COLS / 2},
{NUM_ROWS / 2, NUM_COLS / 2 - 1},
{NUM_ROWS / 2 + 1, NUM_COLS / 2},
{NUM_ROWS / 2, NUM_COLS / 2 + 1}
};
Формирование цепочек:
Если клетка игрока имеет соседнюю клетку, также занятую этим игроком, это считается цепочкой.
За каждую такую связь добавляется бонус +2 (значение CHAIN_BONUS).
Это поощряет игрока создавать группы клеток, которые могут быть использованы для захвата или защиты.
Потенциальные угрозы:
Если клетка игрока находится под угрозой захвата противником (например, если рядом с ней есть клетка противника, за которой есть пустая клетка), вычитается штраф -1 (значение THREAT_BONUS).
Если клетка противника находится под угрозой захвата игроком, добавляется бонус +1.
Формула вычисления оценки
Оценка вычисляется по следующей формуле:
Оценка=Клетки PLAYER1−Клетки PLAYER2+Центральные бонусы+Цепочки−УгрозыОценка=Клетки PLAYER1−Клетки PLAYER2+Центральные бонусы+Цепочки−Угрозы
Где:
Клетки PLAYER1: количество клеток, занятых игроком 1.
Клетки PLAYER2: количество клеток, занятых игроком 2.
Центральные бонусы: бонусы за контроль центральных клеток.
Цепочки: бонусы за формирование цепочек.
Угрозы: штрафы за потенциальные угрозы.
пример расчета ОФ (игровая ситуация находиться на середине партии)
Рассмотрим пример игрового поля:
Шаги вычисления:
Клетки PLAYER1:
Игрок 1 контролирует 1 клетку (2, 2) → +1.
Клетки PLAYER2:
Игрок 2 контролирует 2 клетки (1, 2) и (2, 3) → -2.
Центральные бонусы:
Клетка (2, 2) игрока 1 находится в центре → +3.
Цепочки:
У игрока 1 нет соседних клеток, занятых им же → 0.
Потенциальные угрозы:
Клетка (2, 2) игрока 1 может быть захвачена игроком 2 через клетку (2, 3) → -1.
Клетка (2, 3) игрока 2 может быть захвачена игроком 1 через клетку (2, 2) → +1.
Итоговая оценка:
Оценка=1−2+3+0−1+1=2Оценка=1−2+3+0−1+1=2
Эти факторы позволяют оценить текущее состояние игры и определить, какой игрок имеет преимущество. В приведенном примере оценка 2 указывает на небольшое преимущество игрока 1.
программный код с комментариями всех участвующих в расчете функций
int Evaluation(TPlaying_Field* Playing_Field) {
int score = 0;
// Весовые коэффициенты для различных факторов
const int CENTRAL_CELL_BONUS = 3; // Бонус за контроль центральных клеток
const int CHAIN_BONUS = 2; // Бонус за формирование цепочек
const int THREAT_BONUS = 1; // Бонус за потенциальные угрозы
// Центральные клетки
std::vector<std::pair<int, int>> centralCells = {
{NUM_ROWS / 2, NUM_COLS / 2},
{NUM_ROWS / 2 - 1, NUM_COLS / 2},
{NUM_ROWS / 2, NUM_COLS / 2 - 1},
{NUM_ROWS / 2 + 1, NUM_COLS / 2},
{NUM_ROWS / 2, NUM_COLS / 2 + 1}
};
// Функция для обработки клетки игрока
auto evaluateCell = [&](int i, int j, CellState player, int playerModifier) {
// Базовый счет за клетку
score += playerModifier;
// Бонус за контроль центральных клеток
for (const auto& cell : centralCells) {
if (i == cell.first && j == cell.second) {
score += CENTRAL_CELL_BONUS * playerModifier;
}
}
// Оценка соседних клеток
for (const auto& dir : DIRECTIONS) {
int ni = i + dir[0];
int nj = j + dir[1];
if (IsInBounds(ni, nj)) {
if (Playing_Field->board[ni][nj] == EMPTY) {
score += 1 * playerModifier; // Пустая соседняя клетка
} else if (Playing_Field->board[ni][nj] != player) {
score -= 1 * playerModifier; // Клетка противника
}
}
}
// Бонус за формирование цепочек
for (const auto& dir : DIRECTIONS) {
int ni = i + dir[0];
int nj = j + dir[1];
if (IsInBounds(ni, nj) && Playing_Field->board[ni][nj] == player) {
score += CHAIN_BONUS * playerModifier;
}
}
// Учет потенциальных угроз
for (const auto& dir : DIRECTIONS) {
int ni = i + dir[0];
int nj = j + dir[1];
if (IsInBounds(ni, nj) && Playing_Field->board[ni][nj] != player && Playing_Field->board[ni][nj] != EMPTY) {
// Проверяем, может ли противник захватить клетку
int nni = ni + dir[0];
int nnj = nj + dir[1];
if (IsInBounds(nni, nnj) && Playing_Field->board[nni][nnj] == EMPTY) {
score -= THREAT_BONUS * playerModifier; // Штраф за потенциальную угрозу
}
}
}
};
// Основной цикл
for (int i = 0; i < NUM_ROWS; ++i) {
for (int j = 0; j < NUM_COLS; ++j) {
if (Playing_Field->board[i][j] == PLAYER1) {
evaluateCell(i, j, PLAYER1, 1); // Обработка клетки PLAYER1
} else if (Playing_Field->board[i][j] == PLAYER2) {
evaluateCell(i, j, PLAYER2, -1); // Обработка клетки PLAYER2
}
}
}
return score;
}