From 503ebff62d2cb9e023b82a732f0c60b320f63899 Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Wed, 27 Sep 2023 22:25:49 +0800 Subject: [PATCH] Write Gaussian-Jordan Elimination --- src/include/client.h | 106 +++++++++++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 29 deletions(-) diff --git a/src/include/client.h b/src/include/client.h index b070e7c..dd03218 100644 --- a/src/include/client.h +++ b/src/include/client.h @@ -1,12 +1,14 @@ #ifndef CLIENT_H #define CLIENT_H +#include #include #include #include #include #include #include +#include extern int rows; // The count of rows of the game map extern int columns; // The count of columns of the game map @@ -75,27 +77,11 @@ int map_status[max_size] // And when a block's status is updated from 0 to 1, // it will be pushed into no_mine_block_to_be_clicked /** - * @brief The definition of function PreProcessData() + * @brief The definition of function ProcessSimpleCase() * - * @details This function is designed to preprocess the data of the game map - * immedietly after reading it. - * It will check unknown blocks and use Gaussian Elimination to find if there is - * any block that definitely has no mine or has mine. If there is a block - * definitely has no mine, it will push the block into - * no_mine_block_to_be_clicked. - * Note that if some block is found to be definitely has no mine or has mine, it - * will be marked as known even if it is not clicked. + * @details This function is designed to process the simplest case */ -void PreProcessData() { - using namespace Client; - // scan the game_map and mark clicked block in map_status - for (int i = 0; i < rows; i++) - for (int j = 0; j < columns; j++) - if (game_map[i][j] != '?') { - assert(game_map[i][j] >= '0' && game_map[i][j] <= '8'); - map_status[i][j] = 2; - } - // scan the map and process the simplest case +void ProcessSimpleCase() { for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) if (map_status[i][j] == 2) { @@ -134,20 +120,82 @@ void PreProcessData() { } } } - // find all unkown blocks that are adjacnent to clicked blocks and prepare for - // Gaussian Elimination +} +/** + * @brief The definition of function GenerateEquations() + * + * @details This function is designed to scan the game_map and map_status to + * generate the equations that will be used in Gaussian-Jordan Elimination. + * It returns a vector> equations, where equations[i] is the i th equation. + */ - // start Gaussian Elimination +/** + * @brief The definition of function GaussianJordanElimination() + * @details This function is designed to use Gaussian-Jordan Elimination to + * solve the equations. It returns the processed vector> + * &equations + * @param vector> &equations The equations to be solved + */ +const double eps = 1e-8; +std::vector > &GaussianJordanElimination( + std::vector > &equations) { + using std::abs; + int n = equations.size(), m = equations[0].size(); + assert(n + 1 == m); + for (int i = 0; i < n; i++) { + int pivot = i; + for (int j = i + 1; j < n; j++) + if (abs(equations[j][i]) > abs(equations[pivot][i])) pivot = j; + std::swap(equations[i], equations[pivot]); + if (abs(equations[i][i]) < eps) continue; + const double pivot_value = equations[i][i]; + for (int j = 0; j < n; j++) equations[i][j] /= pivot_value; + for (int j = 0; j < n; j++) + if (j != i) { + const double tmp = equations[j][i]; + for (int k = 0; k < n; k++) equations[j][k] -= tmp * equations[i][k]; + } + } + return equations; +} +/** + * @brief The definition of function PreProcessData() + * + * @details This function is designed to preprocess the data of the game map + * immedietly after reading it. + * It will check unknown blocks and use Gaussian Elimination to find if there + * is any block that definitely has no mine or has mine. If there is a block + * definitely has no mine, it will push the block into + * no_mine_block_to_be_clicked. + * Note that if some block is found to be definitely has no mine or has mine, + * it will be marked as known even if it is not clicked. + */ +void PreProcessData() { + using namespace Client; + // scan the game_map and mark clicked block in map_status + for (int i = 0; i < rows; i++) + for (int j = 0; j < columns; j++) + if (game_map[i][j] != '?') { + assert(game_map[i][j] >= '0' && game_map[i][j] <= '8'); + map_status[i][j] = 2; + } + // scan the map and process the simplest case + ProcessSimpleCase(); + // find all unkown blocks that are adjacnent to clicked blocks and prepare + // for Gaussian-Jordan Elimination. - // interpret the result of Gaussian Elimination,store the result in map_status - // and push the newly found block that definitely has no mine into - // no_mine_block_to_be_clicked + // start Gaussian-Jordan Elimination + + // interpret the result of Gaussian-Jordan Elimination,store the result in + // map_status and push the newly found block that definitely has no mine + // into no_mine_block_to_be_clicked } /** * @brief The definition of function TotalRandomGuess() * - * @details This function is designed to make a total random guess when there is - * no definite none-mine block to be clicked. + * @details This function is designed to make a total random guess when there + * is no definite none-mine block to be clicked. Note that this function is + * just used temporarily before a better algorithm is designed. */ std::pair TotalRandomGuess() { using namespace Client; @@ -175,8 +223,8 @@ std::pair MakeBestGuess() { /** * @brief The definition of function GenerateNextStep() * - * @details This function is designed to generate the next step when playing the - * client's (or player's) role. + * @details This function is designed to generate the next step when playing + * the client's (or player's) role. */ std::pair GenerateNextStep() { using namespace Client;