C语言俄罗斯方块游戏课程设计
更新时间:2021年06月18日 17:23:24 作者:网络
这篇文章主要为大家详细介绍了C语言俄罗斯方块游戏课程设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了C语言实现俄罗斯方块游戏的具体代码,供大家参考,具体内容如下
1、设计流程
2、相关程序
#include<stdio.h> #include<stdlib.h> #include<graphics.h> #include<time.h> #include<dos.h> #include<bios.h> #define LEFT 0x4b00 /*键盘码*/ #define RIGHT 0x4d00 #define DOWN 0x5000 #define UP 0x4800 #define ESC 0x011b #define TIMER 0x1c /* 时钟中断的中断号 */ struct Snow { int x; int y; int speed; }snow[100]; typedef struct { int box[4][4]; int color; int next; }SHAPE; int x=0,y=4,form[16][12]={ /*x,y是用作记录每个方块的最左上角的编号*/ {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,1}, {1,1,1,1,1,1,1,1,1,1,1,1}, }; /*俄罗斯方块初始化界面*/ SHAPE shapes[19]={ {1,0,0,0, 1,0,0,0, 1,1,0,0, 0,0,0,0,CYAN,1}, {1,1,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0,CYAN,2}, {1,1,0,0, 0,1,0,0, 0,1,0,0, 0,0,0,0,CYAN,3}, {0,0,0,0, 0,0,1,0, 1,1,1,0, 0,0,0,0,CYAN,0}, {0,1,0,0, 0,1,0,0, 1,1,0,0, 0,0,0,0,MAGENTA,5}, {1,0,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0,MAGENTA,6}, {1,1,0,0, 1,0,0,0, 1,0,0,0, 0,0,0,0,MAGENTA,7}, {1,1,1,0, 0,0,1,0, 0,0,0,0, 0,0,0,0,MAGENTA,4}, {1,0,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0,YELLOW,9}, {0,1,1,0, 1,1,0,0, 0,0,0,0, 0,0,0,0,YELLOW,8}, {0,1,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0,BROWN,11}, {1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0,BROWN,10}, {0,1,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0,WHITE,13}, {1,0,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0,WHITE,14}, {1,1,1,0, 0,1,0,0, 0,0,0,0, 0,0,0,0,WHITE,15}, {0,1,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0,WHITE,12}, {1,0,0,0, 1,0,0,0, 1,0,0,0, 1,0,0,0,RED,17}, {1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0,RED,16}, {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0,BLUE,18} }; int TimerCounter=0; int snownum=0; int size; int change1=10; int annal[4][2],score=0,level=0,color,Boxnumber; void plot(); void operation(); void *save1,*save2; void Copy(); void DrawSnow(); void Pr(); void interrupt ( *oldhandler)(); void interrupt newhandler( ) { TimerCounter++; TimerCounter==36; oldhandler(); } void SetTimer(void interrupt (*IntProc)()) { oldhandler=getvect(TIMER); disable(); /* 设置新的时钟中断处理过程时,禁止所有中断 */ setvect(TIMER,IntProc); enable(); /* 开启中断 */ } void KillTimer() { disable(); setvect(TIMER,oldhandler); enable(); } void main() { int gdriver=DETECT,gmode; SetTimer(newhandler); /* 修改时钟中断 */ registerbgidriver(EGAVGA_driver); initgraph(&gdriver,&gmode,"c:\\turboc2"); Copy(); DrawSnow(); closegraph(); initgraph(&gdriver,&gmode,"E:\\TC20H\\INCLUDE\\GRAPHICS.H"); /*初始化图形*/ plot(); operation(); getch(); } void Copy() { setcolor(0); setfillstyle(SOLID_FILL,15); fillellipse(200,200,4,4); size=imagesize(196,196,204,204); save1=malloc(size); save2=malloc(size); getimage(196,196,204,204,save1); getimage(96,96,104,104,save2); } void Pr() { int fr[]={392,392,440,294,262,262,220,294,392,392, 440,532,440,392,262,262,220,294,392,294, 262,247,220,196,392,294,330,294,262,262, 220,294,330,294,262,294,22,247,220,196}; setcolor(change1/10); settextstyle(0,0,3); outtextxy(100,200,"Welcome to our Game!!!”); sound(fr[change1/10]); } void DrawSnow() { int i; int sx[62]; randomize(); for(i=0;i<62;i++) sx[i]=(i+2)*10; cleardevice(); while(!kbhit()) { Pr(); if (snownum!=100) { snow[snownum].speed=2+random(5); i=random(62); snow[snownum].x=sx[i]; snow[snownum].y=10-random(100); } for(i=0;i<snownum;i++) putimage(snow[i].x,snow[i].y,save2,COPY_PUT); Pr(); if(snownum!=100) snownum++; /*delay(300);*/ setfillstyle(SOLID_FILL,15); for(i=0;i<snownum;i++) { snow[i].y+=snow[i].speed; putimage(snow[i].x,snow[i].y,save1,COPY_PUT); if(snow[i].y>500) snow[i].y=10-random(200); } change1++; if(change1==140) change1=10; } nosound(); } void plot() { int i,j; char ch1[]={24,'-','R','o','l','l','\0'}, ch2[]={25,'-','D','o','w','n','w','a','r','d','s','\0'}, ch3[]={26,'-','T','u','r','n',' ','L','e','f','t','\0'}, ch4[]={27,'-','T','u','r','n',' ','R','i','g','h','t','\0'}; setcolor(LIGHTGRAY); rectangle(200,30,350,255); i=0; while((i++)<10) line(200+i*15,30,200+i*15,255); i=0; while((i++)<15) line(200,30+i*15,350,30+i*15); setcolor(WHITE); rectangle(170,270,390,330); outtextxy(190,280,ch1); outtextxy(270,280,ch2); outtextxy(190,300,ch3); outtextxy(290,300,ch4); outtextxy(190,320,"Esc-Exit"); settextjustify(1,1); outtextxy(390,50,"score"); outtextxy(390,100,"lexel"); outtextxy(390,150,"Next box"); outtextxy(390,65,"0"); outtextxy(390,115,"0"); } void nextboxfun(SHAPE shapes[],int i) { int m,n; for(m=0;m<4;m++) for(n=0;n<4;n++) if(shapes[i].box[m][n]) { setfillstyle(1,shapes[i].color); bar(370+n*15+1,180+m*15+1,370+n*15+15-1,180+m*15+15-1); setcolor(LIGHTGRAY); rectangle(370+n*15,180+m*15,370+n*15+15,180+m*15+15); } } int Leftmobile() { int m,k=-1; /*暂时存放annal中的坐标数据,用来判断左移是否成立*/ for(m=0;m<4;m++) { if(annal[m][0]!=k) { if(form[annal[m][0]][annal[m][1]-1]) return(0); k=annal[m][0]; } } return(1); } int Rightmobile() { int m,k=-1; for(m=3;m>=0;m--) { if(annal[m][0]!=k) { if(form[annal[m][0]][annal[m][1]+1]) return(0); k=annal[m][0]; } } return(1); } int Downmobile() { int m; for(m=0;m<4;m++) form[annal[m][0]][annal[m][1]]=2; /*将方块此时的位置设置成2以方便后面的判断*/ for(m=0;m<4;m++) { if(form[annal[m][0]+1][annal[m][1]]==1) /*如果等于1说明此处已经有方块*/ { for(m=0;m<4;m++)/*将原本数值还原*/ form[annal[m][0]][annal[m][1]]=1; return(0); } } for(m=0;m<4;m++) /*将原本数值还原*/ form[annal[m][0]][annal[m][1]]=1; return(1); } void LeftRedraw() { int m; y--; for(m=0;m<4;m++) { setfillstyle(1,BLACK); bar(200+(annal[m][1]-1)*15+1,30+annal[m][0]*15+1,200+(annal[m][1]-1)*15+15-1,30+annal[m][0]*15+15-1); /*将原图像位置设置为黑色框*/ } for(m=0;m<4;m++) form[annal[m][0]][annal[m][1]]=0; for(m=0;m<4;m++) { annal[m][1]--; form[annal[m][0]][annal[m][1]]=1; setfillstyle(1,color); bar(200+(annal[m][1]-1)*15+1,30+annal[m][0]*15+1,200+(annal[m][1]-1)*15+15-1,30+annal[m][0]*15+15-1); /*在新的位置重绘图像*/ } } void RightRedraw() { int m; y++; for(m=0;m<4;m++) { setfillstyle(1,BLACK); bar(200+(annal[m][1]-1)*15+1,30+annal[m][0]*15+1,200+(annal[m][1]-1)*15+15-1,30+annal[m][0]*15+15-1); /*将原图像位置设置为黑色框*/ } for(m=0;m<4;m++) form[annal[m][0]][annal[m][1]]=0; for(m=0;m<4;m++) { annal[m][1]++; form[annal[m][0]][annal[m][1]]=1; setfillstyle(1,color); bar(200+(annal[m][1]-1)*15+1,30+annal[m][0]*15+1,200+(annal[m][1]-1)*15+15-1,30+annal[m][0]*15+15-1); } /*在新的位置重绘图像*/ } void DownRedraw() { int m,n; x++; for(m=0;m<4;m++) { setfillstyle(1,BLACK); bar(200+(annal[m][1]-1)*15+1,30+annal[m][0]*15+1,200+(annal[m][1]-1)*15+15-1,30+annal[m][0]*15+15-1); /*将原图像位置设置为黑色框*/ } for(m=0;m<4;m++) form[annal[m][0]][annal[m][1]]=0; for(m=0;m<4;m++) { annal[m][0]++; form[annal[m][0]][annal[m][1]]=1; setfillstyle(1,color); bar(200+(annal[m][1]-1)*15+1,30+annal[m][0]*15+1,200+(annal[m][1]-1)*15+15-1,30+annal[m][0]*15+15-1); /*在新的位置重绘图像*/ } } int UPmobile() { int m,n,k; k=shapes[Boxnumber].next;/*k==此方块下一个方块的编号*/ for(m=0;m<4;m++) form[annal[m][0]][annal[m][1]]=2; for(m=0;m<4;m++) for(n=0;n<4;n++) { if(form[x+m][y+n]==1&&shapes[k].box[m][n]) { for(m=0;m<4;m++) form[annal[m][0]][annal[m][1]]=1;/*将2还原为1*/ return(0); } } for(m=0;m<4;m++) form[annal[m][0]][annal[m][1]]=1; return(1); } void change() { int m,n,k,i=0; k=Boxnumber=shapes[Boxnumber].next;/*等于要转变的方块编号*/ for(m=0;m<4;m++) { setfillstyle(1,BLACK); bar(200+(annal[m][1]-1)*15+1,30+annal[m][0]*15+1,200+(annal[m][1]-1)*15+15-1,30+annal[m][0]*15+15-1); /*将原图像位置设置为黑色框*/ } for(m=0;m<4;m++) /*将原方块位置改为0*/ form[annal[m][0]][annal[m][1]]=0; for(m=0;m<4;m++) /*重新记录新的形状坐标*/ for(n=0;n<4;n++) if(shapes[k].box[m][n]) { annal[i][0]=x+m; /*annal更新新的坐标*/ annal[i][1]=y+n; i++; } for(m=0;m<4;m++) /*将新坐标设置为1并绘图*/ { form[annal[m][0]][annal[m][1]]=1; setfillstyle(1,color); bar(200+(annal[m][1]-1)*15+1,30+annal[m][0]*15+1,200+(annal[m][1]-1)*15+15-1,30+annal[m][0]*15+15-1) ;/*在新的位置重绘图像*/ } } void FulllineJudge() { void *p1; int m,n,i,k,p,q; char *ch; if(!(p1=malloc(imagesize(200,30,350,255)))) { printf("开辟空间失败\n"); getch(); exit(1); } i=0; for(m=14;m>=0;m--) /*逐行判断是否有满行情况*/ { for(n=1;n<=10;n++) { if(!form[m][n]) /*如果有一个为0那么退出本行的循环*/ break; else if(n==10) /*1-10全为1*/ { i++; /*用来记录所消行数*/ for(p=m;p>=1;p--) for(q=1;q<=10;q++) /*所有行数信息下降1行*/ form[p][q]=form[p-1][q]; for(p=1;p<=10;p++) /*最顶行清零*/ form[0][p]=0; getimage(200,30,350,30+m*15,p1); putimage(200,45,p1,0); m++; } } if(i==4) /*如果已经消掉4行则不用再进行判断*/ break; } if(i==1) /*一次所消行数进行不同分数奖励*/ score+=10; if(i==2) score+=30; if(i==3) score+=60; if(i==4) score+=100; setcolor(WHITE); /*绘图部分*/ sprintf(ch,"%d",score); setfillstyle(1,BLACK); bar(380,60,400,80); outtextxy(390,65,ch); level=score/500; setfillstyle(1,BLACK); bar(380,110,400,130); sprintf(ch,"%d",level); outtextxy(390,115,ch); free(p1); } void operation() { int newbox,nextbox,m,n,k=1,i,KEY,l,o; o=1; srand((unsigned)time(NULL)); nextbox=rand()%19; while(o) { if(k) /*产生新方块*/ { x=0,y=4; /*还原x,y*/ Boxnumber=newbox=nextbox; nextbox=rand()%19; setfillstyle(1,BLACK); bar(360,160,430,250); nextboxfun(shapes,nextbox); i=0; color=shapes[newbox].color; for(m=0;m<4;m++) for(n=0;n<4;n++) if(shapes[newbox].box[m][n]) /*将新方块在俄罗斯方块界面的坐标记录在annal中*/ { annal[i][0]=0+m; /*记录坐标*/ annal[i][1]=4+n; if(form[0+m][4+n]) { setfillstyle(1,BLACK); bar(240,130,310,150); setcolor(RED); outtextxy(275,140,"GAME OVER"); getch(); o=0; } form[0+m][4+n]=1; setfillstyle(1,shapes[newbox].color); bar(200+n*15+1+45,30+m*15+1,200+n*15+15-1+45,30+m*15+15-1);/*将对应的位画上颜色*/ setcolor(LIGHTGRAY); rectangle(200+n*15+45,30+m*15,200+n*15+15+45,30+m*15+15); i++; } k=0; } if(bioskey(1)) /*读取键盘*/ KEY=bioskey(0); else KEY=0; switch(KEY) { case LEFT:/*左*/ if(Leftmobile()) LeftRedraw();break; case RIGHT:/*右*/ if(Rightmobile()) RightRedraw();break; case DOWN:/*下*/ if(Downmobile()) DownRedraw(); else {FulllineJudge();k=1;}break; case UP:/*变形*/ if(UPmobile()) change();break; case ESC:o=0;break; } if(TimerCounter>(36-level*2)) /*TimerCounter每秒钟增加18*/ { TimerCounter=0; if(Downmobile()) /*作下降处理*/ DownRedraw(); else {FulllineJudge();k=1;} } } KillTimer(); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
最新评论