浅析ANSI-C语言中的中断处理(如有疑问,敬请留言)

          设置一个好的时钟中断,将能使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);
				}
				else
					seed2++;
			}
 
			/*画一个方格的炸弹作为动画的开始*/
			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);
						else
							setfillstyle(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            0x3062
int 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) ;
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值