Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ТП_23_ИСТ_1_1_Какушкина_Ольга_Витальевна_KР_02ММ.docx
Скачиваний:
0
Добавлен:
23.06.2025
Размер:
324.42 Кб
Скачать

МИНОБРНАУКИ РОССИИ

Ф едеральное государственное бюджетное образовательное учреждение высшего образования

НИЖЕГОРОДСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ

УНИВЕРСИТЕТ им. Р.Е.АЛЕКСЕЕВА

Институт радиоэлектроники и информационных технологий

Кафедра информатики и систем управления

Программа играющая в «ГЕКСАГОН»

(наименование темы проекта или работы)

Курсовая работа (2-ый этап)

по дисциплине

Алгоритмы и структуры данных

(наименование дисциплины)

РУКОВОДИТЕЛЬ:

________________ Капранов С. Н.

(подпись) (фамилия, и.,о.)

СТУДЕНТ:

________________ Какушкина О. В.

(подпись) (фамилия, и.,о.)

23-ИСТ-1-1

(шифр группы)

Работа защищена «___» ____________

С оценкой ________________________

Нижний Новгород 2025

  1. Текст задачи:

Функция MiniMax и связанные компоненты

  1. Структура игрового поля (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];

}

}

}

};

  1. Генерация возможных ходов (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;

}