VC++ 6.0 C語言實(shí)現(xiàn)俄羅斯方塊詳細(xì)教程
今天把我之前寫的大作業(yè)分享一下吧,并教你們?nèi)绾螌?shí)現(xiàn),希望你們看了前面的教程也能自己寫一個。
1.要先下載一個 graphics.h 的頭文件來繪圖。
2.初始化窗口:initgraph(x, y);這是先創(chuàng)建一個窗口的函數(shù),以左上角為(0,0),向右為x軸,向下為y軸,其中x表示長x個單位,y表示寬y個單位。
3.關(guān)閉圖像窗口:closegraph();結(jié)束時(shí)用來關(guān)閉用的。
4.按任意鍵繼續(xù):getch();這個就和getchar();差不多,為了防止以運(yùn)行完就關(guān)了,這樣能停頓一下,他的頭文件是:conio.h 。
5.畫線:line(x1, y1, x2, y2);在你創(chuàng)建的那么窗口里以(x1,y1)和(x2,y2)為兩個端點(diǎn)畫線。
6.畫矩形:rectangle(x1,y1,x2,y2);以(x1,y1)和(x2,y2)為對角畫一個矩形。
7.畫圓:circle(x,y,r);以(x,y)為圓點(diǎn),r為半徑畫圓。
8.顏色:setcolor(x);用來設(shè)置顏色的,其中x是你要設(shè)置的顏色,可以填這16種:黑 BLACK、藍(lán) BLUE、綠 GREEN、青 CYAN、紅 RED、紫 MAGENTA、棕 BROWN、淺灰 LIGHTGRAY、深灰 DARKGRAY、亮藍(lán) LIGHTBLUE、亮綠 LIGHTGREEN、亮青 LIGHTCYAN、亮紅 LIGHTRED、亮紫 LIGHTMAGENTA、黃 YELLOW、白 WHITE;當(dāng)然,你也可以根據(jù)光的三原色來調(diào)自己喜歡的顏色,方法是:setcolor(RGB(x,y,z));其中RGB分別代表紅綠藍(lán),對應(yīng)的x,y,z是你選的該顏色的多少,范圍是[0,255]。
根據(jù)上面的這些就能畫出很多圖形了.比如:
# include <graphics.h> # include <conio.h> void main() { initgraph(640,480); setcolor(BROWN); line(200,200,300,130); line(400,200,300,130); rectangle(200,200,400,380); setcolor(RGB(100,150,200)); circle(255,260,20); circle(345,260,20); rectangle(280,300,310,360); getch(); closegraph(); }
還有這個,畫一個圓,圓心是(320,240),半徑r=200,根據(jù)角度的公式畫一個圓:
# include <graphics.h> # include <conio.h> # include <math.h> # define PI 3.1415926 void main() { initgraph(640, 480); int x,y,r=200,c; double a; for(a=0; a<PI*2; a+=0.0001) { x=(int)(r*cos(a)+320+0.5); y=(int)(r*sin(a)+240+0.5); c=(int)(a*255/(2*PI)); setcolor(RGB(c,200-c/2,100+c/2)); line(320,240,x,y); } getch(); closegraph(); }
9.停頓:Sleep(x);停頓x/1000秒。
有了Sleep();函數(shù),就能讓線動起來了,原理就是:先畫一條線,然后再畫一條黑色的線覆蓋原來的那條,然后再畫一條線,這樣不斷的畫線能行了。
# include <graphics.h> # include <conio.h> void main() { int i,y; initgraph(640,480); for(y=0;y<480-2;y++) { setcolor(RGB(y,125,y/2%256)); line(0,y,639,y); line(0,y+2,639,y+2); Sleep(10); setcolor(BLACK); line(0,y,639,y); } getch(); closegraph(); }
10.隨機(jī)數(shù)發(fā)生器:srand();使用方法:srand(time(NULL));使用時(shí)要有頭文件time.h。
11.隨機(jī)函數(shù):rand();隨機(jī)生成一個數(shù),頭文件是:stdlib.h,比如:
# include <stdio.h> # include <time.h> # include <graphics.h> void main() { int t=10; while(t--) { srand(time(NULL)); printf("%d\n",rand()); Sleep(1000); } }
12.判斷鍵盤是否有輸入:kbhit();如果有的話返回1,否則返回0.
13.方向鍵:方健健的ASCII值我們不知道,普通的getchar();也不能輸入,但是getch();通過運(yùn)行程序可以發(fā)現(xiàn)方向比較特殊,分別是:上 224+72、下 224+80、左 224+75、右 224+77,就是說他們是由兩個字符組成的,所以判斷上下左右時(shí)就先判斷if(kbhit()),然后判斷if(getch()==224),如果是的話在判斷if(getch()==72),是的話就是上,下左右同理。
# include <stdio.h> # include <graphics.h> # include <conio.h> void main() { int key; while(1) { if(kbhit()) { key=getch(); if(key==224) key=getch(); printf("%d",key); } else printf("*"); Sleep(500); } }
14.輸出:outtextxy(x,y,s);在坐標(biāo)為(x,y)的地方輸出字符串s。
15.數(shù)字轉(zhuǎn)字符串:sprintf(s,"%d",a);將數(shù)字a,轉(zhuǎn)化為字符串s,頭文件是stdio.h。
16.設(shè)置字體:setfont(x,y,"字體");其中x表示你你要輸出的字的大小,y會改變形狀一般都是設(shè)為0,"字體"為你想要輸出的字體,比如:setfont(40,0,"楷體");
# include <graphics.h> # include <conio.h> # include <stdio.h> void main() { char s[10]; initgraph(640,480); setfont(42,0,"隸體"); outtextxy(200,200,"俄羅斯方塊"); sprintf(s,"%d",2015); outtextxy(250,250,s); getch(); closegraph(); }
上面這些都學(xué)會了的話,差不多就能夠自己完成編寫一個俄羅斯方塊了,下面分享一下我寫的代碼。
# include <stdio.h> # include <time.h> # include <conio.h> # include <graphics.h> int a,visit[30][15],Color[30][15],minX=30,minY=30,maxX=310,maxY=610,speed=500,score=0,rank=0; int color[]={GREEN,CYAN,MAGENTA,BROWN,LIGHTGRAY,LIGHTBLUE,LIGHTGREEN,LIGHTRED,YELLOW}; int block[36][5][5]= { {0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0}, {0,0,1,1,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,1,0}, {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0}, {0,1,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,1,1,0,0}, {0,0,0,0,0,1,0,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0}, {0,1,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0} }; void Interface();//界面的設(shè)計(jì) void nextblock();//生成下一個方塊 void newblock();//將下一個放到主方框中 void move(int x,int y,int A);//移動方塊 int couldmove(int x0,int y0,int A,char dir,int next);//判斷能否移動 int couldrotate(int x0,int y0,int A,int next);//判斷能否旋轉(zhuǎn) void mark(int x0,int y0,int A,int next);//標(biāo)記方塊固定后的位置 void full();//判斷有沒有能夠消行的 void down(int x);//有消行的將上面的方塊下移一行 int gameover();//判斷游戲是否結(jié)束 int main() { int i,j; Interface(); nextblock(); Sleep(500); memset(visit,0,sizeof(visit)); while(1) { newblock(); full(); if(gameover()) break; } getch(); closegraph(); return 0; } void Interface() { int i,j; char str[10]; initgraph(550, 660); HWND hwnd = GetHWnd(); SetWindowText(hwnd, "NEW俄羅斯方塊 制作:丶阿明"); Sleep(2000); setfont(40,0,"隸體"); setcolor(RED); outtextxy(145,200,"NEW"); setfont(40,0,"楷體"); for(i=0;i<=255;i++) for(j=0;j<=255;j++) { setcolor(RGB((i+j+128)%255,i,j)); outtextxy(205,200,"俄羅斯方塊!"); } Sleep(2000); setcolor(YELLOW); setfont(22,0,"隸體"); outtextxy(310,300,"←_←"); setfont(22,0,"楷體"); outtextxy(180,300,"這逼裝的可以"); setcolor(LIGHTMAGENTA); Sleep(2500); outtextxy(175,300,"請按任意鍵開始游戲!"); getch(); cleardevice(); setcolor(WHITE); rectangle(29,29,334,633); rectangle(28,28,335,634); rectangle(370,50,515,195); setfont(24,0, "楷體"); setcolor(LIGHTGRAY); outtextxy(405,215,"下一個:"); setcolor(RED); outtextxy(405,280,"分?jǐn)?shù):"); sprintf(str,"%d",score); outtextxy(415,310,str); outtextxy(405,375,"等級:"); sprintf(str,"%d",rank); outtextxy(425,405,str); setfont(22,0, "楷體"); setcolor(LIGHTBLUE); outtextxy(390,475,"操作說明:"); outtextxy(390,500,"↑: 旋轉(zhuǎn)"); outtextxy(390,525,"↓: 下降"); outtextxy(390,550,"←: 左移"); outtextxy(390,575,"→: 右移"); outtextxy(390,600,"空格: 暫停"); } void nextblock() { int i,j,x=391,y=71; setfont(23,0,"楷體"); setcolor(BLACK); for(i=0;i<5;i++) for(j=0;j<5;j++) outtextxy(x+20*j,y+20*i,"■"); srand(time(NULL)); a=rand()%9; setcolor(color[a]); for(i=0;i<5;i++) for(j=0;j<5;j++) if(block[4*a][i][j]==1) outtextxy(x+20*j,y+20*i,"■"); } void newblock() { int i,j,x=130,y=30,A=a; if(A==0||A==1||A==6) y-=60; else if(A==2||A==3||A==5||A==7||A==8) y-=40; else y-=80; setfont(23,0,"楷體"); setcolor(color[A]); for(i=0;i<5;i++) for(j=0;j<5;j++) if(block[4*A][i][j]==1&&y+20*i>=30) outtextxy(x+20*j,y+20*i,"■"); Sleep(100); nextblock(); move(x,y,A); } void move(int x,int y,int A) { int i,j,f,k=0,next=0,Speed=speed,key,nex; while(1) { f=couldmove(x,y+k,A,'x',next); if(f==0) { mark(x,y+k,A,next); break; } if(kbhit()) { key=getch(); if(key==32) getch(); } setcolor(BLACK); for(i=0;i<5;i++) for(j=0;j<5;j++) if(block[4*A+next][i][j]==1&&y+20*i+k>=30) outtextxy(x+20*j,y+20*i+k,"■"); if(kbhit()) { key=getch(); if(key==72) { nex=(next+1)%4; if(couldrotate(x,y+k,A,nex)) next=nex; } else if(key==80) Speed=50; else if(key==75&&couldmove(x,y+k+20,A,'z',next)) x-=20; else if(key==77&&couldmove(x,y+k+20,A,'y',next)) x+=20; } setcolor(color[A]); for(i=0;i<5;i++) for(j=0;j<5;j++) if(block[4*A+next][i][j]==1&&y+20*i+k+20>=30) outtextxy(x+20*j,y+20*i+k+20,"■"); Sleep(Speed); k+=20; } } int couldmove(int x0,int y0,int A,char dir,int next) { int i,j,x,y,f=1; x=(y0-minY)/20; y=(x0-minX)/20; if(dir=='x') { for(i=0;i<5;i++) for(j=0;j<5;j++) if(block[4*A+next][i][j]==1&&(x+i+1==30||(x+i+1>=0&&x+i+1<30&&y+j>=0&&y+j<15&&visit[x+i+1][y+j]==1))) f=0; } else if(dir=='z') { for(i=0;i<5;i++) for(j=0;j<5;j++) if(block[4*A+next][i][j]==1&&(y+j==0||(x+i>=0&&x+i<30&&y+j-1>=0&&y+j-1<15&&visit[x+i][y+j-1]==1))) f=0; } else if(dir=='y') { for(i=0;i<5;i++) for(j=0;j<5;j++) if(block[4*A+next][i][j]==1&&(y+j+1==15||(x+i>=0&&x+i<30&&y+j+1>=0&&y+j+1<15&&visit[x+i][y+j+1]==1))) f=0; } return f; } int couldrotate(int x0,int y0,int A,int next) { int i,j,x,y,f=1; x=(y0-minY)/20; y=(x0-minX)/20; if(!couldmove(x0,y0,A,'x',next)) f=0; for(i=0;i<5;i++) for(j=0;j<5;j++) if(block[4*A+next][i][j]==1&&(y+j==-1||y+j==15||(x+i>=0&&x+i<30&&y+j>=0&&y+j<15&&visit[x+i][y+j]==1))) f=0; return f; } void mark(int x0,int y0,int A,int next) { int i,j,x,y; x=(y0-minY)/20; y=(x0-minX)/20; for(i=0;i<5;i++) for(j=0;j<5;j++) if(block[4*A+next][i][j]==1) { visit[x+i][y+j]=1; Color[x+i][y+j]=color[A]; } } void full() { int i,j,k=0; char str[10]; for(i=29;i>=0;i--) { for(j=0;j<15;j++) if(visit[i][j]==0) break; if(j==15) { k++; down(i); i++; } } setcolor(RED); score+=10*k; sprintf(str,"%d",score); outtextxy(415,310,str); rank=(score/50); sprintf(str,"%d",rank); outtextxy(425,405,str); speed=500-100*rank; if(speed==0) speed=100; if(score>=300) speed=75; } void down(int x) { int i,j; for(i=x;i>0;i--) for(j=0;j<15;j++) if(visit[i-1][j]==1) { visit[i][j]=visit[i-1][j]; Color[i][j]=Color[i-1][j]; setcolor(Color[i-1][j]); outtextxy(minX+20*j,minY+20*i,"■"); } else { visit[i][j]=visit[i-1][j]; setcolor(BLACK); outtextxy(minX+20*j,minY+20*i,"■"); } setcolor(BLACK); for(j=0;j<15;j++) { visit[0][j]=0; outtextxy(minX+20*j,minY,"■"); } } int gameover() { int i,j; for(i=0;i<15;i++) if(visit[0][i]==1) { for(i=0;i<=7;i++) { setcolor(RGB(35*i,255-35*i,255)); for(j=i;j<30-i;j++,Sleep(20)) outtextxy(30+20*i,30+20*j,"■"); for(j=i;j<15-i;j++,Sleep(20)) outtextxy(30+20*j,30+20*(29-i),"■"); for(j=30-1-i;j>=i;j--,Sleep(20)) outtextxy(30+20*(14-i),30+20*j,"■"); for(j=15-1-i;j>=i;j--,Sleep(20)) outtextxy(30+20*j,30+20*i,"■"); } setcolor(WHITE); setfont(45,0,"隸體"); outtextxy(75,300,"GAME OVER!"); Sleep(5000); return 1; } return 0; }
我設(shè)置的一行能放15個小格子,一共能放30行,二維數(shù)組visit[30][15],來判斷某個位置是否有方塊,比如visit[29][5]=1表示第30行第6個方塊的位置有方塊了,0表示沒方塊,Color[30][15]用來記錄某個位置的方塊的顏色。minX=30,minY=30表示左上角的方塊也就是第1行第1列的方塊對應(yīng)在界面的坐標(biāo),maxX,maxY同理。speed表示方塊的下落速度,一開始初始化為500,沒0.5s往下落一行,score記錄分?jǐn)?shù),每消一行加10分,rank表示等級,每50分等級+1,且速度減100,當(dāng)速度減到100時(shí),就不變了,只有當(dāng)分?jǐn)?shù)超過300速度才會減為75,且以后都不會再減少了。
我一個設(shè)計(jì)了9種方塊,每種方塊都有4種形態(tài),每順時(shí)針旋轉(zhuǎn)90°就有一種形態(tài),所以一共是36個方塊。每個方塊都用5*5的二維數(shù)組來表示,36種就是36個二維數(shù)組,所以用block[36][5][5]來表示,block[k][5][5],(k<36&&k%4==0)表示每種方塊的初始形態(tài),k+1,+2,+3,分別表示第k種方塊選擇90°、180°、270°之后的形態(tài)。比如block[1][5][5]保存的是第1種方塊旋轉(zhuǎn)90°的方塊,其中block[1][i][j]=1表示這個方塊第i+1行,j+1列有一個小方塊,=0代表沒有,所以我的block[36][5][5],有36行,一行25個數(shù)列,表示一種方塊。一維數(shù)組color[]依次表示9種方塊的顏色。
附上效果圖:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++生成隨機(jī)數(shù)的實(shí)現(xiàn)代碼
這篇文章主要介紹了C++生成隨機(jī)數(shù)的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04C++??STL?_?Vector使用及模擬實(shí)現(xiàn)
這篇文章主要介紹了C++ STL_Vector使用及模擬實(shí)現(xiàn),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08C語言利用數(shù)組和文件實(shí)現(xiàn)登錄注冊功能
這篇文章主要為大家詳細(xì)介紹了C語言利用數(shù)組和文件實(shí)現(xiàn)登錄注冊功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12C++實(shí)現(xiàn)歌手比賽評分系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)歌手比賽評分系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03C++深入淺出探索數(shù)據(jù)結(jié)構(gòu)的原理
C++的數(shù)據(jù)結(jié)構(gòu)很多,很復(fù)雜,所以本文將通過示例帶大家深入了解一下C++中的數(shù)據(jù)結(jié)構(gòu)與算法。文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-05-05C++ 中二分查找遞歸非遞歸實(shí)現(xiàn)并分析
這篇文章主要介紹了C++ 中二分查找遞歸非遞歸實(shí)現(xiàn)并分析的相關(guān)資料,需要的朋友可以參考下2017-06-06