头文件 “minesweeping.h”
#ifndef _MINESWEEPING_H_
#include <stdio.h>
#define line 9//行数
#define rank 9//列数
#define mines 10//雷数
void menu();
void initboundary(int line1,int rank1);
void play();
void setmines(char playing[line+2][rank+2],int line2,int rank2,int mines2);
void firstplay(char playing[line + 2][rank + 2],int line3,int rank3,int x,int y);
void nextplay();
void setmathboundary(int strench[line + 2][rank + 2], int sum1[line + 2][rank + 2], int x, int y, int line6, int rank6);
void putmathboundary(int sum1[line + 2][rank + 2], int line7, int rank7,int x,int y);
char playing[line][rank] ;
int strench[line+2][rank+2];
int sum1[line + 2][rank + 2];//展开给玩家看死法的矩阵
void convert(int strench[line + 2][rank + 2], char playing[line][rank], int line4, int rank4);
//放雷的矩阵
#endif
game.c
#include "minesweeping.h"
void menu()
{
printf("*************************\n");
printf("*********请选择:*********\n");
printf("*********1.play**********\n");
printf("*********0.exit**********\n");
}
void initboundary(int line1,int rank1)
{
int i = 0; int j = 0;
for (i = 0; i < line1; i++)
{
for (j = 0; j < rank1; j++)
printf("___|");
printf("\n");
}
}
void setmines(char playing[line ][rank ], int line2, int rank2, int mines2)//随机数放雷
{
int x = 0; int y = 0;
while (mines2)
{
while (1)
{
x = (rand()) % line2;
y = (rand()) % rank2;
if (playing[x][y] != '*') { playing[x][y] = '*'; mines2--; break; }
}
}
}
void resetmine(char playing[line ][rank ], int line5,int rank5,int x,int y)
{
int e = 0; int f = 0;
while (1)
{
e = (rand()) % line5;
f = (rand()) % rank5;
if (playing[e][f] != '*'&&e!=x-1&&f!=y-1) { playing[e][f] = '*'; break; }
}
}
void firstplay(char playing[line ][rank], int line3, int rank3,int x,int y)
{
int i = 0; int j = 0;
if (playing[x - 1][y - 1] == '*') { playing[x - 1][y - 1] = '\0'; resetmine(playing, line, rank, x, y); }
}//如果点开的第一个是雷,偷偷移走,重新放这个雷。
void convert(int strench[line+2][rank+2],char playing[line][rank], int line4, int rank4)
{
int i = 0; int j = 0;
for (i = 0; i < line; i++)
{
for (j = 0; j < rank; j++)
{
if (playing[i][j] == '*') strench[i + 1][j + 1] = 1;
else strench[i + 1][j + 1] = 0;
}
}
for (j = 0; j < rank; j++) strench[0][j] = 0;
for (i = 0; i < line; i++) strench[i][0] = 0;
}
void setmathboundary(int strench[line + 2][rank + 2],int sum1[line+2][rank+2],int x, int y, int line6, int rank6)
{
int i = 0; int j = 0;
//if (strench[x ][y - 1] + strench[x ][y+1] + strench[x - 1][y] + strench[x+1][y ] + strench[x - 1][y - 1] + strench[x+1][y - 1] + strench[x - 1][y+1] + strench[x+1][y+1]!=0)
sum1[x][y] = strench[x][y -1] + strench[x][y+1] + strench[x -1][y] + strench[x+1][y] + strench[x-1][y -1] + strench[x+1][y -1] + strench[x - 1][y+1] + strench[x+1][y+1];
//else sum1[x][y] =8;
//printf("sum\n");
//for (i = 0; i < line + 2; i++)
//{
// for (j = 0; j < rank + 2; j++)
// printf("%d", sum1[i][j]);
// printf("\n");
//}
/*setmathboundary(strench,sum1, x,y-1,line, rank);
setmathboundary(strench,sum1,x,y+1, line, rank);
setmathboundary(strench,sum1,x-1,y,line,rank);
setmathboundary(strench,sum1,x+1,y,line, rank);
setmathboundary(strench,sum1,x-1,y-1, line,rank);
setmathboundary(strench,sum1,x+1,y-1,line, rank);
setmathboundary(strench,sum1,x-1,y+1,line, rank);
setmathboundary(strench,sum1,x+1,y+1,line,rank);*///感觉这里的递归写错了,先注释掉试一下。
}
void putmathboundary(int sum1[line+2][rank+2],int line7,int rank7,int x,int y)
{
int i = 0; int j = 0;
for (i = 1; i < line7+1; i++)
{
for (j = 1; j < rank7 + 1; j++)
{
if ((i == x) && (j == y)) printf("_%d_|", sum1[i][j]);
else printf("___|");
}
printf("\n");
}//通过遍历输出展开后的界面.只需要输出9*9,不用+2.
}
//如果第一个点开的不是雷,就第一次展示数字方阵。
test.c
#define _CRT_SECURE_NO_WARNINGS_
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "minesweeping.h"
int main()
{
char playing[line][rank] = { 0 };
int strench[line+2][rank+2] = { 0 };
int sum1[line + 2][rank + 2] = { 0 };
memset(playing,sizeof(playing), '\0');
//将棋盘初始化除了雷以外都是\0。
int input=0;
srand((unsigned int)time(NULL));
do{menu();
scanf_s("%d", &input);switch (input)
{case 1:play(); break;
case 0:break;
default:printf("无效!请重新输入:\n"); break;}
} while (input);
system("pause");
return 0;
}
void play()
{
int i = 0; int j = 0;
int x = 0; int y = 0;
initboundary(line, rank);//展示初始棋盘
setmines(playing, line, rank, mines);//先随机数把雷放好
/*for (i = 0; i < line; i++)
{
for (j = 0; j < rank; j++)
printf("%c", playing[i][j]);
printf("\n");
} */ //测试时检验雷盘雷放好了没有
printf("请输入打开方格的坐标\n");
scanf_s("%d,%d", &x, &y);
firstplay(playing,line,rank,x,y);//为保证玩家第一次点开不被炸死。
//for (i = 0; i < line; i++)
//{
// for (j = 0; j < rank; j++)
// printf("%c", playing[i][j]);
// printf("\n");
//} //测试时检验雷盘雷放好了没有
convert(strench,playing,line,rank);//放好雷后需要给全部数字数组赋值,只赋值,不求和。
//printf("strench\n");
//for (i = 0; i < line + 2; i++)
//{
// for (j = 0; j < rank + 2; j++)
// printf("%d", strench[i][j]);
// printf("\n");
//}
//用于检验两个数组是否正常,已检验。
setmathboundary(strench, sum1, x, y, line, rank);//在sum数组中放好九宫格和。
putmathboundary(sum1,line,rank,x,y);//展示界面。
while (1)
{
printf("请输入打开方格的坐标\n");
scanf_s("%d,%d", &x, &y);
if (strench[x + 1][y + 1] == 1)
{
printf("踩雷!游戏结束\n");
for (i = 0; i < line; i++)
{
for (j = 0; j < rank; j++)
printf("_%c_|", playing[i][j]);
printf("\n");
}break;
}
else setmathboundary(strench, sum1, x, y, line, rank);
putmathboundary(sum1, line, rank, x, y);
}
//nextplay();//继续点开
//判断是否被炸死。
//展示界面
//继续点开······
}
反思:写扫雷程序中的进步在于我能够边写代码边检查当前功能能否正常实现,且玩家可自行改变格数和雷数。而缺点在于该游戏过于初级,想通过递归实现多层展开,可是不知道什么原因,编译时显示堆栈溢出了,而且插旗排雷的功能也没能实现,这是后期优化可考虑的。