Write Gaussian-Jordan Elimination

This commit is contained in:
2023-09-27 22:25:49 +08:00
parent 679a5fb694
commit 503ebff62d

View File

@ -1,12 +1,14 @@
#ifndef CLIENT_H #ifndef CLIENT_H
#define CLIENT_H #define CLIENT_H
#include <algorithm>
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <queue> #include <queue>
#include <random> #include <random>
#include <utility> #include <utility>
#include <vector>
extern int rows; // The count of rows of the game map extern int rows; // The count of rows of the game map
extern int columns; // The count of columns 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, // And when a block's status is updated from 0 to 1,
// it will be pushed into no_mine_block_to_be_clicked // 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 * @details This function is designed to process the simplest case
* 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() { void ProcessSimpleCase() {
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
for (int i = 0; i < rows; i++) for (int i = 0; i < rows; i++)
for (int j = 0; j < columns; j++) for (int j = 0; j < columns; j++)
if (map_status[i][j] == 2) { 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<vector<double>> 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<vector<double>>
* &equations
* @param vector<vector<double>> &equations The equations to be solved
*/
const double eps = 1e-8;
std::vector<std::vector<double> > &GaussianJordanElimination(
std::vector<std::vector<double> > &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 // start Gaussian-Jordan Elimination
// and push the newly found block that definitely has no mine into
// no_mine_block_to_be_clicked // 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() * @brief The definition of function TotalRandomGuess()
* *
* @details This function is designed to make a total random guess when there is * @details This function is designed to make a total random guess when there
* no definite none-mine block to be clicked. * 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<int, int> TotalRandomGuess() { std::pair<int, int> TotalRandomGuess() {
using namespace Client; using namespace Client;
@ -175,8 +223,8 @@ std::pair<int, int> MakeBestGuess() {
/** /**
* @brief The definition of function GenerateNextStep() * @brief The definition of function GenerateNextStep()
* *
* @details This function is designed to generate the next step when playing the * @details This function is designed to generate the next step when playing
* client's (or player's) role. * the client's (or player's) role.
*/ */
std::pair<int, int> GenerateNextStep() { std::pair<int, int> GenerateNextStep() {
using namespace Client; using namespace Client;