Skip to content

Commit e7c2145

Browse files
author
¨Sayan
committed
first commit
1 parent 8000663 commit e7c2145

File tree

2 files changed

+261
-0
lines changed

2 files changed

+261
-0
lines changed

minesweeper.cpp

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
#include "minesweeper.hpp"
2+
#include <algorithm>
3+
#include <numeric>
4+
#include <iostream>
5+
#include <iterator>
6+
7+
struct RNG {
8+
int operator() (int n) {
9+
return std::rand() / (1.0 + RAND_MAX) * n;
10+
}
11+
};
12+
13+
using std::cout, std::cin, std::endl;
14+
Minesweeper::Minesweeper(int _numRows, int _numColumns, int _numMines){
15+
16+
numRows = _numRows;
17+
numColumns = _numColumns;
18+
numMines = _numMines;
19+
int totalBlocks = numRows*numColumns;
20+
21+
//randomly set-up mines
22+
std::vector<int> temp(totalBlocks);
23+
std::iota(temp.begin(), temp.end(), 1);
24+
std::srand(2904);
25+
std::random_shuffle(temp.begin(), temp.end(), RNG());
26+
27+
//set-up locations
28+
for (int i=0; i < numRows; i++){
29+
for (int j=0; j < numColumns; j++){
30+
int linearIndex = i*numColumns + j;
31+
location currLocation;
32+
currLocation.rowIndex = i;
33+
currLocation.columnIndex = j;
34+
currLocation.isOpen = false;
35+
currLocation.isMarkedBomb = false;
36+
currLocation.isMarkedDoubt = false;
37+
38+
//assign mines
39+
temp.erase(temp.begin()+numMines, temp.end());
40+
std::vector<int>::iterator it = find(temp.begin(), temp.end(), linearIndex);
41+
if (it != temp.end())
42+
currLocation.isMine = true;
43+
else
44+
currLocation.isMine = false;
45+
46+
locations.push_back(currLocation);
47+
}
48+
}
49+
}
50+
51+
int Minesweeper::countMinesAround(const location &loc) const {
52+
53+
int numMinesAround = 0;
54+
int rowIndex = loc.rowIndex;
55+
int columnIndex = loc.columnIndex;
56+
57+
for (int i = -1; i <= 1; i++){
58+
for (int j = -1; j <= 1; j++){
59+
int neighborRowIndex = rowIndex-i;
60+
int neighborColumnIndex = columnIndex-j;
61+
if ((neighborRowIndex < 0) || (neighborRowIndex >= numRows) || (neighborColumnIndex < 0) || (neighborColumnIndex >= numColumns))
62+
continue;
63+
else{
64+
int neighborLinearIndex = (rowIndex-i)*numColumns + (columnIndex-j);
65+
if ((i == 0) && (j == 0))
66+
continue;
67+
else if (locations[neighborLinearIndex].isMine) numMinesAround++;
68+
}
69+
}
70+
}
71+
return numMinesAround;
72+
}
73+
74+
void Minesweeper::openLocation(location &loc){
75+
76+
if (loc.isOpen || loc.isMarkedBomb || loc.isMarkedDoubt)
77+
return;
78+
else{
79+
int minesAround = countMinesAround(loc);
80+
loc.isOpen = true;
81+
int rowIndex = loc.rowIndex;
82+
int columnIndex = loc.columnIndex;
83+
84+
if (minesAround == 0){
85+
for (int i = -1; i <= 1; i++){
86+
for (int j = -1; j <= 1; j++){
87+
int neighborRowIndex = rowIndex-i;
88+
int neighborColumnIndex = columnIndex-j;
89+
int neighborLinearIndex = neighborRowIndex*numColumns + neighborColumnIndex;
90+
if ((neighborRowIndex < 0)
91+
|| (neighborRowIndex >= numRows)
92+
|| (neighborColumnIndex < 0)
93+
|| (neighborColumnIndex >= numColumns)
94+
|| ((i == 0) && (j == 0)))
95+
continue;
96+
else
97+
openLocation(locations[neighborLinearIndex]);
98+
}
99+
}
100+
}
101+
else
102+
return;
103+
}
104+
}
105+
106+
bool Minesweeper::onlyMinesLeft() const{
107+
return (std::all_of(locations.cbegin(), locations.cend(),
108+
[](const location &loc) {
109+
return (loc.isOpen || loc.isMarkedBomb);
110+
}));
111+
}
112+
113+
void Minesweeper::displayBoard() const{
114+
115+
cout << " ";
116+
for (int i=0; i < numColumns; i++)
117+
cout << i << " ";
118+
cout << endl;
119+
for (int i=0; i < numRows; i++){
120+
cout << i << " ";
121+
for (int j=0; j < numColumns; j++){
122+
int linearIndex = i*numColumns + j;
123+
location loc = locations[linearIndex];
124+
int minesAround = countMinesAround(loc);
125+
if ((!loc.isOpen) && (!loc.isMarkedBomb) && (!loc.isMarkedDoubt))
126+
cout << "\u25A0 ";
127+
else if (loc.isMarkedDoubt) cout << "x ";
128+
else if (loc.isMarkedBomb) cout << "\u25CF ";
129+
else if (minesAround == 0) { cout << "\u25A1 "; }
130+
else { cout << minesAround << " "; }
131+
}
132+
cout << endl;
133+
}
134+
cout << endl;
135+
}
136+
137+
void Minesweeper::displayAll() const{
138+
139+
cout << " ";
140+
for (int i=0; i < numColumns; i++)
141+
cout << i << " ";
142+
cout << endl;
143+
for (int i=0; i < numRows; i++){
144+
cout << i << " ";
145+
for (int j=0; j < numColumns; j++){
146+
int linearIndex = i*numColumns + j;
147+
location loc = locations[linearIndex];
148+
if (loc.isMine) cout << "\u2639 ";
149+
else cout << "\u25A1 ";
150+
}
151+
cout << endl;
152+
}
153+
cout << endl;
154+
}
155+
156+
void Minesweeper::markAsDoubt(const int x, const int y){
157+
if (!locations[x*numRows +y].isOpen)
158+
locations[x*numRows + y].isMarkedDoubt = true;
159+
}
160+
void Minesweeper::markAsBomb(const int x, const int y){
161+
if (!locations[x*numRows +y].isOpen)
162+
locations[x*numRows + y].isMarkedBomb = true;
163+
}
164+
void Minesweeper::unmarkLocation(const int x, const int y){
165+
if (locations[x*numRows +y].isMarkedDoubt || locations[x*numRows +y].isMarkedBomb){
166+
locations[x*numRows + y].isMarkedDoubt = false;
167+
locations[x*numRows +y].isMarkedBomb = false;
168+
}
169+
}
170+
171+
int main(){
172+
int rows, columns, mines;
173+
cout << "Enter No. of Rows: ";
174+
cin >> rows;
175+
176+
cout << "Enter No. of Columns: ";
177+
cin >> columns;
178+
179+
cout << "Enter No. of Mines: ";
180+
cin >> mines;
181+
182+
Minesweeper game(rows,columns,mines);
183+
std::system("clear");
184+
185+
int x,y;
186+
char mark;
187+
while (true){
188+
game.displayBoard();
189+
cout << "Enter (S,x,y) location to open;\n (M,x,y) to mark as Doubt;\n (B,x,y) to mark as Bomb;\n (U,x,y) to unmark" << endl;
190+
cin >> mark >> x >> y;
191+
if (!game.isValidLocation(x, y)){
192+
std::system("clear");
193+
continue;
194+
}
195+
if (game.locationIsMine(x,y) && (mark == 's')){
196+
std::system("clear");
197+
cout << "Busted" << endl;
198+
game.displayAll();
199+
break;
200+
}
201+
else{
202+
std::system("clear");
203+
if (mark == 'm')
204+
game.markAsDoubt(x,y);
205+
else if (mark == 'u')
206+
game.unmarkLocation(x,y);
207+
else if (mark == 'b')
208+
game.markAsBomb(x,y);
209+
else
210+
game.openLocation(x,y);
211+
cout << endl;
212+
if (game.onlyMinesLeft()){
213+
cout << "Congratualtions! You Won." << endl;
214+
game.displayBoard();
215+
game.displayAll();
216+
break;
217+
}
218+
}
219+
}
220+
}
221+

minesweeper.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
#include <vector>
3+
4+
class Minesweeper{
5+
private:
6+
int numRows;
7+
int numColumns;
8+
int numMines;
9+
10+
struct location{
11+
int rowIndex;
12+
int columnIndex;
13+
bool isMine;
14+
bool isOpen;
15+
bool isMarkedDoubt;
16+
bool isMarkedBomb;
17+
};
18+
19+
std::vector<location> locations;
20+
21+
public:
22+
Minesweeper(int numRows, int numColumns, int numMines);
23+
24+
void displayBoard() const;
25+
void displayAll() const;
26+
27+
void openLocation(location &loc);
28+
void openLocation(const int x, const int y) { openLocation(locations[x*numRows + y]); }
29+
30+
void markAsDoubt(const int x, const int y);
31+
void markAsBomb(const int x, const int y);
32+
void unmarkLocation(const int x, const int y);
33+
34+
int countMinesAround(const location &loc) const;
35+
bool onlyMinesLeft() const;
36+
bool locationIsMine(int x, int y) const{ return locations[x*numRows + y].isMine; }
37+
38+
bool isValidLocation(int x, int y) const { return ((x < numRows) && (x >= 0) && (y < numColumns) && (y >= 0)) ? true : false; }
39+
};
40+

0 commit comments

Comments
 (0)