浅析ANSI-C语言中的中断处理(如有疑问,敬请留言)
来源:互联网 发布:lte网络架构图 编辑:程序博客网 时间:2024/06/04 17:39
设置一个好的时钟中断,将能使1个CPU发挥2个CPU的功效,大大方便和简化程序的编制,提高系统的运行效率和可操作性。我们可以把一些例行的或者需要定时执行的时钟中断中,还可以利用时钟中断完成定时、延时等操作。
对于一般的C语言爱好者而言,就如何在C中使用中断例程这一问题应该已经非常熟悉,例如,我们可以通过INT86()函数调用13H号中断直接对磁盘物理扇区进行操作,也可以通过INT86()函数调用33H号中断在屏幕上显示鼠标光标等。其实,13H号也好,33H号也好,它们只不过就是一些函数,这些函数的参数通过CPU的寄存器传递。中断号也只不过是间接地指向函数体的起始内存单元,说它是间接的,也就是说,函数的起始段地址和偏移量是由中断号通过一种方法算得的(具体如何操作,下面会作解释)。如此一来,程序员不必要用太多的时间去写操作硬件的程序了,只要在自己的程序中设置好参数,再调用BIOS或DOS提供的中断服务程序就可以了,大大减小了程序开发难度,缩短了程序开发周期。那么中断既然是函数,就可以由用户任意的调用、由用户任意地编写。
计算机内存的前1024个字节(偏移量00000H到003FFH)保存着256个中断向量,每个中断向量占4个字节,前两个字节保存着中断服务程序的入口地址偏移量,后两个字节保存着中断程序的入口段地址,使用时,只要将它们分别调入寄存器IP及CS中,就可以转入中断服务程序实现中断调用。每当中断发生时,CPU将中断号乘以4,在中断向量表中得到该中断向量地址,进而获得IP及CS值,从而转到中断服务程序的入口地址,调用中断。这就是中断服务程序通过中断号调用的基本过程。在计算机启动的时候,BIOS将基本的中断填入中断向量表,当DOS得到系统控制权后,它又要将一些中断向量填入表中,还要修改一部分BIOS的中断向量。有一部分中断向量是系统为用户保留的,如60H到67H号中断,用户可以将自己的中断服务程序写入这些中断向量中。不仅如此,用户还可以自己更改和完善系统已有的中断向量。
一、键盘中断的设计
例程如下:
/*键盘中断的设计*/#include<stdio.h>#include<dos.h>#include<conio.h>#include<math.h>#include<bios.h>#include<graphics.h>#include<stdlib.h>#include<string.h>/*定义按键*/#define ENTER 7181#define UP 18432#define DOWN 20480#define LEFT 19200#define RIGHT 19712#define LOWERV 12150/*定义delay()函数的间隔,根据电脑的不同请调节数字*/#define TIME 1500#define TIME2 1500/*myi,myj是自己的坐标,number记录豆子数,seed,seed2是种子参数,为产生随机数*/int myi,myj,number=0,seed=0,seed2=100;int a[25][19]; /*a[][]记录每个方格的信息,1墙,6豆子*/int d[4]={2,3,22,22},e[4]={5,16,3,16}; /*记录4个敌人的坐标,d记录横坐标,e纵坐标*/int i,j,k;/*指针记录自己坐标,以便于函数中的操作,具体请看moveright等函数*/int* p1=&myi;int* p2=&myj;int q=0,z=0;char num[4];/*存储画面用*/int size2,size3,size4,size5,size6;void *buffer2;void *buffer3;void *buffer4;void *buffer5;void *buffer6; /*主函数*/int main(){ int graphdriver=VGA; int graphmode=VGAHI; int* moveup(int*,int*); /*该函数,自己向上移动一格,后三个类似*/ int* movedown(int*,int*); int* moveleft(int*,int*); int* moveright(int*,int*); int dmove(int,int); /*怪的移动:和自己拉近距离*/ int dmove2(int,int); /*怪的移动:为了不让怪逼得太紧,该函数产生随机坐标,怪向那个坐标靠近一步*/ int zhadan1(int,int); /*炸弹*/ for(i=0;i<25;i++) /*数组a清零*/ for(j=0;j<19;j++) a[i][j]=0; for(i=0;i<25;i++) /*最边上一圈设为7,(只为了填充颜色表示界限)之后会参数改1,表示墙体*/ a[i][0]=7,a[i][18]=7; for(j=0;j<19;j++) a[0][j]=7,a[24][j]=7; /*以下是墙体*/ a[6][1]=1;a[13][1]=1;a[2][2]=1;a[20][2]=1;a[4][3]=1;a[8][3]=1;a[22][3]=1; a[2][4]=1; a[6][4]=1; a[13][4]=1; a[18][4]=1;a[15][5]=1;a[4][6]=1;a[7][7]=1;a[10][7]=1;a[20][7]=1;a[3][8]=1;a[5][8]=1;a[16][8]=1; a[12][9]=1; a[2][10]=1; a[19][10]=1; a[22][10]=0; a[5][11]=0;a[10][11]=1; a[17][12]=1; a[14][13]=1; a[22][13]=1; a[3][14]=1;a[7][14]=1; a[5][15]=1; a[10][15]=1; a[2][16]=1; a[14][16]=1; a[19][16]=1; a[6][17]=1;a[16][17]=1;a[9][1]=1; a[11][2]=1; a[16][2]=1; a[9][5]=1; a[11][5]=1; a[22][5]=1; a[1][7]=1;a[17][6]=1;a[22][5]=1; a[13][7]=1; a[23][7]=1; a[18][8]=1; a[8][9]=1; a[15][10]=1; a[13][11]=1;a[3][12]=1;a[8][12]=1; a[20][12]=1; a[1][13]=1; a[12][14]=1; a[16][14]=1; a[19][14]=1; a[11][17]=1; /*以下是豆子*/a[15][1]=6;a[18][1]=6;a[3][2]=6;a[18][2]=6;a[22][2]=6;a[7][3]=6;a[9][3]=6;a[11][3]=6;a[13][3]=6;a[1][4]=6;a[15][4]=6;a[20][4]=6;a[5][5]=6;a[13][5]=6;a[16][6]=6;a[19][6]=6;a[2][7]=6;a[15][7]=6;a[1][8]=6;a[9][8]=6;a[10][8]=6;a[11][8]=6;a[15][8]=6;a[6][9]=6;a[9][9]=6;a[17][9]=6;a[21][9]=6;a[3][10]=6;a[9][10]=6;a[10][10]=6;a[11][10]=6;a[16][10]=6;a[1][11]=6;a[8][11]=6;a[6][12]=6;a[9][12]=6;a[12][12]=6;a[16][12]=6;a[4][13]=6;a[9][14]=6;a[21][14]=6;a[17][15]=6;a[3][16]=6;a[7][16]=6;a[13][16]=6;a[9][17]=6;clrscr();initgraph(&graphdriver,&graphmode,"");/*墙体上色,参数1的为淡灰色,参数7的为棕色*/for(i=0;i<25;i++)for(j=0;j<19;j++){if(a[i][j]==1){setfillstyle(1,7);bar(i*25+1,j*25+1,25*i+25,25*j+25);}if(a[i][j]==7){setfillstyle(1,6);bar(i*25+1,j*25+1,25*i+25,25*j+25);}}/*参数7改1,表示墙体,以便于后边统一操作*/for(i=0;i<25;i++)a[i][0]=1,a[i][18]=1;for(j=0;j<19;j++)a[0][j]=1,a[24][j]=1;/*画自己,一个扇形*/setfillstyle(1,4);pieslice(288,238,15,345,11);myi=11,myj=9;/*画敌人*/setfillstyle(8,2);for(i=0;i<4;i++){bar(d[i]*25+3,e[i]*25+3,d[i]*25+24,e[i]*25+24);}/*画豆子*/for(j=1;j<18;j++)for(i=1;i<24;i++) {if(a[i][j]==6) {setfillstyle(1,14);pieslice(i*25+13,j*25+13,0,360,9);}} /*游戏的循环体开始了*/ /*游戏的循环体开始了*/do{int flag=0; /*flag记录游戏状态,1输,2豆子未吃完,继续游戏,0游戏胜利*/int x,y,s=0;int key;/*判断一段时间内是否有按键按下,按下去执行按键判断部分,否则去执行敌人移动部分,用参数S来控制*/for(i=0;i<50;i++){delay(1);if(bioskey(1)!=0){ s=1; break; } }if(s==1){ key=bioskey(0);switch(key){ /*按键判断:前四个方向,最后一个炸弹*/case UP:moveup(&myi,&myj);break;case DOWN:movedown(&myi,&myj);break;case RIGHT:moveright(&myi,&myj);break;case LEFT:moveleft(&myi,&myj);break;case LOWERV:zhadan1(myi,myj);break;}} /*判游戏是否输了*/ for(i=0;i<4;i++){ if(myi==d[i]&&myj==e[i])flag=1; } if(flag==1){printf(" you lose! ");getchar();break; }/*根据敌人的移动,来设置敌人坐标的变化*/for(z=0;z<4;z++)if (q++%3==0) { /*每三次里面有一次为向自己移动,另两次随机动,可以把三改掉来修改游戏难度*/x=dmove(d[z],e[z]);if(x==1)d[z]-- ;else if(x==2)d[z]++ ;else if(x==3)e[z]++ ;else if(x==4)e[z]-- ;}else{y=dmove2(d[z],e[z]);if(y==1)d[z]-- ;else if(y==2)d[z]++ ;else if(y==3)e[z]++ ;else if(y==4)e[z]-- ;}/*左上角显示拥有的豆子数*/setfillstyle(1,8);bar(1,1,150,22);k=number;itoa(k,num,10);settextstyle(1,0,1);outtextxy(1,1," your peas: ");outtextxy(120,1,num);/*敌人移动过了,所以再次判断是否输了*/for(i=0;i<4;i++){ if(myi==d[i]&&myj==e[i])flag=1;}if(flag==1){printf(" you lose! ");getchar();break;}/*判断是否胜利*/for(j=1;j<18;j++)for(i=1;i<24;i++) {if(a[i][j]==6)flag=2;}if(flag==0){printf(" you win! ");getchar();break;}}while(1);} /*自己向右移动的函数:传地址进来,以便直接在函数中改坐标,而不用像怪移动那样在主函数里改坐标*/int* moveright(int *p1 ,int *p2) { if(a[*p1+1][*p2]!=1) /*右边不是墙体才可以动*/ { /*这四行画自己,嘴巴向右*/ setfillstyle(1,0); bar(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25); setfillstyle(1,4); pieslice(*p1*25+13,*p2*25+13,15,345,11); /*保存自己的图像,以便于动画*/ size2=imagesize(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25); buffer2=malloc(size2); getimage(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25,buffer2); /*向右移动时的动画*/for(i=0;i<25;i++){setfillstyle(1,0);bar(*p1*25+i+1,*p2*25+1,*p1*25+i+2,*p2*25+25); /*每次把最左边一条竖线擦掉*/putimage(*p1*25+i+2,*p2*25+1,buffer2,0); /*每次图像显示向右一个像素*/delay(TIME2);}(*p1)++; /*自己的横坐标加1*/if(a[*p1][*p2]==6) /*移动后有豆子就吃掉,同时参数6被改掉*/a[*p1][*p2]=4,number++;free(buffer2); /*释放存储图像的指针,不然移动多次后内存不够用,会去侵占number变量的 内存,导致number变0,这个问题自己调试了好久*/}} /*自己向右移动的函数,由于pieslice()函数无法一笔画(反正我自己不会),所以画图像要解释下*/ int* moveleft(int *p1,int *p2) {if(a[*p1-1][*p2]!=1) { setfillstyle(1,0); /*先把当前一格变成背景黑色 */ bar(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25); setfillstyle(1,4); /*画个红色的圆,默认白色边界*/ fillellipse(*p1*25+13,*p2*25+13,11,11); setfillstyle(1,0); /*画个黑色扇形,这个可以一笔画,但是边界是白色,相当于嘴巴被白色封了*/ pieslice(*p1*25+13,*p2*25+13,162,202,11); /*至于为什么是162°到202°,因为160-200显示的时 候多个角,不知道为什么*/ setcolor(0); /*设置 黑色*/ arc(*p1*25+13,*p2*25+13,157,200,11); /*用黑色的线画一条弧,用来覆盖原来的白色*/ setcolor(15); /*把前景色还原为白色,不然以后画出来的都要黑色了*/ /*这些跟上面函数一样,不罗嗦了,之后的两个函数也一样*/ size3=imagesize(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25); buffer3=malloc(size3); getimage(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25,buffer3);for(i=0;i<25;i++){setfillstyle(1,0);bar(*p1*25+24-i,*p2*25+1,*p1*25+25-i,*p2*25+25);putimage(*p1*25-i,*p2*25+1,buffer3,0);delay(TIME2);} (*p1)--;if(a[*p1][*p2]==6)a[*p1][*p2]=4,number++; free(buffer3); }} int* moveup(int* p1,int* p2){ if(a[myi][myj-1]!=1) { setfillstyle(1,0); bar(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25); setfillstyle(1,4); fillellipse(*p1*25+13,*p2*25+13,11,11); setfillstyle(1,0); pieslice(*p1*25+13,*p2*25+13,70,110,11); setcolor(0); arc(*p1*25+13,*p2*25+13,70,110,11); setcolor(15); size4=imagesize(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25); buffer4=malloc(size4); getimage(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25,buffer4); for(i=0;i<25;i++) {setfillstyle(1,0);bar(*p1*25+1,*p2*25+24-i,*p1*25+25,*p2*25+25-i);putimage(*p1*25+1,*p2*25-i,buffer4,0);delay(TIME2); } (*p2)--; if(a[*p1][*p2]==6)number++,a[*p1][*p2]=4; free(buffer4); }} int* movedown(int *p1,int *p2){ if(a[myi][myj+1]!=1){ setfillstyle(1,0); bar(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25); setfillstyle(1,4); fillellipse(*p1*25+13,*p2*25+13,11,11); setfillstyle(1,0); pieslice(*p1*25+13,*p2*25+13,250,290,11); setcolor(0); arc(*p1*25+13,*p2*25+13,247,288,11); setcolor(15); size5=imagesize(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25); buffer5=malloc(size5); getimage(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25,buffer5); for(i=0;i<25;i++){setfillstyle(1,0);bar(*p1*25+1,*p2*25+1+i,*p1*25+25,*p2*25+i+1);putimage(*p1*25+1,*p2*25+2+i,buffer5,0);delay(TIME2); } (*p2)++; if(a[*p1][*p2]==6) number++,a[*p1][*p2]=4; free(buffer5);}} /*怪的移动:向自己靠近*/int dmove(d,e){ if(d-myi>0&&a[d][e]==6&&a[d-1][e]!=1){ /*怪在自己的右方&&怪现在的坐标有豆子&&左边一格不 是墙*//* 怪移动的动画*/ for(i=0;i<25;i++){setfillstyle(1,0); /*每次用背景黑色擦掉最右边一竖线*/bar(d*25+25-i,e*25+1,d*25+26-i,e*25+25);setfillstyle(8,2); /*每次在左边画一条线,怪设计成正方形方便(不用图像存储),偷个懒*/bar(d*25-i,e*25+1,d*25+1-i,e*25+25);delay(TIME); }/*因为有豆子,所以添上豆子*/setfillstyle(1,14);pieslice(d*25+13,e*25+13,0,360,9);return 1; /*1传回去表示让怪的横坐标要减一*/ } else if(d-myi>0&&a[d-1][e]!=1&&a[d][e]!=6){/*没豆子的情况:本来可以和上面合并,不改了*/ for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+25-i,e*25+1,d*25+26-i,e*25+25);setfillstyle(8,2);bar(d*25-i,e*25+1,d*25+1-i,e*25+25);delay(TIME); }return 1; }if(d-myi<0&&a[d][e]==6&&a[d+1][e]!=1){/*怪在自己的左方,有豆子,其他都同上上面那个*/for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1+i,e*25+1,d*25+2+i,e*25+25);setfillstyle(8,2);bar(d*25+25+i,e*25+1,d*25+26+i,e*25+25);delay(TIME);} setfillstyle(1,14);pieslice(d*25+13,e*25+13,0,360,9);return 2;}else if(d-myi<0&&a[d+1][e]!=1&&a[d][e]!=6){ /*怪在自己左方,没豆子*/ for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1+i,e*25+1,d*25+2+i,e*25+25);setfillstyle(8,2);bar(d*25+25+i,e*25+1,d*25+26+i,e*25+25);delay(TIME);}return 2;} /*如果横坐标和自己同或者左右移动时碰到墙了,就要动纵坐标了,和上面几乎一样*/if(d==myi||(d-myi<0&&a[d+1][e]==1)||(d-myi>0&&a[d-1][e]==1)){if(e-myj<0&&a[d][e]==6&&a[d][e+1]!=1){ for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1,e*25+1+i,d*25+25,e*25+2+i);setfillstyle(8,2);bar(d*25+1,e*25+25+i,d*25+25,e*25+26+i);delay(TIME);}setfillstyle(1,14);pieslice(d*25+13,e*25+13,0,360,9);return 3;}else if(e-myj<0&&a[d][e+1]!=1&&a[d][e]!=6){ for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1,e*25+1+i,d*25+25,e*25+2+i);setfillstyle(8,2);bar(d*25+1,e*25+25+i,d*25+25,e*25+26+i);delay(TIME);}return 3;}if(e-myj>0&&a[d][e]==6&&a[d][e-1]!=1){for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1,e*25+24-i,d*25+25,e*25+25-i);setfillstyle(8,2);bar(d*25+1,e*25-i,d*25+25,e*25+1-i) ;delay(TIME);}setfillstyle(1,14);pieslice(d*25+13,e*25+13,0,360,9);return 4;}else if(e-myj>0&&a[d][e-1]!=1&&a[d][e]!=6){for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1,e*25+24-i,d*25+25,e*25+25-i);setfillstyle(8,2);bar(d*25+1,e*25-i,d*25+25,e*25+1-i);delay(TIME);}return 4;}}} /*怪随机动,其实和前面那个一样,就是和自己坐标myi,myj比较变成了和随机产生的坐标(a1,b)比较,既然一样,就不多说,产生随机数解释下*/int dmove2(d,e){ int a1,b; srand(seed++); /*种子每次要变,不然产生的随机数会相同*/ a1=rand()%24; /*取余数才能使坐标落在我游戏画面内*/ b=rand()%18; if(d-a1>0&&a[d][e]==6&&a[d-1][e]!=1){for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+25-i,e*25+1,d*25+26-i,e*25+25);setfillstyle(8,2);bar(d*25-i,e*25+1,d*25+1-i,e*25+25); delay(TIME);}setfillstyle(1,14);pieslice(d*25+13,e*25+13,0,360,9);return 1; } else if(d-a1>0&&a[d-1][e]!=1&&a[d][e]!=6){ for(i=0;i<25;i++){ setfillstyle(1,0); bar(d*25+25-i,e*25+1,d*25+26-i,e*25+25); setfillstyle(8,2); bar(d*25-i,e*25+1,d*25+1-i,e*25+25); delay(TIME); } return 1; } if(d-a1<0&&a[d][e]==6&&a[d+1][e]!=1){for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1+i,e*25+1,d*25+2+i,e*25+25);setfillstyle(8,2);bar(d*25+25+i,e*25+1,d*25+26+i,e*25+25);delay(TIME);} setfillstyle(1,14);pieslice(d*25+13,e*25+13,0,360,9);return 2; } else if(d-a1<0&&a[d+1][e]!=1&&a[d][e]!=6){ for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1+i,e*25+1,d*25+2+i,e*25+25);setfillstyle(8,2);bar(d*25+25+i,e*25+1,d*25+26+i,e*25+25);delay(TIME);}return 2; }if(d==a1||(d-a1<0&&a[d+1][e]==1)||(d-a1>0&&a[d-1][e]==1)){if(e-b<0&&a[d][e]==6&&a[d][e+1]!=1){for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1,e*25+1+i,d*25+25,e*25+2+i);setfillstyle(8,2);bar(d*25+1,e*25+25+i,d*25+25,e*25+26+i) ;delay(TIME);}setfillstyle(1,14);pieslice(d*25+13,e*25+13,0,360,9); return 3; }else if(e-b<0&&a[d][e+1]!=1&&a[d][e]!=6){ for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1,e*25+1+i,d*25+25,e*25+2+i);setfillstyle(8,2);bar(d*25+1,e*25+25+i,d*25+25,e*25+26+i) ;delay(TIME);}return 3;}if(e-b>0&&a[d][e]==6&&a[d][e-1]!=1){for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1,e*25+24-i,d*25+25,e*25+25-i);setfillstyle(8,2);bar(d*25+1,e*25-i,d*25+25,e*25+1-i);delay(TIME);}setfillstyle(1,14);pieslice(d*25+13,e*25+13,0,360,9);return 4;}else if(e-b>0&&a[d][e-1]!=1&&a[d][e]!=6){for(i=0;i<25;i++){setfillstyle(1,0);bar(d*25+1,e*25+24-i,d*25+25,e*25+25-i);setfillstyle(8,2);bar(d*25+1,e*25-i,d*25+25,e*25+1-i) ;delay(TIME);}return 4;}}} /*炸弹的函数*/int zhadan1(myi,myj){if(number<3) /*豆子数比三大才能炸*/return 0;else{number=number-3; /*炸一次消耗三个豆子*//*保存自己的图像*/size6=imagesize(*p1*25+1,*p2*25+1,*p1*25+25,*p2*25+25);buffer6=malloc(size6);getimage(myi*25+1,myj*25+1,myi*25+25,myj*25+25,buffer6); /*判断怪是否在炸弹的威力范围里面,若在,怪的坐标变掉,用随机数产生,但是不能产生在墙里,也不能靠自己太近*/for(i=0;i<4;i++){if(myi-1==d[i]&&myj==e[i]){do{srand(seed2++);d[i]=rand()%24;e[i]=rand()%18;}while(a[d[i]][e[i]]==1||(d[i]-myi)*(d[i]-myi)+(e[i]-myj)*(e[i]-myj)<5);setfillstyle(1,7);bar(d[i]*25+1,e[i]*25+1,d[i]*25+25,e[i]*25+25);}else if(myi+1==d[i]&&myj==e[i]){do{srand(seed2++);d[i]=rand()%24;e[i]=rand()%18;}while(a[d[i]][e[i]]==1||d[i]==myi&&e[i]==myj);setfillstyle(1,7);bar(d[i]*25+1,e[i]*25+1,d[i]*25+25,e[i]*25+25);}else if(myi==d[i]&&myj-1==e[i]){do{srand(seed2++);d[i]=rand()%24;e[i]=rand()%18;}while(a[d[i]][e[i]]==1||d[i]==myi&&e[i]==myj) ;setfillstyle(1,7);bar(d[i]*25+1,e[i]*25+1,d[i]*25+25,e[i]*25+25);}else if(myi==d[i]&&myj+1==e[i]){do{srand(seed2++);d[i]=rand()%24;e[i]=rand()%18;}while(a[d[i]][e[i]]==1||d[i]==myi&&e[i]==myj);setfillstyle(1,7);bar(d[i]*25+1,e[i]*25+1,d[i]*25+25,e[i]*25+25);}elseseed2++;} /*画一个方格的炸弹作为动画的开始*/setfillstyle(7,13);bar(myi*25+1,myj*25+1,myi*25+25,myj*25+25);/*炸弹的动画,每次在上一步的基础上,上下左右各添一条线*/for(i=0;i<24;i++){setfillstyle(7,13);bar(myi*25-1-i,myj*25+1,myi*25-i,myj*25+25);bar(myi*25+26+i,myj*25+1,myi*25+27+i,myj*25+25);bar(myi*25+1,myj*25-1-i,myi*25+25,myj*25+25);bar(myi*25+1,myj*25+26+i,myi*25+25,myj*25+27+i);delay(2000);}delay(10000);/*炸弹动画结束以后把炸弹炸到的区域清成背景黑色*/setfillstyle(1,0);bar(myi*25-24,myj*25+1,myi*25+50,myj*25+25);bar(myi*25+1,myj*25-24,myi*25+25,myj*25+50);/*如果该范围里面有墙体,要重新补上*/for(i=myi-1;i<=myi+1;i++)for(j=myj-1;j<=myj+1;j++){if(a[i][j]==1){if(i==0||i==24||j==0||j==18)setfillstyle(1,6),bar(i*25+1,j*25+1,25*i+25,25*j+25);elsesetfillstyle(1,7),bar(i*25+1,j*25+1,25*i+25,25*j+25);}}/*炸弹范围内的豆子被炸掉,所以参数6要被改掉,索性非墙的方格参数全设为5*/for(i=myi-1;i<=myi+1;i++) {if(a[i][myj]!=1)a[i][myj]=5;}for(i=myj-1;i<=myj+1;i++){if(a[myi][i]!=1)a[myi][i]=5;}/*最后把自己的图像补上*/putimage(myi*25+1,myj*25+1,buffer6,0);free(buffer6);}}
二、鼠标中断的设计
例程如下:
头文件例程
/*鼠标中断设计*/#ifndef __KEY_MOU_H__#define __KEY_MOU_H__#include<stdio.h>#include<graphics.h>#include<dos.h>#include<stdlib.h>union REGS regs;void shubiao(int x,int y);int init(int xmin,int xmax,int ymin,int ymax);void read();void cursor(int x,int y);void newxy();void mouse_scan1(int * x,int * y,int * buttons,int * done1,int * help);void mouse_scan2(int * x,int * y,int * buttons,int * done2,int *done);#define KB_S_N_DOWN 80 //定义各功能键的扫描码#define KB_S_N_UP 72 #define KB_S_N_HOME 71 #define KB_S_N_END 79#define KB_S_N_ENTER 28 #define KB_S_N_F1 59 #define KB_S_N_D 32 #define KB_S_N_H 35 #define KB_S_N_O 24 #define KB_S_N_Q 16#define KB_S_N_X 45#define KB_S_N_B 0x3062int getkey();void key_scan1(int it_num,int * done1,int * hp,void * buffer);void key_scan2(int it_num,int * done2,int * done,void *buffer);int row=0;extern int a;int help();void quit(void * buffer);#endif
函数体例程
/*鼠标中断设计*/#include"key_mou.h"/*************鼠标函数*********************/void shubiao(int x,int y){int xmin=2;int xmax=638;int ymin=2;int ymax=478;setwritemode(XOR_PUT);if(init(xmin,xmax,ymin,ymax)==0){printf("Mouse or Mouse Driver Absent,Please Install!");delay(5000);exit(1);}cursor(x,y);delay(5);}int init(int xmin,int xmax,int ymin,int ymax){int retcode;regs.x.ax=0;//鼠标复位及取状态int86(51,®s,®s);retcode=regs.x.ax;if(retcode==0){return 0;//返回0表示鼠标或鼠标驱动程序未安装}regs.x.ax=7;//设置水平位置最大值regs.x.cx=xmin;regs.x.dx=xmax;int86(51,®s,®s);regs.x.ax=8;//设置垂直位置最大值regs.x.cx=ymin;regs.x.dx=ymax;int86(51,®s,®s); //表示鼠标器和安装程序已安装return retcode;}void read(int *px,int *py,int *mbutt)//读鼠标的按键位置和按键状态{regs.x.ax=3;//取按钮状态和鼠标位置int86(51,®s,®s);* px=regs.x.cx;* py=regs.x.dx;* mbutt=regs.x.bx;delay(100);}void cursor(int x,int y)//画十字光标函数{ setwritemode(1); setcolor(BLUE); setlinestyle(0,0,1); line(x,y,x,y+11); line(x+1,y+1,x+1,y+10); line(x+2,y+2,x+2,y+9); line(x+3,y+3,x+8,y+8); line(x+3,y+4,x+7,y+8); line(x+3,y+5,x+6,y+8); line(x+3,y+6,x+5,y+8); line(x+3,y+7,x+4,y+8); line(x+3,y+8,x+3,y+8); setwritemode(0);} void newxy(int * x,int * y,int * mbutt){int xx0=* x,yy0=* y;int mx,my;read(&mx,&my,mbutt);cursor(xx0,yy0);cursor(mx,my);delay(5);* x=mx;* y=my;} /***************菜单一中扫描鼠标**********************/void mouse_scan1(int * x,int * y,int * buttons,int * done1,int * hp){int k=0;/*读鼠标*/newxy(x,y,buttons);if(* x>=210&&* x<=435&&* y>=215&&* y<=260&&* buttons==1){* done1=1;}else if(* x>=210&&* x<=435&&* y>=260&&* y<=305&&* buttons==1){k=help();if(k==1){cleardevice();* done1=1;* hp=1;}}else if(* x>=210&&* x<=435&&* y>=305&&* y<=350&&* buttons==1){cleardevice();closegraph();exit(0);//回到系统}}/*****************菜单二中扫描鼠标*************************/void mouse_scan2(int * x,int * y,int * buttons,int * done2,int *done){/*读鼠标*/newxy(x,y,buttons);if(*x>=400&&* x<=530&&*y>=160&&* y<=200&&* buttons==1){a=1; //进入单人游戏* done2=1;* done=1;}else if(* x>=400&&* x<=530&&* y>=220&&* y<=260&&* buttons==1){a=2; //进入双人游戏* done2=1;* done=1;}else if(* x>=400&&* x<=530&&* y>=220&&* y<=320&&* buttons==1){cleardevice();* done2=1;}}/*******************键盘函数*************************/int getkey(){union REGS rg;rg.h.ah=0;int86(0x16,&rg,&rg);return rg.h.ah;}/*****菜单一中扫描键盘*******/void key_scan1(int it_num,int * done1,int * hp,void * buffer) {int key=0;int k=0;key=getkey();switch(key){case KB_S_N_UP:putimage(180,220+row*45,buffer,XOR_PUT); //消除原来的光标row-=1;if(row==-1){row=it_num-1;}putimage(180,220+row*45,buffer,XOR_PUT); //光标上移并显示break;case KB_S_N_DOWN:putimage(180,220+row*45,buffer,XOR_PUT); //消除原来的光标row+=1;if(row==3){row=0;}putimage(180,220+row*45,buffer,XOR_PUT); //光标下移并显示break;case KB_S_N_F1:k=help();if(k==1){cleardevice();* done1=1;* hp=1;}break;case KB_S_N_X:quit(buffer);break;case KB_S_N_ENTER:switch(row){case 0: * done1=1;break;case 1: k=help(); if(k==1) { cleardevice(); * done1=1; * hp=1; }break;case 2: quit(buffer);break;}break;case 0:break;}}/*******菜单二中键盘扫描键盘*********/void key_scan2(int it_num,int * done2,int * done,void *buffer){int key=0;key=getkey();switch(key){case KB_S_N_UP:putimage(375,170+row*60,buffer,XOR_PUT); //消除原来的光标row-=1;if(row==-1){row=it_num-1;}putimage(375,170+row*60,buffer,XOR_PUT); //光标上移并显示break;case KB_S_N_DOWN:putimage(375,170+row*60,buffer,XOR_PUT); //消除原来的光标row+=1;if(row==3){row=0;}putimage(375,170+row*60,buffer,XOR_PUT); //光标下移并显示break;case KB_S_N_ENTER:switch(row){case 0: a=1; //进入单人模式* done2=1;* done=1;break;case 1: a=2; //进入双人模式* done2=1;* done=1;break;case 2: cleardevice();setbkcolor(BLACK);* done2=1;break;}break;case 0:break;}}
三、禁用鼠标中断或键盘中断的设计
例程如下:
/*禁用键盘中断或鼠标中断的设计*/#define _WIN32_WINNT 0x0400#include <windows.h> HHOOK mouseHook = NULL;HHOOK keyboardHook = NULL; HINSTANCE hInst = NULL; int WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved){ switch(dwReason) { case DLL_PROCESS_ATTACH: hInst = hInstance; break; case DLL_PROCESS_DETACH: if (keyboardHook) { UnhookWindowsHookEx(keyboardHook); } if (mouseHook) { UnhookWindowsHookEx(mouseHook); } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return 1;}long CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam){ return 1;}long CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam){ return 1;}BOOL CALLBACK LockKeyboard(BOOL bDisable){ if (bDisable) { if (keyboardHook == NULL) { keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardProc, hInst, NULL); } if (mouseHook == NULL) { mouseHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)MouseProc, hInst, NULL); } return keyboardHook != NULL && mouseHook != NULL; } else { if (keyboardHook && UnhookWindowsHookEx(keyboardHook)) { keyboardHook = NULL; } return keyboardHook == NULL && mouseHook == NULL; }}//调用事例 C/C++ code#include <windows.h>#define DLLFILENAME TEXT("locklib.dll")typedef BOOL (__stdcall *LockKeyboard)(BOOL);LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT ("AutoUpgrade") ; MSG msg ; HWND hwnd ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (hInstance, szAppName) ; wndclass.hCursor = NULL wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = szAppName ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("AutoUpgrade"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; ShowCursor(FALSE); while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ;}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static HINSTANCE hInstance; static LockKeyboard lockKeyboard; switch (message) { case WM_CREATE: hInstance = LoadLibrary(DLLFILENAME); if (hInstance) { lockKeyboard = (LockKeyboard)GetProcAddress(hInstance, TEXT("LockKeyboard")); if (lockKeyboard != NULL) { (lockKeyboard)(TRUE); } } break; case WM_DESTROY : if (lockKeyboard) { (lockKeyboard)(FALSE); } if (hInstance) { FreeLibrary(hInstance); } PostQuitMessage (0); return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ;}
- 浅析ANSI-C语言中的中断处理(如有疑问,敬请留言)
- 教你如何配置Apache的PHP网站开发环境(如有疑问,敬请留言)
- 关于ANSI C中的异常处理
- C语言中断处理机制
- ANSI C语言中的全部转义字符
- 浅析C语言中的指针
- 删除C语言程序中所以的注释语句(有疑问)
- 删除C语言程序中所有的注释语句(有疑问)
- linux中断处理浅析
- Linux中断处理浅析
- 中断处理浅析
- linux中断处理浅析
- Linux中断处理浅析
- linux中断处理浅析
- linux中断处理浅析
- linux中断处理浅析
- linux中断处理浅析
- linux中断处理浅析
- Makefile 的使用函数
- Codeforces Round #131 (Div. 2)
- Swing中JRadioButton多选框的用法
- Your branch is ahead of 'origin/master' by 1 commit
- AfxBeginThread 和 CreateThread 区别
- 浅析ANSI-C语言中的中断处理(如有疑问,敬请留言)
- BIN OBJ 区别
- jsp中的request.getContextPath()
- hdoj 4081
- Javascript数组的排序 sort()方法和reverse()方法
- WIN7/XP用注册表关联指定后缀名和打开程序(手动【图文】和C编程两种实现)
- 网页爬虫抓取URL简单实现
- c++ string中的replace
- 记ORA-01031: insufficient privileges一则