目录
前言
下面将要用C语言简单制作一个扫雷的游戏,细分扫雷游戏的各部分逻辑
一、扫雷游戏基本逻辑
1.制作一个扫雷游戏的简单界面
2.创建一个用于显示和放置雷的基本棋盘
3.往这个棋盘中随机布置10个雷
4.输入排雷的数据
5.进行判断输入的数据是否处于雷的位置
二、操作步骤
1.主函数
代码如
int main() { int key = 0;//获取键盘上的值,以用来判断是否开始游戏 srand((unsigned int)time(NULL));//用于后面的随机布雷 do{ printf("请输入是否开始扫雷游戏\n"); printf(" 1.play / 0.exit \n"); scanf("%d", &key); if (key==1) { Game();//当输入的值为1时,调用Game()函数,运行扫雷游戏 } else if (key==0) { printf("已退出扫雷游戏\n"); break;//当输入的值为0时,提示退出游戏,并终止运行 } else { printf("输入错误\n");//输入别的值时,提示输入错误,并重新输入 } } while (key); return 0; }
2.游戏函数Game()
1.首先理解基本棋盘的逻辑
我们可以把雷看作是字符‘1’,不是雷的地方看作字符‘0’,当我们排查一个坐标数据时,这个坐标数据如果是‘0’,则去计算周围8格中雷的数量;如果是‘1’,则说明踩到雷了,游戏就结束了。
当我们去统计雷数量的时候,就要注意一种情况:如果是9*9的棋盘,当我们排查的数据处于棋盘边缘或者角落的时候,周围其实是统计不到8格的数据,所以我们制作的棋盘要比这个大一圈,做成11*11的棋盘。
void Game() { char mine[Rows][Cols] = { 0 };//Rows等数据在Game.h文件中进项了定义 char show[Rows][Cols] = { 0 }; CreateBoard(mine,Rows,Cols,'0');//用于布置雷的棋盘 CreateBoard(show, Rows, Cols, '*');//用于展示出来的棋盘 //ShowBoard(mine, rows, cols); BuryMine(mine, rows, cols, '1');//用于埋雷的函数 //ShowBoard(mine, rows, cols); ShowBoard(show, rows, cols);//用于展示的函数 ScreenMine(mine,show,rows,cols);//用于排查雷的函数 }
Game.h文件具体定义:
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h> #include <time.h> #define Rows 11 #define Cols 11 #define rows 9 #define cols 9 #define Mines 10 void CreateBoard(char mine[Rows][Cols],int row,int col,char set); void ShowBoard(char mine[Rows][Cols], int row, int col); void BuryMine(char mine[Rows][Cols], int row, int col, char set); void ScreenMine(char mine[Rows][Cols], char show[Rows][Cols], int row, int col);
2.制作两个棋盘
其中一个棋盘用于放置雷,另一个棋盘则用于游戏的最终展示。
放置雷:
最终展示:
void CreateBoard(char mine[Rows][Cols], int row, int col, char set) { for (int i = 0; i < row;i++) { for (int j = 0; j < col;j++) { mine[i][j] = set; } } }
3.展示棋盘
通过ShowBoard()函数展示刚刚创建的两个棋盘(一个用于自己调试,一个用于最终展示)
注意:是只展示9*9棋盘,而我们创建的是11*11的,所以我们的循环起始是从1开始,循环九次。
void ShowBoard(char mine[Rows][Cols], int row, int col) { printf("———————————————————————\n"); printf("| 扫雷 |\n"); printf("———————————————————————\n"); printf("| y ");//上面这些基本样式可以根据自己喜欢调整 for (int i = 1; i <= row;i++) { if(i==row) printf("%d |", i); else printf("%d ", i); }//打印y坐标 printf("\n|x ————————————————————\n"); for (int i = 1; i <=row;i++) { printf("|%d| ", i);//打印x轴坐标 for (int j = 1; j <=col;j++) { if (j==col) { printf("%c |", mine[i][j]); }else printf("%c ", mine[i][j]); } printf("\n"); } printf("———————————————————————\n"); }
4.埋雷
因为我们展示的棋盘是9*9的,所以雷也只应该布置在这块区域内,即下标为1-9的地方
4.1生成随机数
int x = rand()%row+1;//棋盘x的坐标,%row值为0-8,+1值变成0-9 int y = rand()%col+1;//棋盘y的坐标,同上0-9
4.2判断在是否会重复埋雷
if (mine[x][y] == '0') { mine[x][y] = set; mines--; }
4.3确定我们一共要布置的雷数,进行循环
void BuryMine(char mine[Rows][Cols], int row, int col, char set) { int mines = Mines; while (mines) { int x = rand() % row + 1; int y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = set; mines--; } } }
5.排雷
排雷有两个结束游戏的基础条件:
1.踩到雷,游戏结束
2.雷全部被排完,游戏结束
我们首先先进行第二个条件的判断:
先设置一个变量count用于统计我们排了多少次雷,当count等于所有可排雷次数时,游戏结束
if (count== row*col - Mines) { system("cls");//通关时把屏幕清理干净 printf("恭喜您通过此游戏!!!!\n"); ShowBoard(mine, rows, cols);//通过游戏时展示所有雷处 printf("\n\n"); }
然后进行第一个条件的判断:
当玩家踩到雷时游戏结束
if (mine[x][y] == '1') { system("cls");//清理屏幕 printf("游戏结束,踩到雷了\n"); ShowBoard(mine, rows, cols);//同样展示雷处 printf("\n"); break; }
因为要进行多次排雷,所以还要进行循环,因为踩雷的判断有break用于跳出循环,所以正常跳出循环的条件就是排完所有雷(count>=row*col-Mines)。
同时我们还需要把输入的x,y轴坐标进行规范在1-9之间
if (x>0&&x<=row&&y>0&&y<=col)
下面就是统计我们输入的坐标的周围8格雷的数量,由于我们埋雷时用的是字符‘1’,其他没有雷的地块是字符‘0’,字符‘1’对应的ASCII值为49,而字符‘0’对应的是48,所以我们只需要把周围8格全部加在一起再减去8个字符‘0’对应的48,代码如下:
int Num(char mine[Rows][Cols],int x,int y) { int num = mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1]-8*48; return num; }
当周围有雷时,我们输入的坐标应在棋盘上显示周围雷的数量
show[x][y] = num + '0';//show[x][y]的值是char类型‘*’,而我们num的值是int类型,所以后面加个字符‘0’
把以上内容结合在一起,再进行一些规范,就是以下代码:
void ScreenMine(char mine[Rows][Cols],char show[Rows][Cols],int row, int col) { int count = 0; while (count< row * col - Mines) { int x = 0; int y = 0; printf("请输入您要排查的坐标(x y):"); scanf("%d %d", &x, &y); if (x>0&&x<=row&&y>0&&y<=col) { int num = Num(mine, x, y); if (mine[x][y] == '1') { system("cls"); printf("游戏结束,踩到雷了\n"); ShowBoard(mine, rows, cols); printf("\n"); break; } else { if (show[x][y] != '*') { printf("此坐标已经被排查过了\n"); } else { show[x][y] = num + '0'; count++; } ShowBoard(show, rows, cols); } } else { printf("输入的坐标非法,请重新输入\n"); } } if (count== row*col - Mines) { system("cls"); printf("恭喜您通过此游戏!!!!\n"); ShowBoard(mine, rows, cols); printf("\n\n"); } }
至此,一个简单的扫雷小游戏就完成了。
三、源码
1.Game.h
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h> #include <time.h> #define Rows 11//用于创建棋盘的行 #define Cols 11//用于创建棋盘的列 #define rows 9//用于展示的棋盘的行 #define cols 9//用于展示的棋盘的列 #define Mines 10//我们布置的雷数 void CreateBoard(char mine[Rows][Cols],int row,int col,char set);//创建棋盘函数 void ShowBoard(char mine[Rows][Cols], int row, int col);//展示棋盘函数 void BuryMine(char mine[Rows][Cols], int row, int col, char set);//埋雷函数 void ScreenMine(char mine[Rows][Cols], char show[Rows][Cols], int row, int col);//排雷函数
2.Game.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "Game.h" //创建扫雷背景棋盘 void CreateBoard(char mine[Rows][Cols], int row, int col, char set) { for (int i = 0; i < row;i++) { for (int j = 0; j < col;j++) { mine[i][j] = set; } } } //展示棋盘 void ShowBoard(char mine[Rows][Cols], int row, int col) { printf("———————————————————————\n"); printf("| 扫雷 |\n"); printf("———————————————————————\n"); printf("| y "); for (int i = 1; i <= row;i++) { if(i==row) printf("%d |", i); else printf("%d ", i); } printf("\n|x ————————————————————\n"); for (int i = 1; i <=row;i++) { printf("|%d| ", i); for (int j = 1; j <=col;j++) { if (j==col) { printf("%c |", mine[i][j]); }else printf("%c ", mine[i][j]); } printf("\n"); } printf("———————————————————————\n"); } //埋雷 void BuryMine(char mine[Rows][Cols], int row, int col, char set) { int mines = Mines; while (mines) { int x = rand() % row + 1; int y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = set; mines--; } } } //统计点开的坐标的周围有几个雷 int Num(char mine[Rows][Cols],int x,int y) { int num = mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1]-8*48; return num; } //判断是否踩到雷(是则游戏结束/否则继续游戏直到找到所有空处) void ScreenMine(char mine[Rows][Cols],char show[Rows][Cols],int row, int col) { int count = 0; while (count< row * col - Mines) { int x = 0; int y = 0; printf("请输入您要排查的坐标(x y):"); scanf("%d %d", &x, &y); if (x>0&&x<=row&&y>0&&y<=col) { int num = Num(mine, x, y); if (mine[x][y] == '1') { system("cls"); printf("游戏结束,踩到雷了\n"); ShowBoard(mine, rows, cols); printf("\n"); break; } else { if (show[x][y] != '*') { printf("此坐标已经被排查过了\n"); } else { show[x][y] = num + '0'; count++; } ShowBoard(show, rows, cols); } } else { printf("输入的坐标非法,请重新输入\n"); } } if (count== row*col - Mines) { system("cls"); printf("恭喜您通过此游戏!!!!\n"); ShowBoard(mine, rows, cols); printf("\n\n"); } }
3.Main.c
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include "Game.h" void Game() { char mine[Rows][Cols] = { 0 }; char show[Rows][Cols] = { 0 }; CreateBoard(mine,Rows,Cols,'0');//用于布置雷的棋盘 CreateBoard(show, Rows, Cols, '*');//用于展示出来的棋盘 //ShowBoard(mine, rows, cols); BuryMine(mine, rows, cols, '1');//用于埋雷的函数 //ShowBoard(mine, rows, cols); ShowBoard(show, rows, cols);//用于展示的函数 ScreenMine(mine,show,rows,cols);//用于排查雷的函数 } int main() { int key = 0; srand((unsigned int)time(NULL)); do{ printf("请输入是否开始扫雷游戏\n"); printf(" 1.play / 0.exit \n"); scanf("%d", &key); if (key==1) { Game(); } else if (key==0) { printf("已退出扫雷游戏\n"); break; } else { printf("输入错误\n"); } } while (key); return 0; }