game.h
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define row 9
#define line 9
#define rows row+2
#define lines line+2
void initbroad(char arr[lines][rows], int a, int b, char sign);
void printbroad(char arr[lines][rows]);
void set(char arr[lines][rows]);
int found(char arr[lines][rows], int a, int b);
void win(char mine[lines][rows], char show[lines][rows]);
game.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "game.h"
#include <time.h>
#include <stdlib.h>
int wins = line * row - 10;
void initbroad(char arr[lines][rows],int a,int b,char sign)
{
for (int i = 0;i < a;i++)
{
for (int j = 0; j < b; j++)
{
arr[i][j] = sign;
}
}
}
void printbroad(char arr[lines][rows])
{
int i = 0;
int j = 0;
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= line; i++)
{
printf("%d ", i);
for (j = 1; j <= row; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
void set(char arr[lines][rows])
{
srand((unsigned int)time(NULL));
int count = 10;
while(count)
{
int a = rand() % 9 + 1;
int b = rand() % 9 + 1;
if (arr[a][b] != '1')
{
arr[a][b] = '1';
count--;
}
}
}
int found(char arr[lines][rows], int a, int b)
{
return (arr[a + 1][b] + arr[a + 1][b + 1] + arr[a + 1][b - 1] + arr[a][b + 1] + arr[a][b - 1] + arr[a - 1][b] + arr[a - 1][b + 1] + arr[a - 1][b - 1] - 8 * '0');
}
void clear(char mine[lines][rows],char show[lines][rows],int a,int b)
{
for (int i = 0; i <= 1; i++)
{
for (int j = 0; j <= 1; j++)
{
if ((a + i) <= 9 && (a + i) >= 1 && (b + j) <= 9 && (b + j) >= 1&&(show[a + i][b + j] == '*'))
{
if (mine[a + i][b + j] == '0')
{
int vc = found(mine, a+i, b + j);
show[a+i][b + j] = vc + '0';
wins--;
}
}
if ((a + i) <= 9 && (a + i) >= 1 && (b - j) <= 9 && (b - j) >= 1 && (show[a + i][b - j] == '*'))
{
if (mine[a + i][b - j] == '0')
{
int vc = found(mine, a+i, b - j);
show[a+i][b - j] = vc + '0';
wins--;
}
}
}
}
for (int i = 0; i <= 1; i++)
{
for (int j = 0; j <= 1; j++)
{
if ((a - i) <= 9 && (a - i) >= 1 && (b + j) <= 9 && (b + j) >= 1 && (show[a - i][b + j] == '*'))
{
if (mine[a - i][b + j] == '0')
{
int vc = found(mine, a, b + j);
show[a-i][b + j] = vc + '0';
wins--;
}
}
if ((a - i) <= 9 && (a - i) >= 1 && (b - j) <= 9 && (b - j) >= 1 && (show[a - i][b - j] == '*'))
{
if (mine[a - i][b - j] == '0')
{
int vc = found(mine, a-i, b - j);
show[a-i][b - j] = vc + '0';
wins--;
}
}
}
}
}
void win(char mine[lines][rows], char show[lines][rows])
{
while (wins >= 0)
{
if (wins == 0)
{
printf("WIN\n");
break;
}
printbroad(show);
printf("选择纵坐标及横坐标:\n");
int a, b;
scanf("%d%d", &a, &b);
if (a >= 1 && a <= 9 && b >= 1 && b <= 9&&(show[a][b]=='*'))
{
if (mine[a][b] == '0')
{
int vc = found(mine, a, b);
show[a][b] = vc + '0';
wins--;
clear(mine,show,a,b);
}
else
{
printf("踩雷了\n");
printbroad(mine);
break;
}
}
else
{
printf("输入错误,重试\n");
}
}
}
main.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include "game.h"
void menu()
{
printf("************************************************\n");
printf("******************** 1.play ********************\n");
printf("******************** 0.exit ********************\n");
printf("************************************************\n");
}
char show[lines][rows];
char mine[lines][rows];
void game()
{
initbroad(show, lines, rows, '*');
initbroad(mine, lines, rows, '0');
set(mine);
win(mine, show);
}
int main()
{
int input = 0;
do
{
menu();
printf("请输入:\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("********************开始游戏********************\n");
game();
break;
case 0:
printf("已退出\n");
default:
printf("输入错误,请重试\n");
}
} while (input);
return 0;
}
本扫雷游戏非常简陋,代码量在200行左右。
在这个程序中,我们需要实现的功能有菜单、初始化棋盘、显示棋盘、放置地雷、输入坐标后判断是否为雷、显示周围雷数、判断胜利条件。
由于以上功能需多次使用,防止代码堆积过多不易查看,将其放于头文件中保存。
1、菜单的建立:
void menu()
{
printf("************************************************\n");
printf("******************** 1.play ********************\n");
printf("******************** 0.exit ********************\n");
printf("************************************************\n");
}
2、创立棋盘:
char show[lines][rows];
char mine[lines][rows];
我们需要两块棋盘,一块用于记录雷的位置,一块用于展示给玩家看。
该棋盘大小为9x9;但由于我们需要为展示的棋盘标序号,且判断周围雷数时不能超越数组范围,所以需要设定棋盘大小为11x11。
为方便管理,我们可将其用define定义于game.h中,并在game.c中引用即可。
#define row 9
#define line 9
#define rows row+2
#define lines line+2
3、初始化棋盘:
void initbroad(char arr[lines][rows],int a,int b,char sign)
{
for (int i = 0;i < a;i++)
{
for (int j = 0; j < b; j++)
{
arr[i][j] = sign;
}
}
}
遍历整个二维数组,赋予选定的字符,如show给予*,而mine给予‘0’。
4、打印棋盘及横纵坐标:
void printbroad(char arr[lines][rows])
{
int i = 0;
int j = 0;
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= line; i++)
{
printf("%d ", i);
for (j = 1; j <= row; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
initbroad(show,lines,rows,'*');
printbroad(show);
结果如下:
5、 放置地雷:
为防止地雷不随机,使用rand函数(stdlib.h),并使用srand((unsigned int)time(NULL))来根据时间设定种子(time.h)。
void set(char arr[lines][rows])
{
srand((unsigned int)time(NULL));
int count = 10;
while(count)
{
int a = rand() % 9 + 1;//使a在1~9之间
int b = rand() % 9 + 1;
if (arr[a][b] != '1')//判断该位置是否为雷
{
arr[a][b] = '1';
count--;//每放一个雷count减1,只会放置十个雷
}
}
}
6、选择坐标并判断是否胜利:
首先设定胜利目标,即找出所有的非雷坐标,即9x9-10个;设其为wins。
int wins = line * row - 10;
void win(char mine[lines][rows], char show[lines][rows])
{
while (wins >= 0)
{
if (wins == 0)//wins=0时代表剩余非雷坐标数为0
{
printf("WIN\n");
break;
}
printbroad(show);
printf("选择纵坐标及横坐标:\n");
int a, b;
scanf("%d%d", &a, &b);
if (a >= 1 && a <= 9 && b >= 1 && b <= 9&&(show[a][b]=='*'))//使(a,b)在棋盘内
{
if (mine[a][b] == '0')//判断是否为雷
{
int vc = found(mine, a, b);//判断周围雷数,函数定义在下面
show[a][b] = vc + '0';//使show对应位置为周围雷数
wins--;
clear(mine,show,a,b);
}
else
{
printf("踩雷了\n");
printbroad(mine);
break;
}
}
else
{
printf("输入错误,重试\n");
}
}
}
7、判断周围雷数:
int found(char arr[lines][rows], int a, int b)
{
return (arr[a + 1][b] + arr[a + 1][b + 1] + arr[a + 1][b - 1] + arr[a][b + 1] + arr[a][b - 1] + arr[a - 1][b] + arr[a - 1][b + 1] + arr[a - 1][b - 1] - 8 * '0');
}
8、如果排查位置不为雷且周围没有雷,可以展开一片:
机理与上方几条一致
void clear(char mine[lines][rows],char show[lines][rows],int a,int b)
{
for (int i = 0; i <= 1; i++)
{
for (int j = 0; j <= 1; j++)
{
if ((a + i) <= 9 && (a + i) >= 1 && (b + j) <= 9 && (b + j) >= 1&&(show[a + i][b + j] == '*'))
{
if (mine[a + i][b + j] == '0')
{
int vc = found(mine, a+i, b + j);
show[a+i][b + j] = vc + '0';
wins--;
}
}
if ((a + i) <= 9 && (a + i) >= 1 && (b - j) <= 9 && (b - j) >= 1 && (show[a + i][b - j] == '*'))
{
if (mine[a + i][b - j] == '0')
{
int vc = found(mine, a+i, b - j);
show[a+i][b - j] = vc + '0';
wins--;
}
}
}
}
for (int i = 0; i <= 1; i++)
{
for (int j = 0; j <= 1; j++)
{
if ((a - i) <= 9 && (a - i) >= 1 && (b + j) <= 9 && (b + j) >= 1 && (show[a - i][b + j] == '*'))
{
if (mine[a - i][b + j] == '0')
{
int vc = found(mine, a, b + j);
show[a-i][b + j] = vc + '0';
wins--;
}
}
if ((a - i) <= 9 && (a - i) >= 1 && (b - j) <= 9 && (b - j) >= 1 && (show[a - i][b - j] == '*'))
{
if (mine[a - i][b - j] == '0')
{
int vc = found(mine, a-i, b - j);
show[a-i][b - j] = vc + '0';
wins--;
}
}
}
}
}
最后将这几个功能结合便可得到扫雷代码。