
МИНОБРНАУКИ РОССИИ
Ф
едеральное
государственное бюджетное образовательное
учреждение высшего образования
НИЖЕГОРОДСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ
УНИВЕРСИТЕТ им. Р.Е.АЛЕКСЕЕВА
Институт радиоэлектроники и информационных технологий
Кафедра информатики и систем управления
Программа играющая в «ГЕКСАГОН»
(наименование темы проекта или работы)
Курсовая работа (2-ый этап)
по дисциплине
Алгоритмы и структуры данных
(наименование дисциплины)
РУКОВОДИТЕЛЬ:
________________ Капранов С. Н.
(подпись) (фамилия, и.,о.)
СТУДЕНТ:
________________ Какушкина О. В.
(подпись) (фамилия, и.,о.)
23-ИСТ-1-1
(шифр группы)
Работа защищена «___» ____________
С оценкой ________________________
Нижний Новгород 2025
Текст задачи:
Функция MiniMax и связанные компоненты
Структура игрового поля (TPlaying_Field)
Назначение: Хранит состояние игрового поля (клетки могут быть пустыми, занятыми игроком или ИИ).
struct TPlaying_Field {
CellState board[NUM_ROWS][NUM_COLS];
TPlaying_Field() {
for (int i = 0; i < NUM_ROWS; ++i) {
for (int j = 0; j < NUM_COLS; ++j) {
board[i][j] = EMPTY;
}
}
}
TPlaying_Field(const TPlaying_Field& other) {
for (int i = 0; i < NUM_ROWS; ++i) {
for (int j = 0; j < NUM_COLS; ++j) {
board[i][j] = other.board[i][j];
}
}
}
};
Генерация возможных ходов (GenerateMoves)
Логика работы:
Первый ход:
ИИ пытается занять центр (NUM_ROWS/2, NUM_COLS/2).
Если центр занят, выбирает угловые клетки.
Последующие ходы:
Перемещение фишек на соседние пустые клетки.
Установка новых фишек рядом с существующими.
Приоритет отдается ходам, которые захватывают фишки противника.
Возвращает: Список возможных ходов (координаты {i, j}).
std::vector<std::pair<int, int>> GenerateMoves(TPlaying_Field* field, CellState player) {
std::vector<std::pair<int, int>> moves;
bool hasPieces = false;
// Проверяем наличие фишек игрока
for (int i = 0; i < NUM_ROWS && !hasPieces; ++i) {
for (int j = 0; j < NUM_COLS && !hasPieces; ++j) {
if (field->board[i][j] == player) {
hasPieces = true;
}
}
}
// Первый ход - стратегические позиции
if (!hasPieces) {
// Проверяем центр в первую очередь
int centerX = NUM_ROWS / 2;
int centerY = NUM_COLS / 2;
if (IsInBounds(centerX, centerY) && field->board[centerX][centerY] == EMPTY) {
moves.push_back({ centerX, centerY });
return moves; // Возвращаем только центр, если он свободен
}
// Если центр занят, используем остальные приоритетные позиции
std::vector<std::pair<int, int>> priorityPositions = {
{1, 1}, {1, NUM_COLS - 2}, {NUM_ROWS - 2, 1}, {NUM_ROWS - 2, NUM_COLS - 2} // Углы
};
for (const auto& pos : priorityPositions) {
if (IsInBounds(pos.first, pos.second) &&
field->board[pos.first][pos.second] == EMPTY) {
moves.push_back(pos);
}
}
// Если все приоритетные позиции заняты, выбираем любую свободную
if (moves.empty()) {
for (int i = 0; i < NUM_ROWS; ++i) {
for (int j = 0; j < NUM_COLS; ++j) {
if (field->board[i][j] == EMPTY) {
moves.push_back({ i, j });
return moves;
}
}
}
}
return moves;
}
// Генерация всех возможных ходов с приоритетом на атакующие ходы
for (int i = 0; i < NUM_ROWS; ++i) {
for (int j = 0; j < NUM_COLS; ++j) {
if (field->board[i][j] == player) {
// Ходы с перемещением фишки
for (const auto& dir : DIRECTIONS) {
int ni = i + dir[0];
int nj = j + dir[1];
if (IsInBounds(ni, nj) && field->board[ni][nj] == EMPTY) {
// Проверяем, будет ли этот ход захватывать фишки противника
TPlaying_Field temp = *field;
MakeMove(&temp, i, j, ni, nj, player);
int captures = 0;
for (const auto& dir2 : DIRECTIONS) {
int ti = ni + dir2[0];
int tj = nj + dir2[1];
if (IsInBounds(ti, tj) && temp.board[ti][tj] == player &&
field->board[ti][tj] != player) {
captures++;
}
}
// Добавляем ход несколько раз в зависимости от его "качества"
int repetitions = 1 + captures * 2;
for (int k = 0; k < repetitions; ++k) {
moves.push_back({ ni, nj });
}
}
}
}
// Ходы с установкой новой фишки
if (field->board[i][j] == EMPTY) {
bool nearPlayer = false;
for (const auto& dir : DIRECTIONS) {
int ni = i + dir[0];
int nj = j + dir[1];
if (IsInBounds(ni, nj) && field->board[ni][nj] == player) {
nearPlayer = true;
break;
}
}
if (nearPlayer) {
// Проверяем потенциальные захваты
TPlaying_Field temp = *field;
temp.board[i][j] = player;
CaptureOpponentPieces(i, j, player, &temp);
int captures = 0;
for (const auto& dir : DIRECTIONS) {
int ni = i + dir[0];
int nj = j + dir[1];
if (IsInBounds(ni, nj) && temp.board[ni][nj] == player &&
field->board[ni][nj] != player) {
captures++;
}
}
// Добавляем ход несколько раз в зависимости от его "качества"
int repetitions = 1 + captures * 3;
for (int k = 0; k < repetitions; ++k) {
moves.push_back({ i, j });
}
}
}
}
}
return moves;
}