Write Gaussian-Jordan Elimination
This commit is contained in:
@ -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;
|
||||||
|
Reference in New Issue
Block a user