bug一堆,勿介
//by JesCaim
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
#include <cstring>
using namespace std;
typedef long long ll;
#define M 32
#define random(x) rand()%(x)
char ches[2 * M + 10][M + 10];
char hid[2 * M + 10][M + 10];
bool vis[2 * M + 10][M + 10];
int r, c;
int num;
int cnt = 0;
int cal(char a[][M + 10], int i, int j) {
int cnt = 0;
if (a[i + 1][j] == '*') cnt++;
if (a[i - 1][j] == '*') cnt++;
if (a[i][j + 1] == '*') cnt++;
if (a[i][j - 1] == '*') cnt++;
if (a[i + 1][j + 1] == '*') cnt++;
if (a[i + 1][j - 1] == '*') cnt++;
if (a[i - 1][j + 1] == '*') cnt++;
if (a[i - 1][j - 1] == '*') cnt++;
return cnt;
}
char tras(int n) {
return '0' + n;
}
void print(char a[][M + 10]) {
for (int i = 0; i <= r; i++) {
for (int j = 0; j <= c; j++) {
cout << a[i][j];
}
cout << endl;
}
cout << endl;
}
void print_mine() {
for (int i = 0; i <= r; i++) {
for (int j = 0; j <= c; j++) {
if (ches[i][j] == '*') cout << '*';
else cout << hid[i][j];
}
cout << endl;
}
}
void dfs(int i, int j) { //二维深搜
if (vis[i][j]) return;
else if ((i<1 || i>r) || (j<1 || j>r)) return;
else if (ches[i][j] == '*') return;
else if (hid[i][j] == '@') return;
else if (ches[i][j] >= '0' && ches[i][j] <= '9') {
vis[i][j] = true;
hid[i][j] = ches[i][j];
return;
}
else {
vis[i][j] = true;
hid[i][j] = ches[i][j];
dfs(i + 1, j);
dfs(i - 1, j);
dfs(i, j + 1);
dfs(i, j - 1);
dfs(i + 1, j + 1);
dfs(i + 1, j - 1);
dfs(i - 1, j + 1);
dfs(i - 1, j - 1);
}
}
bool isEmpty(char a[][M + 10]) {
int ct = 0;
for (int i = 1; i <= r; i++)
for (int j = 1; j <= c; j++)
if (a[i][j] != '-') ct++;
if (ct == r * c) return true;
else return false;
}
void done() { //自动标记所有剩余格并结算
for (int i = 1; i <= r; i++)
for (int j = 1; j <= c; j++)
if (hid[i][j] == '-') hid[i][j] = '@';
}
int main() {
printf("/**************说明**************/\n");
printf("首先输入尺寸宽*高,例:16 16 并回车\n");
printf("然后输入埋设雷的数量,例:40 并回车\n");
printf("游戏中有三条指令:\n");
printf("例:click 3 2并回车,指点击第3行第2列格子\n");
printf("例:sign 3 2并回车,指标记第3行第2列格子为雷,标记后显示为@\n");
printf("例:done并回车,指标记剩余所有未显露的格子并结算,游戏结束\n\n\n\n");
srand((int)time(0)); //随机种子
ches[0][0] = ' '; hid[0][0] = ' '; //边缘绘制
for (int i = 1; i <= 64; i++) {
if (i % 5 == 1) ches[0][i] = 'A' + i / 5;
else ches[0][i] = ' ';
}
for (int i = 1; i <= 64; i++) {
if (i % 5 == 1) ches[i][0] = 'A' + i / 5;
else ches[i][0] = ' ';
}
for (int i = 1; i <= 64; i++) {
if (i % 5 == 1) hid[0][i] = 'A' + i / 5;
else hid[0][i] = ' ';
}
for (int i = 1; i <= 64; i++) {
if (i % 5 == 1) hid[i][0] = 'A' + i / 5;
else hid[i][0] = ' ';
}
printf("Enter the size:(MAX 32*32)\n");
cin >> c >> r; //输入尺寸
printf("Enter the number of mine:(MAX 1000,建议数量为size的1/10)\n");
cin >> num; //输入地雷数量
if (num >= r * c) {
printf("Error_number!\n");
return 0;
}
int tmp = num; while (tmp > 0) { //随机设置雷
for (int i = 1; i <= r; i++) {
for (int j = 1; j <= c; j++) {
if (((random(c) + 1) == 2) && (ches[i][j] != '*') & tmp != 0) {
ches[i][j] = '*';
tmp--;
}
else if (ches[i][j] != '*') ches[i][j] = '.';
if (tmp == 0) continue;
}
}
}
for (int i = 1; i <= r; i++) { //设置数字
for (int j = 1; j <= c; j++) {
if (cal(ches, i, j) != 0 && ches[i][j] != '*') ches[i][j] = tras(cal(ches, i, j));
}
}
for (int i = 1; i <= r; i++) //绘制隐藏面
for (int j = 1; j <= c; j++) {
hid[i][j] = '-';
}
//print(ches);
bool temp = true;
for (int i = 1; i <= r; i++) //开始时打开一块区域
for (int j = 1; j <= c; j++) {
if (temp && ches[i][j] == '.') {
temp = false;
memset(vis, false, sizeof(vis));
dfs(i, j);
}
}
while (1) {
if (isEmpty(hid)) { //全部显露后开始结算
for (int i = 1; i <= r; i++) {
for (int j = 1; j <= c; j++) {
if (ches[i][j] == '*') {
if (hid[i][j] != '@') {
print_mine();
printf("---------------------------------------------------------------\n");
printf("*****You Lose!*****\n");
system("pause");
return 0;
}
}
else {
if (hid[i][j] == '@') {
print_mine();
printf("---------------------------------------------------------------\n");
printf("*****You Lose!*****\n");
system("pause");
return 0;
}
}
}
}
print(hid);
printf("---------------------------------------------------------------\n");
printf("\n*****YOU WIN!*****\n");
system("pause");
return 0;
}
printf("---------------------------------------------------------------\n");
printf("\n********剩余:%d********\n\n",num-cnt);
print(hid);
printf("点击:click r c\n");
printf("标记雷:sign r c\n");
printf("标记所有剩余格:done\n");
printf("Please enter your command:\n");
string cmd; int row, col;
cin >> cmd;
if (cmd == "done") {
done();
continue;
}
else {
cin >> row >> col;
if (cmd == "click") {
if (hid[row][col] != '-') { //无效点击已标记或已显露部分,跳过
printf("Invalid click!\n");
continue;
}
else if (ches[row][col] == '*') { //踩雷,展示剩余雷,游戏结束
print_mine();
printf("---------------------------------------------------------------\n");
printf("*****You Lose!*****\n");
system("pause");
return 0;
}
else { //非踩雷,深搜
memset(vis, false, sizeof(vis));
dfs(row, col);
}
}
else if (cmd == "sign") { //标记地雷
hid[row][col] = '@';
cnt++;
}
else
printf("Error_command!\n");
}
}
system("pause");
return 0;
}