用c++写的扫雷
所需要的头文件:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <windows.h>
#include <limits>
using namespace std;
游戏各项参数:
// 默认的游戏参数
int WIDTH = 10; // 棋盘宽度
int HEIGHT = 10; // 棋盘高度
int MINES = 10; // 地雷数量
enum Cell {
HIDDEN,
REVEALED,
MARKED
};
struct BoardCell {
int mineCount;
Cell state;
bool isMine;
BoardCell() : mineCount(0), state(HIDDEN), isMine(false) {}
};
游戏类:
class Minesweeper {
public:
Minesweeper(int width, int height, int mines) : WIDTH(width), HEIGHT(height), MINES(mines) {
board.resize(HEIGHT, vector<BoardCell>(WIDTH));
placeMines();
calculateMineCounts();
}
void displayBoard(bool revealMines = false) {
cout << " ";
for (int x = 0; x < WIDTH; x++) {
cout << x << " ";
}
cout << endl;
for (int i = 0; i < HEIGHT; ++i) {
cout << ' ' << i << " ";
for (int j = 0; j < WIDTH; ++j) {
printCell(board[i][j], revealMines);
}
cout << endl << endl;
}
}
void revealCell(int x, int y) {
if (isOutOfBounds(x, y) || board[y][x].state != HIDDEN) {
return;
}
board[y][x].state = REVEALED;
if (board[y][x].isMine) {
gameOver();
return;
}
if (board[y][x].mineCount == 0) {
// 递归揭示周围的单元格
for (int dy = -1; dy <= 1; ++dy) {
for (int dx = -1; dx <= 1; ++dx) {
revealCell(x + dx, y + dy);
}
}
}
checkVictory(); // 检查是否胜利
}
void markCell(int x, int y) {
if (isOutOfBounds(x, y) || board[y][x].state != HIDDEN) {
return;
}
board[y][x].state = MARKED;
}
void unmarkCell(int x, int y) {
if (isOutOfBounds(x, y) || board[y][x].state != MARKED) {
return;
}
board[y][x].state = HIDDEN;
}
private:
int WIDTH;
int HEIGHT;
int MINES;
vector<vector<BoardCell>> board;
void placeMines() {
int placedMines = 0;
while (placedMines < MINES) {
int x = rand() % WIDTH;
int y = rand() % HEIGHT;
if (!board[y][x].isMine) {
board[y][x].isMine = true;
placedMines++;
}
}
}
void calculateMineCounts() {
for (int y = 0; y < HEIGHT; ++y) {
for (int x = 0; x < WIDTH; ++x) {
if (board[y][x].isMine) {
continue;
}
int count = 0;
for (int dy = -1; dy <= 1; ++dy) {
for (int dx = -1; dx <= 1; ++dx) {
if (isOutOfBounds(x + dx, y + dy)) {
continue;
}
if (board[y + dy][x + dx].isMine) {
count++;
}
}
}
board[y][x].mineCount = count;
}
}
}
bool isOutOfBounds(int x, int y) {
return (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT);
}
void gameOver() {
system("cls");
cout << "Game Over! You hit a mine!" << endl;
displayBoard(true);
offerRestart();
system("cls");
}
void checkVictory() {
int revealedCells = 0;
int nonMineCells = WIDTH * HEIGHT - MINES;
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
if (board[y][x].state == REVEALED) {
revealedCells++;
}
}
}
if (revealedCells == nonMineCells) {
system("cls");
cout << "Congratulations! You've revealed all cells without hitting a mine!" << endl;
displayBoard(true);
offerRestart();
}
}
void offerRestart() {
char response;
system("cls");
cout << "再来一次? (y/n): ";
cin >> response;
if (response == 'y' || response == 'Y') {
cout << "选择难度 (1 - 简单, 2 - 中等, 3 - 困难): ";
int difficulty;
cin >> difficulty;
setDifficulty(difficulty);
resetGame(); system("cls");
} else {
cout << "Thank you for playing!" << endl;
exit(0);
}
}
void resetGame() {
board.clear();
board.resize(HEIGHT, vector<BoardCell>(WIDTH));
placeMines();
calculateMineCounts();
}
void setDifficulty(int level) {
switch (level) {
case 1: // Easy
WIDTH = 8;
HEIGHT = 8;
MINES = 10;
break;
case 2: // Medium
WIDTH = 12;
HEIGHT = 12;
MINES = 30;
break;
case 3: // Hard
WIDTH = 16;
HEIGHT = 16;
MINES = 40;
break;
default:
WIDTH = 10;
HEIGHT = 10;
MINES = 10;
break;
}
}
void printCell(const BoardCell& cell, bool revealMines) {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (cell.state == HIDDEN) {
SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
cout << "+ ";
} else if (cell.state == REVEALED) {
if (cell.isMine) {
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
cout << "* "; // 地雷
} else {
if (cell.mineCount == 0) {
cout << " "; // 空白
} else {
cout << cell.mineCount << " "; // 显示周围地雷的数量
}
}
} else if (cell.state == MARKED) {
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
cout << "o "; // 标记
}
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
};
主函数:
int main() {
system("cls");
cout << "扫雷游戏!" << endl;
// 选择难度
cout << "选择难度 (1 - 简单, 2 - 中等, 3 - 困难): "<<endl<<"请输入:";
int difficulty;
cin >> difficulty;
system("cls");
int width, height, mines;
switch (difficulty) {
case 1: // Easy
width = 8; height = 8; mines = 10; break;
case 2: // Medium
width = 12; height = 12; mines = 30; break;
case 3: // Hard
width = 16; height = 16; mines = 40; break;
default:
width = 10; height = 10; mines = 10; break;
}
Minesweeper game(width, height, mines);
while (true) {
cout << "棋盘:" << endl << endl;
game.displayBoard();
cout << "输入 x y 去揭示格子,或 o x y 标注格子,q x y 去掉标注:";
string command;
cin >> command;
if (command == "o") {
int x, y;
cin >> x >> y;
game.markCell(x, y);
}
else if (command == "q") {
int x, y;
cin >> x >> y;
game.unmarkCell(x, y);
}
else {
try {
int x = stoi(command);
int y;
cin >> y;
game.revealCell(y, x);
} catch (const invalid_argument&) {
cout << "Invalid input, please enter valid coordinates." << endl;
cin.clear(); // Clear error flag
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // Clear input buffer
} catch (const out_of_range&) {
cout << "Input out of range, please enter valid coordinates." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
system("cls");
}
return 0;
}
最终代码:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <windows.h>
#include <limits>
using namespace std;
// 默认的游戏参数
int WIDTH = 10; // 棋盘宽度
int HEIGHT = 10; // 棋盘高度
int MINES = 10; // 地雷数量
enum Cell {
HIDDEN,
REVEALED,
MARKED
};
struct BoardCell {
int mineCount;
Cell state;
bool isMine;
BoardCell() : mineCount(0), state(HIDDEN), isMine(false) {}
};
class Minesweeper {
public:
Minesweeper(int width, int height, int mines) : WIDTH(width), HEIGHT(height), MINES(mines) {
board.resize(HEIGHT, vector<BoardCell>(WIDTH));
placeMines();
calculateMineCounts();
}
void displayBoard(bool revealMines = false) {
cout << " ";
for (int x = 0; x < WIDTH; x++) {
cout << x << " ";
}
cout << endl;
for (int i = 0; i < HEIGHT; ++i) {
cout << ' ' << i << " ";
for (int j = 0; j < WIDTH; ++j) {
printCell(board[i][j], revealMines);
}
cout << endl << endl;
}
}
void revealCell(int x, int y) {
if (isOutOfBounds(x, y) || board[y][x].state != HIDDEN) {
return;
}
board[y][x].state = REVEALED;
if (board[y][x].isMine) {
gameOver();
return;
}
if (board[y][x].mineCount == 0) {
// 递归揭示周围的单元格
for (int dy = -1; dy <= 1; ++dy) {
for (int dx = -1; dx <= 1; ++dx) {
revealCell(x + dx, y + dy);
}
}
}
checkVictory(); // 检查是否胜利
}
void markCell(int x, int y) {
if (isOutOfBounds(x, y) || board[y][x].state != HIDDEN) {
return;
}
board[y][x].state = MARKED;
}
void unmarkCell(int x, int y) {
if (isOutOfBounds(x, y) || board[y][x].state != MARKED) {
return;
}
board[y][x].state = HIDDEN;
}
private:
int WIDTH;
int HEIGHT;
int MINES;
vector<vector<BoardCell>> board;
void placeMines() {
int placedMines = 0;
while (placedMines < MINES) {
int x = rand() % WIDTH;
int y = rand() % HEIGHT;
if (!board[y][x].isMine) {
board[y][x].isMine = true;
placedMines++;
}
}
}
void calculateMineCounts() {
for (int y = 0; y < HEIGHT; ++y) {
for (int x = 0; x < WIDTH; ++x) {
if (board[y][x].isMine) {
continue;
}
int count = 0;
for (int dy = -1; dy <= 1; ++dy) {
for (int dx = -1; dx <= 1; ++dx) {
if (isOutOfBounds(x + dx, y + dy)) {
continue;
}
if (board[y + dy][x + dx].isMine) {
count++;
}
}
}
board[y][x].mineCount = count;
}
}
}
bool isOutOfBounds(int x, int y) {
return (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT);
}
void gameOver() {
system("cls");
cout << "Game Over! You hit a mine!" << endl;
displayBoard(true);
offerRestart();
system("cls");
}
void checkVictory() {
int revealedCells = 0;
int nonMineCells = WIDTH * HEIGHT - MINES;
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
if (board[y][x].state == REVEALED) {
revealedCells++;
}
}
}
if (revealedCells == nonMineCells) {
system("cls");
cout << "Congratulations! You've revealed all cells without hitting a mine!" << endl;
displayBoard(true);
offerRestart();
}
}
void offerRestart() {
char response;
system("cls");
cout << "再来一次? (y/n): ";
cin >> response;
if (response == 'y' || response == 'Y') {
cout << "选择难度 (1 - 简单, 2 - 中等, 3 - 困难): ";
int difficulty;
cin >> difficulty;
setDifficulty(difficulty);
resetGame(); system("cls");
} else {
cout << "Thank you for playing!" << endl;
exit(0);
}
}
void resetGame() {
board.clear();
board.resize(HEIGHT, vector<BoardCell>(WIDTH));
placeMines();
calculateMineCounts();
}
void setDifficulty(int level) {
switch (level) {
case 1: // Easy
WIDTH = 8;
HEIGHT = 8;
MINES = 10;
break;
case 2: // Medium
WIDTH = 12;
HEIGHT = 12;
MINES = 30;
break;
case 3: // Hard
WIDTH = 16;
HEIGHT = 16;
MINES = 40;
break;
default:
WIDTH = 10;
HEIGHT = 10;
MINES = 10;
break;
}
}
void printCell(const BoardCell& cell, bool revealMines) {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (cell.state == HIDDEN) {
SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
cout << "+ ";
} else if (cell.state == REVEALED) {
if (cell.isMine) {
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
cout << "* "; // 地雷
} else {
if (cell.mineCount == 0) {
cout << " "; // 空白
} else {
cout << cell.mineCount << " "; // 显示周围地雷的数量
}
}
} else if (cell.state == MARKED) {
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
cout << "o "; // 标记
}
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
};
int main() {
system("cls");
cout << "扫雷游戏!" << endl;
// 选择难度
cout << "选择难度 (1 - 简单, 2 - 中等, 3 - 困难): "<<endl<<"请输入:";
int difficulty;
cin >> difficulty;
system("cls");
int width, height, mines;
switch (difficulty) {
case 1: // Easy
width = 8; height = 8; mines = 10; break;
case 2: // Medium
width = 12; height = 12; mines = 30; break;
case 3: // Hard
width = 16; height = 16; mines = 40; break;
default:
width = 10; height = 10; mines = 10; break;
}
Minesweeper game(width, height, mines);
while (true) {
cout << "棋盘:" << endl << endl;
game.displayBoard();
cout << "输入 x y 去揭示格子,或 o x y 标注格子,q x y 去掉标注:";
string command;
cin >> command;
if (command == "o") {
int x, y;
cin >> x >> y;
game.markCell(x, y);
}
else if (command == "q") {
int x, y;
cin >> x >> y;
game.unmarkCell(x, y);
}
else {
try {
int x = stoi(command);
int y;
cin >> y;
game.revealCell(y, x);
} catch (const invalid_argument&) {
cout << "Invalid input, please enter valid coordinates." << endl;
cin.clear(); // Clear error flag
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // Clear input buffer
} catch (const out_of_range&) {
cout << "Input out of range, please enter valid coordinates." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
system("cls");
}
return 0;
}