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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment