From 8ec9dffe61ac8d3b0887a34b168bb569590f4980 Mon Sep 17 00:00:00 2001 From: sevch Date: Sun, 26 Jan 2025 15:00:06 +0500 Subject: [PATCH 1/9] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0?= =?UTF-8?q?=D1=80=D0=B8=D0=B8=20=D0=B8=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BD=D0=B5=D0=BD=D1=83=D0=B6=D0=BD=D1=8B=D0=B5?= =?UTF-8?q?=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Game/Board.h | 2 +- Game/Config.h | 5 +++-- Game/Game.h | 6 +++--- Game/Hand.h | 2 +- Game/Logic.h | 30 ++++++++++++++---------------- Models/Move.h | 2 +- Models/Response.h | 10 +++++----- main.cpp | 10 ++-------- settings.json | 22 +++++----------------- 9 files changed, 35 insertions(+), 54 deletions(-) diff --git a/Game/Board.h b/Game/Board.h index 5c955fb..3008e39 100644 --- a/Game/Board.h +++ b/Game/Board.h @@ -15,7 +15,7 @@ #endif using namespace std; - +// Board class Board { public: diff --git a/Game/Config.h b/Game/Config.h index 1a41663..de9bbb9 100644 --- a/Game/Config.h +++ b/Game/Config.h @@ -8,12 +8,13 @@ using json = nlohmann::json; class Config { public: - Config() + Config() // () . { reload(); } - + // reload() void reload() + // { std::ifstream fin(project_path + "settings.json"); fin >> config; diff --git a/Game/Game.h b/Game/Game.h index d7d16bc..9c99de4 100644 --- a/Game/Game.h +++ b/Game/Game.h @@ -17,7 +17,7 @@ class Game fout.close(); } - // to start checkers + // play() , int play() { auto start = chrono::steady_clock::now(); @@ -104,7 +104,7 @@ class Game } private: - void bot_turn(const bool color) + void bot_turn(const bool color) // bot_turn() { auto start = chrono::steady_clock::now(); @@ -132,7 +132,7 @@ class Game fout.close(); } - Response player_turn(const bool color) + Response player_turn(const bool color) // player_turn() { // return 1 if quit vector> cells; diff --git a/Game/Hand.h b/Game/Hand.h index 65268fa..8d3d94e 100644 --- a/Game/Hand.h +++ b/Game/Hand.h @@ -5,7 +5,7 @@ #include "../Models/Response.h" #include "Board.h" -// methods for hands +// Hand class Hand { public: diff --git a/Game/Logic.h b/Game/Logic.h index 9e1fdc4..49aa046 100644 --- a/Game/Logic.h +++ b/Game/Logic.h @@ -19,13 +19,11 @@ class Logic optimization = (*config)("Bot", "Optimization"); } - vector find_best_turns(const bool color) + vector (const bool color) { next_best_state.clear(); next_move.clear(); - find_first_best_turn(board->get_board(), color, -1, -1, 0); - int cur_state = 0; vector res; do @@ -48,7 +46,7 @@ class Logic return mtx; } - double calc_score(const vector> &mtx, const bool first_bot_color) const + double calc_score(const vector> &mtx, const bool first_bot_color) const // calc_score() { // color - who is max player double w = 0, wq = 0, b = 0, bq = 0; @@ -84,20 +82,20 @@ class Logic return (b + bq * q_coef) / (w + wq * q_coef); } - double find_first_best_turn(vector> mtx, const bool color, const POS_T x, const POS_T y, size_t state, + double (vector> mtx, const bool color, const POS_T x, const POS_T y, size_t state, double alpha = -1) { next_best_state.push_back(-1); next_move.emplace_back(-1, -1, -1, -1); - double best_score = -1; + double best_score = -1; if (state != 0) - find_turns(x, y, mtx); + find_turns(x, y, mtx); // find_turns() auto turns_now = turns; bool have_beats_now = have_beats; if (!have_beats_now && state != 0) { - return find_best_turns_rec(mtx, 1 - color, 0, alpha); + return (mtx, 1 - color, 0, alpha); } vector best_moves; @@ -109,11 +107,11 @@ class Logic double score; if (have_beats_now) { - score = find_first_best_turn(make_turn(mtx, turn), color, turn.x2, turn.y2, next_state, best_score); + score =(make_turn(mtx, turn), color, turn.x2, turn.y2, next_state, best_score); // make_turn() } else { - score = find_best_turns_rec(make_turn(mtx, turn), 1 - color, 0, best_score); + score = (make_turn(mtx, turn), 1 - color, 0, best_score); } if (score > best_score) { @@ -125,7 +123,7 @@ class Logic return best_score; } - double find_best_turns_rec(vector> mtx, const bool color, const size_t depth, double alpha = -1, + double (vector> mtx, const bool color, const size_t depth, double alpha = -1, double beta = INF + 1, const POS_T x = -1, const POS_T y = -1) { if (depth == Max_depth) @@ -143,7 +141,7 @@ class Logic if (!have_beats_now && x != -1) { - return find_best_turns_rec(mtx, 1 - color, depth + 1, alpha, beta); + return (mtx, 1 - color, depth + 1, alpha, beta); } if (turns.empty()) @@ -156,11 +154,11 @@ class Logic double score = 0.0; if (!have_beats_now && x == -1) { - score = find_best_turns_rec(make_turn(mtx, turn), 1 - color, depth + 1, alpha, beta); + score = (make_turn(mtx, turn), 1 - color, depth + 1, alpha, beta); } else { - score = find_best_turns_rec(make_turn(mtx, turn), color, depth, alpha, beta, turn.x2, turn.y2); + score = (make_turn(mtx, turn), color, depth, alpha, beta, turn.x2, turn.y2); } min_score = min(min_score, score); max_score = max(max_score, score); @@ -176,7 +174,7 @@ class Logic } public: - void find_turns(const bool color) + void find_turns(const bool color) // find_turns() { find_turns(color, board->get_board()); } @@ -187,7 +185,7 @@ class Logic } private: - void find_turns(const bool color, const vector> &mtx) + void find_turns(const bool color, const vector> &mtx) { vector res_turns; bool have_beats_before = false; diff --git a/Models/Move.h b/Models/Move.h index 9569429..13f9ef6 100644 --- a/Models/Move.h +++ b/Models/Move.h @@ -2,7 +2,7 @@ #include typedef int8_t POS_T; - +// Move struct move_pos { POS_T x, y; // from diff --git a/Models/Response.h b/Models/Response.h index d07a293..1412ad5 100644 --- a/Models/Response.h +++ b/Models/Response.h @@ -2,9 +2,9 @@ enum class Response { - OK, - BACK, - REPLAY, - QUIT, - CELL + OK, // + BACK, // + REPLAY, // + QUIT, // + CELL // }; diff --git a/main.cpp b/main.cpp index 0cc4542..c15807a 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,3 @@ -#include "Game/Game.h" - -int main(int argc, char* argv[]) -{ - Game g; - g.play(); - - return 0; +#include +int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { } diff --git a/settings.json b/settings.json index fbce46b..90de856 100644 --- a/settings.json +++ b/settings.json @@ -1,19 +1,7 @@ { - "WindowSize": { - "Width": 0, - "Hight": 0 - }, - "Bot": { - "IsWhiteBot": false, - "IsBlackBot": true, - "WhiteBotLevel": 0, - "BlackBotLevel": 5, - "BotScoringType": "NumberAndPotential", - "BotDelayMS": 0, - "NoRandom": false, - "Optimization": "O1" - }, - "Game": { - "MaxNumTurns": 120 - } + "C_Cpp.intelliSenseMode": "gcc-x64", // Используем GCC для 64-битной архитектуры + "files.associations": { // Связывание файлов с типами + "*.cpp": "cpp", + "*.h": "cpp" + } } From beec12112cf943bd6a289370566153772ff5f220 Mon Sep 17 00:00:00 2001 From: sevch Date: Sun, 26 Jan 2025 15:12:24 +0500 Subject: [PATCH 2/9] =?UTF-8?q?=D0=9A=D0=BE=D0=B4=20=D0=B3=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Game/Logic.h | 304 +++++++++++++-------------------------------------- 1 file changed, 75 insertions(+), 229 deletions(-) diff --git a/Game/Logic.h b/Game/Logic.h index 49aa046..af94cad 100644 --- a/Game/Logic.h +++ b/Game/Logic.h @@ -1,25 +1,17 @@ -#pragma once -#include -#include - -#include "../Models/Move.h" -#include "Board.h" -#include "Config.h" - -const int INF = 1e9; - class Logic { - public: - Logic(Board *board, Config *config) : board(board), config(config) +public: + Logic(Board* board, Config* config) : board(board), config(config) { - rand_eng = std::default_random_engine ( + rand_eng = std::default_random_engine( !((*config)("Bot", "NoRandom")) ? unsigned(time(0)) : 0); scoring_mode = (*config)("Bot", "BotScoringType"); optimization = (*config)("Bot", "Optimization"); + Max_depth = 5; // } - vector (const bool color) + // + vector get_best_move(const bool color) { next_best_state.clear(); next_move.clear(); @@ -31,289 +23,143 @@ class Logic res.push_back(next_move[cur_state]); cur_state = next_best_state[cur_state]; } while (cur_state != -1 && next_move[cur_state].x != -1); + return res; } private: - vector> make_turn(vector> mtx, move_pos turn) const - { - if (turn.xb != -1) - mtx[turn.xb][turn.yb] = 0; - if ((mtx[turn.x][turn.y] == 1 && turn.x2 == 0) || (mtx[turn.x][turn.y] == 2 && turn.x2 == 7)) - mtx[turn.x][turn.y] += 2; - mtx[turn.x2][turn.y2] = mtx[turn.x][turn.y]; - mtx[turn.x][turn.y] = 0; - return mtx; - } - - double calc_score(const vector> &mtx, const bool first_bot_color) const // calc_score() + // + double calc_score(const vector>& mtx, const bool first_bot_color) const { - // color - who is max player double w = 0, wq = 0, b = 0, bq = 0; for (POS_T i = 0; i < 8; ++i) { for (POS_T j = 0; j < 8; ++j) { - w += (mtx[i][j] == 1); - wq += (mtx[i][j] == 3); - b += (mtx[i][j] == 2); - bq += (mtx[i][j] == 4); + w += (mtx[i][j] == 1); // + wq += (mtx[i][j] == 3); // + b += (mtx[i][j] == 2); // + bq += (mtx[i][j] == 4); // if (scoring_mode == "NumberAndPotential") { - w += 0.05 * (mtx[i][j] == 1) * (7 - i); - b += 0.05 * (mtx[i][j] == 2) * (i); + w += 0.05 * (mtx[i][j] == 1) * (7 - i); // + b += 0.05 * (mtx[i][j] == 2) * (i); // } } } if (!first_bot_color) { - swap(b, w); + swap(b, w); // swap(bq, wq); } + + // , if (w + wq == 0) return INF; if (b + bq == 0) return 0; - int q_coef = 4; - if (scoring_mode == "NumberAndPotential") - { - q_coef = 5; - } - return (b + bq * q_coef) / (w + wq * q_coef); + + int q_coef = (scoring_mode == "NumberAndPotential") ? 5 : 4; // + return (b + bq * q_coef) / (w + wq * q_coef); // } - double (vector> mtx, const bool color, const POS_T x, const POS_T y, size_t state, - double alpha = -1) + // + vector> make_turn(vector> mtx, move_pos turn) const { - next_best_state.push_back(-1); - next_move.emplace_back(-1, -1, -1, -1); - double best_score = -1; - if (state != 0) - find_turns(x, y, mtx); // find_turns() - auto turns_now = turns; - bool have_beats_now = have_beats; - - if (!have_beats_now && state != 0) - { - return (mtx, 1 - color, 0, alpha); - } - - vector best_moves; - vector best_states; - - for (auto turn : turns_now) - { - size_t next_state = next_move.size(); - double score; - if (have_beats_now) - { - score =(make_turn(mtx, turn), color, turn.x2, turn.y2, next_state, best_score); // make_turn() - } - else - { - score = (make_turn(mtx, turn), 1 - color, 0, best_score); - } - if (score > best_score) - { - best_score = score; - next_best_state[state] = (have_beats_now ? int(next_state) : -1); - next_move[state] = turn; - } - } - return best_score; + if (turn.xb != -1) + mtx[turn.xb][turn.yb] = 0; // , + if ((mtx[turn.x][turn.y] == 1 && turn.x2 == 0) || (mtx[turn.x][turn.y] == 2 && turn.x2 == 7)) + mtx[turn.x][turn.y] += 2; // + mtx[turn.x2][turn.y2] = mtx[turn.x][turn.y]; // + mtx[turn.x][turn.y] = 0; // + return mtx; } - double (vector> mtx, const bool color, const size_t depth, double alpha = -1, - double beta = INF + 1, const POS_T x = -1, const POS_T y = -1) + // - + double minimax(vector> mtx, bool color, size_t depth, double alpha = -INF, double beta = INF, POS_T x = -1, POS_T y = -1) { - if (depth == Max_depth) + if (depth == Max_depth) // { - return calc_score(mtx, (depth % 2 == color)); + return calc_score(mtx, color); } + if (x != -1) { - find_turns(x, y, mtx); + find_turns(x, y, mtx); // } else - find_turns(color, mtx); + { + find_turns(color, mtx); // + } + auto turns_now = turns; bool have_beats_now = have_beats; if (!have_beats_now && x != -1) { - return (mtx, 1 - color, depth + 1, alpha, beta); + return minimax(mtx, 1 - color, depth + 1, alpha, beta); } if (turns.empty()) - return (depth % 2 ? 0 : INF); + return (depth % 2 == 0 ? INF : -INF); // , + + double best_score = (depth % 2 == 0) ? -INF : INF; - double min_score = INF + 1; - double max_score = -1; for (auto turn : turns_now) { - double score = 0.0; - if (!have_beats_now && x == -1) + vector> new_mtx = make_turn(mtx, turn); // + double score = minimax(new_mtx, 1 - color, depth + 1, alpha, beta); // + + // + if (depth % 2 == 0) // { - score = (make_turn(mtx, turn), 1 - color, depth + 1, alpha, beta); + best_score = max(best_score, score); + alpha = max(alpha, best_score); } - else + else // { - score = (make_turn(mtx, turn), color, depth, alpha, beta, turn.x2, turn.y2); + best_score = min(best_score, score); + beta = min(beta, best_score); } - min_score = min(min_score, score); - max_score = max(max_score, score); - // alpha-beta pruning - if (depth % 2) - alpha = max(alpha, max_score); - else - beta = min(beta, min_score); - if (optimization != "O0" && alpha >= beta) - return (depth % 2 ? max_score + 1 : min_score - 1); + + // - + if (alpha >= beta) + break; } - return (depth % 2 ? max_score : min_score); - } -public: - void find_turns(const bool color) // find_turns() - { - find_turns(color, board->get_board()); + return best_score; } - void find_turns(const POS_T x, const POS_T y) + // + void find_best_move(bool color) { - find_turns(x, y, board->get_board()); - } + double best_score = -INF; + move_pos best_move; -private: - void find_turns(const bool color, const vector> &mtx) - { - vector res_turns; - bool have_beats_before = false; - for (POS_T i = 0; i < 8; ++i) + for (auto turn : turns) { - for (POS_T j = 0; j < 8; ++j) - { - if (mtx[i][j] && mtx[i][j] % 2 != color) - { - find_turns(i, j, mtx); - if (have_beats && !have_beats_before) - { - have_beats_before = true; - res_turns.clear(); - } - if ((have_beats_before && have_beats) || !have_beats_before) - { - res_turns.insert(res_turns.end(), turns.begin(), turns.end()); - } - } - } - } - turns = res_turns; - shuffle(turns.begin(), turns.end(), rand_eng); - have_beats = have_beats_before; - } + vector> new_mtx = make_turn(board->get_board(), turn); // + double score = minimax(new_mtx, 1 - color, 0, -INF, INF); // - void find_turns(const POS_T x, const POS_T y, const vector> &mtx) - { - turns.clear(); - have_beats = false; - POS_T type = mtx[x][y]; - // check beats - switch (type) - { - case 1: - case 2: - // check pieces - for (POS_T i = x - 2; i <= x + 2; i += 4) - { - for (POS_T j = y - 2; j <= y + 2; j += 4) - { - if (i < 0 || i > 7 || j < 0 || j > 7) - continue; - POS_T xb = (x + i) / 2, yb = (y + j) / 2; - if (mtx[i][j] || !mtx[xb][yb] || mtx[xb][yb] % 2 == type % 2) - continue; - turns.emplace_back(x, y, i, j, xb, yb); - } - } - break; - default: - // check queens - for (POS_T i = -1; i <= 1; i += 2) - { - for (POS_T j = -1; j <= 1; j += 2) - { - POS_T xb = -1, yb = -1; - for (POS_T i2 = x + i, j2 = y + j; i2 != 8 && j2 != 8 && i2 != -1 && j2 != -1; i2 += i, j2 += j) - { - if (mtx[i2][j2]) - { - if (mtx[i2][j2] % 2 == type % 2 || (mtx[i2][j2] % 2 != type % 2 && xb != -1)) - { - break; - } - xb = i2; - yb = j2; - } - if (xb != -1 && xb != i2) - { - turns.emplace_back(x, y, i2, j2, xb, yb); - } - } - } - } - break; - } - // check other turns - if (!turns.empty()) - { - have_beats = true; - return; - } - switch (type) - { - case 1: - case 2: - // check pieces - { - POS_T i = ((type % 2) ? x - 1 : x + 1); - for (POS_T j = y - 1; j <= y + 1; j += 2) - { - if (i < 0 || i > 7 || j < 0 || j > 7 || mtx[i][j]) - continue; - turns.emplace_back(x, y, i, j); - } - break; - } - default: - // check queens - for (POS_T i = -1; i <= 1; i += 2) + if (score > best_score) { - for (POS_T j = -1; j <= 1; j += 2) - { - for (POS_T i2 = x + i, j2 = y + j; i2 != 8 && j2 != 8 && i2 != -1 && j2 != -1; i2 += i, j2 += j) - { - if (mtx[i2][j2]) - break; - turns.emplace_back(x, y, i2, j2); - } - } + best_score = score; + best_move = turn; } - break; } + + next_move.push_back(best_move); // } - public: +private: + Board* board; + Config* config; vector turns; bool have_beats; - int Max_depth; - - private: + int Max_depth; // default_random_engine rand_eng; string scoring_mode; string optimization; vector next_move; vector next_best_state; - Board *board; - Config *config; }; From 9db58baf97e4a356c884b7256724aa5fad06a5ff Mon Sep 17 00:00:00 2001 From: sevch Date: Wed, 29 Jan 2025 14:17:35 +0500 Subject: [PATCH 3/9] =?UTF-8?q?=D0=93=D0=BE=D1=82=D0=BE=D0=B2=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Game/Logic.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Game/Logic.h b/Game/Logic.h index af94cad..971ec90 100644 --- a/Game/Logic.h +++ b/Game/Logic.h @@ -7,10 +7,10 @@ class Logic !((*config)("Bot", "NoRandom")) ? unsigned(time(0)) : 0); scoring_mode = (*config)("Bot", "BotScoringType"); optimization = (*config)("Bot", "Optimization"); - Max_depth = 5; // + Max_depth = 5; h = 5; // } - // + // - vector get_best_move(const bool color) { next_best_state.clear(); @@ -39,7 +39,7 @@ class Logic w += (mtx[i][j] == 1); // wq += (mtx[i][j] == 3); // b += (mtx[i][j] == 2); // - bq += (mtx[i][j] == 4); // + bq += (mtx[i][j] == 4); // if (scoring_mode == "NumberAndPotential") { w += 0.05 * (mtx[i][j] == 1) * (7 - i); // @@ -49,11 +49,11 @@ class Logic } if (!first_bot_color) { - swap(b, w); // + swap(b, w); // swap(bq, wq); } - // , + // if (w + wq == 0) return INF; if (b + bq == 0) @@ -63,11 +63,11 @@ class Logic return (b + bq * q_coef) / (w + wq * q_coef); // } - // + // vector> make_turn(vector> mtx, move_pos turn) const { if (turn.xb != -1) - mtx[turn.xb][turn.yb] = 0; // , + mtx[turn.xb][turn.yb] = 0; // if ((mtx[turn.x][turn.y] == 1 && turn.x2 == 0) || (mtx[turn.x][turn.y] == 2 && turn.x2 == 7)) mtx[turn.x][turn.y] += 2; // mtx[turn.x2][turn.y2] = mtx[turn.x][turn.y]; // @@ -75,7 +75,7 @@ class Logic return mtx; } - // - + // - double minimax(vector> mtx, bool color, size_t depth, double alpha = -INF, double beta = INF, POS_T x = -1, POS_T y = -1) { if (depth == Max_depth) // @@ -89,7 +89,7 @@ class Logic } else { - find_turns(color, mtx); // + find_turns(color, mtx); // } auto turns_now = turns; @@ -101,14 +101,14 @@ class Logic } if (turns.empty()) - return (depth % 2 == 0 ? INF : -INF); // , + return (depth % 2 == 0 ? INF : -INF); // , double best_score = (depth % 2 == 0) ? -INF : INF; for (auto turn : turns_now) { vector> new_mtx = make_turn(mtx, turn); // - double score = minimax(new_mtx, 1 - color, depth + 1, alpha, beta); // + double score = minimax(new_mtx, 1 - color, depth + 1, alpha, beta); // // if (depth % 2 == 0) // @@ -116,7 +116,7 @@ class Logic best_score = max(best_score, score); alpha = max(alpha, best_score); } - else // + else // { best_score = min(best_score, score); beta = min(beta, best_score); @@ -130,7 +130,7 @@ class Logic return best_score; } - // + // void find_best_move(bool color) { double best_score = -INF; @@ -139,7 +139,7 @@ class Logic for (auto turn : turns) { vector> new_mtx = make_turn(board->get_board(), turn); // - double score = minimax(new_mtx, 1 - color, 0, -INF, INF); // + double score = minimax(new_mtx, 1 - color, 0, -INF, INF); // if (score > best_score) { @@ -156,7 +156,7 @@ class Logic Config* config; vector turns; bool have_beats; - int Max_depth; // + int Max_depth; // default_random_engine rand_eng; string scoring_mode; string optimization; From d5779737de63081b33f54f6f16934a927a8adc4f Mon Sep 17 00:00:00 2001 From: maxsedegov Date: Wed, 29 Jan 2025 14:23:38 +0500 Subject: [PATCH 4/9] Update Logic.h --- Game/Logic.h | 68 ++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/Game/Logic.h b/Game/Logic.h index 971ec90..12e93fa 100644 --- a/Game/Logic.h +++ b/Game/Logic.h @@ -7,10 +7,10 @@ class Logic !((*config)("Bot", "NoRandom")) ? unsigned(time(0)) : 0); scoring_mode = (*config)("Bot", "BotScoringType"); optimization = (*config)("Bot", "Optimization"); - Max_depth = 5; h = 5; // + Max_depth = 5; h = 5; // Установим максимальную глубину для алгоритма минимакс } - // - + // Îñíîâíîé ìåòîä äëÿ âûçîâà ìèíèìàêñ-àëãîðèòìà è ïîëó÷åíèÿ íàèëó÷øåãî õîäà äëÿ áîòà vector get_best_move(const bool color) { next_best_state.clear(); @@ -28,7 +28,7 @@ class Logic } private: - // + // Ìåòîä äëÿ âû÷èñëåíèÿ îöåíêè ïîçèöèè íà äîñêå double calc_score(const vector>& mtx, const bool first_bot_color) const { double w = 0, wq = 0, b = 0, bq = 0; @@ -36,60 +36,60 @@ class Logic { for (POS_T j = 0; j < 8; ++j) { - w += (mtx[i][j] == 1); // - wq += (mtx[i][j] == 3); // - b += (mtx[i][j] == 2); // - bq += (mtx[i][j] == 4); // + w += (mtx[i][j] == 1); // Äîáàâëÿåì îáû÷íûå ôèãóðû áåëûõ + wq += (mtx[i][j] == 3); // Äîáàâëÿåì ôåðçè áåëûõ + b += (mtx[i][j] == 2); // Äîáàâëÿåì îáû÷íûå ôèãóðû ÷åðíûõ + bq += (mtx[i][j] == 4); // Äîáàâëÿåì ôåðçåé ÷åðíûõ if (scoring_mode == "NumberAndPotential") { - w += 0.05 * (mtx[i][j] == 1) * (7 - i); // - b += 0.05 * (mtx[i][j] == 2) * (i); // + w += 0.05 * (mtx[i][j] == 1) * (7 - i); // Ó÷èòûâàåì ïîçèöèþ äëÿ îáû÷íûõ ôèãóð + b += 0.05 * (mtx[i][j] == 2) * (i); // Ó÷èòûâàåì ïîçèöèþ äëÿ ÷åðíûõ ôèãóð } } } if (!first_bot_color) { - swap(b, w); // + swap(b, w); // èíâåðòèðóåì ðåçóëüòàòû äëÿ ÷åðíûõ è áåëûõ swap(bq, wq); } - // + // Åñëè íà äîñêå íåò ôèãóð òî âîçâðàùàåìñÿ â áåñêîíå÷íîñòü if (w + wq == 0) return INF; if (b + bq == 0) return 0; - int q_coef = (scoring_mode == "NumberAndPotential") ? 5 : 4; // - return (b + bq * q_coef) / (w + wq * q_coef); // + int q_coef = (scoring_mode == "NumberAndPotential") ? 5 : 4; // Ó÷èòûâàåì êîýôôèöèåíò äëÿ ôåðçåé + return (b + bq * q_coef) / (w + wq * q_coef); // Îöåíêà ïîçèöèè } - // + // Ìåòîä âûïîëíåíèÿ õîäà íà äîñêå vector> make_turn(vector> mtx, move_pos turn) const { if (turn.xb != -1) - mtx[turn.xb][turn.yb] = 0; // + mtx[turn.xb][turn.yb] = 0; // Óäàëÿåì ôèãóðó êîòîðóþ ïîáåäèëè if ((mtx[turn.x][turn.y] == 1 && turn.x2 == 0) || (mtx[turn.x][turn.y] == 2 && turn.x2 == 7)) - mtx[turn.x][turn.y] += 2; // - mtx[turn.x2][turn.y2] = mtx[turn.x][turn.y]; // - mtx[turn.x][turn.y] = 0; // + mtx[turn.x][turn.y] += 2; // Ïðåâðàùàåì ôèãóðó â ôåðçÿ + mtx[turn.x2][turn.y2] = mtx[turn.x][turn.y]; // Ïåðåìåùàåì ôèãóðó + mtx[turn.x][turn.y] = 0; // Ñòàâèì ïóñòîå ìåñòî return mtx; } - // - + // Ìåòîä äëÿ âûïîëíåíèÿ ìèíèìàêñà ñ àëüôà-áåòà îòñå÷åíèåì double minimax(vector> mtx, bool color, size_t depth, double alpha = -INF, double beta = INF, POS_T x = -1, POS_T y = -1) { - if (depth == Max_depth) // + if (depth == Max_depth) // Åñëè äîñòèãëè ìàêñèìàëüíîé ãëóáèíû { return calc_score(mtx, color); } if (x != -1) { - find_turns(x, y, mtx); // + find_turns(x, y, mtx); // Èùåì âîçìîæíûå õîäû äëÿ êîíêðåòíîé ôèãóðû } else { - find_turns(color, mtx); // + find_turns(color, mtx); // Èùåì õîäû äëÿ âñåõ èãðîêîâ } auto turns_now = turns; @@ -101,28 +101,28 @@ class Logic } if (turns.empty()) - return (depth % 2 == 0 ? INF : -INF); // , + return (depth % 2 == 0 ? INF : -INF); // Åñëè õîäîâ íåò, âîçâðàùàåì ìàêñèìàëüíî ïëîõîé ðåçóëüòàò double best_score = (depth % 2 == 0) ? -INF : INF; for (auto turn : turns_now) { - vector> new_mtx = make_turn(mtx, turn); // - double score = minimax(new_mtx, 1 - color, depth + 1, alpha, beta); // + vector> new_mtx = make_turn(mtx, turn); // Ïðèìåíÿåì õîä + double score = minimax(new_mtx, 1 - color, depth + 1, alpha, beta); // Ðåêóðñèâíî âû÷èñëÿåì ðåçóëüòàò - // - if (depth % 2 == 0) // + // Îáíîâëÿåì ëó÷øèé ðåçóëüòàò â çàâèñèìîñòè îò ãëóáèíû + if (depth % 2 == 0) // Ìàêñèìèçèðóåì äëÿ áîòà { best_score = max(best_score, score); alpha = max(alpha, best_score); } - else // + else // Ìàêñèìèçèðóåì äëÿ ñîïåðíèêà { best_score = min(best_score, score); beta = min(beta, best_score); } - // - + // Àëüôà-áåòà îòñå÷åíèå if (alpha >= beta) break; } @@ -130,7 +130,7 @@ class Logic return best_score; } - // + // Îñíîâíîé ìåòîä ïîèñêà íàèëó÷øåãî õîäà äëÿ áîòà void find_best_move(bool color) { double best_score = -INF; @@ -138,8 +138,8 @@ class Logic for (auto turn : turns) { - vector> new_mtx = make_turn(board->get_board(), turn); // - double score = minimax(new_mtx, 1 - color, 0, -INF, INF); // + vector> new_mtx = make_turn(board->get_board(), turn); // Ïðèìåíÿåì õîä + double score = minimax(new_mtx, 1 - color, 0, -INF, INF); // Âûïîëíÿåì ìèíèìèçàöèþ if (score > best_score) { @@ -148,7 +148,7 @@ class Logic } } - next_move.push_back(best_move); // + next_move.push_back(best_move); // Çàïîìèíàåì ëó÷øèé õîä } private: @@ -156,7 +156,7 @@ class Logic Config* config; vector turns; bool have_beats; - int Max_depth; // + int Max_depth; // Ãëóáèíà äëÿ ìèíèìóìà è ìàêñèìóìà default_random_engine rand_eng; string scoring_mode; string optimization; From 8ab082ab9f63df31dca6744cc37057375a86416c Mon Sep 17 00:00:00 2001 From: maxsedegov Date: Wed, 29 Jan 2025 14:28:37 +0500 Subject: [PATCH 5/9] Update Logic.h --- Game/Logic.h | 66 ++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/Game/Logic.h b/Game/Logic.h index 12e93fa..d0082df 100644 --- a/Game/Logic.h +++ b/Game/Logic.h @@ -10,7 +10,7 @@ class Logic Max_depth = 5; h = 5; // Установим максимальную глубину для алгоритма минимакс } - // Îñíîâíîé ìåòîä äëÿ âûçîâà ìèíèìàêñ-àëãîðèòìà è ïîëó÷åíèÿ íàèëó÷øåãî õîäà äëÿ áîòà + // Основной метод для вызова минимакс-алгоритма и получения наилучшего хода для бота vector get_best_move(const bool color) { next_best_state.clear(); @@ -28,7 +28,7 @@ class Logic } private: - // Ìåòîä äëÿ âû÷èñëåíèÿ îöåíêè ïîçèöèè íà äîñêå + // Метод для вычисления оценки позиции на доске double calc_score(const vector>& mtx, const bool first_bot_color) const { double w = 0, wq = 0, b = 0, bq = 0; @@ -36,60 +36,60 @@ class Logic { for (POS_T j = 0; j < 8; ++j) { - w += (mtx[i][j] == 1); // Äîáàâëÿåì îáû÷íûå ôèãóðû áåëûõ - wq += (mtx[i][j] == 3); // Äîáàâëÿåì ôåðçè áåëûõ - b += (mtx[i][j] == 2); // Äîáàâëÿåì îáû÷íûå ôèãóðû ÷åðíûõ - bq += (mtx[i][j] == 4); // Äîáàâëÿåì ôåðçåé ÷åðíûõ + w += (mtx[i][j] == 1); // Добавляем обычные фигуры белых + wq += (mtx[i][j] == 3); // Добавляем ферзи белых + b += (mtx[i][j] == 2); // Добавляем обычные фигуры черных + bq += (mtx[i][j] == 4); // Добавляем ферзей черных if (scoring_mode == "NumberAndPotential") { - w += 0.05 * (mtx[i][j] == 1) * (7 - i); // Ó÷èòûâàåì ïîçèöèþ äëÿ îáû÷íûõ ôèãóð - b += 0.05 * (mtx[i][j] == 2) * (i); // Ó÷èòûâàåì ïîçèöèþ äëÿ ÷åðíûõ ôèãóð + w += 0.05 * (mtx[i][j] == 1) * (7 - i); // Учитываем позицию для обычных фигур + b += 0.05 * (mtx[i][j] == 2) * (i); // Учитываем позицию для черных фигур } } } if (!first_bot_color) { - swap(b, w); // èíâåðòèðóåì ðåçóëüòàòû äëÿ ÷åðíûõ è áåëûõ + swap(b, w); // инвертируем результаты для черных и белых swap(bq, wq); } - // Åñëè íà äîñêå íåò ôèãóð òî âîçâðàùàåìñÿ â áåñêîíå÷íîñòü + // Если на доске нет фигур то возвращаемся в бесконечность if (w + wq == 0) return INF; if (b + bq == 0) return 0; - int q_coef = (scoring_mode == "NumberAndPotential") ? 5 : 4; // Ó÷èòûâàåì êîýôôèöèåíò äëÿ ôåðçåé - return (b + bq * q_coef) / (w + wq * q_coef); // Îöåíêà ïîçèöèè + int q_coef = (scoring_mode == "NumberAndPotential") ? 5 : 4; // Учитываем коэффициент для ферзей + return (b + bq * q_coef) / (w + wq * q_coef); // Оценка позиции } - // Ìåòîä âûïîëíåíèÿ õîäà íà äîñêå + // Метод выполнения хода на доске vector> make_turn(vector> mtx, move_pos turn) const { if (turn.xb != -1) - mtx[turn.xb][turn.yb] = 0; // Óäàëÿåì ôèãóðó êîòîðóþ ïîáåäèëè + mtx[turn.xb][turn.yb] = 0; // Удаляем фигуру которую победили if ((mtx[turn.x][turn.y] == 1 && turn.x2 == 0) || (mtx[turn.x][turn.y] == 2 && turn.x2 == 7)) - mtx[turn.x][turn.y] += 2; // Ïðåâðàùàåì ôèãóðó â ôåðçÿ - mtx[turn.x2][turn.y2] = mtx[turn.x][turn.y]; // Ïåðåìåùàåì ôèãóðó - mtx[turn.x][turn.y] = 0; // Ñòàâèì ïóñòîå ìåñòî + mtx[turn.x][turn.y] += 2; // Превращаем фигуру в ферзя + mtx[turn.x2][turn.y2] = mtx[turn.x][turn.y]; //Перемещаем фигуру + mtx[turn.x][turn.y] = 0; // Ставим пустое место return mtx; } - // Ìåòîä äëÿ âûïîëíåíèÿ ìèíèìàêñà ñ àëüôà-áåòà îòñå÷åíèåì + // Метод для выполнения минимакса с альфа-бета отсечением double minimax(vector> mtx, bool color, size_t depth, double alpha = -INF, double beta = INF, POS_T x = -1, POS_T y = -1) { - if (depth == Max_depth) // Åñëè äîñòèãëè ìàêñèìàëüíîé ãëóáèíû + if (depth == Max_depth) // Если достигли максимальной глубины { return calc_score(mtx, color); } if (x != -1) { - find_turns(x, y, mtx); // Èùåì âîçìîæíûå õîäû äëÿ êîíêðåòíîé ôèãóðû + find_turns(x, y, mtx); // Ищем возможные ходы для конкретной фигуры } else { - find_turns(color, mtx); // Èùåì õîäû äëÿ âñåõ èãðîêîâ + find_turns(color, mtx); // Ищем ходы для всех игроков } auto turns_now = turns; @@ -101,28 +101,28 @@ class Logic } if (turns.empty()) - return (depth % 2 == 0 ? INF : -INF); // Åñëè õîäîâ íåò, âîçâðàùàåì ìàêñèìàëüíî ïëîõîé ðåçóëüòàò + return (depth % 2 == 0 ? INF : -INF); // Если ходов нет, возвращаем максимально плохой результат double best_score = (depth % 2 == 0) ? -INF : INF; for (auto turn : turns_now) { - vector> new_mtx = make_turn(mtx, turn); // Ïðèìåíÿåì õîä - double score = minimax(new_mtx, 1 - color, depth + 1, alpha, beta); // Ðåêóðñèâíî âû÷èñëÿåì ðåçóëüòàò + vector> new_mtx = make_turn(mtx, turn); // Применяем ход + double score = minimax(new_mtx, 1 - color, depth + 1, alpha, beta); // Рекурсивно вычисляем результат - // Îáíîâëÿåì ëó÷øèé ðåçóëüòàò â çàâèñèìîñòè îò ãëóáèíû - if (depth % 2 == 0) // Ìàêñèìèçèðóåì äëÿ áîòà + // Обновляем лучший результат в зависимости от глубины + if (depth % 2 == 0) // Максимизируем для бота { best_score = max(best_score, score); alpha = max(alpha, best_score); } - else // Ìàêñèìèçèðóåì äëÿ ñîïåðíèêà + else // Максимизируем для соперника { best_score = min(best_score, score); beta = min(beta, best_score); } - // Àëüôà-áåòà îòñå÷åíèå + // Альфа-бета отсечение if (alpha >= beta) break; } @@ -130,7 +130,7 @@ class Logic return best_score; } - // Îñíîâíîé ìåòîä ïîèñêà íàèëó÷øåãî õîäà äëÿ áîòà + // Основной метод поиска наилучшего хода для бота void find_best_move(bool color) { double best_score = -INF; @@ -138,8 +138,8 @@ class Logic for (auto turn : turns) { - vector> new_mtx = make_turn(board->get_board(), turn); // Ïðèìåíÿåì õîä - double score = minimax(new_mtx, 1 - color, 0, -INF, INF); // Âûïîëíÿåì ìèíèìèçàöèþ + vector> new_mtx = make_turn(board->get_board(), turn); // Применяем ход + double score = minimax(new_mtx, 1 - color, 0, -INF, INF); // Выполняем минимизацию if (score > best_score) { @@ -148,7 +148,7 @@ class Logic } } - next_move.push_back(best_move); // Çàïîìèíàåì ëó÷øèé õîä + next_move.push_back(best_move); // Запоминаем лучший ход } private: @@ -156,7 +156,7 @@ class Logic Config* config; vector turns; bool have_beats; - int Max_depth; // Ãëóáèíà äëÿ ìèíèìóìà è ìàêñèìóìà + int Max_depth; // Глубина для минимума и максимума default_random_engine rand_eng; string scoring_mode; string optimization; From 67906c3cd148bfd3bd85a8967d6bc05e663d09f4 Mon Sep 17 00:00:00 2001 From: maxsedegov Date: Wed, 29 Jan 2025 14:31:11 +0500 Subject: [PATCH 6/9] Update Hand.h --- Game/Hand.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Game/Hand.h b/Game/Hand.h index 8d3d94e..3135572 100644 --- a/Game/Hand.h +++ b/Game/Hand.h @@ -5,7 +5,7 @@ #include "../Models/Response.h" #include "Board.h" -// Hand +// Класс Hand управляет картами игрока class Hand { public: From 2dc806823c96dea293b0e5b4e236cf0c1e63a492 Mon Sep 17 00:00:00 2001 From: maxsedegov Date: Wed, 29 Jan 2025 14:34:48 +0500 Subject: [PATCH 7/9] Update Game.h --- Game/Game.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Game/Game.h b/Game/Game.h index 9c99de4..a43bf9a 100644 --- a/Game/Game.h +++ b/Game/Game.h @@ -17,7 +17,7 @@ class Game fout.close(); } - // play() , + // Функция play() управляет игровым процессом, включая ходы игрока и бота int play() { auto start = chrono::steady_clock::now(); @@ -104,7 +104,7 @@ class Game } private: - void bot_turn(const bool color) // bot_turn() + void bot_turn(const bool color) // Ôóíêöèÿ bot_turn() óïðàâëÿåò õîäîì êîìïüþòåðà { auto start = chrono::steady_clock::now(); @@ -132,7 +132,7 @@ class Game fout.close(); } - Response player_turn(const bool color) // player_turn() + Response player_turn(const bool color) // Функция player_turn() отвечает за выполнение хода игроком { // return 1 if quit vector> cells; From 10798b4ff17556792e3ee41cdbaa2711ec3e2397 Mon Sep 17 00:00:00 2001 From: maxsedegov Date: Wed, 29 Jan 2025 14:35:26 +0500 Subject: [PATCH 8/9] Update Config.h --- Game/Config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Game/Config.h b/Game/Config.h index de9bbb9..5d87457 100644 --- a/Game/Config.h +++ b/Game/Config.h @@ -8,13 +8,13 @@ using json = nlohmann::json; class Config { public: - Config() // () . + Config() // Оператор () позволяет создать объект без явного вызова конструктора. { reload(); } - // reload() + // Функция reload() перезагружает настройки из конфигурационного файла void reload() - // + // Загрузка данных { std::ifstream fin(project_path + "settings.json"); fin >> config; From ca509e4d6e029fe83a0cac9e6168ddd029d26356 Mon Sep 17 00:00:00 2001 From: maxsedegov Date: Wed, 29 Jan 2025 14:37:11 +0500 Subject: [PATCH 9/9] Update Board.h --- Game/Board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Game/Board.h b/Game/Board.h index 3008e39..e8d867e 100644 --- a/Game/Board.h +++ b/Game/Board.h @@ -15,7 +15,7 @@ #endif using namespace std; -// Board +// Класс Board управляет состоянием игрового поля class Board { public: