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(); }
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。