#include <iostream>
#include <random>
#include <vector>
class RandomCount
{
public:
using rand_type = unsigned long long;
RandomCount( rand_type lvalue, rand_type rvalue, rand_type count )
{
unsigned long long size = rvalue - lvalue + 1;
std::random_device rd;
std::mt19937_64 rnd(rd());
std::vector<bool> _overlap_check(size);
for (rand_type i = 0; i < count && i < size; i++)
{
do {
rand_type real = rnd() % size + lvalue;
if (!_overlap_check[real - lvalue])
{
m_vec.push_back(real);
_overlap_check[real - lvalue] = true;
break;
}
} while (true);
}
}
inline rand_type operator[](rand_type index) const
{
return m_vec[index];
}
private:
std::vector<rand_type> m_vec;
};
typedef enum MineSweeperType
{
Number=0, /* 0 ~ 9 */
Mine=10,
} MineSweeperType;
typedef enum MineSweeperHide
{
Hide=0,
Shown=1,
} MineSweeperHide;
class MineSweeperBase
{
MineSweeperType* pannel;
MineSweeperHide* hides;
size_t row, column, mines;
public:
MineSweeperBase(size_t row, size_t column, size_t mines)
: row(row), column(column), mines(mines)
{
pannel = new MineSweeperType[row*column];
hides = new MineSweeperHide[row*column];
memset(pannel, 0, sizeof(MineSweeperType)*row*column);
memset(hides, 0, sizeof(MineSweeperHide)*row*column);
RandomCount rc(0, row*column-1, mines);
for ( int i = 0; i < mines; i++ )
pannel[rc[i]] = MineSweeperType::Mine;
for ( int i = 0; i < row; i++ )
for ( int j = 0; j < column; j++ )
if ( pannel[i*column+j] == MineSweeperType::Mine )
for ( int k = i-1; k <= i+1; k++ )
for ( int l = j-1; l <= j+1; l++ )
if ( k >= 0 && k < row && l >= 0 && l < column )
if ( pannel[k*column+l] != MineSweeperType::Mine )
pannel[k*column+l] = (MineSweeperType)(1 + pannel[k*column+l]);
}
bool expand(size_t r, size_t c)
{
if ( pannel[r*row+c] == MineSweeperType::Mine ) return false;
expand_recur(r,c);
return true;
}
void print_pannel(bool force = false)
{
for ( int i = 0; i < row; i++ )
{
for ( int j = 0; j < column; j++ )
{
if ( hides[i*column+j] == MineSweeperHide::Hide && !force )
{std::cout << '@'; continue;}
int p = pannel[(i*column)+j];
if ( p == 0 ) std::cout << '.';
else if ( p == 10 ) std::cout << '*';
else std::cout << p;
}
std::cout << ' ';
}
std::cout << ' ';
}
private:
void expand_recur(size_t r, size_t c)
{
if ( hides[r*column+c] == MineSweeperHide::Shown ) return;
if ( pannel[r*column+c] == MineSweeperType::Mine ) return;
hides[r*column+c] = MineSweeperHide::Shown;
if ( pannel[r*column+c] > 0 )
{
if ( r > 0 && pannel[(r-1)*column+c] == 0 && hides[(r-1)*column+c] == MineSweeperHide::Hide ) expand_recur(r-1,c);
if ( r < row-1 && pannel[(r+1)*column+c] == 0 && hides[(r+1)*column+c] == MineSweeperHide::Hide ) expand_recur(r+1,c);
if ( c > 0 && pannel[r*column+c-1] == 0 && hides[r*column+c-1] == MineSweeperHide::Hide ) expand_recur(r,c-1);
if ( c < column-1 && pannel[r*column+c+1] == 0 && hides[r*column+c+1] == MineSweeperHide::Hide ) expand_recur(r,c+1);
return;
}
if ( r > 0 ) expand_recur(r-1,c);
if ( r < row-1 ) expand_recur(r+1, c);
if ( c > 0 ) expand_recur(r,c-1);
if ( c < column-1 ) expand_recur(r, c+1);
}
};
int main()
{
MineSweeperBase msb(20,60,150);
msb.print_pannel(true);
msb.expand(2,3);
msb.print_pannel();
return 0;
}
댓글 0