1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > C语言初阶之扫雷

C语言初阶之扫雷

时间:2020-09-26 19:49:28

相关推荐

C语言初阶之扫雷

目录

扫雷

准备环境

大致思路分析

编写主函数

重点塑造的game.c

1.game

2.board

3.playboard

4.board2

5.play

6.win

7.clearance

扫雷

hello!各位小伙伴们,今天小春宝将给大家分享扫雷,扫雷其实并没有大家想象中那么困难,接下来,教大家如何创建一个扫雷项目

准备环境

再写扫雷之前,我们得新建一个项目和三个文件

1.game.h

2.game.c

3.test.c

老规矩,先给大家献上头文件的内容

#ifndef __GAME_H__#define __GAME_H__#define _CRT_SECURE_NO_WARNINGS 1#define H 9#define L 9#define N 10#include<stdio.h>#include<stdlib.h>#include<time.h>void menu();void game();void board(char board[H][L], int x, int y);void playboard(char board[H][L], int x, int y);void board2(char arr1[H][L], int x, int y, int a, int b);void play(char arr[H][L], char arr1[H][L], int x, int y);int win(char arr[H][L], int x, int y);void clearance(char arr[H][L], char arr1[H][L], int a, int b, int x, int y);#endif

大致思路分析

扫雷与三子棋不同,我们得有一个大致的框架才能够顺利的开始扫雷的构建,扫雷游戏的玩耍是翻开遮蔽的地方,如果是雷我们就被炸死了,如果不是会告诉我们附近是否有雷,这个时候我们需要两个棋盘,一个棋盘是给玩家看的,一个棋盘是实际上的棋盘,这个棋盘既要有雷,也要有提示雷的信息,为了防止用户第一步就被炸死了,我们需要在下完的第一步才确定雷的位置,为了尽量还原游戏的功能,我们可以增加标记这一功能来确定雷的位置。

编写主函数

看过三子棋的小伙伴们,应该对主函数的构建并不陌生,因为三子棋的主函数构建也是如出一辙,话不多说,直接上代码

#include"game.h"void menu() {printf("**********************\n");printf("****1.play 0.exit*****\n");printf("**********************\n");}int main() {int n;do {menu();a:printf("请选择:");scanf("%d", &n);switch (n){case 1:game();break;case 0:printf("退出程序\n");break;default:printf("输出错误,请重新输入\n");goto a;}} while (n);return 0;}

重点塑造的game.c

1.game

由于game函数本体十分简单,这里直接给大家上game

void game() {char arr[H][L] = { 0 };char arr1[H][L] = { 0 };int n;printf("扫雷游戏即将开始,敬请期待\n");board(arr, H, L);playboard(arr, H, L);n = 1;while (n){play(arr, arr1, H, L);n = win(arr, H, L);}}

2.board

borad函数是初始化那个给玩家看的棋盘,他的载体是board[9][9]为了方便修改棋盘内容,我们定义两个常量H代表行,L代表列,我们今天要实现的扫雷是一个9*9十个雷的棋盘为了一种什么感,我们选择'*'来给大家看到void board(char board[H][L], int x, int y) {int i, j;for (i = 0; i < x; i++)for (j = 0; j < y; j++)board[i][j] = '*';}

3.playboard

接下来又是今天的一个难题,在我看来,扫雷的棋盘相比于三子棋的棋盘难度更高些,实现这个棋盘需要大家不断的尝试和调整,直接上我们要的效果

首先我们先得打印而不去管那些数字,数字是为了提高用户体验之后加的

void playboard(char board[H][L], int x, int y) {int i, j;for (i = 0; i < x; i++) {for (j = 0; j < y; j++) {printf("|---");}printf("|\n");for (j = 0; j < y; j++) {printf("| %c ", board[i][j]);}printf("|\n");}for (j = 0; j < y; j++) {printf("|---");}printf("|\n");}

这个是效果,但这个棋盘太大,我们需要数字来提示用户,添加数组这一步大家一定要多加尝试

void playboard(char board[H][L], int x, int y) {int i, j,k;for (k = 0; k < x + 1; k++) {if (k == 0)printf("%d ", k);else printf("%d ", k);}printf("\n");for (i = 0; i < x; i++) {printf(" ");for (j = 0; j < y; j++) {printf("|---");}printf("|\n");printf("%d", i + 1);for (j = 0; j < y; j++) {printf("| %c ", board[i][j]);}printf("|\n");}printf(" ");for (j = 0; j < y; j++) {printf("|---");}printf("|\n");}

这样之后扫雷就是完全体了,当然大家也可以靠着自己的意愿进行修改,我的这只是一个参考

4.board2

首先我们暂时以A代表雷,每个字符暂定为0,只要周围有雷就加1因为雷是随机的,我们这个时候需要随机值rand来协助我们完成void board2(char arr1[H][L], int x, int y, int a, int b) {//a,b是用户第一次扫雷的位置的坐标int i, j, k, m, n;srand((unsigned)time(NULL));for (i = 0; i < x; i++)for (j = 0; j < y; j++)arr1[i][j] = '0';for (k = 0; k < N; k++){a:i = rand() % x;j = rand() % y;if (arr1[i][j] != 'A' && i != a && j != b)arr1[i][j] = 'A';elsegoto a;for (m = i - 1; m <= i + 1; m++) {for (n = j - 1; n <= j + 1; n++) {if (m < x && m >= 0 && n < y && n >= 0 && arr1[m][n] != 'A')arr1[m][n]++;}}//这两层循环是用来给雷旁边的字符都加一的,并且我们需要判断该位置的合法性和是不是雷}}

5.play

我们得让用户选择操作,开始扫雷,进行标记并且取消标记,开始扫雷我们先来实现扫雷功能void play(char arr[H][L], char arr1[H][L], int x, int y) {int i, j, n;static int k = 0;b:printf("(1.标记 0.开始扫雷 2.取消标记 )请选择:");scanf("%d", &n);switch (n){case 0:a:printf("(提示,以x y的形式输入,x代表行,y代表列)请输入你要扫的坐标:");scanf("%d%d", &i, &j);if (k < 1) {board2(arr1, x, y, i - 1, j - 1);k++;}if (i >= 1 && i <= x && j >= 1 && j <= 9){if (arr[i - 1][j - 1] == '*')arr[i - 1][j - 1] = arr1[i - 1][j - 1];else {printf("该位置无法进行扫雷操作,请重新输入\n");goto a;}}else{printf("输入坐标非法,请重新输入\n");goto a;}break;case 1:break;case 2:break;default:printf("选择错误,请重新选择\n");goto b;}system("cls");playboard(arr, H, L);}

这里面包括了play函数的框架,这个时候我们再来进行标记的编写,我们约定被标记过的雷用'*'来表示接下来我们直接编写case 1中的内容c:printf("请选择你要标记的坐标(提示以x y的形式输入x代表行,y代表列)\n");scanf("%d %d", &i, &j);if (arr[i - 1][j - 1] == '*'){arr[i - 1][j - 1] = '#';printf("标记成功\n");}else {printf("输出错误,请重新输入\n");goto c;}break;

接着便是标记以后,若是用户觉得标记错误或者是不小心标记了,我们可以随时让用户选择取消标记printf("请选择你要取消标记的坐标(提示以x y的形式输入x代表行,y代表列)\n");scanf("%d%d", &i, &j);if (arr[i - 1][j - 1] == '#'){printf("取消成功\n");arr[i - 1][j - 1] = '*';}else {printf("取消标记失败\n");goto b;}//为预防用户误点取消标记,而当还未进行标记时就一直出不来了,所以避免这种情况,我们选择让用户直//接回到b标记点的位置来重新选择操作//接下来我们组装一下便可得到play

void play(char arr[H][L], char arr1[H][L], int x, int y) {int i, j, n;static int k = 0;b:printf("(1.标记 0.开始扫雷 2.取消标记 )请选择:");scanf("%d", &n);switch (n){case 0:a:printf("(提示,以x y的形式输入,x代表行,y代表列)请输入你要扫的坐标:");scanf("%d%d", &i, &j);if (k < 1) {board2(arr1, x, y, i - 1, j - 1);k++;}if (i >= 1 && i <= x && j >= 1 && j <= 9){if (arr[i - 1][j - 1] == '*')arr[i - 1][j - 1] = arr1[i - 1][j - 1];else {printf("该位置无法进行扫雷操作,请重新输入\n");goto a;}}else{printf("输入坐标非法,请重新输入\n");goto a;}break;case 1:c:printf("请选择你要标记的坐标(提示以x y的形式输入x代表行,y代表列)\n");scanf("%d %d", &i, &j);if (arr[i - 1][j - 1] == '*'){arr[i - 1][j - 1] = '#';printf("标记成功\n");}else {printf("输出错误,请重新输入\n");goto c;}break;case 2:printf("请选择你要取消标记的坐标(提示以x y的形式输入x代表行,y代表列)\n");scanf("%d%d", &i, &j);if (arr[i - 1][j - 1] == '#'){printf("取消成功\n");arr[i - 1][j - 1] = '*';}else {printf("取消标记失败\n");goto b;}break;default:printf("选择错误,请重新选择\n");goto b;}system("cls");playboard(arr, H, L);}

这个play函数比较长,但是大家在编写play函数时千万不要着急,我们最后还会对play函数进行一次修改

6.win

我们不能无止境的扫雷,而win函数就是用于判断是否游戏结束的函数int win(char arr[H][L], int x, int y) {int i = 0, j = 0;int count = 0;for (i = 0; i < x; i++) {for (j = 0; j < y; j++) {if (arr[i][j] == 'A'){printf("很遗憾,你输了\n");return 0;}else if (arr[i][j] == '*' || arr[i][j] == '#')count++;}}if (count > N)return 1;else{printf("恭喜你,你赢了\n");return 0;}}//根据我们编写的game函数可知win返回0的时候游戏继续,返回1游戏将继续

7.clearance

其实扫雷写到这里就可以结束了,但是如果就这样结束可能会让大家玩的很累,扫雷还有一种性质,只要旁边没有雷就会推开一片,然后不断的推开,知道旁边有雷,这个操作需要使用递归的思想,所以希望大家在编写这个函数时一定要多加思考,切勿盲目的编写,而这个函数的出现迫使我们不得不对play也进行修改

我们先来设计一下clearance函数void clearance(char arr[H][L], char arr1[H][L], int a, int b, int x, int y) {int m,n;for (m = a ; m <= a+2; m++) {for (n = b; n <= b + 2; n++) {if (m >= 0 && m < x && n < y && n >= 0) {if (arr1[m][n] == '0' && arr[m][n] == '*'){arr[m][n] = arr1[m][n];clearance(arr, arr1, m - 1, n - 1, x, y);}else if (arr[m][n] != '#')arr[m][n] = arr1[m][n];}}}}

然后我们再对play函数进行小小的修改a:printf("请选择你要扫的位置(提示以x y的形式输入x代表行,y代表列)\n");scanf("%d %d", &i, &j);if (k < 1) {board2(arr1, H, L, i - 1, j - 1);k++;}if (i <= x && i >= 1 && j <= y && j >= 1) {if (arr[i - 1][j - 1] == '*'){arr[i - 1][j - 1] = arr1[i - 1][j - 1];if (arr[i - 1][j - 1] == '0')clearance(arr, arr1, i - 2, j - 2, H, L);}else {printf("该位置已经扫过,请重新输入\n");goto a;}}else{printf("位置错误,请重新输入\n");goto a;}将case 0中的内容进行以下修改

当你看完这里,今天的扫雷就实现完成了,看完之后,大家应该可以做出属于自己的扫雷,最后送上完整的game.c

如果有需要完整的代码的也可以上我的码云去寻找

#include"game.h"void board(char board[H][L], int x, int y) {int i, j;for (i = 0; i < x; i++)for (j = 0; j < y; j++)board[i][j] = '*';}void playboard(char board[H][L], int x, int y) {int i, j,k;for (k = 0; k < x + 1; k++) {if (k == 0)printf("%d ", k);else printf("%d ", k);}printf("\n");for (i = 0; i < x; i++) {printf(" ");for (j = 0; j < y; j++) {printf("|---");}printf("|\n");printf("%d", i + 1);for (j = 0; j < y; j++) {printf("| %c ", board[i][j]);}printf("|\n");}printf(" ");for (j = 0; j < y; j++) {printf("|---");}printf("|\n");}void board2(char arr1[H][L], int x, int y, int a, int b) {int i, j, k, m, n;srand((unsigned)time(NULL));for (i = 0; i < x; i++)for (j = 0; j < y; j++)arr1[i][j] = '0';for (k = 0; k < N; k++){a:i = rand() % x;j = rand() % y;if (arr1[i][j] != 'A' && i != a && j != b)arr1[i][j] = 'A';elsegoto a;for (m = i - 1; m <= i + 1; m++) {for (n = j - 1; n <= j + 1; n++) {if (m < x && m >= 0 && n < y && n >= 0 && arr1[m][n] != 'A')arr1[m][n]++;}}}}void play(char arr[H][L], char arr1[H][L], int x, int y) {int i, j, n;static int k = 0;b:printf("(1.标记 0.开始扫雷 2.取消标记 )请选择:");scanf("%d", &n);switch (n){case 0:a:printf("请选择你要扫的位置(提示以x y的形式输入x代表行,y代表列)\n");scanf("%d %d", &i, &j);if (k < 1) {board2(arr1, H, L, i - 1, j - 1);k++;}if (i <= x && i >= 1 && j <= y && j >= 1) {if (arr[i - 1][j - 1] == '*'){arr[i - 1][j - 1] = arr1[i - 1][j - 1];if (arr[i - 1][j - 1] == '0')clearance(arr, arr1, i - 2, j - 2, H, L);}else {printf("该位置已经扫过,请重新输入\n");goto a;}}else{printf("位置错误,请重新输入\n");goto a;}break;case 1:c:printf("请选择你要标记的坐标(提示以x y的形式输入x代表行,y代表列)\n");scanf("%d %d", &i, &j);if (arr[i - 1][j - 1] == '*'){arr[i - 1][j - 1] = '#';printf("标记成功\n");}else {printf("输出错误,请重新输入\n");goto c;}break;case 2:printf("请选择你要取消标记的坐标(提示以x y的形式输入x代表行,y代表列)\n");scanf("%d%d", &i, &j);if (arr[i - 1][j - 1] == '#'){printf("取消成功\n");arr[i - 1][j - 1] = '*';}else {printf("取消标记失败\n");goto b;}break;default:printf("选择错误,请重新选择\n");goto b;}system("cls");playboard(arr, H, L);}int win(char arr[H][L], int x, int y) {int i = 0, j = 0;int count = 0;for (i = 0; i < x; i++) {for (j = 0; j < y; j++) {if (arr[i][j] == 'A'){printf("很遗憾,你输了\n");return 0;}else if (arr[i][j] == '*' || arr[i][j] == '#')count++;}}if (count > N)return 1;else{printf("恭喜你,你赢了\n");return 0;}}void clearance(char arr[H][L], char arr1[H][L], int a, int b, int x, int y) {int m,n;for (m = a ; m <= a+2; m++) {for (n = b; n <= b + 2; n++) {if (m >= 0 && m < x && n < y && n >= 0) {if (arr1[m][n] == '0' && arr[m][n] == '*'){arr[m][n] = arr1[m][n];clearance(arr, arr1, m - 1, n - 1, x, y);}else if (arr[m][n] != '#')arr[m][n] = arr1[m][n];}}}}void game() {char arr[H][L] = { 0 };char arr1[H][L] = { 0 };int n;printf("扫雷游戏即将开始,敬请期待\n");board(arr, H, L);playboard(arr, H, L);n = 1;while (n){play(arr, arr1, H, L);n = win(arr, H, L);}}

最后奉上码云网站C语言代码: 储存一些认真编写的C语言代码 ()/build-xiaochunbao/c-language-code

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。