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

Факторы оценки:

Победа/поражение:

+100000 за победу ИИ, -100000 за победу игрока.

Контроль клеток:

+3 за каждую фишку ИИ, -3 за фишку игрока.

Центральные клетки:

Бонус +15 за фишки в центре (чем ближе к центру, тем выше бонус).

Цепочки фишек:

+8 за каждую соседнюю фишку того же игрока.

Мобильность:

Бонус за количество возможных ходов (+5 за разницу в мобильности).

Угрозы:

Штраф -10 за фишки под угрозой захвата.

Формула: Оценка = Базовые_фишки + Центральные_бонусы + Цепочки + Мобильность - Угрозы

int Evaluation(TPlaying_Field* field) {

if (CheckWin(field, PLAYER2)) return 100000;

if (CheckWin(field, PLAYER1)) return -100000;

int score = 0;

const int CENTRAL_BONUS = 15;

const int CHAIN_BONUS = 8;

const int EDGE_BONUS = 12;

const int MOBILITY_BONUS = 5;

const int THREAT_BONUS = 10;

// Оценка мобильности (количество возможных ходов)

int playerMoves = GenerateMoves(field, PLAYER2).size();

int opponentMoves = GenerateMoves(field, PLAYER1).size();

score += (playerMoves - opponentMoves) * MOBILITY_BONUS;

// Оценка позиций и угроз

for (int i = 0; i < NUM_ROWS; ++i) {

for (int j = 0; j < NUM_COLS; ++j) {

if (field->board[i][j] == PLAYER2) {

score += 3; // Базовое значение фишки

// Бонус за центр (чем ближе к центру, тем больше бонус)

int centerDist = std::abs(i - NUM_ROWS / 2) + std::abs(j - NUM_COLS / 2);

score += (NUM_ROWS - centerDist) * CENTRAL_BONUS / NUM_ROWS;

// Бонус за приближение к правому краю (цель AI)

score += j * EDGE_BONUS / NUM_COLS;

// Бонус за соединения

int connections = 0;

for (const auto& dir : DIRECTIONS) {

int ni = i + dir[0];

int nj = j + dir[1];

if (IsInBounds(ni, nj) && field->board[ni][nj] == PLAYER2) {

connections++;

}

}

score += connections * CHAIN_BONUS;

// Бонус за потенциальные угрозы (фишки рядом с пустыми клетками)

for (const auto& dir : DIRECTIONS) {

int ni = i + dir[0];

int nj = j + dir[1];

if (IsInBounds(ni, nj)) {

if (field->board[ni][nj] == EMPTY) {

score += THREAT_BONUS / 2;

}

else if (field->board[ni][nj] == PLAYER1) {

score += THREAT_BONUS;

}

}

}

}

else if (field->board[i][j] == PLAYER1) {

score -= 3; // Базовое значение фишки противника

// Штраф за центр

int centerDist = std::abs(i - NUM_ROWS / 2) + std::abs(j - NUM_COLS / 2);

score -= (NUM_ROWS - centerDist) * CENTRAL_BONUS / NUM_ROWS;

// Штраф за приближение к нижнему краю (цель игрока)

score -= (NUM_ROWS - 1 - i) * EDGE_BONUS / NUM_ROWS;

// Штраф за соединения противника

int connections = 0;

for (const auto& dir : DIRECTIONS) {

int ni = i + dir[0];

int nj = j + dir[1];

if (IsInBounds(ni, nj) && field->board[ni][nj] == PLAYER1) {

connections++;

}

}

score -= connections * CHAIN_BONUS;

}

}

}

return score;

}

void CaptureOpponentPieces(int x, int y, CellState player, TPlaying_Field* field) {

for (const auto& dir : DIRECTIONS) {

int ni = x + dir[0];

int nj = y + dir[1];

if (IsInBounds(ni, nj) && field->board[ni][nj] != EMPTY &&

field->board[ni][nj] != player) {

field->board[ni][nj] = player;

}

}

}

bool CheckWin(TPlaying_Field* field, CellState player) {

bool visited[NUM_ROWS][NUM_COLS] = { false };

std::vector<std::pair<int, int>> stack;

if (player == PLAYER1) {

for (int j = 0; j < NUM_COLS; ++j) {

if (field->board[0][j] == PLAYER1) {

stack.push_back({ 0, j });

visited[0][j] = true;

}

}

}

else {

for (int i = 0; i < NUM_ROWS; ++i) {

if (field->board[i][0] == PLAYER2) {

stack.push_back({ i, 0 });

visited[i][0] = true;

}

}

}

while (!stack.empty()) {

auto current = stack.back();

stack.pop_back();

int i = current.first;

int j = current.second;

if ((player == PLAYER1 && i == NUM_ROWS - 1) ||

(player == PLAYER2 && j == NUM_COLS - 1)) {

return true;

}

for (const auto& dir : DIRECTIONS) {

int ni = i + dir[0];

int nj = j + dir[1];

if (IsInBounds(ni, nj) && field->board[ni][nj] == player && !visited[ni][nj]) {

visited[ni][nj] = true;

stack.push_back({ ni, nj });

}

}

}

return false;

}