C语言扫雷答辩ppt
- 格式:pptx
- 大小:1.69 MB
- 文档页数:17
c语言程序设计课程设计扫雷一、课程目标知识目标:1. 理解C语言中数组、循环和条件判断等基本概念,掌握其在扫雷游戏中的应用;2. 学会使用C语言编写扫雷游戏的逻辑代码,实现游戏的基本功能;3. 了解扫雷游戏的规则,理解其背后的算法原理。
技能目标:1. 能够运用所学知识,独立设计并编写简单的C语言程序,实现扫雷游戏的基本功能;2. 培养逻辑思维能力,提高编程解决问题的能力;3. 学会运用调试工具,分析并解决程序中的错误。
情感态度价值观目标:1. 培养对编程的兴趣,激发学习C语言的积极性;2. 增强团队协作能力,培养良好的编程习惯;3. 认识到编程在现实生活中的应用,树立正确的价值观。
本课程针对高年级学生,在学生已掌握C语言基础知识的前提下,通过设计扫雷游戏,提高学生的编程实践能力。
课程注重培养学生的逻辑思维和团队协作能力,使学生能够运用所学知识解决实际问题。
课程目标具体、可衡量,以便学生和教师能够清晰地了解课程的预期成果,为后续的教学设计和评估提供依据。
二、教学内容1. C语言基础知识回顾:数组、循环、条件判断等基本概念及其应用;2. 扫雷游戏规则介绍:游戏界面、雷区、标记、计时等;3. 扫雷游戏算法原理:递归、随机数生成、数组操作等;4. 编程实践:a. 设计游戏界面和数据结构;b. 编写扫雷逻辑代码,实现游戏的基本功能;c. 调试与优化程序,提高游戏性能;5. 团队协作与编程规范:分工合作、代码规范、注释使用等。
教学内容依据课程目标,结合教材相关章节,确保科学性和系统性。
教学大纲安排如下:第一课时:C语言基础知识回顾,介绍扫雷游戏规则;第二课时:讲解扫雷游戏算法原理,引导学生思考如何实现游戏功能;第三课时:分组讨论,设计游戏界面和数据结构;第四课时:编写扫雷逻辑代码,实现游戏基本功能;第五课时:调试与优化程序,提高游戏性能;第六课时:团队协作与编程规范,总结课程收获。
三、教学方法本课程采用以下教学方法,旨在激发学生学习兴趣,提高教学效果:1. 讲授法:教师通过生动的语言和示例,为学生讲解C语言基础知识和扫雷游戏算法原理,使学生在短时间内掌握课程重点。
C语⾔实现扫雷游戏详解本⽂实例为⼤家分享了C语⾔实现扫雷游戏的具体代码,供⼤家参考,具体内容如下功能设计扫雷⼤家应该都玩过,这是⼀个⼗分经典的游戏,今天我将给⼤家讲解如何⽤C语⾔实现扫雷,我的这个扫雷有如下⼏个功能:1、显⽰该点周围雷的个数2、第⼀次下⼦,不炸死3、坐标周围没雷,可以实现展开4、游戏结束后展⽰玩家⽤时效果展⽰话不多说,先附上效果图:设计思路我们只要输⼊坐标就可以扫雷了,是不是很有趣?其实要想实现这也不难,我们要⽤⼏个算法模块来模拟游戏规则,需要⽤函数来调⽤各个模块使游戏跑起来。
那么第⼀步我们就要构思⼀个棋盘,看见上⾯第⼀张图没,在开始游戏的界⾯我打印了两个棋盘,有0和1的棋盘是给我们设计者看的,它可以显⽰出当前雷的真实分布,这有利于我们测试代码的正确性,⽽全是 * 的棋盘是给玩家扫雷⽤的。
那我们就需要⽤⼆维数组来打印两个棋盘,假如我们要打印10X10的棋盘,那我们的⼆维数组元素也要为10X10个吗?,不能,因为我们在设计算法时需要统计坐标周围8个⽅位雷的个数,假如要统计边界坐标周围雷的个数,那么就会有数组越界的问题,那我们就要在10X10的边界多上⼀圈元素,也就要定义12X12的数组元素,这些元素我们不要打印出来,⼼⾥有数就⾏,如下图:#define row 12#define col 12show_mine[row][col];//玩家数组real_mine[row][col];//设计者数组我们在⼀个项⽬⾥建⽴三个源⽂件,如下:1、我们打印设计者棋盘要⽤数组real_mine,打印玩家棋盘要⽤数组show_mine,两个数组在开始必须要初始化,在设计者棋盘中字符0代表不是雷,字符1代表雷,先初始化两个数组代码如下:void init_mine()//初始化两个雷阵{int i = 0;int j = 0;for (int i = 0; i < row; i++){for (j = 0; j < col; j++){show_mine[i][j] = '*';real_mine[i][j] = '0';}}}2、打印两个雷阵(不要忘了打印横竖序号以便确定坐标)void print_player()//打印玩家棋盘{int i = 0;int j = 0;printf("0 ");for (i = 1; i <row-1; i++){printf("%d ", i);//打印横标(0--10)}printf("\n");for (i = 1; i <row-2; i++)//打印竖标(1--10){printf("%d ", i);for (j = 1; j < col-1; j++){printf("%c ", show_mine[i][j]);//玩家棋盘数组}printf("\n");}printf("10 ");//开始打印最后⼀⾏for (i = 1; i < row-1; i++){printf("%c ", show_mine[10][i]);}printf("\n");}void print_mine()//打印设计者棋盘{int i = 0;int j = 0;printf("0 ");for (i = 1; i <row - 1; i++){printf("%d ", i);//打印横标(0--10)}printf("\n");for (i = 1; i <row - 2; i++)//打印竖标(1--10){printf("%c ", real_mine[i][j]);}printf("\n");}printf("10 ");//开始打印最后⼀⾏for (i = 1; i < row - 1; i++){printf("%c ", real_mine[10][i]);}printf("\n");}3、我们在每⼀次玩的时候设计者棋盘中的雷分布都必须不相同,使⽤随机数⽣成横竖坐标确定布雷坐标,代码如下:void set_mine()//给设计者棋盘布雷{int x = 0;int y = 0;int count = COUNT;//雷总数while (count)//雷布完后跳出循环{int x = rand() % 10 + 1;//产⽣1到10的随机数,在数组下标为1到10的范围内布雷int y = rand() % 10 + 1;//产⽣1到10的随机数,在数组下标为1到10的范围内布雷if (real_mine[x][y] == '0')//找不是雷的地⽅布雷{real_mine[x][y] = '1';count--;}}}4、为了统计当前坐标周围雷的个数,定义⼀个函数实现:int count_mine(int x, int y)//检测周围8个区域雷的个数{int count = 0;if (real_mine[x - 1][y - 1] == '1')count++;if (real_mine[x - 1][y] == '1')count++;if (real_mine[x - 1][y + 1] == '1')count++;if (real_mine[x][y - 1] == '1')count++;if (real_mine[x][y + 1] == '1')count++;if (real_mine[x + 1][y - 1] == '1')count++;if (real_mine[x + 1][y] == '1')count++;if (real_mine[x + 1][y + 1] == '1')count++;return count;}5、为了确保第⼀次不被雷炸死,我们需要定义个函数来实现,如果第⼀次选到雷就将这颗雷放在其他不是雷的地⽅,代码如下:void safe_mine()//避免第⼀次炸死{int x = 0;int y = 0;char ch = 0;int count = 0;int ret = 1;printf("输⼊坐标扫雷\n");while (1){scanf("%d%d", &x, &y);//只能输⼊1到10,输⼊错误重新输⼊if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判断输⼊坐标是否有误{if (real_mine[x][y] == '1')//第⼀次踩到雷后补救show_mine[x][y] = ch + '0';//数字对应的ASCII值和数字字符对应的ASCII值相差48,即'0'的ASCII值open_mine(x, y);while (ret)//在其余有空的地⽅设置⼀个雷{int x = rand() % 10 + 1;//产⽣1到10的随机数,在数组下标为1到10的范围内布雷int y = rand() % 10 + 1;//产⽣1到10的随机数,在数组下标为1到10的范围内布雷if (real_mine[x][y] == '0')//找不是雷的地⽅布雷{real_mine[x][y] = '1';ret--;break;}}break;//跳出此函数}if (real_mine[x][y] == '0'){char ch = count_mine(x, y);show_mine[x][y] = ch + '0';//数字对应的ASCII值和数字字符对应的ASCII值相差48,即'0'的ASCII值open_mine(x, y);break;}}else//坐标错误{printf("输⼊错误重新输⼊\n");}}}6、为了实现展开功能,需要展开函数模块(展开的坐标还要显⽰其坐标周围的雷数),如下:void open_mine(int x, int y)//坐标周围展开函数{if (real_mine[x - 1][y - 1]== '0'){show_mine[x - 1][y - 1] = count_mine(x - 1, y - 1) + '0';//显⽰该坐标周围雷数}if (real_mine[x - 1][y] == '0'){show_mine[x - 1][y] = count_mine(x - 1, y) + '0';//显⽰该坐标周围雷数}if (real_mine[x - 1][y + 1] == '0'){show_mine[x - 1][y + 1] = count_mine(x - 1, y + 1) + '0';//显⽰该坐标周围雷数}if (real_mine[x][y - 1] == '0'){show_mine[x][y - 1] = count_mine(x, y - 1) + '0';//显⽰该坐标周围雷数}if (real_mine[x][y + 1] == '0'){show_mine[x][y + 1] = count_mine(x, y + 1) + '0';//显⽰该坐标周围雷数}if (real_mine[x + 1][y - 1] == '0'){show_mine[x + 1][y - 1] = count_mine(x + 1, y - 1) + '0';//显⽰该坐标周围雷数}if (real_mine[x + 1][y] == '0'){show_mine[x + 1][y] = count_mine(x + 1, y) + '0';//显⽰该坐标周围雷数}if (real_mine[x + 1][y + 1] == '0'){show_mine[x + 1][y + 1] = count_mine(x + 1, y + 1) + '0';//显⽰该坐标周围雷数}}7、扫雷函数是⼀个重要的模块,代码如下:int sweep_mine()//扫雷函数,踩到雷返回1,没有踩到雷返回0{int x = 0;int y = 0;if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判断输⼊坐标是否有误,输⼊错误重新输⼊{if (real_mine[x][y] == '0')//没踩到雷{char ch = count_mine(x,y);show_mine[x][y] = ch+'0';//数字对应的ASCII值和数字字符对应的ASCII值相差48,即'0'的ASCII值open_mine(x, y);if (count_show_mine() == COUNT)//判断剩余未知区域的个数,个数为雷数时玩家赢{print_mine();printf("玩家赢!\n\n");return 0;}}else if (real_mine[x][y]=='1')//踩到雷{return 1;}}else{printf("输⼊错误重新输⼊\n");}return 0;//没踩到雷}到最后需要确定游戏胜利的条件,我们要统计当前状态玩家棋盘中显⽰的剩余 * 的个数,如果个数等于总雷数时说明扫雷完成,游戏胜利,定义⼀个函数实现:int count_show_mine()//判断剩余未知区域的个数,个数为雷数时玩家赢{int count = 0;int i = 0;int j = 0;for (i = 1; i <= row - 2; i++){for (j = 1; j <= col - 2; j++){if (show_mine[i][j] == '*'){count++;}}}return count;}我们将以上函数的定义放在 game.c ⽂件中以上就是我们要实现扫雷的模块,要想把这些模块整合起来运⾏,就需要⼀个游戏执⾏函数来调⽤这些模块,定义个game()函数实现,代码如下:#define _CRT_SECURE_NO_WARNINGS 1#include"game.h"double start, finish;void game(){int ret = 0;init_mine();//初始化玩家棋盘和设计者棋盘set_mine();//给设计者棋盘布雷print_mine();//打印设计者棋盘(可不打印)printf("\n");print_player();//打印玩家棋盘start = clock();safe_mine();//避免第⼀次被炸死if (count_show_mine() == COUNT)//⼀步就赢的情况{print_mine();while (1)//循环扫雷{int ret=sweep_mine();//扫雷,踩到雷返回1,没有踩到雷返回0if (count_show_mine() == COUNT)//若玩家棋盘的'*'个数为雷数时,扫雷完成,游戏胜利 {print_mine();//打印设计者棋盘printf("玩家赢!\n\n");finish = clock();//取结束时间printf("⽤时%d 秒\n",(int) (finish - start) / CLOCKS_PER_SEC);break;}if (ret)//判断是否踩到雷{printf("被雷炸死\t");finish = clock();//取结束时间printf("⽤时%d 秒\n", (int)(finish - start) / CLOCKS_PER_SEC);print_mine();//打印设计者雷阵查看雷的分布break;}print_player();//打印玩家棋盘}}int main(){srand((unsigned int)time(NULL));//产⽣随机数⽣成器int input = 0;muen();//菜单do{scanf("%d", &input);switch (input){case 1:game();break;case 0:exit(1);//退出游戏break;default:printf("输⼊错误,重新输⼊\n");break;}muen();printf("contiue?\n");} while (1);//循环玩游戏system("pause");return 0;}在头⽂件game.h中声明各种函数:game.h#ifndef __GAME_H__#define __GAME__H__#include<stdio.h>#include<stdlib.h>#include<string.h>#include<time.h>#define row 12#define col 12#define COUNT 10//棋盘中雷的总数extern char show_mine[row][col];//展⽰数组extern char real_mine[row][col];//布雷数组void muen();//菜单函数void init_mine();//初始化数组函数void set_mine();//布雷函数int count_mine();//统计周围雷的个数void print_player();//打印玩家棋盘void print_mine();//打印设计者棋盘int sweep_mine();//扫雷函数#endif //__GAME_H__将上⾯这个函数放在main.c⽂件中以上我们便完成了扫雷的所有C语⾔代码,接下来我们测验⼀下:1、检测第⼀次是否能不被炸死2、检测周围没雷可以展开总结测试显⽰我们的代码没有问题,我们总结⼀下,这个程序的难点的就是如何实现展开和和保证第⼀次不被炸死,如果你仔细理解以上的程序,你就会明⽩其中的原理,包括为什么要在数组元素周围多⼀圈元素,这些模块都是游戏的核⼼,等你掌握了这个程序,你的逻辑思维能⼒就会有很⼤的提⾼!附game.c⽂件源码:#define _CRT_SECURE_NO_WARNINGS 1#include"game.h"char show_mine[row][col] = { 0 };char real_mine[row][col] = { 0 };void muen(){printf("*******************************\n");printf("*****1.play 0.exit*******\n");printf("*******************************\n");}void init_mine()//初始化两个棋盘{int i = 0;int j = 0;for (int i = 0; i < row; i++){for (j = 0; j < col; j++){}}void print_player()//打印玩家棋盘{int i = 0;int j = 0;printf("0 ");for (i = 1; i <row-1; i++){printf("%d ", i);//打印横标(0--10)}printf("\n");for (i = 1; i <row-2; i++)//打印竖标(1--10){printf("%d ", i);for (j = 1; j < col-1; j++){printf("%c ", show_mine[i][j]);//玩家棋盘数组}printf("\n");}printf("10 ");//开始打印最后⼀⾏for (i = 1; i < row-1; i++){printf("%c ", show_mine[10][i]);}printf("\n");}void print_mine()//打印设计者棋盘{int i = 0;int j = 0;printf("0 ");for (i = 1; i <row - 1; i++){printf("%d ", i);//打印横标(0--10)}printf("\n");for (i = 1; i <row - 2; i++)//打印竖标(1--10){printf("%d ", i);for (j = 1; j < col - 1; j++){printf("%c ", real_mine[i][j]);}printf("\n");}printf("10 ");//开始打印最后⼀⾏for (i = 1; i < row - 1; i++){printf("%c ", real_mine[10][i]);}printf("\n");}void set_mine()//给设计者棋盘布雷{int x = 0;int y = 0;int count = COUNT;//雷总数while (count)//雷布完后跳出循环{int x = rand() % 10 + 1;//产⽣1到10的随机数,在数组下标为1到10的范围内布雷 int y = rand() % 10 + 1;//产⽣1到10的随机数,在数组下标为1到10的范围内布雷 if (real_mine[x][y] == '0')//找不是雷的地⽅布雷{real_mine[x][y] = '1';count--;int count_mine(int x, int y)//检测周围8个区域雷的个数{int count = 0;if (real_mine[x - 1][y - 1] == '1')count++;if (real_mine[x - 1][y] == '1')count++;if (real_mine[x - 1][y + 1] == '1')count++;if (real_mine[x][y - 1] == '1')count++;if (real_mine[x][y + 1] == '1')count++;if (real_mine[x + 1][y - 1] == '1')count++;if (real_mine[x + 1][y] == '1')count++;if (real_mine[x + 1][y + 1] == '1')count++;return count;}void safe_mine()//避免第⼀次炸死{int x = 0;int y = 0;char ch = 0;int count = 0;int ret = 1;printf("输⼊坐标扫雷\n");while (1){scanf("%d%d", &x, &y);//只能输⼊1到10,输⼊错误重新输⼊if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判断输⼊坐标是否有误{if (real_mine[x][y] == '1')//第⼀次踩到雷后补救{real_mine[x][y] = '0';char ch = count_mine(x, y);show_mine[x][y] = ch + '0';//数字对应的ASCII值和数字字符对应的ASCII值相差48,即'0'的ASCII值 open_mine(x, y);while (ret)//在其余有空的地⽅设置⼀个雷{int x = rand() % 10 + 1;//产⽣1到10的随机数,在数组下标为1到10的范围内布雷int y = rand() % 10 + 1;//产⽣1到10的随机数,在数组下标为1到10的范围内布雷if (real_mine[x][y] == '0')//找不是雷的地⽅布雷{real_mine[x][y] = '1';ret--;break;}}break;//跳出此函数}if (real_mine[x][y] == '0'){char ch = count_mine(x, y);show_mine[x][y] = ch + '0';//数字对应的ASCII值和数字字符对应的ASCII值相差48,即'0'的ASCII值 open_mine(x, y);break;}}else//坐标错误{printf("输⼊错误重新输⼊\n");}}}int sweep_mine()//扫雷函数,踩到雷返回1,没有踩到雷返回0{printf("输⼊坐标扫雷\n");scanf("%d%d", &x, &y);//只能输⼊1到10if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判断输⼊坐标是否有误,输⼊错误重新输⼊{if (real_mine[x][y] == '0')//没踩到雷{char ch = count_mine(x,y);show_mine[x][y] = ch+'0';//数字对应的ASCII值和数字字符对应的ASCII值相差48,即'0'的ASCII值 open_mine(x, y);if (count_show_mine() == COUNT)//判断剩余未知区域的个数,个数为雷数时玩家赢{print_mine();printf("玩家赢!\n\n");return 0;}}else if (real_mine[x][y]=='1')//踩到雷{return 1;}}else{printf("输⼊错误重新输⼊\n");}return 0;//没踩到雷}void open_mine(int x, int y)//坐标周围展开函数{if (real_mine[x - 1][y - 1]== '0'){show_mine[x - 1][y - 1] = count_mine(x - 1, y - 1) + '0';//显⽰该坐标周围雷数}if (real_mine[x - 1][y] == '0'){show_mine[x - 1][y] = count_mine(x - 1, y) + '0';//显⽰该坐标周围雷数}if (real_mine[x - 1][y + 1] == '0'){show_mine[x - 1][y + 1] = count_mine(x - 1, y + 1) + '0';//显⽰该坐标周围雷数}if (real_mine[x][y - 1] == '0'){show_mine[x][y - 1] = count_mine(x, y - 1) + '0';//显⽰该坐标周围雷数}if (real_mine[x][y + 1] == '0'){show_mine[x][y + 1] = count_mine(x, y + 1) + '0';//显⽰该坐标周围雷数}if (real_mine[x + 1][y - 1] == '0'){show_mine[x + 1][y - 1] = count_mine(x + 1, y - 1) + '0';//显⽰该坐标周围雷数}if (real_mine[x + 1][y] == '0'){show_mine[x + 1][y] = count_mine(x + 1, y) + '0';//显⽰该坐标周围雷数}if (real_mine[x + 1][y + 1] == '0'){show_mine[x + 1][y + 1] = count_mine(x + 1, y + 1) + '0';//显⽰该坐标周围雷数}}int count_show_mine()//判断剩余未知区域的个数,个数为雷数时玩家赢{int count = 0;int i = 0;int j = 0;for (i = 1; i <= row - 2; i++){for (j = 1; j <= col - 2; j++){if (show_mine[i][j] == '*'){count++;}}}return count;}以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。