Skip to content

Instantly share code, notes, and snippets.

@Leask
Last active August 23, 2017 12:11
Show Gist options
  • Save Leask/c11ee24147496504fc6475020bfc0823 to your computer and use it in GitHub Desktop.
Save Leask/c11ee24147496504fc6475020bfc0823 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <vector>
#include <set>
#include <sstream>
using namespace std;
struct Node {
int x;
int y;
bool isBomb;
bool marked;
bool revealed;
};
struct Game {
int width;
int height;
int bombCount;
vector< vector< Node > > nodes;
};
Game *game;
string toString(const int value) {
std::ostringstream oss;
oss << value;
return oss.str();
}
int fromString(const string* str) {
istringstream ss(*str);
int i;
ss >> i;
return i;
}
void clearScreen() {
cout << "\x1B[2J\x1B[H";
}
int aroundBombs(Node* node) {
int x = node->x;
int y = node->y;
bool isTop = y == 0;
bool isBottom = y == game->height - 1;
bool isLeft = x == 0;
bool isRight = x == game->width - 1;
int count = 0;
if (!isTop) {
count += game->nodes[y - 1][x].isBomb ? 1 : 0;
if (!isLeft) {
count += game->nodes[y - 1][x - 1].isBomb ? 1 : 0;
}
if (!isRight) {
count += game->nodes[y - 1][x + 1].isBomb ? 1 : 0;
}
}
if (!isBottom) {
count += game->nodes[y + 1][x].isBomb ? 1 : 0;
if (!isLeft) {
count += game->nodes[y + 1][x - 1].isBomb ? 1 : 0;
}
if (!isRight) {
count += game->nodes[y + 1][x + 1].isBomb ? 1 : 0;
}
}
if (!isLeft) {
count += game->nodes[y][x - 1].isBomb ? 1 : 0;
}
if (!isRight) {
count += game->nodes[y][x + 1].isBomb ? 1 : 0;
}
return count;
}
int remainBombs() {
int count = game->bombCount;
for (int i = 0; i < game->nodes.size(); i++) {
for (int j = 0; j < game->nodes[i].size(); j++) {
if (game->nodes[i][j].marked) {
count --;
}
}
}
if (count < 0) count = 0;
return count;
}
void render() {
clearScreen();
cout << "\nWelcome to Mattsweeper!\n";
cout << "\nYou have " << remainBombs() << " bombs still to find\n\n";
// Header row numbers
cout << "  ";
for (int i = 0; i < game->width; i++) {
cout << " " << i;
}
// Header row dashs
cout << endl << "  ";
for (int i = 0; i < game->width; i++) {
cout << " " << '-';
}
for (int row = 0; row < game->height; row++) {
cout << endl << row << " ";
for (int i = 0; i <= game->width; i++) {
cout << "| ";
if (i == game->width) {
continue;
}
Node node = game->nodes[row][i];
if (node.marked) {
cout << 'M';
} else if (node.revealed && node.isBomb) {
cout << 'X';
} else if (node.revealed) {
int count = aroundBombs(&node);
cout << count;
} else {
cout << ' ';
}
cout << ' ';
}
cout << endl << "  ";
for (int i = 0; i < game->width; i++) {
cout << " " << '-';
}
}
cout << endl;
}
void func1(Node node) {
node.x = 1;
}
void func2(Node *node) {
node->x = 2;
}
void initNodes() {
int width = game->width;
int height = game->height;
set<string> randoms;
while (randoms.size() < game->bombCount) {
ostringstream s;
s << rand() % width;
s << "," << rand() % height;
string point = s.str();
randoms.insert(point);
}
// Init two dimen vector
vector<vector <Node> > ivec(height, vector<Node>(width));
for (int row = 0; row < height; row++) {
int random = rand() % width;
for (int column = 0; column < width; column++) {
Node node;
node.x = column;
node.y = row;
node.revealed = false;
node.marked = false;
ostringstream s;
s << column;
s << "," << row;
string point = s.str();
if (randoms.find(point) != randoms.end()) {
node.isBomb = true;
} else {
node.isBomb = false;
}
ivec[row][column] = node;
}
}
game->nodes = ivec;
}
template<typename Out>
void split(const string &s, char delim, Out result) {
stringstream ss;
ss.str(s);
string item;
while (getline(ss, item, delim)) {
*(result++) = item;
}
}
vector<string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
bool isWon() {
int nodeCount = game->width * game->height;
int revealedCount = 0;
int markedCount = 0;
int markedBoomCount = 0;
for (int i = 0; i < game->nodes.size(); i++) {
for (int j = 0; j < game->nodes[i].size(); j++) {
Node *node = &game->nodes[i][j];
if (node->revealed) {
revealedCount++;
}
if (node->marked) {
markedCount++;
}
if (node->marked && node->isBomb) {
markedBoomCount++;
}
}
}
if (markedBoomCount == markedCount && markedCount == game->bombCount) {
return true;
}
if (markedCount == markedBoomCount && revealedCount + game->bombCount == nodeCount) {
return true;
}
return false;
}
void revealAll() {
for (int i = 0; i < game->nodes.size(); i++) {
for (int j = 0; j < game->nodes[i].size(); j++) {
Node *node = &game->nodes[i][j];
node->revealed = true;
}
}
}
int main() {
game = new Game();
game->width = 5;
game->height = 10;
game->bombCount = 10;
initNodes();
render();
while (true) {
cout << "Select a point, X,Y: ";
string input = "";
getline(cin, input);
vector<string> eles = split(input, ',');
if (eles.size() != 2) {
cout << "Invalid point: " << input << endl;
getline(cin, input);
continue;
}
render();
int x = fromString(&eles[0]);
int y = fromString(&eles[1]);
if (x >= game->width || x < 0) {
cout << "X is out of bound, Press enter to retry";
getline(cin, input);
continue;
}
if (y >= game->height || y < 0) {
cout << "Y is out of bound, Press enter to retry";
getline(cin, input);
continue;
}
bool valid = false;
do {
cout << "What would you like to do? (r)eveal, (m)ark: ";
getline(cin, input);
valid = input == "r" || input == "m";
if (!valid) {
cout << "Invalid action!" << endl;
}
} while (!valid);
Node *node = &game->nodes[y][x];
if (input == "r") {
node->revealed = true;
} else {
node->marked = true;
}
if (node->isBomb && input == "r") {
revealAll();
render();
cout << "BOOM! You Lose\n";
exit(1);
}
if (isWon()) {
revealAll();
cout << "Congratulation! You WON!\n";
exit(0);
}
render();
}
// for (int i = 0; i < game->nodes.size(); i++) {
// for (int j = 0; j < game->nodes[i].size(); j++) {
// Node node = game->nodes[i][j];
// cout << node.x << ',' << node.y << "," << (node.isBomb ? 'X' : ' ') << '\t';
// }
// cout << endl;
// }
// cout << aroundBombs(&game->nodes[1][2]);
delete game;
return 0;
}
Display the source blob
Display the rendered blob
Raw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment