第一篇:C语言程序设计扫雷游戏
C语言程序设计报告
题目: 扫雷小游戏设计
电子通信与物理学院 日期:2018年7月 12 日
指导教师评语
目录
1.课程设计内容...........................................................................................................1 2.课程设计目的...........................................................................................................1 3.背景知识..................................................................................................................1 4.工具/准备工作..........................................................................................................3 5.设计步骤、方法.....................................................................................................3
5.1........................................................................................................................3 5.2定义全局变量..................................................................................................4 5.3挖雷部分函数的分析.......................................................................................5 6.设计结果及分析.....................................................................................................11 7.设计结论...............................................................................................................16 8.参考文献...............................................................................................................17 附录...........................................................................................................................17
1.课程设计内容
在计算机逐步渗入社会生活各个层面的今天,计算机已经成为人们日常生活的一分,越来越多的人使用计算机办公、娱乐等等。
扫雷游戏是Windows操作系统自带的一款小游戏,在过去的几年里,Windows操作系统历经数次换代更新,变得越来越庞大、复杂,功能也越来越强大,但是这款小游戏依然保持原来的容貌,可见这款小游戏受到越来越多人的喜爱。我利用C-free编写了与它功能相仿的挖地雷游戏,寓学于乐。
即:设计一个功能与Windows中的挖雷游戏相同的小游戏。
2.课程设计目的
1.培养学生综合运用所学知识独立完成课题的能力。
2.试学生更深入地理解和掌握该课程中的有关基本概念,程序设计思想和方法。3.提高对工作认真负责、一丝不苟,对同学团结友爱,协作攻关的基本素质。4.培养勇于探索、严谨推理、实事求是、有错必改,用实践来检验理论,全方位考虑问题等科学技术人员应具有的素质。
5.培养从资料文献、科学实验中获得知识的能力,提高从别人经验中找到解决问题的新途径的悟性,初步培养工程意识和创新能力。
6.对掌握知识的深度、运用理论去处理问题的能力、实验能力、课程设计能力、书面及口头表达能力进行考核
3.背景知识
游戏区包括雷区、地雷计数器(位于左上角,记录剩余地雷数)和计时器(位于 右上角,记录游戏时间),确定大小的矩形雷区中随机布置一定数量的地雷(初级为9*9个方块10个雷,中级为16*16个方块40个雷,高级为16*30个方块99个雷,自定义级别可以自己设定雷区大小和雷数,但是雷区大小不能超过24*30),玩家需要尽快找出雷区中的所有不是地雷的方块,而不许踩到地雷。
游戏的基本操作包括左键单击(Left Click)、右键单击(Right Click)、双击(Chording)三种。其中左键用于打开安全的格子,推进游戏进度;右键用于标记地雷,以辅助判断,或为接下来的双击做准备;双击在一个数字周围的地雷标记完时,相当于对数字周围未打开的方块均进行一次左键单击操作:
左键单击:在判断出不是雷的方块上按下左键,可以打开该方块。如果方块上出现数字,则该数字表示其周围3×3区域中的地雷数(一般为8个格子,对于边块为5个格子,对于角块为3个格子。所以扫雷中最大的数字为8);如果方块上为空(相当于0),则可以递归地打开与空相邻的方块;如果不幸触雷,则游戏结束。
双击:同时按下左键和右键完成双击。当双击位置周围已标记雷数等于该位置数字时操作有效,相当于对该数字周围未打开的方块均进行一次左键单击操作。地雷未标记完全时使用双击无效。若数字周围有标错的地雷,则游戏结束,标错的地雷上会显示一个“ ×”(见下图)
扫雷的设计原理: 扫雷游戏分为几个步骤: 第一步,使用二维数组表示地图; 第二步,随机生成几个地雷;
第三步,点击方格的反应,计算每个非雷区方格点开后的数字; 第四步,当方格数字为0的情况; 第五步,当方格为地雷的情况。
第一步地图的大小和第二步地雷的数量都应该是程序中给定的,或者玩家输入的。这个是多少自己决定吧。第三步,计算非雷区方格点开后的数字就把这个方格在二维数组中周围八个方向的方格是否是地雷都检查一遍,一定要注意不要越出数组边界。这个数字可以在游戏初始化时全都计算好,也可以在玩家点击的时候再计算。点 击非雷区方格,显示数字,这个方格标记为“已点过”。第四步,当方格数字为0时,这里要用到递归调用,就是让程序自动“点击”这个数字为0方格周围的八个方格,然后再看结果,如果不是0,就停止,如果是0,依然递归调用,直到没有0为止,或者直到点遍所有方格为止,一定要注意不要越出数组边界。第五步,很简单,宣布玩家死亡就可以了。
4.准备工作
查阅相关资料,了解扫雷的的玩法,了解扫雷的设计思想方法。借鉴他人写过的程序,从中找到突破口。从程序中了解需要的各种函数准备,再进一步获悉该函数的功能与使用方法。
对自己要设计的挖地雷游戏进行功能分析,大致如下:
总体游戏过程分析:在屏幕上显示一个游戏界面,雷区范围内预先埋设了一定数量的随机分布的地雷(用数字9代替地雷);玩家通过从键盘中输入(行数X,列数Y)↙进行点击;若能点中所有非雷区,则游戏胜利;否则踩雷,游戏失败。简易版扫雷游戏要具备以下功能:
1)开局:首先选择游戏等级,然后生成不同等级的雷区界面。游戏等级分 为三级:各等级行列数为———:简单:10×
10、普通:15×
15、困难:20×20;雷区每个*号下面或埋藏有1个地雷,或者没有地雷;
2)挖雷:从键盘中输入(行数X,列数Y),并按回车键,可挖开它;若所揭方块下有9,则踩雷,此时所有含地雷的块都出现9,该局游戏失败;如果方块上出现数字,它代表 在它周围的8个方块中共有多少颗地雷;
3)输入:通过键盘输入相关指示信息; 4)输出:提示游戏失败,是否继续再来一遍;
5.设计步骤、方法 5.1主函数第一步,写出主程序的基本框架,确定各子模块名字和参数。具体的函数流程如图5-3 所示:
定义使用到的常数、全局变量、函数原型说明。然后初始化图形系统,调用游戏控制函数,游戏只接受键盘,通过鼠标结束游戏,关闭系统,退出游戏。
主控模块的各子模块说明:
void InitialValue_game()用于棋盘初始化; InitialMine_game()用于棋盘的随机布雷; void print_game()用于打印棋盘; int judge_game()用于判断游戏是否结束; int openmap()用于点开地图;
5.2定义全局变量
#include
5.3挖雷部分函数的分析
void InitialValue_game(struct Games *g){ int i,j;for(i=0;i InitialMine_game(struct Games *g){ 5 int i,j,next1,next2;int sum=0;srand((unsigned)time(NULL));while(1){ i=rand()%x;j=rand()%y;if((*g).game_int[i][j]==9)continue;(*g).game_int[i][j]=9;++sum;for(next1=-1;next1<2;next1++){ for(next2=-1;next2<2;next2++){ if(-1 void print_game(struct Games *g,int Logo){ int i,j;int a[s];for(i=0;i int judge_game(struct Games *g){ int sum=0;int i,j;for(i=0;i 运行第一步: 按ENTER键进入: 11 选择游戏难度(简单、普通、困难、任意),按ENTER键进入: 简单难度: 普通难度: 困难难度: 任意难度: 游戏界面,开始从键盘输入数字,格式为(行数X,列数Y),点击Enter键: 游戏结束页面: 7.设计结论 一学期结束了,对C语言也有了一些认识,不过自我感觉学得不太好,好在还是学到了知识: 了解了C的发展以及编程的基本步骤,学会了Printf输出语句,C语言的运算,知道了有哪几种数据类型,还有我觉得经常用的if语句,if--eles语句,for循环,while 语句,do-while语句等等,基本会用数组和指针,还有字符串的处理,对了还有才学的结构体。 还有许多知识点,不一罗列了,总之C语言要学的东西太多了,听大三的都说C很简单,但我并不认为他像人们说的那样简单,C是最基础的,基础不代表简单,也可能是我没学好才有这样的感受。 在这次设计过程中,不仅复习课本上所学知识,还通过查资料、问同学学到了课本上没有的知识。从而启发我,要想写好程序,在写好课本知识的同时还需要多读和专业有关的一些书籍,同时还需要多动脑子,尽量把所学的知识综合起来应用,力争写出完美的程序。除此之外,我还得到了一些有用的教训:写程序时必须要细心,不能输错一个字符标点,就连全角半角也得注意。在修改时要有耐心,编译出错后必须逐个错误去改正,绝不能心急浮躁,否则修改之后还会有新的错误。 8.参考文献 郭翠英主编的《C语言课程设计实例精编》; 张芳妮 吕波 译《C语言编程常见问题解答》; 谭浩强《C程序设计题解与上机指导(第二版)》。伍俊良.VB课程设计与系统开发案例[M].北京 附录: #include main(){ int i,j;/*定义i,j变量*/ int NO;int begin=1;int h;/*确定雷的个数*/ while(begin){ printf(“nnnnnnn” “ttt=================================n” “ttt 欢迎进入扫雷 nnn” “ttt 按回车键继续 n” “ttt=================================n” “ttt n”);getchar();/*游戏开始界面*/ system(“cls”);printf(“ nnnnnnnnn”);printf(“ 请选择游戏难度:nn”);printf(“ 1简单难度nn”);printf(“ 2普通难度nn”);printf(“ 3困难难度nn”);printf(“ 4自定义难度nn”);scanf(“%d”,&h);getchar();/*确定游戏难度*/ if(0 void InitialValue_game(struct Games *g){ int i,j;for(i=0;i InitialMine_game(struct Games *g){ int i,j,next1,next2;int sum=0;srand((unsigned)time(NULL));while(1){ i=rand()%x;j=rand()%y;if((*g).game_int[i][j]==9)continue;(*g).game_int[i][j]=9;++sum;for(next1=-1;next1<2;next1++){ for(next2=-1;next2<2;next2++){ if(-1 void print_game(struct Games *g,int Logo){ int i,j;int a[s];for(i=0;i int judge_game(struct Games *g){ int sum=0;int i,j;for(i=0;i 中南大学 程序设计基础实践报告 学生姓名 张兰兰 学 院 信息科学与工程学院 专业班级 物联网工程1301班 完成时间 2014.1 题 目 设计一个和window系统类似的小游戏【挖地雷】 《计算机程序设计实践》403591717.docx 目录 1.课程设计内容.............................................................................................3 2.课程设计目的.............................................................................................3 3.背景知识....................................................................................................3 4.工具/准备工作............................................................................................5 5.设计步骤、方法.........................................................................................5 5.1.步骤1:步骤名称(二级标题).......................................................错误!未定义书签。 步骤1.1:步骤名称(三级标题)..............................................................................5 5.1.1.5.2.5.3.步骤2:步骤名称..........................................................................错误!未定义书签。步骤n:步骤名称..........................................................................错误!未定义书签。 6.设计结果及分析.........................................................................................5 7.设计结论..................................................................................................15 8.问题及心得体会.......................................................................................16 9.对本设计过程及方法、手段的改进建议....................................................17 10.参考文献..................................................................................................17 《计算机程序设计实践》403591717.docx printf(“请输入棋盘行列数(小于20且用逗号隔开):”); scanf(“%d,%d”,&x,&y); getchar(); printf(“请输入雷的个数:”); scanf(“%d”,&b); getchar(); break; } break; } else { printf(“输入错误请重新输n”); } } while(begin){ system(“cls”); InitialValue_game(&g); InitialMine_game(&g); print_game(&g,2); NO=1; while(NO) { printf(“Please choose:”); scanf(“%d,%d”,&i,&j);getchar();if(-1 { switch(openmap(&g,i-1,j-1)) { case 1: print_game(&g,1); printf(“游戏结束!按回车键再来一局n”); 《计算机程序设计实践》403591717.docx if(getchar()=='n')begin=1; else begin=0; NO=0; break; case 2: if(judge_game(&g)==b) { printf(“win!n”); print_game(&g,1); printf(“按回车键再来一局n”); if(getchar()=='n')begin=1; else begin=0; NO=0; break; } else print_game(&g,2);NO=1;break; default:break; } } else { printf(“你输入错误!请重新输入n”); } } } } 中南大学 程序设计基础实践报告 学生姓名 张兰兰 学 院 信息科学与工程学院 专业班级 物联网工程1301班 完成时间 2014.1 题 目 设计一个和window系统类似的小游戏【挖地雷】 《计算机程序设计实践》错误!未指定书签。 目录 1.课程设计内容.............................................................................................3 2.课程设计目的.............................................................................................3 3.背景知识....................................................................................................3 4.工具/准备工作............................................................................................5 5.设计步骤、方法.........................................................................................5 5.1.步骤1:步骤名称(二级标题).......................................................错误!未定义书签。 步骤1.1:步骤名称(三级标题)..............................................................................5 5.1.1.5.2.5.3.步骤2:步骤名称..........................................................................错误!未定义书签。步骤n:步骤名称..........................................................................错误!未定义书签。 6.设计结果及分析.........................................................................................5 7.设计结论..................................................................................................15 8.问题及心得体会.......................................................................................16 9.对本设计过程及方法、手段的改进建议....................................................17 10.参考文献..................................................................................................17 《计算机程序设计实践》错误!未指定书签。 case 4: system(“cls”); printf(“请输入棋盘行列数(小于20且用逗号隔开):”); scanf(“%d,%d”,&x,&y); getchar(); printf(“请输入雷的个数:”); scanf(“%d”,&b); getchar(); break; } break; } else { printf(“输入错误请重新输n”); } } while(begin){ system(“cls”); InitialValue_game(&g); InitialMine_game(&g); print_game(&g,2); NO=1; while(NO) { printf(“Please choose:”); scanf(“%d,%d”,&i,&j);getchar();if(-1 { switch(openmap(&g,i-1,j-1)) { case 1: 《计算机程序设计实践》错误!未指定书签。 print_game(&g,1); printf(“游戏结束!按回车键再来一局n”); if(getchar()=='n')begin=1; else begin=0; NO=0; break; case 2: if(judge_game(&g)==b) { printf(“win!n”); print_game(&g,1); printf(“按回车键再来一局n”); if(getchar()=='n')begin=1; else begin=0; NO=0; break; } else print_game(&g,2);NO=1;break; default:break; } } else { printf(“你输入错误!请重新输入n”); } } } } C语言扫雷源代码.txt如果背叛是一种勇气,那么接受背叛则需要更大的勇气。爱情是块砖,婚姻是座山。砖不在多,有一块就灵;山不在高,守一生就行。#include /*鼠标信息宏定义*/ #define WAITING 0xff00 #define LEFTPRESS 0xff01 #define LEFTCLICK 0xff10 #define LEFTDRAG 0xff19 #define RIGHTPRESS 0xff02 #define RIGHTCLICK 0xff20 #define RIGHTDRAG 0xff2a #define MIDDLEPRESS 0xff04 #define MIDDLECLICK 0xff40 #define MIDDLEDRAG 0xff4c #define MOUSEMOVE 0xff08 struct { int num;/*格子当前处于什么状态,1有雷,0已经显示过数字或者空白格子*/ int roundnum;/*统计格子周围有多少雷*/ int flag;/*右键按下显示红旗的标志,0没有红旗标志,1有红旗标志*/ }Mine[10][10]; int gameAGAIN=0;/*是否重来的变量*/ int gamePLAY=0;/*是否是第一次玩游戏的标志*/ int mineNUM;/*统计处理过的格子数*/ char randmineNUM[3];/*显示数字的字符串*/ int Keystate;int MouseExist;int MouseButton;int MouseX;int MouseY;int up[16][16],down[16][16],mouse_draw[16][16],pixel_save[16][16]; void MouseMath()/*计算鼠标的样子*/ {int i,j,jj,k;long UpNum[16]={ 0x3fff,0x1fff,0x0fff,0x07ff, 0x03ff,0x01ff,0x00ff,0x007f, 0x003f,0x00ff,0x01ff,0x10ff, 0x30ff,0xf87f,0xf87f,0xfc3f };long DownNum[16]={ 0x0000,0x7c00,0x6000,0x7000, 0x7800,0x7c00,0x7e00,0x7f00, 0x7f80,0x7e00,0x7c00,0x4600, 0x0600,0x0300,0x0300,0x0180 };for(i=0;i<16;i++){ j=jj=15;while(UpNum[i]!=0){ up[i][j]=UpNum[i]%2;j--;UpNum[i]/=2;} while(DownNum[i]!=0){ down[i][jj--]=DownNum[i]%2;DownNum[i]/=2;} for(k=j;k>=0;k--)up[i][k]=0;for(k=jj;k>=0;k--)down[i][k]=0;for(k=0;k<16;k++)/*四种组合方式*/ { if(up[i][k]==0&&down[i][k]==0)mouse_draw[i][k]=1;else if(up[i][k]==0&&down[i][k]==1)mouse_draw[i][k]=2;else if(up[i][k]==1&&down[i][k]==0)mouse_draw[i][k]=3;else mouse_draw[i][k]=4;} } mouse_draw[1][2]=4;/*特殊点*/ } void Init(void);/*图形驱动*/ void MouseOn(int,int);/*鼠标光标显示*/ void MouseOff(void);/*鼠标光标隐藏*/ void MouseSetXY(int,int);/*设置当前位置*/ int LeftPress(void);/*左键按下*/ int RightPress(void);/*鼠标右键按下*/ int MiddlePress();void MouseGetXY(void);/*得到当前位置*/ int MouseStatus();void Control(void);/*游戏开始,重新,关闭*/ void GameBegain(void);/*游戏开始画面*/ void DrawSmile(void);/*画笑脸*/ void DrawRedflag(int,int);/*显示红旗*/ void DrawEmpty(int,int,int,int);/*两种空格子的显示*/ void GameOver(void);/*游戏结束*/ void GameWin(void);/*显示胜利*/ int MineStatistics(int,int);/*统计每个格子周围的雷数*/ int ShowWhite(int,int);/*显示无雷区的空白部分*/ void GamePlay(void);/*游戏过程*/ void Close(void);/*图形关闭*/ void main(void){ Init();MouseMath();//MouseOn(MouseX,MouseY);Control();Close();} void Init(void)/*图形开始*/ { int gd=DETECT,gm;registerbgidriver(EGAVGA_driver);initgraph(&gd,&gm,“");} void Close(void)/*图形关闭*/ { closegraph();} /*鼠标光标显示*/ void MouseOn(int x,int y){ int i,j;int color; for(i=0;i<16;i++)/*画鼠标*/ { for(j=0;j<16;j++){ pixel_save[i][j]=getpixel(x+j,y+i);/*保存原来的颜色*/ if(mouse_draw[i][j]==1)putpixel(x+j,y+i,0);else if(mouse_draw[i][j]==2)putpixel(x+j,y+i,15);} } } /*隐藏鼠标*/ void MouseOff(){ int i,j,x,y,color;x=MouseX;y=MouseY;for(i=0;i<16;i++)/*原位置异或消去*/ for(j=0;j<16;j++){ if(mouse_draw[i][j]==3||mouse_draw[i][j]==4)continue;color=getpixel(x+j,y+i);putpixel(x+j,y+i,color^color);putpixel(x+j,y+i,pixel_save[i][j]);} } void MouseSetXY(int x,int y)/*设置当前位置*/ { _CX=x;_DX=y;_AX=0x04;geninterrupt(0x33);} int LeftPress(void)/*鼠标左键按下*/ { _AX=0x03;geninterrupt(0x33);return(_BX&1);} int RightPress(void)/*鼠标右键按下*/ { _AX=0x03;geninterrupt(0x33);return(_BX&2);} /*是否按下中键 返回值同上 */ int MiddlePress(){ _AX=0x03;geninterrupt(0x33);return(_BX&4);} void MouseGetXY(void)/*得到当前位置*/ { _AX=0x03;geninterrupt(0x33);MouseX=_CX;MouseY=_DX;} /*鼠标按键情况,返回0表示只移动,返回1表示左右键同时按下,2表示只按了左键,3表示只按了右键*/ int MouseStatus(){ int x,y;int status;int press=0; int i,j,color;status=0;/*默认鼠标没有移动*/ x=MouseX;y=MouseY; while(x==MouseX&&y==MouseY&&status==0&&press==0){ if(LeftPress()&&RightPress())press=1;else if(LeftPress())press=2;else if(RightPress())press=3;MouseGetXY();if(MouseX!=x||MouseY!=y)status=1;} if(status)/*移动情况才重新显示鼠标*/ { for(i=0;i<16;i++)/*原位置异或消去*/ for(j=0;j<16;j++){ if(mouse_draw[i][j]==3||mouse_draw[i][j]==4)continue;color=getpixel(x+j,y+i);putpixel(x+j,y+i,color^color);putpixel(x+j,y+i,pixel_save[i][j]);} MouseOn(MouseX,MouseY);/*新位置显示*/ } if(press!=0)/*有按键的情况*/ return press;return 0;/*只移动的情况*/ } void Control(void)/*游戏开始,重新,关闭*/ { int gameFLAG=1;/*游戏失败后判断是否重新开始的标志*/ while(1){ MouseStatus();if(gameFLAG)/*游戏失败后没判断出重新开始或者退出游戏的话就继续判断*/ { GameBegain();/*游戏初始画面*/ GamePlay();/*具体游戏*/ if(gameAGAIN==1)/*游戏中重新开始*/ { gameAGAIN=0;continue;} } gameFLAG=0;if(LeftPress())/*判断是否重新开始*/ { if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85){ gameFLAG=1;continue;} } if(kbhit())/*判断是否按键退出*/ break;} } void DrawSmile(void)/*画笑脸*/ { MouseOff();setfillstyle(SOLID_FILL,YELLOW);fillellipse(290,75,10,10);setcolor(YELLOW);setfillstyle(SOLID_FILL,BLACK);/*眼睛*/ fillellipse(285,75,2,2);fillellipse(295,75,2,2);setcolor(BLACK);/*嘴巴*/ bar(287,80,293,81);MouseGetXY();MouseOn(MouseX,MouseY);} void DrawRedflag(int i,int j)/*显示红旗*/ { MouseOff();setcolor(7);setfillstyle(SOLID_FILL,RED);bar(198+j*20,95+i*20,198+j*20+5,95+i*20+5);setcolor(BLACK);line(198+j*20,95+i*20,198+j*20,95+i*20+10);MouseGetXY();MouseOn(MouseX,MouseY);} void DrawEmpty(int i,int j,int mode,int color)/*两种空格子的显示*/ { MouseOff();setcolor(color);setfillstyle(SOLID_FILL,color);if(mode==0)/*没有单击过的大格子*/ bar(200+j*20-8,100+i*20-8,200+j*20+8,100+i*20+8);else if(mode==1)/*单击过后显示空白的小格子*/ bar(200+j*20-7,100+i*20-7,200+j*20+7,100+i*20+7);MouseGetXY();MouseOn(MouseX,MouseY);} void GameBegain(void)/*游戏开始画面*/ { int i,j;cleardevice();if(gamePLAY!=1){ MouseSetXY(290,70);/*鼠标一开始的位置,并作为它的初始坐标*/ MouseX=290;MouseY=70;} gamePLAY=1;/*下次按重新开始的话鼠标不重新初始化*/ mineNUM=0;setfillstyle(SOLID_FILL,7);bar(190,60,390,290);for(i=0;i<10;i++)/*画格子*/ for(j=0;j<10;j++)DrawEmpty(i,j,0,8);setcolor(7);DrawSmile();/*画脸*/ randomize();for(i=0;i<10;i++)/*100个格子随机赋值有没有地雷*/ for(j=0;j<10;j++){ Mine[i][j].num=random(8);/*如果随机数的结果是1表示这个格子有地雷*/ if(Mine[i][j].num==1)mineNUM++;/*现有雷数加1*/ else Mine[i][j].num=2;Mine[i][j].flag=0;/*表示没红旗标志*/ } sprintf(randmineNUM,”%d“,mineNUM);/*显示这次总共有多少雷数*/ setcolor(1);settextstyle(0,0,2);outtextxy(210,70,randmineNUM);mineNUM=100-mineNUM;/*变量取空白格数量*/ } void GameOver(void)/*游戏结束画面*/ { int i,j;setcolor(0);for(i=0;i<10;i++)for(j=0;j<10;j++)if(Mine[i][j].num==1)/*显示所有的地雷*/ { DrawEmpty(i,j,0,RED);setfillstyle(SOLID_FILL,BLACK);MouseOff();fillellipse(200+j*20,100+i*20,7,7); MouseGetXY();MouseOn(MouseX,MouseY);} } void GameWin(void)/*显示胜利*/ { setcolor(11);settextstyle(0,0,2);outtextxy(230,30,”YOU WIN!“);} int MineStatistics(int i,int j)/*统计每个格子周围的雷数*/ { int nNUM=0;if(i==0&&j==0)/*左上角格子的统计*/ { if(Mine[0][1].num==1)nNUM++;if(Mine[1][0].num==1)nNUM++;if(Mine[1][1].num==1)nNUM++;} else if(i==0&&j==9)/*右上角格子的统计*/ { if(Mine[0][8].num==1)nNUM++;if(Mine[1][9].num==1)nNUM++;if(Mine[1][8].num==1)nNUM++;} else if(i==9&&j==0)/*左下角格子的统计*/ { if(Mine[8][0].num==1)nNUM++;if(Mine[9][1].num==1)nNUM++;if(Mine[8][1].num==1)nNUM++;} else if(i==9&&j==9)/*右下角格子的统计*/ { if(Mine[9][8].num==1)nNUM++;if(Mine[8][9].num==1)nNUM++;if(Mine[8][8].num==1)nNUM++;} else if(j==0)/*左边第一列格子的统计*/ { if(Mine[i][j+1].num==1)nNUM++;if(Mine[i+1][j].num==1)nNUM++;if(Mine[i-1][j].num==1)nNUM++;if(Mine[i-1][j+1].num==1)nNUM++;if(Mine[i+1][j+1].num==1)nNUM++;} else if(j==9)/*右边第一列格子的统计*/ { if(Mine[i][j-1].num==1)nNUM++;if(Mine[i+1][j].num==1)nNUM++;if(Mine[i-1][j].num==1)nNUM++;if(Mine[i-1][j-1].num==1)nNUM++;if(Mine[i+1][j-1].num==1)nNUM++;} else if(i==0)/*第一行格子的统计*/ { if(Mine[i+1][j].num==1)nNUM++;if(Mine[i][j-1].num==1)nNUM++;if(Mine[i][j+1].num==1)nNUM++;if(Mine[i+1][j-1].num==1)nNUM++;if(Mine[i+1][j+1].num==1)nNUM++;} else if(i==9)/*最后一行格子的统计*/ { if(Mine[i-1][j].num==1)nNUM++;if(Mine[i][j-1].num==1)nNUM++;if(Mine[i][j+1].num==1)nNUM++;if(Mine[i-1][j-1].num==1)nNUM++;if(Mine[i-1][j+1].num==1)nNUM++;} else/*普通格子的统计*/ { if(Mine[i-1][j].num==1)nNUM++;if(Mine[i-1][j+1].num==1)nNUM++;if(Mine[i][j+1].num==1)nNUM++;if(Mine[i+1][j+1].num==1)nNUM++;if(Mine[i+1][j].num==1)nNUM++;if(Mine[i+1][j-1].num==1)nNUM++;if(Mine[i][j-1].num==1)nNUM++;if(Mine[i-1][j-1].num==1)nNUM++;} return(nNUM);/*把格子周围一共有多少雷数的统计结果返回*/ } int ShowWhite(int i,int j)/*显示无雷区的空白部分*/ { if(Mine[i][j].flag==1||Mine[i][j].num==0)/*如果有红旗或该格处理过就不对该格进行任何判断*/ return;mineNUM--;/*显示过数字或者空格的格子就表示多处理了一个格子,当所有格子都处理过了表示胜利*/ if(Mine[i][j].roundnum==0&&Mine[i][j].num!=1)/*显示空格*/ { DrawEmpty(i,j,1,7); Mine[i][j].num=0;} else if(Mine[i][j].roundnum!=0)/*输出雷数*/ { DrawEmpty(i,j,0,8);sprintf(randmineNUM,”%d“,Mine[i][j].roundnum);setcolor(RED);MouseOff();outtextxy(195+j*20,95+i*20,randmineNUM);MouseGetXY();MouseOn(MouseX,MouseY);Mine[i][j].num=0;/*已经输出雷数的格子用0表示已经用过这个格子*/ return;} /*8个方向递归显示所有的空白格子*/ if(i!=0&&Mine[i-1][j].num!=1)ShowWhite(i-1,j);if(i!=0&&j!=9&&Mine[i-1][j+1].num!=1)ShowWhite(i-1,j+1);if(j!=9&&Mine[i][j+1].num!=1)ShowWhite(i,j+1);if(j!=9&&i!=9&&Mine[i+1][j+1].num!=1)ShowWhite(i+1,j+1);if(i!=9&&Mine[i+1][j].num!=1)ShowWhite(i+1,j);if(i!=9&&j!=0&&Mine[i+1][j-1].num!=1)ShowWhite(i+1,j-1);if(j!=0&&Mine[i][j-1].num!=1)ShowWhite(i,j-1);if(i!=0&&j!=0&&Mine[i-1][j-1].num!=1)ShowWhite(i-1,j-1);} void GamePlay(void)/*游戏过程*/ { int i,j,Num;/*Num用来接收统计函数返回一个格子周围有多少地雷*/ for(i=0;i<10;i++)for(j=0;j<10;j++)Mine[i][j].roundnum=MineStatistics(i,j);/*统计每个格子周围有多少地雷*/ while(!kbhit()){ MouseStatus();if(LeftPress())/*鼠标左键盘按下*/ { if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85)/*重新来*/ { gameAGAIN=1;break;} if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*当前鼠标位置在格子范围内*/ { j=(MouseX-190)/20;/*x坐标*/ i=(MouseY-90)/20;/*y坐标*/ if(Mine[i][j].flag==1)/*如果格子有红旗则左键无效*/ continue;if(Mine[i][j].num!=0)/*如果格子没有处理过*/ { if(Mine[i][j].num==1)/*鼠标按下的格子是地雷*/ { GameOver();/*游戏失败*/ break;} else/*鼠标按下的格子不是地雷*/ { Num=MineStatistics(i,j);if(Num==0)/*周围没地雷就用递归算法来显示空白格子*/ ShowWhite(i,j);else/*按下格子周围有地雷*/ { MouseOff();sprintf(randmineNUM,”%d",Num);/*输出当前格子周围的雷数*/ setcolor(RED);outtextxy(195+j*20,95+i*20,randmineNUM);mineNUM--; MouseGetXY();MouseOn(MouseX,MouseY);} Mine[i][j].num=0;/*点过的格子周围雷数的数字变为0表示这个格子已经用过*/ if(mineNUM<1)/*胜利了*/ { GameWin();break;} } } } } if(RightPress())/*鼠标右键键盘按下*/ { if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*当前鼠标位置在格子范围内*/ { j=(MouseX-190)/20;/*x坐标*/ i=(MouseY-90)/20;/*y坐标*/ if(Mine[i][j].flag==0&&Mine[i][j].num!=0)/*本来没红旗现在显示红旗*/ { DrawRedflag(i,j);Mine[i][j].flag=1;} else if(Mine[i][j].flag==1)/*有红旗标志再按右键就红旗消失*/ { DrawEmpty(i,j,0,8);Mine[i][j].flag=0;} } delay(1000000);delay(1000000);delay(1000000);delay(1000000);delay(1000000);} } } 编游戏 C语言程序设计案例精编.txt让人想念而死,是谋杀的至高境界,就连法医也鉴定不出死因。。。C语言 编游戏案例精编 案例一 贪吃蛇游戏 #define N 200 #include food.x++;while(food.y%10!=0) food.y++; food.yes=0;/*画面上有食物了*/ } if(food.yes==0)/*画面上有食物了就要显示*/ { setcolor(GREEN);rectangle(food.x,food.y,food.x+10,food.y-10);} for(i=snake.node-1;i>0;i--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/ { snake.x[i]=snake.x[i-1];snake.y[i]=snake.y[i-1];} /*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/ switch(snake.direction){ case 1:snake.x[0]+=10;break;case 2: snake.x[0]-=10;break;case 3: snake.y[0]-=10;break;case 4: snake.y[0]+=10;break;} for(i=3;i snake.direction=2;else if(key==DOWN&&snake.direction!=3) snake.direction=4;}/*endwhile(1)*/ } /*游戏结束*/ void GameOver(void){ cleardevice();PrScore();setcolor(RED);settextstyle(0,0,4);outtextxy(200,200,“GAME OVER”);getch();} /*输出成绩*/ void PrScore(void){ char str[10];setfillstyle(SOLID_FILL,YELLOW);bar(50,15,220,35);setcolor(6);settextstyle(0,0,2);sprintf(str,“score:%d”,score);outtextxy(55,20,str);} /*图形结束*/ void Close(void){ getch();closegraph();} 案例二 计算器 #include x=x0; m=0;} else { x=x+width+width/2; m++;} /*否则,右移到下一个字符位置*/ if(v==LEFT)/*左移箭头时新位置计算*/ if(x<=x0){ x=x0+6*width; m=4;} /*如果移到头,再左移,则移动到最右边字符位置*/ else { x=x-width-width/2; m--;} /*否则,左移到前一个字符位置*/ if(v==UP)/*上移箭头时新位置计算*/ if(y<=y0){ y=y0+4*height+height/2; n=3;} /*如果移到头,再上移,则移动到最下边字符位置*/ else { y=y-height-height/2;n--;} /*否则,移到上边一个字符位置*/ if(v==DOWN)/*下移箭头时新位置计算*/ if(y>=7*height){ y=y0;n=0;} /*如果移到尾,再下移,则移动到最上边字符位置*/ else { y=y+height+height/2; n++;} /*否则,移到下边一个字符位置*/ putimage(x,y,rar,XOR_PUT);/*在新的位置显示光标箭头*/ } c=str1[n*5+m];/*将字符保存到变量c中*/ if(isdigit(c)||c=='.')/*判断是否是数字或小数点*/ { if(flag==-1)/*如果标志为-1,表明为负数*/ { strcpy(str2,”-“);/*将负号连接到字符串中*/ flag=1;} /*将标志值恢复为1*/ sprintf(temp,”%c“,c);/*将字符保存到字符串变量temp中*/ strcat(str2,temp);/*将temp中的字符串连接到str2中*/ setfillstyle(SOLID_FILL,color+3);bar(2*width+width/2,height/2,15*width/2,3*height/2);outtextxy(5*width,height,str2);/*显示字符串*/ } if(c=='+'){ num1=atof(str2);/*将第一个操作数转换为浮点数*/ strcpy(str2,”“);/*将str2清空*/ act=1;/*做计算加法标志值*/ setfillstyle(SOLID_FILL,color+3);bar(2*width+width/2,height/2,15*width/2,3*height/2);outtextxy(5*width,height,”0.“);/*显示字符串*/ } if(c=='-'){ if(strcmp(str2,”“)==0)/*如果str2为空,说明是负号,而不是减号*/ flag=-1;/*设置负数标志*/ else { num1=atof(str2);/*将第二个操作数转换为浮点数*/ strcpy(str2,”“);/*将str2清空*/ act=2;/*做计算减法标志值*/ setfillstyle(SOLID_FILL,color+3);bar(2*width+width/2,height/2,15*width/2,3*height/2);/*画矩形*/ outtextxy(5*width,height,”0.“);/*显示字符串*/ } } if(c=='*'){ num1=atof(str2);/*将第二个操作数转换为浮点数*/ strcpy(str2,”“);/*将str2清空*/ act=3;/*做计算乘法标志值*/ setfillstyle(SOLID_FILL,color+3);bar(2*width+width/2,height/2,15*width/2,3*height/2);outtextxy(5*width,height,”0.“);/*显示字符串*/ } if(c=='/'){ num1=atof(str2);/*将第二个操作数转换为浮点数*/ strcpy(str2,”“);/*将str2清空*/ act=4;/*做计算除法标志值*/ setfillstyle(SOLID_FILL,color+3);bar(2*width+width/2,height/2,15*width/2,3*height/2);outtextxy(5*width,height,”0.“);/*显示字符串*/ } if(c=='^'){ num1=atof(str2);/*将第二个操作数转换为浮点数*/ strcpy(str2,”“);/*将str2清空*/ act=5;/*做计算乘方标志值*/ setfillstyle(SOLID_FILL,color+3);/*设置用淡绿色实体填充*/ bar(2*width+width/2,height/2,15*width/2,3*height/2);/*画矩形*/ outtextxy(5*width,height,”0.“);/*显示字符串*/ } if(c=='%'){ num1=atof(str2);/*将第二个操作数转换为浮点数*/ strcpy(str2,”“);/*将str2清空*/ act=6;/*做计算模运算乘方标志值*/ setfillstyle(SOLID_FILL,color+3);/*设置用淡绿色实体填充*/ bar(2*width+width/2,height/2,15*width/2,3*height/2);/*画矩形*/ outtextxy(5*width,height,”0.“);/*显示字符串*/ } if(c=='='){ num2=atof(str2);/*将第二个操作数转换为浮点数*/ switch(act)/*根据运算符号计算*/ { case 1:result=num1+num2;break;/*做加法*/ case 2:result=num1-num2;break;/*做减法*/ case 3:result=num1*num2;break;/*做乘法*/ case 4:result=num1/num2;break;/*做除法*/ case 5:result=pow(num1,num2);break;/*做x的y次方*/ case 6:result=fmod(num1,num2);break;/*做模运算*/ } setfillstyle(SOLID_FILL,color+3);/*设置用淡绿色实体填充*/ bar(2*width+width/2,height/2,15*width/2,3*height/2);/*覆盖结果区*/ sprintf(temp,”%f“,result);/*将结果保存到temp中*/ outtextxy(5*width,height,temp);/*显示结果*/ } if(c=='c'){ num1=0;/*将两个操作数复位0,符号标志为1*/ num2=0;flag=1;strcpy(str2,”“);/*将str2清空*/ setfillstyle(SOLID_FILL,color+3);/*设置用淡绿色实体填充*/ bar(2*width+width/2,height/2,15*width/2,3*height/2);/*覆盖结果区*/ outtextxy(5*width,height,”0.“);/*显示字符串*/ } if(c=='Q')exit(0);/*如果选择了q回车,结束计算程序*/ } putimage(x,y,rar,XOR_PUT);/*在退出之前消去光标箭头*/ return;/*返回*/ } /*窗口函数*/ void mwindow(char *header){ int height;cleardevice(); /* 清除图形屏幕 */ setcolor(MaxColors1);/*设置当前颜色为白色 */ setlinestyle(SOLID_LINE, 0, NORM_WIDTH);/*设置画线方式*/ getviewsettings(&vp);/*将当前视口信息装入vp所指的结构中*/ rectangle(0, 0, vp.right-vp.left, vp.bottom-vp.top);/*画矩形边框*/ } /*设计鼠标图形函数*/ int arrow(){ int size;int raw[]={4,4,4,8,6,8,14,16,16,16,8,6,8,4,4,4};/*定义多边形坐标*/ setfillstyle(SOLID_FILL,2);/*设置填充模式*/ fillpoly(8,raw);/*画出一光标箭头*/ size=imagesize(4,4,16,16);/*测试图象大小*/ rar=malloc(size);/*分配内存区域*/ getimage(4,4,16,16,rar);/*存放光标箭头图象*/ putimage(4,4,rar,XOR_PUT);/*消去光标箭头图象*/ return 0;} /*按键函数*/ int specialkey(void){ int key;while(bioskey(1)==0);/*等待键盘输入*/ key=bioskey(0);/*键盘输入*/ key=key&0xff? key&0xff:key>>8;/*只取特殊键的扫描值,其余为0*/ return(key);/*返回键值*/ } 案例三 黑白棋游戏 #include ”graphics.h“ /*图形系统头文件*/ #define LEFT 0x4b00 /*光标左键值*/ #define RIGHT 0x4d00 /*光标右键值*/ #define DOWN 0x5000 /*光标下键值*/ #define UP 0x4800 /*光标上键值*/ #define ESC 0x011b /* ESC键值*/ #define ENTER 0x1c0d /* 回车键值*/ int a[8][8]={0},key,score1,score2;/*具体分数以及按键与存放棋子的变量*/ char playone[3],playtwo[3];/*两个人的得分转换成字符串输出*/ void playtoplay(void);/*人人对战函数*/ void DrawQp(void);/*画棋盘函数*/ void SetPlayColor(int x);/*设置棋子第一次的颜色*/ void MoveColor(int x,int y);/*恢复原来棋盘状态*/ int QpChange(int x,int y,int z);/*判断棋盘的变化*/ void DoScore(void);/*处理分数*/ void PrintScore(int n);/*输出成绩*/ void playWin(void);/*输出胜利者信息*/ /******主函数*********/ void main(void){ int gd=DETECT,gr;initgraph(&gd,&gr,”c: c“);/*初始化图形系统*/ DrawQp();/*画棋盘*/ playtoplay();/*人人对战*/ getch();closegraph();/*关闭图形系统*/ } void DrawQp()/*画棋盘*/ { int i,j;score1=score2=0;/*棋手一开始得分都为0*/ setbkcolor(BLUE);for(i=100;i<=420;i+=40){ line(100,i,420,i);/*画水平线*/ line(i,100,i,420);/*画垂直线*/ } setcolor(0);/*取消圆周围的一圈东西*/ setfillstyle(SOLID_FILL,15);/*白色实体填充模式*/ fillellipse(500,200,15,15);/*在显示得分的位置画棋*/ setfillstyle(SOLID_FILL,8);/*黑色实体填充模式*/ fillellipse(500,300,15,15);a[3][3]=a[4][4]=1;/*初始两个黑棋*/ a[3][4]=a[4][3]=2;/*初始两个白棋*/ setfillstyle(SOLID_FILL,WHITE);fillellipse(120+3*40,120+3*40,15,15);fillellipse(120+4*40,120+4*40,15,15);setfillstyle(SOLID_FILL,8);fillellipse(120+3*40,120+4*40,15,15);fillellipse(120+4*40,120+3*40,15,15);score1=score2=2;/*有棋后改变分数*/ DoScore();/*输出开始分数*/ } void playtoplay()/*人人对战*/ { int x,y,t=1,i,j,cc=0;while(1)/*换棋手走棋*/ { x=120,y=80;/*每次棋子一开始出来的坐标,x为行坐标,y为列坐标*/ while(1)/*具体一个棋手走棋的过程*/ { PrintScore(1);/*输出棋手1的成绩*/ PrintScore(2);/*输出棋手2的成绩*/ SetPlayColor(t);/*t变量是用来判断棋手所执棋子的颜色*/ fillellipse(x,y,15,15);key=bioskey(0);/*接收按键*/ if(key==ESC)/*跳出游戏*/ break;else if(key==ENTER)/*如果按键确定就可以跳出循环*/ { if(y!=80&&a[(x-120)/40][(y-120)/40]!=1 &&a[(x-120)/40][(y-120)/40]!=2)/*如果落子位置没有棋子*/ { if(t%2==1)/*如果是棋手1移动*/ a[(x-120)/40][(y-120)/40]=1;else/*否则棋手2移动*/ a[(x-120)/40][(y-120)/40]=2;if(!QpChange(x,y,t))/*落子后判断棋盘的变化*/ { a[(x-120)/40][(y-120)/40]=0;/*恢复空格状态*/ cc++;/*开始统计尝试次数*/ if(cc>=64-score1-score2)/*如果尝试超过空格数则停步*/ { MoveColor(x,y); fillellipse(x,y,15,15); break;} else continue;/*如果按键无效*/ } DoScore();/*分数的改变*/ break;/*棋盘变化了,则轮对方走棋*/ } else/*已经有棋子就继续按键*/ continue;} else /*四个方向按键的判断*/ if(key==LEFT&&x>120)/*左方向键*/ { MoveColor(x,y);fillellipse(x,y,15,15);SetPlayColor(t);x-=40;fillellipse(x,y,15,15);} else if(key==RIGHT&&x<400&&y>80)/*右方向键*/ { MoveColor(x,y);fillellipse(x,y,15,15);SetPlayColor(t);x+=40;fillellipse(x,y,15,15);} else if(key==UP&&y>120)/*上方向键*/ { MoveColor(x,y);fillellipse(x,y,15,15);SetPlayColor(t);y-=40;fillellipse(x,y,15,15);} else if(key==DOWN&&y<400)/*下方向键*/ { MoveColor(x,y);fillellipse(x,y,15,15);SetPlayColor(t);y+=40;fillellipse(x,y,15,15);} } if(key==ESC)/*结束游戏*/ break;if((score1+score2)==64||score1==0||score2==0)/*格子已经占满或一方棋子为0判断胜负*/ { playWin();/*输出最后结果*/ break;} t=t%2+1;/*一方走后,改变棋子颜色即轮对方走*/ cc=0;/*计数值恢复为0*/ } /*endwhile*/ } void SetPlayColor(int t)/*设置棋子颜色*/ { if(t%2==1)setfillstyle(SOLID_FILL,15);/*白色*/ else setfillstyle(SOLID_FILL,8);/*灰色*/ } void MoveColor(int x,int y)/*走了一步后恢复原来格子的状态*/ { if(y<100)/*如果是从起点出发就恢复蓝色*/ setfillstyle(SOLID_FILL,BLUE);else/*其他情况如果是1就恢复白色棋子,2恢复黑色棋子,或恢复蓝色棋盘*/ switch(a[(x-120)/40][(y-120)/40]){ case 1: setfillstyle(SOLID_FILL,15);break;/*白色*/ case 2: setfillstyle(SOLID_FILL,8);break;/*黑色*/ default: setfillstyle(SOLID_FILL,BLUE);/*蓝色*/ } } int QpChange(int x,int y,int t)/*判断棋盘的变化*/ { int i,j,k,kk,ii,jj,yes;yes=0;i=(x-120)/40;/*计算数组元素的行下标*/ j=(y-120)/40;/*计算数组元素的列下标*/ SetPlayColor(t);/*设置棋子变化的颜色*/ /*开始往8个方向判断变化*/ if(j<6)/*往右边*/ { for(k=j+1;k<8;k++)if(a[i][k]==a[i][j]||a[i][k]==0)/*遇到自己的棋子或空格结束*/ break;if(a[i][k]!=0&&k<8){ for(kk=j+1;kk 案例四 迷宫问题 #include DrawPeople(&x,&y,4);/*右下*/ else if(c=='x'&&map[x+1][y]!=1) DrawPeople(&x,&y,5);/*下*/ else if(c=='z'&&map[x+1][y-1]!=1) DrawPeople(&x,&y,6);/*左下*/ else if(c=='a'&&map[x][y-1]!=1) DrawPeople(&x,&y,7);/*左*/ else if(c=='q'&&map[x-1][y-1]!=1) DrawPeople(&x,&y,8);/*左上*/ } setfillstyle(SOLID_FILL,WHITE);/*消去红色探索物,恢复原迷宫图*/ bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6);if(x==N-2&&y==N-2)/*人工控制找成功的话*/ yes=1;/*如果成功标志为1*/ } void WayCopy(int(*oldmap)[N],int(*map)[N])/*拷贝迷宫数组 */ { int i,j;for(i=0;i 案例五 扫地雷游戏 #include if(i==9&&j==9)/*右下角格子的统计*/ { if(Mine[9][8].num==1)nNUM++;if(Mine[8][9].num==1)nNUM++;if(Mine[8][8].num==1)nNUM++;} else if(j==0)/*左边第一列格子的统计*/ { if(Mine[i][j+1].num==1)nNUM++;if(Mine[i+1][j].num==1)nNUM++;if(Mine[i-1][j].num==1)nNUM++;if(Mine[i-1][j+1].num==1)nNUM++;if(Mine[i+1][j+1].num==1)nNUM++;} else if(j==9)/*右边第一列格子的统计*/ { if(Mine[i][j-1].num==1)nNUM++;if(Mine[i+1][j].num==1)nNUM++;if(Mine[i-1][j].num==1)nNUM++;if(Mine[i-1][j-1].num==1)nNUM++;if(Mine[i+1][j-1].num==1)nNUM++;} else if(i==0)/*第一行格子的统计*/ { if(Mine[i+1][j].num==1)nNUM++;if(Mine[i][j-1].num==1)nNUM++;if(Mine[i][j+1].num==1)nNUM++;if(Mine[i+1][j-1].num==1) nNUM++;if(Mine[i+1][j+1].num==1) nNUM++;} else if(i==9)/*最后一行格子的统计*/ { if(Mine[i-1][j].num==1) nNUM++;if(Mine[i][j-1].num==1) nNUM++;if(Mine[i][j+1].num==1) nNUM++;if(Mine[i-1][j-1].num==1) nNUM++;if(Mine[i-1][j+1].num==1) nNUM++;} else/*普通格子的统计*/ { if(Mine[i-1][j].num==1) nNUM++;if(Mine[i-1][j+1].num==1) nNUM++;if(Mine[i][j+1].num==1) nNUM++;if(Mine[i+1][j+1].num==1) nNUM++;if(Mine[i+1][j].num==1) nNUM++;if(Mine[i+1][j-1].num==1) nNUM++;if(Mine[i][j-1].num==1) nNUM++;if(Mine[i-1][j-1].num==1) nNUM++;} return(nNUM);/*把格子周围一共有多少雷数的统计结果返回*/ } int ShowWhite(int i,int j)/*显示无雷区的空白部分*/ { if(Mine[i][j].flag==1||Mine[i][j].num==0)/*如果有红旗或该格处理过就不对该格进行任何判断*/ return;mineNUM--;/*显示过数字或者空格的格子就表示多处理了一个格子,当所有格子都处理过了表示胜利*/ if(Mine[i][j].roundnum==0&&Mine[i][j].num!=1)/*显示空格*/ { DrawEmpty(i,j,1,7);Mine[i][j].num=0;} else if(Mine[i][j].roundnum!=0)/*输出雷数*/ { DrawEmpty(i,j,0,8);sprintf(randmineNUM,”%d“,Mine[i][j].roundnum);setcolor(RED);outtextxy(195+j*20,95+i*20,randmineNUM);Mine[i][j].num=0;/*已经输出雷数的格子用0表示已经用过这个格子*/ return;} /*8个方向递归显示所有的空白格子*/ if(i!=0&&Mine[i-1][j].num!=1)ShowWhite(i-1,j);if(i!=0&&j!=9&&Mine[i-1][j+1].num!=1)ShowWhite(i-1,j+1);if(j!=9&&Mine[i][j+1].num!=1)ShowWhite(i,j+1);if(j!=9&&i!=9&&Mine[i+1][j+1].num!=1)ShowWhite(i+1,j+1);if(i!=9&&Mine[i+1][j].num!=1)ShowWhite(i+1,j);if(i!=9&&j!=0&&Mine[i+1][j-1].num!=1)ShowWhite(i+1,j-1);if(j!=0&&Mine[i][j-1].num!=1)ShowWhite(i,j-1);if(i!=0&&j!=0&&Mine[i-1][j-1].num!=1)ShowWhite(i-1,j-1);} void GamePlay(void)/*游戏过程*/ { int i,j,Num;/*Num用来接收统计函数返回一个格子周围有多少地雷*/ for(i=0;i<10;i++)for(j=0;j<10;j++)Mine[i][j].roundnum=MineStatistics(i,j);/*统计每个格子周围有多少地雷*/ while(!kbhit()){ if(LeftPress())/*鼠标左键盘按下*/ { */ */ MouseGetXY();if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85)/*重新来*/ { MouseOff();gameAGAIN=1;break;} if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*当前鼠标位置在格子范围内 { j=(MouseX-190)/20;/*x坐标*/ i=(MouseY-90)/20;/*y坐标*/ if(Mine[i][j].flag==1)/*如果格子有红旗则左键无效*/ continue;if(Mine[i][j].num!=0)/*如果格子没有处理过*/ { if(Mine[i][j].num==1)/*鼠标按下的格子是地雷*/ { MouseOff();GameOver();/*游戏失败*/ break;} else/*鼠标按下的格子不是地雷*/ { MouseOff();Num=MineStatistics(i,j);if(Num==0)/*周围没地雷就用递归算法来显示空白格子*/ ShowWhite(i,j);else/*按下格子周围有地雷*/ { sprintf(randmineNUM,”%d“,Num);/*输出当前格子周围的雷数*/ setcolor(RED);outtextxy(195+j*20,95+i*20,randmineNUM);mineNUM--;} MouseOn();Mine[i][j].num=0;/*点过的格子周围雷数的数字变为0表示这个格子已经用过 if(mineNUM<1)/*胜利了*/ { GameWin();break;} } } } } if(RightPress())/*鼠标右键键盘按下*/ { MouseGetXY();if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*当前鼠标位置在格子范围内*/ { j=(MouseX-190)/20;/*x坐标*/ i=(MouseY-90)/20;/*y坐标*/ MouseOff();if(Mine[i][j].flag==0&&Mine[i][j].num!=0)/*本来没红旗现在显示红旗*/ { DrawRedflag(i,j);Mine[i][j].flag=1;} else if(Mine[i][j].flag==1)/*有红旗标志再按右键就红旗消失*/ { DrawEmpty(i,j,0,8);Mine[i][j].flag=0;} } MouseOn();sleep(1);} } } 案例六 速算24 #define N 20 #define COL 100 #define ROW 40 #include ”stdio.h“ #include ”time.h“ /*系统时间函数*/ #include ”graphics.h“ /*图形函数*/ #include ”alloc.h“/*动态地址分配函数*/ #include ”stdlib.h“ /*库函数*/ #include ”string.h“ /*字符串函数*/ #include ”ctype.h“ /*字符操作函数*/ char p[4][13]={ {'A','2','3','4','5','6','7','8','9','0','J','Q','K'},/*扑克牌,10用0来表示*/ {'A','2','3','4','5','6','7','8','9','0','J','Q','K'}, {'A','2','3','4','5','6','7','8','9','0','J','Q','K'}, {'A','2','3','4','5','6','7','8','9','0','J','Q','K'}};typedef struct node { int data;struct node *link;}STACK1;/*栈1*/ typedef struct node2 { char data;struct node2 *link;}STACK2;/*栈2*/ void init(void);/*图形驱动*/ void close(void);/*图形关闭*/ void play(void);/*发牌的具体过程*/ void rand1(int j);/*随机发牌函数*/ void change(char *e,char *a);/*中缀变后缀函数*/ int computer(char *s);/*后缀表达式计算函数*/ STACK1 *initstack1(STACK1 *top);/*栈1初始化*/ STACK1 *push(STACK1 *top,int x);/*栈1入栈运算*/ STACK1 *pop(STACK1 *top);/*栈1删除栈顶元素*/ int topx(STACK1 *top);/*栈1读栈顶元素*/ STACK1 *ptop(STACK1 *top,int *x);/*栈1读出栈顶元素值并删除栈顶元素*/ int empty(STACK1 *top);/*判栈1是否为空函数*/ STACK2 *initstack2(STACK2 *top);/*栈2初始化*/ STACK2 *push2(STACK2 *top,char x);/*栈2入栈运算*/ STACK2 *pop2(STACK2 *top);/*栈2删除栈顶元素*/ char topx2(STACK2 *top);/*栈2读栈顶元素*/ STACK2 *ptop2(STACK2 *top,char *x);/*栈2读出栈顶元素值并删除栈顶元素*/ int empty2(STACK2 *top);/*判栈2是否为空函数* int text1(char *s);/*显示文本*/ main(){ char s[N],s1[N],ch;int i,result;int gdriver, gmode;clrscr();/*清屏*/ init();/*初始化函数*/ while(1){ setbkcolor(BLACK);/*设置背景颜色*/ cleardevice();/*清屏*/ play();/*发牌*/ gotoxy(1,15);/*移动光标*/ printf(”--------------------Note-------------------n“);printf(” Please enter express accroding to above four numbern“);/*提示信息*/ printf(” Format as follows:2.*(5.+7.)n“);/*提示输入字符串格式*/ printf(”---------------n“);scanf(”%s%c“,s1,&ch);/*输入字符串压回车键*/ change(s1,s);/*调用change函数将中缀表达式s1转换为后缀表达式s*/ result=computer(s);/*计算后缀表达式的值,返回结果result */ if(result==24)/*如果结果等于24*/ text1(”very good“);/*调用函数text1显示字符串”very good“*/ else text1(”wrong!!“);/*否则函数text1显示字符串”wrong!!“*/ printf(”Continue(y/n)?n“);/*提示信息,是否继续*/ scanf(”%c“,&ch);/*输入一字符*/ if(ch=='n'||ch=='N')/*如果该字符等于n或N*/ break;/*跳出循环,程序结束*/ } /*否则,开始下一轮循环*/ close();return;/*返回*/ } void rand1(int j)/*随机发牌函数*/ { int kind,num;char str[3],n;randomize();while(1)/*循环直到有牌发*/ { kind=random(4);/*花色随机数*/ num=random(13);/*大小随机数*/ if(p[kind][num]!=-1)/*该数未取过*/ { n=p[kind][num];/*取相应位置的扑克牌数*/ p[kind][num]=-1;/*牌发好以后相应位置的元素置-1*/ break;} } switch(kind)/*花式的判断*/ { case 0:setcolor(RED);sprintf(str,”%c“,3);break;/*红桃*/ case 1:setcolor(BLACK);sprintf(str,”%c“,3);break;/*黑桃*/ case 2:setcolor(RED);sprintf(str,”%c“,4);break;/*方片*/ case 3:setcolor(BLACK);sprintf(str,”%c“,5);break;/*草花*/ } settextstyle(0,0,2);outtextxy(COL+j*100-30,ROW+100-46,str);/*显示左上角花色*/ outtextxy(COL+j*100+16,ROW+100+32,str);/*显示右下角花色*/ if(n!='0')/*输出其他牌*/ { settextstyle(0,0,3);sprintf(str,”%c“,n);outtextxy(COL+j*100-5,ROW+100-5,str);/*显示牌的大小*/ } else/*输出10的时候*/ { sprintf(str,”%d“,10);outtextxy(COL+j*100-6,ROW+100-5,str);} } void play(void)/*发牌的具体过程*/ { int j;for(j=0;j<4;j++){ bar(COL+j*100-35,ROW+100-50,COL+j*100+35,ROW+1*100+50);/*画空牌*/ setcolor(BLUE);rectangle(COL+j*100-32,ROW+100-48,COL+j*100+32,ROW+100+48);/*画矩形框*/ rand1(j);/*随机取牌*/ delay(10000);/*延时显示*/ } } void init(void)/*图形驱动*/ { int gd=DETECT,gm;initgraph(&gd,&gm,”c: c“);cleardevice();} void close(void)/*图形关闭*/ { closegraph();} void change(char *e,char *a)/*中缀字符串e转后缀字符串a函数*/ { STACK2 *top=NULL;/* 定义栈顶指针*/ int i,j;char w;i=0;j=0;while(e[i]!=' ')/*当字符串没有结束时*/ { if(isdigit(e[i]))/*如果字符是数字*/ { do{ a[j]=e[i];/*将数字原样拷贝到数组a中*/ i++;/*e数组的下标加1*/ j++;/*a数组的下标加1*/ }while(e[i]!='.');/*直到字符为数字结束符“.”为止*/ a[j]='.';j++;/*将数字结束符“.”拷贝到a数组依然保持结束标记*/ } if(e[i]=='(')/*如果字符是“(”时*/ top=push2(top,e[i]);/*将其压入堆栈*/ if(e[i]==')')/*如果字符是“)”时*/ { top=ptop2(top,&w);/*取出栈顶元素,并从栈顶删除该元素*/ while(w!='(')/*如果字符不是“(”时反复循环*/ { a[j]=w;/*将栈顶元素存入a数组*/ j++;/*下标加1*/ top=ptop2(top,&w);/*取出栈顶元素,并从栈顶删除该元素*/ } } if(e[i]=='+'||e[i]=='-')/*如果字符是加或减号时*/ { if(!empty2(top))/*如栈不为空*/ { w=topx2(top);while(w!='(')/*当栈顶元素不是“(”时反复循环*/ { a[j]=w;j++;/*将栈顶元素存入表达式a中,a的下标加1*/ top=pop2(top);/*删除栈顶元素*/ if(empty2(top))/*如果栈为空*/ break;/*跳出循环*/ else w=topx2(top);/*否则读栈顶元素*/ } } top=push2(top,e[i]);/*将当前e的字符元素压入堆栈*/ } if(e[i]=='*'||e[i]=='/')/*如果字符是乘或除号时*/ { if(!empty2(top))/*如栈不为空*/ { w=topx2(top);/*读栈顶元素存入w*/ while(w=='*'||w=='/')/*当栈顶元素是乘或除时反复循环*/ { a[j]=w;j++;/*将栈顶元素存入字符串a中,a的下标加1*/ top=pop2(top);/*删除栈顶元素*/ if(empty2(top))/*如果栈为空*/ break;/*跳出循环*/ else w=topx2(top);/*否则读栈顶元素*/ } } top=push2(top,e[i]);/*将当前e字符元素压入堆栈*/ } i++;/*e的下标加1*/ } while(!empty2(top))/*当不为空时反复循环*/ top=ptop2(top,&a[j++]);/*将栈顶元素存入数组a中*/ a[j]=' ';/*将字符串结束标记写入最后一个数组元素中构成字符串*/ } int computer(char *s)/* 计算函数*/ { STACK1 *top=NULL;int i,k,num1,num2,result;i=0;while(s[i]!=' ')/*当字符串没有结束时作以下处理*/ { if(isdigit(s[i]))/*判字符是否为数字*/ { k=0;/*k初值为0*/ do{ k=10*k+s[i]-'0';/*将字符连接为十进制数字*/ i++;/*i加1*/ }while(s[i]!='.');/*当字符不为‘.’时重复循环*/ top=push(top,k);/*将生成的数字压入堆栈*/ } if(s[i]=='+')/*如果为'+'号*/ { top=ptop(top,&num2);/*将栈顶元素取出存入num2中*/ top=ptop(top,&num1);/*将栈顶元素取出存入num1中*/ result=num2+num1;/*将num1和num2相加存入result中*/ top=push(top,result);/*将result压入堆栈*/ } if(s[i]=='-')/*如果为'-'号*/ { top=ptop(top,&num2);/*将栈顶元素取出存入num2中*/ top=ptop(top,&num1);/*将栈顶元素取出存入num1中*/ result=num1-num2;/*将num1减去num2结果存入result中*/ top=push(top,result);/*将result压入堆栈*/ } if(s[i]=='*')/*如果为'*'号*/ { top=ptop(top,&num2);/*将栈顶元素取出存入num2中*/ top=ptop(top,&num1);/*将栈顶元素取出存入num1中*/ result=num1*num2;/*将num1与num2相乘结果存入result中*/ top=push(top,result);/*将result压入堆栈*/ } if(s[i]=='/')/*如果为'/'号*/ { top=ptop(top,&num2);/*将栈顶元素取出存入num2中*/ top=ptop(top,&num1);/*将栈顶元素取出存入num1中*/ result=num1/num2;/*将num1除num2结果存入result中* top=push(top,result);/*将result压入堆栈*/ } i++;/*i加1*/ } top=ptop(top,&result);/*最后栈顶元素的值为计算的结果*/ return result;/*返回结果*/ } STACK1 *initstack1(STACK1 *top)/*初始化*/ { top=NULL;/*栈顶指针置为空*/ return top;/*返回栈顶指针*/ } STACK1 *push(STACK1 *top,int x)/*入栈函数*/ { STACK1 *p;/*临时指针类型为STACK1*/ p=(STACK1 *)malloc(sizeof(STACK1));/*申请STACK1大小的空间*/ if(p==NULL)/*如果p为空*/ { printf(”memory is overflown!“);/*显示内存溢出*/ exit(0);/*退出*/ } p->data=x;/*保存值x到新空间*/ p->link=top;/*新结点的后继为当前栈顶指针*/ top=p;/*新的栈顶指针为新插入的结点*/ return top;/*返回栈顶指针*/ } STACK1 *pop(STACK1 *top)/*出栈*/ { STACK1 *q;/*定义临时变量*/ q=top;/*保存当前栈顶指针*/ top=top->link;/*栈顶指针后移*/ free(q);/*释放q*/ return top;/*返回栈顶指针*/ } int topx(STACK1 *top)/*读栈顶元素*/ { if(top==NULL)/*栈是否为空*/ { printf(”Stack is nulln“);/*显示栈为空信息*/ return 0;/*返回整数0*/ } return top->data;/*返回栈顶元素*/ } STACK1 *ptop(STACK1 *top,int *x)/*取栈顶元素,并删除栈顶元素*/ { *x=topx(top);/*读栈顶元素*/ top=pop(top);/*删除栈顶元素*/ return top;/*返回栈顶指针*/ } int empty(STACK1 *top)/*判栈是否为空*/ { if(top==NULL)/*如果为空*/ return 1;/*返回1*/ else return 0;/*否则返回0*/ } STACK2 *initstack2(STACK2 *top)/*初始化*/ { top=NULL;/*栈顶指针置为空*/ return top;/*返回栈顶指针*/ } STACK2 *push2(STACK2 *top,char x)/*入栈函数*/ { STACK2 *p;/*临时指针类型为STACK2*/ p=(STACK2 *)malloc(sizeof(STACK2));/*申请STACK2大小的空间*/ if(p==NULL)/*如果p为空*/ { printf(”memory is overflown!“);/*显示内存溢出*/ exit(0);/*退出*/ } p->data=x;/*保存值x到新空间*/ p->link=top;/*新结点的后继为当前栈顶指针*/ top=p;/*新的栈顶指针为新插入的结点*/ return top;/*返回栈顶指针*/ } STACK2 *pop2(STACK2 *top)/*出栈*/ { STACK2 *q;/*定义临时变量*/ q=top;/*保存当前栈顶指针*/ top=top->link;/*栈顶指针后移*/ free(q);/*释放q*/ return top;/*返回栈顶指针*/ } char topx2(STACK2 *top)/*读栈顶元素*/ { if(top==NULL)/*栈是否为空*/ { printf(”Stack is nulln“);/*显示栈为空信息*/ return '';/*返回空字符*/ } return top->data;/*返回栈顶元素*/ } STACK2 *ptop2(STACK2 *top,char *x)/*取栈顶元素,并删除栈顶元素*/ { *x=topx2(top);/*读栈顶元素*/ top=pop2(top);/*删除栈顶元素*/ return top;/*返回栈顶指针*/ } int empty2(STACK2 *top)/*判栈是否为空*/ { if(top==NULL)/*如果为空*/ return 1;/*返回1*/ else return 0;/*否则返回0*/ } int text1(char *s){ setbkcolor(BLUE);/*设置背景颜色为蓝色*/ cleardevice();/*清除屏幕*/ setcolor(12);/*设置文本颜色为淡红色*/ settextstyle(1, 0, 8);/*三重笔划字体, 放大8倍*/ outtextxy(120, 120, s);/*输出字符串s*/ setusercharsize(2, 1, 4, 1);/*水平放大2倍, 垂直放大4倍*/ setcolor(15);/*设置文本颜色为*白色/ settextstyle(3, 0, 5);/*无衬字笔划, 放大5倍*/ outtextxy(220, 220, s);/*输出字符串s*/ getch();/*键盘输入任一字符*/ return;/*返回*/ } 案例七 数据结构CAI系统 案例八 进程调度 #include ”stdio.h“ #include ”stdlib.h“ #include ”string.h“ typedef struct node { char name[10];/*进程标识符*/ int prio;/*进程优先数*/ int round;/*进程时间轮转时间片*/ int cputime;/*进程占用CPU时间*/ int needtime;/*进程到完成还要的时间*/ int count;/*计数器*/ char state;/*进程的状态*/ struct node *next;/*链指针*/ }PCB;PCB *finish,*ready,*tail,*run;/*队列指针*/ int N;/*进程数*/ /*将就绪队列中的第一个进程投入运行*/ firstin(){ run=ready;/*就绪队列头指针赋值给运行头指针*/ run->state='R';/*进程状态变为运行态*/ ready=ready->next;/*就绪对列头指针后移到下一进程*/ } /*标题输出函数*/ void prt1(char a){ if(toupper(a)=='P')/*优先数法*/ printf(” name cputime needtime priority staten“);else printf(” name cputime needtime count round staten“);} /*进程PCB输出*/ void prt2(char a,PCB *q){ if(toupper(a)=='P')/*优先数法的输出*/ printf(” %-10s%-10d%-10d%-10d %cn“,q->name, q->cputime,q->needtime,q->prio,q->state);else/*轮转法的输出*/ printf(” %-10s%-10d%-10d%-10d%-10d %-cn“,q->name, q->cputime,q->needtime,q->count,q->round,q->state);} /*输出函数*/ void prt(char algo){ PCB *p;prt1(algo);/*输出标题*/ if(run!=NULL)/*如果运行指针不空*/ prt2(algo,run);/*输出当前正在运行的PCB*/ p=ready;/*输出就绪队列PCB*/ while(p!=NULL){ prt2(algo,p);p=p->next;} p=finish;/*输出完成队列的PCB*/ while(p!=NULL){ prt2(algo,p);p=p->next;} getch();/*压任意键继续*/ } /*优先数的插入算法*/ insert1(PCB *q){ PCB *p1,*s,*r;int b;s=q;/*待插入的PCB指针*/ p1=ready;/*就绪队列头指针*/ r=p1;/*r做p1的前驱指针*/ b=1;while((p1!=NULL)&&b)/*根据优先数确定插入位置*/ if(p1->prio>=s->prio){ r=p1;p1=p1->next;} else b=0;if(r!=p1)/*如果条件成立说明插入在r与p1之间*/ { r->next=s;s->next=p1;} else { s->next=p1;/*否则插入在就绪队列的头*/ ready=s;} } /*轮转法插入函数*/ insert2(PCB *p2){ tail->next=p2;/*将新的PCB插入在当前就绪队列的尾*/ tail=p2;p2->next=NULL;} /*优先数创建初始PCB信息*/ void create1(char alg){ PCB *p;int i,time;char na[10];ready=NULL;/*就绪队列头指针*/ finish=NULL;/*完成队列头指针*/ run=NULL;/*运行队列指针*/ printf(”Enter name and time of processn“);/*输入进程标识和所需时间创建PCB*/ for(i=1;i<=N;i++){ p=malloc(sizeof(PCB));scanf(”%s“,na);scanf(”%d“,&time);strcpy(p->name,na);p->cputime=0;p->needtime=time;p->state='w';p->prio=50-time;if(ready!=NULL)/*就绪队列不空调用插入函数插入*/ insert1(p);else { p->next=ready;/*创建就绪队列的第一个PCB*/ ready=p;} } clrscr();printf(” output of priority:n“);printf(”************************************************n“);prt(alg);/*输出进程PCB信息*/ run=ready;/*将就绪队列的第一个进程投入运行*/ ready=ready->next;run->state='R';} /*轮转法创建进程PCB*/ void create2(char alg){ PCB *p;int i,time;char na[10];ready=NULL;finish=NULL;run=NULL;printf(”Enter name and time of round processn“);for(i=1;i<=N;i++){ p=malloc(sizeof(PCB));scanf(”%s“,na);scanf(”%d“,&time);strcpy(p->name,na);p->cputime=0;p->needtime=time;p->count=0;/*计数器*/ p->state='w';p->round=2;/*时间片*/ if(ready!=NULL)insert2(p);else { p->next=ready;ready=p;tail=p;} } clrscr();printf(” output of roundn“);printf(”************************************************n");prt(alg);/*输出进程PCB信息*/ run=ready;/*将就绪队列的第一个进程投入运行*/ ready=ready->next;run->state='R';} /*优先数调度算法*/ priority(char alg){ while(run!=NULL)/*当运行队列不空时,有进程正在运行*/ { run->cputime=run->cputime+1;run->needtime=run->needtime-1;run->prio=run->prio-3;/*每运行一次优先数降低3个单位*/ if(run->needtime==0)/*如所需时间为0将其插入完成队列*/ { run->next=finish;finish=run;run->state='F';/*置状态为完成态*/ run=NULL;/*运行队列头指针为空*/ if(ready!=NULL)/*如就绪队列不空*/ firstin();/*将就绪对列的第一个进程投入运行*/ } else /*没有运行完同时优先数不是最大,则将其变为就绪态插入到就绪队列*/ if((ready!=NULL)&&(run->prio第二篇:C语言程序设计扫雷游戏实验报告
第三篇:C语言程序设计扫雷游戏实验报告
第四篇:C语言扫雷源代码
第五篇:编游戏 C语言程序设计案例精编