《俄羅斯方塊C語言程序設計報告.doc》由會員分享,可在線閱讀,更多相關《俄羅斯方塊C語言程序設計報告.doc(18頁珍藏版)》請在裝配圖網(wǎng)上搜索。
C語言課程設計報告
俄羅斯方塊程序設計報告
一、 問題描述
俄羅斯方塊(Tetris, 俄文:Тетрис)是一款電視游戲機和掌上游戲機游戲,它由俄羅斯人阿列克謝帕基特諾夫發(fā)明,故得此名。俄羅斯方塊的基本規(guī)則是移動、旋轉和擺放游戲自動輸出的各種方塊,使之排列成完整的一行或多行并且消除得分。
在本次設計中,要求支持鍵盤操作和若干種不同類型方塊的旋轉變換,并且界面上顯示下一個方塊的提示以及當前的玩家的得分,隨著游戲的進行,等級越高,游戲難度越大,即方塊的下落速度越快,相應的等級,等級越高,為玩家提供了不同的選擇。
二、功能分析
I、俄羅斯方塊游戲需要解決的問題包括:
⑴、隨機產(chǎn)生方塊并自動下移
⑵、用Esc鍵退出游戲
⑶、用 鍵變體
⑷、用 鍵和 鍵左右移動方塊
⑸、用空格鍵使游戲暫停
⑹、能正確判斷滿行并消行、計分、定級別
⑺、設定游戲為不同級別,級別越高難度越大
II、俄羅斯方塊游戲需要設計的功能函數(shù)包括:
⑴、聲明俄羅斯方塊的結構體
⑵、函數(shù)原型聲明
⑶、制作游戲窗口
⑷、制作俄羅斯方塊
⑸、判斷是否可動
⑹、隨機產(chǎn)生俄羅斯方塊類型的序號
⑺、打印俄羅斯方塊
⑻、清除俄羅斯方塊的痕跡
⑼、判斷是否滿行并刪除滿行的俄羅斯方塊
三、程序設計
1、程序總體結構設計
(1)、游戲方塊預覽功能。在游戲過程中,游戲界面右側會有預覽區(qū)。由于在此游戲中存在多種不同的游戲方塊,所以在游戲方塊預覽區(qū)域中顯示隨機生成的游戲方塊有利于游戲玩家控制游戲的策略。
(2)、游戲方塊控制功能。通過各種條件的判斷,實現(xiàn)對游戲方塊的左移、右移、自由下落、旋轉功能,以及行滿消除行的功能。
(3)、游戲數(shù)據(jù)顯示功能。在游戲玩家進行游戲過程中,需要按照一定的游戲規(guī)則給玩家計算游戲分數(shù)。例如,消除一行加100分,游戲分數(shù)達到一定數(shù)量之后,需要給游戲者進行等級的上升,每上升一個等級,游戲方塊的下落速度將加快,游戲的難度將增加。以上游戲數(shù)據(jù)均會在游戲界面右側顯示以提示玩家。
(4)、游戲信息提示功能。玩家進入游戲后,將有對本游戲如何操作的友情提示。
(5)、游戲結束退出功能。判斷游戲結束條件,通過Esc鍵進行退出。
打開程序,運行,進入界面
開始游戲
游戲數(shù)據(jù)顯示功能
游戲信息提示功能
游戲結束退出功能
游戲方塊預覽功能
游戲方塊控制功能
否
游戲是否結束
是
關閉游戲界面返回程序
游戲執(zhí)行主流程圖
2、界面設計
分為左右兩個部分:
*左邊為游戲面板
*右邊有三部分:游戲數(shù)據(jù)提示框、下一個方塊提示框和功能提示框
3、重要功能函數(shù)設計
1)、聲明俄羅斯方塊的結構體
struct Tetris
{
int x; //中心方塊的x軸坐標
int y; //中心方塊的y軸坐標
int flag; //標記方塊類型的序號
int next; //下一個俄羅斯方塊類型的序號
int speed; //俄羅斯方塊移動的速度
int count; //產(chǎn)生俄羅斯方塊的個數(shù)
int score; //游戲的分數(shù)
int level; //游戲的等級
};
2)、函數(shù)原型聲明
//光標移到指定位置
void gotoxy(HANDLE hOut, int x, int y);
//制作游戲窗口
void make_frame();
//隨機產(chǎn)生方塊類型的序號
void get_flag(struct Tetris *);
//制作俄羅斯方塊
void make_tetris(struct Tetris *);
//打印俄羅斯方塊
void print_tetris(HANDLE hOut,struct Tetris *);
//清除俄羅斯方塊的痕跡
void clear_tetris(HANDLE hOut,struct Tetris *);
//判斷是否能移動,返回值為1,能移動,否則,不動
int if_moveable(struct Tetris *);
//判斷是否滿行,并刪除滿行的俄羅斯方塊
void del_full(HANDLE hOut,struct Tetris *);
//開始游戲
void start_game();
3)、制作游戲窗口
void make_frame()
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //定義顯示器句柄變量
gotoxy(hOut,FrameX+Frame_width-5,FrameY-2); //打印游戲名稱
printf("俄羅斯方塊");
gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+7); //打印選擇菜單
printf("**********下一個方塊:");
gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+13);
printf("**********");
gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+17);
printf("↑鍵:變體");
gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+19);
printf("空格:暫停游戲");
gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+15);
printf("Esc :退出游戲");
gotoxy(hOut,FrameX,FrameY); //打印框角并記住該處已有圖案
printf("╔");
gotoxy(hOut,FrameX+2*Frame_width-2,FrameY);
printf("╗");
gotoxy(hOut,FrameX,FrameY+Frame_height);
printf("╚");
gotoxy(hOut,FrameX+2*Frame_width-2,FrameY+Frame_height);
printf("╝");
a[FrameX][FrameY+Frame_height]=2;
a[FrameX+2*Frame_width-2][FrameY+Frame_height]=2;
for(i=2;i<2*Frame_width-2;i+=2)
{
gotoxy(hOut,FrameX+i,FrameY);
printf("═"); //打印上橫框
}
for(i=2;i<2*Frame_width-2;i+=2)
{
gotoxy(hOut,FrameX+i,FrameY+Frame_height);
printf("═"); //打印下橫框
a[FrameX+i][FrameY+Frame_height]=2; //記住下橫框有圖案
}
for(i=1;i
x][tetris->y]=b[0]; //中心方塊位置的圖形狀態(tài):1-有,0-無
switch(tetris->flag) //共6大類,19種類型
{
case 1: //田字方塊
{
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x+2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 2: //直線方塊:----
{
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y]=b[2];
a[tetris->x+4][tetris->y]=b[3];
break;
}
case 3: //直線方塊: |
{
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y-2]=b[2];
a[tetris->x][tetris->y+1]=b[3];
break;
}
case 4: //T字方塊
{
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y]=b[2];
a[tetris->x][tetris->y+1]=b[3];
break;
}
case 5: //T字順時針轉90度方塊
{
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x-2][tetris->y]=b[3];
break;
}
case 6: //T字順時針轉180度方塊
{
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x-2][tetris->y]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 7: //T字順時針轉270度方塊
{
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 8: //Z字方塊
{
a[tetris->x][tetris->y+1]=b[1];
a[tetris->x-2][tetris->y]=b[2];
a[tetris->x+2][tetris->y+1]=b[3];
break;
}
case 9: //Z字順時針轉90度方塊
{
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x-2][tetris->y]=b[2];
a[tetris->x-2][tetris->y+1]=b[3];
break;
}
case 10: //Z字順時針轉180度方塊
{
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x-2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 11: //Z字順時針轉270度方塊
{
a[tetris->x][tetris->y+1]=b[1];
a[tetris->x+2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 12: //7字方塊
{
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x-2][tetris->y-1]=b[3];
break;
}
case 13: //7字順時針轉90度方塊
{
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x-2][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 14: //7字順時針轉180度方塊
{
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y+1]=b[3];
break;
}
case 15: //7字順時針轉270度方塊
{
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 16: //倒7字方塊
{
a[tetris->x][tetris->y+1]=b[1];
a[tetris->x][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y-1]=b[3];
break;
}
case 17: //倒7字順指針轉90度方塊
{
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x-2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 18: //倒7字順時針轉180度方塊
{
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x-2][tetris->y+1]=b[3];
break;
}
case 19: //倒7字順時針轉270度方塊
{
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
}
5)、判斷是否可動
int if_moveable(struct Tetris *tetris)
{
if(a[tetris->x][tetris->y]!=0)//當中心方塊位置上有圖案時,返回值為0,即不可移動
{
return 0;
}
else
{
if( //當為田字方塊且除中心方塊位置外,其他"口"字方塊位置上無圖案時,返回值為1,即可移動
( tetris->flag==1 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x+2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
//或為直線方塊且除中心方塊位置外,其他"口"字方塊位置上無圖案時,返回值為1,即可移動
( tetris->flag==2 && ( a[tetris->x-2][tetris->y]==0 &&
a[tetris->x+2][tetris->y]==0 && a[tetris->x+4][tetris->y]==0 ) ) ||
( tetris->flag==3 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x][tetris->y-2]==0 && a[tetris->x][tetris->y+1]==0 ) ) ||
( tetris->flag==4 && ( a[tetris->x-2][tetris->y]==0 &&
a[tetris->x+2][tetris->y]==0 && a[tetris->x][tetris->y+1]==0 ) ) ||
( tetris->flag==5 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y]==0 ) ) ||
( tetris->flag==6 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
( tetris->flag==7 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x][tetris->y+1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
( tetris->flag==8 && ( a[tetris->x][tetris->y+1]==0 &&
a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y+1]==0 ) ) ||
( tetris->flag==9 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x-2][tetris->y]==0 && a[tetris->x-2][tetris->y+1]==0 ) ) ||
( tetris->flag==10 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x-2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
( tetris->flag==11 && ( a[tetris->x][tetris->y+1]==0 &&
a[tetris->x+2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
( tetris->flag==12 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y-1]==0 ) ) ||
( tetris->flag==13 && ( a[tetris->x-2][tetris->y]==0 &&
a[tetris->x-2][tetris->y+1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
( tetris->flag==14 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x][tetris->y+1]==0 && a[tetris->x+2][tetris->y+1]==0 ) ) ||
( tetris->flag==15 && ( a[tetris->x-2][tetris->y]==0 &&
a[tetris->x+2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
( tetris->flag==16 && ( a[tetris->x][tetris->y+1]==0 &&
a[tetris->x][tetris->y-1]==0 && a[tetris->x+2][tetris->y-1]==0 ) ) ||
( tetris->flag==17 && ( a[tetris->x-2][tetris->y]==0 &&
a[tetris->x-2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
( tetris->flag==18 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y+1]==0 ) ) ||
( tetris->flag==19 && ( a[tetris->x-2][tetris->y]==0 &&
a[tetris->x+2][tetris->y+1]==0 && a[tetris->x+2][tetris->y]==0 ) ) )
{
return 1;
}
}
return 0;
}
6)、隨機產(chǎn)生俄羅斯方塊類型的序號
void get_flag(struct Tetris *tetris)
{
tetris->count++; //記住產(chǎn)生方塊的個數(shù)
srand((unsigned)time(NULL)); //初始化隨機數(shù)
if(tetris->count==1)
{
tetris->flag = rand()%19+1; //記住第一個方塊的序號
}
tetris->next = rand()%19+1; //記住下一個方塊的序號
}
7)、打印俄羅斯方塊
void print_tetris(HANDLE hOut,struct Tetris *tetris)
{
for(i=0;i<4;i++)
{
b[i]=1; //數(shù)組b[4]的每個元素的值都為1
}
make_tetris(tetris); //制作俄羅斯方塊
for( i=tetris->x-2; i<=tetris->x+4; i+=2 )
{
for(j=tetris->y-2;j<=tetris->y+1;j++)
{
if( a[i][j]==1 && j>FrameY )
{
gotoxy(hOut,i,j);
printf("□"); //打印邊框內的方塊
}
}
}
//打印菜單信息
gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+1);
printf("level : %d",tetris->level);
gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+3);
printf("score : %d",tetris->score);
gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+5);
printf("speed : %dms",tetris->speed);
}
8)、清除俄羅斯方塊的痕跡
void clear_tetris(HANDLE hOut,struct Tetris *tetris)
{
for(i=0;i<4;i++)
{
b[i]=0; //數(shù)組b[4]的每個元素的值都為0
}
make_tetris(tetris); //制作俄羅斯方塊
for( i=tetris->x-2; i<=tetris->x+4; i+=2 )
{
for(j=tetris->y-2;j<=tetris->y+1;j++)
{
if( a[i][j]==0 && j>FrameY )
{
gotoxy(hOut,i,j);
printf(" "); //清除方塊
}
}
}
}
9)、判斷是否滿行并刪除滿行的俄羅斯方塊
void del_full(HANDLE hOut,struct Tetris *tetris)
{ //當某行有Frame_width-2個方塊時,則滿行
int k,del_count=0; //分別用于記錄某行方塊的個數(shù)和刪除方塊的行數(shù)的變量
for(j=FrameY+Frame_height-1;j>=FrameY+1;j--)
{
k=0;
for(i=FrameX+2;iFrameY;k--)
{ //如果刪除行以上的位置有方塊,則先清除,再將方塊下移一個位置
for(i=FrameX+2;iscore+=100*del_count; //每刪除一行,得100分
if( del_count>0 && ( tetris->score%1000==0 || tetris->score/1000>tetris->level-1 ) )
{ //如果得1000分即累計刪除10行,速度加快20ms并升一級
tetris->speed-=20;
tetris->level++;
}
}
10)、開始游戲
void start_game()
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //定義顯示器句柄變量
struct Tetris t,*tetris=&t; //定義結構體的指針并指向結構體變量
unsigned char ch; //定義接收鍵盤輸入的變量
tetris->count=0; //初始化俄羅斯方塊數(shù)為0個
tetris->speed=300; //初始移動速度為300ms
tetris->score=0; //初始游戲的分數(shù)為0分
tetris->level=1; //初始游戲為第1關
while(1)
{//循環(huán)產(chǎn)生方塊,直至游戲結束
get_flag(tetris); //得到產(chǎn)生俄羅斯方塊類型的序號
temp=tetris->flag; //記住當前俄羅斯方塊序號
//打印下一個俄羅斯方塊的圖形(右邊窗口)
tetris->x=FrameX+2*Frame_width+6;
tetris->y=FrameY+10;
tetris->flag = tetris->next;
print_tetris(hOut,tetris);
tetris->x=FrameX+Frame_width; //初始中心方塊x坐標
tetris->y=FrameY-1; //初始中心方塊y坐標
tetris->flag=temp; //取出當前的俄羅斯方塊序號
while(1)
{//控制方塊方向,直至方塊不再下移
label:print_tetris(hOut,tetris);//打印俄羅斯方塊
Sleep(tetris->speed); //延緩時間
clear_tetris(hOut,tetris); //清除痕跡
temp1=tetris->x; //記住中心方塊橫坐標的值
temp2=tetris->flag; //記住當前俄羅斯方塊序號
if(kbhit())
{ //判斷是否有鍵盤輸入,有則用ch↓接收
ch=getch();
if(ch==75) //按←鍵則向左動,中心橫坐標減2
{
tetris->x-=2;
}
if(ch==77) //按→鍵則向右動,中心橫坐標加2
{
tetris->x+=2;
}
if(ch==72) //按↑鍵則變體即當前方塊順時針轉90度
{
if( tetris->flag>=2 && tetris->flag<=3 )
{
tetris->flag++;
tetris->flag%=2;
tetris->flag+=2;
}
if( tetris->flag>=4 && tetris->flag<=7 )
{
tetris->flag++;
tetris->flag%=4;
tetris->flag+=4;
}
if( tetris->flag>=8 && tetris->flag<=11 )
{
tetris->flag++;
tetris->flag%=4;
tetris->flag+=8;
}
if( tetris->flag>=12 && tetris->flag<=15 )
{
tetris->flag++;
tetris->flag%=4;
tetris->flag+=12;
}
if( tetris->flag>=16 && tetris->flag<=19 )
{
tetris->flag++;
tetris->flag%=4;
tetris->flag+=16;
}
}
if(ch==32) //按空格鍵,暫停
{
print_tetris(hOut,tetris);
while(1)
{
if(kbhit()) //再按空格鍵,繼續(xù)游戲
{
ch=getch();
if(ch==32)
{
goto label;
}
}
}
}
if(if_moveable(tetris)==0) //如果不可動,上面操作無效
{
tetris->x=temp1;
tetris->flag=temp2;
}
else //如果可動,執(zhí)行操作
{
goto label;
}
}
tetris->y++; //如果沒有操作指令,方塊向下移動
if(if_moveable(tetris)==0) //如果向下移動且不可動,方塊放在此處
{
tetris->y--;
print_tetris(hOut,tetris);
del_full(hOut,tetris);
break;
}
}
for(i=tetris->y-2;iy+2;i++)
{//游戲結束條件:方塊觸到框頂位置
if(i==FrameY)
{
j=0; //如果游戲結束,j=0 }
}
if(j==0)
{
system("cls");
getch();
break;
}
//清除下一個俄羅斯方塊的圖形(右邊窗口)
tetris->flag = tetris->next;
tetris->x=FrameX+2*Frame_width+6;
tetris->y=FrameY+10;
clear_tetris(hOut,tetris);
} }
4、函數(shù)設計流程
進入俄羅斯方塊程序
、
聲明俄羅斯方塊的結構體
struct Tetris
定義全局變量
函數(shù)原型聲明
//制作游戲窗口make_frame();
//開始游戲start_game();
定義主函數(shù)
void main()
制作俄羅斯方塊
判斷是否可動
開始游戲
具體設計運行游戲所需要的各種功能
隨機產(chǎn)生俄羅斯
方塊類型的序號
打印俄羅斯方塊
清除俄羅斯方塊的痕跡
判斷是否滿行并刪除滿行的俄羅斯方塊
鏈接地址:http://m.appdesigncorp.com/p-9108399.html