首先说一下,我的这个小程序没有用什么算法,就是一个很小白的程序,求不喷。
先说一下思路,我是计划用一个二维数组来储存一切数据,即一个扫雷图的全部数据。一切都在这个二维数组里操作。废话不多说,先上程序。
#include <stdio.h>
#include <stdlib.h> //包含srand()和rand()函数
#define SIZE 9 //数组大小(SIZE * SIZE)
_Bool life = 1; //标志是否Gameover
void setbomb(char (*array)[SIZE]); //设定炸弹的位置
void setnum(char (*array)[SIZE]); //计算炸弹数
int countbomb_square(char (*array)[SIZE], int x, int y); //计算每个九宫格的炸弹数
void check(char (*array)[SIZE], int x, int y); //接受输入和操作
void printpic(char (*array)[SIZE]); //打印图像
int main(void)
{
int x = 0, y = 0; //储存用户输入的位置
char array[SIZE][SIZE] = {{0}};
setbomb(array);
setnum(array);
while(1){
printpic(array); //打印图像
if(0 == life) //判断是否Gameover
break;
printf("Enter your chosen in formatted(x y): ");
if(0 == scanf("%d%d", &x, &y))
break;
check(array, x, y); //处理输入
}
if(life)
printf("You win!\n");
else
printf("You lost!\n");
return 0;
}
void setbomb(char (*array)[SIZE])
{
int index1 = 0, index2 = 0;
int temp;
srand((unsigned int)time(NULL));
for(index1 = 0; index1 < SIZE; index1++){
for(index2 = 0; index2 < SIZE; index2++){
temp = rand() % 90;
if((60 < temp) && (temp < 90)) // 1/3 的空格设有炸弹
array[index1][index2] = -1;
}
}
}
void setnum(char (*array)[SIZE])
{
int index1 = 0, index2 = 0;
for(index1 = 0; index1 < SIZE; index1++){
for(index2 = 0; index2 < SIZE; index2++){
if(-1 == array[index1][index2])
array[index1][index2] += 10; //数字大于8的空格不可见
else
array[index1][index2] = countbomb_square(array, index1, index2) + 10;
}
}
}
int countbomb_square(char (*array)[SIZE], int row, int column)
{
int count = 0;
int start_row, final_row;
int start_column, final_column, temp_column;
if(0 != row && SIZE - 1 != row) //有三种可能,最大的可能是中间的空格
start_row = row - 1, final_row = row + 1;
else if(0 == row) //在第一行的空格
start_row = row, final_row = row + 1;
else if(SIZE - 1 == row) //在最后一行的空格
start_row = row - 1, final_row = row;
if(0 != column && SIZE - 1 != column) //也有三种可能,中间的空格
start_column = column - 1, final_column = column + 1;
else if(0 == column) //在第一列的空格
start_column = column, final_column = column + 1;
else if(SIZE - 1 == column) //在最后一列的空格
start_column = column - 1, final_column = column;
temp_column = start_column;
for(; start_row <= final_row; start_row++){
start_column = temp_column;
for(; start_column <= final_column; start_column++){
if((-1 == array[start_row][start_column]) || ( -1 + 10 == array[start_row][start_column]))
count++; //未处理的炸弹格式-1,但处理过的炸弹格+10等于9
}
}
return count;
}
void check(char (*array)[SIZE], int x, int y)
{
if((0 <= array[x][y]) && (array[x][y] <= 8)) //空格已打开,已可见
return;
if(-1 == array[x][y] - 10){ //Gameover, 更改life的值
array[x][y] -= 10;
life = 0;
}
else if(8 < array[x][y])
array[x][y] -= 10; //打开空格
}
void printpic(char (*array)[SIZE])
{
int index1 = 0, index2 = 0;
system("cls");
printf("|*");
for(index1 = 0; index1 < SIZE; index1++)
printf("|%d", index1);
printf("|\n");
for(index1 = 0; index1 < SIZE; index1++){
for(index2 = 0; index2 < SIZE; index2++)
printf("---");
printf("\n|%d", index1);
for(index2 = 0; index2 < SIZE; index2++){
if(8 < array[index1][index2]) //大于8,不可见
printf("| ");
else if((0 <= array[index1][index2]) && (array[index1][index2] <= 8)) //非炸弹格
printf("|%d", array[index1][index2]);
else if(-1 == array[index1][index2]) //炸弹格
printf("|*");
}
printf("|\n");
}
}
程序的核心是计算九宫格内的炸弹数,以下是详细讲解。
用FOR循环来遍历整个二维数组,对每个元素即格子计算炸弹数。
以每个格子为中心的九宫格就如上图所示,行从Row-1行开始到Row+1行,列从Column-1到Column+1,用两个FOR循环来实现九宫格的遍历。还有一个前提,中心的格子,即(Row,Column)没有炸弹,即如果格子有炸弹就跳过这个格子。
还有一些特殊情况,即第一行和最后一行,第一列和最后一列。因为行和列互不影响,所以可以分开处理。
先处理行。
如图所示,行有三种情况,第一行,最后一行和中间的格子。
if(0 != row && SIZE - 1 != row) //有三种可能,最大的可能是中间的空格
start_row = row - 1, final_row = row + 1;
else if(0 == row) //在第一行的空格
start_row = row, final_row = row + 1;
else if(SIZE - 1 == row) //在最后一行的空格
start_row = row - 1, final_row = row;
接着是列的处理,也是三种情况,第一,最后,中间,和行的一样。
以下是代码
if(0 != column && SIZE - 1 != column) //也有三种可能,中间的空格
start_column = column - 1, final_column = column + 1;
else if(0 == column) //在第一列的空格
start_column = column, final_column = column + 1;
else if(SIZE - 1 == column) //在最后一列的空格
start_column = column - 1, final_column = column;
temp_column = start_column;
for(; start_row <= final_row; start_row++){
start_column = temp_column;
for(; start_column <= final_column; start_column++){
if((-1 == array[start_row][start_column]) || ( -1 + 10 == array[start_row][start_column]))
count++; //未处理的炸弹格式-1,但处理过的炸弹格+10等于9
}
}
因为列在每个内循环里都要重新开始,为了效率,添加了一个变量temp_column储存它。
核心的东西已经讲完了,这是一个简陋的扫雷程序,没有标志炸弹位置的功能,也没有打开空格的功能,但可以自己添加上去,自己完善它,就说到这里吧。