700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > C语言小游戏详解—俄罗斯方块

C语言小游戏详解—俄罗斯方块

时间:2019-06-18 03:38:11

相关推荐

C语言小游戏详解—俄罗斯方块

版权声明:本文为博主原创文章,转载请注明CSDN博客源地址!

/Mou_Yang/article/details/82424643

一、游戏组成

俄罗斯方块总共有19种方块,每一种方块都是由4个小格子组成。但其实这19种方块是由7种基本方块通过变形得到的。

下面是这7种基本方块:

第0种基本方块:有1种形态

第1种基本方块:有2种形态

第2种基本方块:有2种形态

第3种基本方块:有4种形态

第4种基本方块:有4种形态

第5种基本方块:有2种形态

第6种基本方块:有4种形态

二、游戏规则

1、在一个行高为20,列高为14的矩形中,随机方块从上方以一定速率下落;

2、其下落过程中可通过按键使它左右移动、变形;

3、方块下落至矩阵底部或者下部与其他方块接触,则固定该方块的位置,并生成新的方块重复步骤2;

4、如果矩阵中的某一行都是方块,则消去该行的方块,并使上面的方块下沉一行;

5、如果方块的堆积高度超过20,则游戏结束。

三、总体设计

我的想法是创建一个25*14的整型数组array,数组元素用0表示空位,1表示堆积的方块,2表示在运动的方块,用另外的数组graph[4][2]记录在运行的方块各个点的坐标。红色位置用作方块运动到底后生成新方块的位置,橙色区域用作玩家可视区域,在该区域方块运动并接收玩家指令变形。

四、定义变量

设置矩阵的行高:

#define H 25

设置列高14:

#define L 14

设置7种方块在红色区域生成时的各点坐标位置:

int block[7][4][2]={{{2,6},{2,7},{3,6},{3,7}},//第0种基本方块{{1,7},{2,7},{2,6},{3,6}},//第1种基本方块{{1,6},{2,6},{2,7},{3,7}},//第2种基本方块{{2,6},{3,6},{3,7},{3,8}},//第3种基本方块{{2,8},{3,8},{3,7},{3,6}},//第4种基本方块{{3,5},{3,8},{3,7},{3,6}},//第5种基本方块{{2,7},{3,6},{3,7},{3,8}}};//第6种基本方块

假设每种方块都有4种变形(如果它只有一种变形,则它的另外三种变形,跟原来一样),每次变形后各点坐标都会变化,创建数组记录坐标变化的差值:

int to_change[7][4][4][2]={{{{0,0},{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0},{0,0}}},//第0种基本方块,每次变化后的坐标都不变,故x,y坐标变化的差值都为0{{{2,1},{1,0},{0,1},{-1,0}},{{-2,-1},{-1,0},{0,-1},{1,0}},{{2,1},{1,0},{0,1},{-1,0}},{{-2,-1},{-1,0},{0,-1},{1,0}}},//第1种基本方块,它有2种变形,故第一次变化的坐标差值跟第三次一样,第二次变化跟第四次一样{{{1,2},{0,1},{1,0},{0,-1}},{{-1,-2},{0,-1},{-1,0},{0,1}},{{1,2},{0,1},{1,0},{0,-1}},{{-1,-2},{0,-1},{-1,0},{0,1}}},//...{{{-1,2},{-2,1},{-1,0},{0,-1}},{{2,0},{1,1},{0,0},{-1,-1}},{{0,-1},{1,0},{0,1},{-1,2}},{{-1,-1},{0,-2},{1,-1},{2,0}}},//...{{{1,0},{0,-1},{-1,0},{-2,1}},{{0,-2},{-1,-1},{0,0},{1,1}},{{-2,1},{-1,2},{0,1},{1,0}},{{1,1},{2,0},{1,-1},{0,-2}}},//...{{{-3,2},{-2,-1},{-1,0},{0,1}},{{3,-2},{2,1},{1,0},{0,-1}},{{-3,2},{-2,-1},{-1,0},{0,1}},{{3,-2},{2,1},{1,0},{0,-1}}},//...{{{0,1},{-2,1},{-1,0},{0,-1}},{{1,-1},{1,1},{0,0},{-1,-1}},{{-1,0},{1,0},{0,1},{-1,2}},{{0,0},{0,-2},{1,-1},{2,0}}}};//...

设置生成的方块的序号:

int picture;//picture=rand()%7;

记录当前运动方块的变形:

int now; //0<=now<=3

记录运动方块4个点的x和y坐标

int graph[4][2];//Xi=graph[i][0] Yi=graph[i][1]

设置记录键盘输入的字符变量

char control;//'w'表示变形 'a'表示左移 'd'表示右移

设置计时:

int start;//每500毫秒方块下降一格

五、主要函数

方块变形:调用数组to_change对方块坐标graph[][]进行修改,实现方块变形。注意:判断方块变形后是否会超出屏幕左右边界,如果超出,就要挪一下方块的位置。

void Change();

左右移动:将玩家输入的字符赋值给control,然后作参数传给M,如果为A/a,则左移,为D/d,则右移。注意:当方块触碰左右边界,或者左右有其他已经固定的方块,是无法在移动的。

void Move(char M);

方块到底部:判断方块是否已经到达底部,或者下部跟其他方块接触,是的话返回1,不是返回0。

int See();

生成方块:重置数组graph[][]的坐标,生成新的方块。

void New();

方块前进:实现方块向下走一格

void Go();

游戏开始:开始游戏,初始化picture,nowgraph[][]等数据。

void Begin();

消去一行:遍历数组array,如果某一行全部为1(该行全是方块),则消去该行,上面的方块下沉一格,并在最上面生成空白的一行。同时判断死亡,如果遍历时发现方块堆积高度大于20,返回1代表游戏结束。

int Elimination();

可视界面:输出矩阵array可视的部分,即游戏界面。

void Cout();

以上是需要自己实现的函数,除此之外还要另外调用4个库函数:

1.实现非显示输入:让用户输入的字符不用在控制台显示出来然后回车赋值给变量,而是直接在输入时就赋值给变量。

#include <conio.h>char getch();

2.判断是否有键盘信息:当检测到有键盘输入 时,该函数返回值>0,否则返回0。

#include <conio.h>int kbhit();

3.记录时间:该函数返回设备的启动时间(单位:毫秒),可多次调用,并用后者减去前者,用以计算两者的时间间隔。

#include <ctime>int GetTickCount();

4.卡住屏幕:在等待到用户的下一步指令之前,卡住程序的运行。

#include <windows.h>system("cls");

六、完整代码

#include<iostream>#include<conio.h>#include<windows.h>#include<stdlib.h>#include<ctime>#define H 25#define L 14//这个里要判断它下一步是否会重叠,如果会则表示已经到底using namespace std;int array[H][L]; //进行方块组合的地方//28中变形int to_change[7][4][4][2]={{{{0,0},{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0},{0,0}}},{{{2,1},{1,0},{0,1},{-1,0}},{{-2,-1},{-1,0},{0,-1},{1,0}},{{2,1},{1,0},{0,1},{-1,0}},{{-2,-1},{-1,0},{0,-1},{1,0}}},{{{1,2},{0,1},{1,0},{0,-1}},{{-1,-2},{0,-1},{-1,0},{0,1}},{{1,2},{0,1},{1,0},{0,-1}},{{-1,-2},{0,-1},{-1,0},{0,1}}},{{{-1,2},{-2,1},{-1,0},{0,-1}},{{2,0},{1,1},{0,0},{-1,-1}},{{0,-1},{1,0},{0,1},{-1,2}},{{-1,-1},{0,-2},{1,-1},{2,0}}},{{{1,0},{0,-1},{-1,0},{-2,1}},{{0,-2},{-1,-1},{0,0},{1,1}},{{-2,1},{-1,2},{0,1},{1,0}},{{1,1},{2,0},{1,-1},{0,-2}}},{{{-3,2},{-2,-1},{-1,0},{0,1}},{{3,-2},{2,1},{1,0},{0,-1}},{{-3,2},{-2,-1},{-1,0},{0,1}},{{3,-2},{2,1},{1,0},{0,-1}}},{{{0,1},{-2,1},{-1,0},{0,-1}},{{1,-1},{1,1},{0,0},{-1,-1}},{{-1,0},{1,0},{0,1},{-1,2}},{{0,0},{0,-2},{1,-1},{2,0}}}};//7个图形int block[7][4][2]={{{2,6},{2,7},{3,6},{3,7}},{{1,7},{2,7},{2,6},{3,6}},{{1,6},{2,6},{2,7},{3,7}},{{2,6},{3,6},{3,7},{3,8}},{{2,8},{3,8},{3,7},{3,6}},{{3,5},{3,8},{3,7},{3,6}},{{2,7},{3,6},{3,7},{3,8}}};int picture;//图形的序号int now; //当前图形的变化号int graph[4][2];//图形的坐标char control;int start;void Change();void Move(char M); //根据输入的AD判断左右移动int See(); //判断是否到底void New(); //开新void Go();//向下走一格void Begin(); //一切值初始化int Elimination(); //把完整行的消去void Cout(); //输出矩阵int main(){Begin();Cout();while(1){if(GetTickCount()-start>=500){start=GetTickCount();if(!See())Go();else {if(Elimination())break;New();}system("cls");Cout();}if(kbhit()){control=getch();if(control=='W'||control=='w')Change();else Move(control);system("cls");Cout();}}//虽然背景板的高度为25,但显示时只显示后20格}void Change(){for(int i=0;i<4;i++)array[graph[i][0]][graph[i][1]]=0;now=(now+1)%4;for(int i=0;i<4;i++){graph[i][0]+=to_change[picture][now][i][0];graph[i][1]+=to_change[picture][now][i][1];}for(int i=0;i<4;i++){if(graph[i][1]<0){int temp=0-graph[i][1];for(int j=0;j<4;j++)graph[j][1]+=temp;}if(graph[i][1]>L-1){int temp=graph[i][1]-(L-1);for(int j=0;j<4;j++)graph[j][1]-=temp;}}for(int i=0;i<4;i++)array[graph[i][0]][graph[i][1]]=2;}void Move(char M){for(int i=0;i<4;i++)array[graph[i][0]][graph[i][1]]=0;if((M=='a'||M=='A')&&graph[0][1]&&graph[1][1]&&graph[2][1]&&graph[3][1])if(array[graph[0][0]][graph[0][1]-1]!=1&&array[graph[1][0]][graph[1][1]-1]!=1&&array[graph[2][0]][graph[2][1]-1]!=1&&array[graph[3][0]][graph[3][1]-1]!=1){graph[0][1]--;graph[1][1]--;graph[2][1]--;graph[3][1]--;}if((M=='d'||M=='D')&&graph[0][1]<L-1&&graph[1][1]<L-1&&graph[2][1]<L-1&&graph[3][1]<L-1)if(array[graph[0][0]][graph[0][1]+1]!=1&&array[graph[1][0]][graph[1][1]+1]!=1&&array[graph[2][0]][graph[2][1]+1]!=1&&array[graph[3][0]][graph[3][1]+1]!=1){graph[0][1]++;graph[1][1]++;graph[2][1]++;graph[3][1]++;}for(int i=0;i<4;i++)array[graph[i][0]][graph[i][1]]=2;}int See(){for(int i=0;i<4;i++)if(graph[i][0]+1==H)return 1;for(int i=0;i<4;i++)if(array[graph[i][0]+1][graph[i][1]]==1)return 1;return 0;}void New(){picture=rand()%7;now=-1;for(int i=0;i<4;i++){graph[i][0]=block[picture][i][0];graph[i][1]=block[picture][i][1];array[graph[i][0]][graph[i][1]]=2;}}void Go(){for(int i=0;i<4;i++){array[graph[i][0]][graph[i][1]]=0;graph[i][0]++;}for(int i=0;i<4;i++)array[graph[i][0]][graph[i][1]]=2;}void Begin(){srand(time(NULL));start=GetTickCount();//开始的时间for(int i=0;i<H;i++)for(int j=0;j<L;j++)array[i][j]=0;picture=rand()%7;now=-1;for(int i=0;i<4;i++){graph[i][0]=block[picture][i][0];graph[i][1]=block[picture][i][1];array[graph[i][0]][graph[i][1]]=2;}}int Elimination(){for(int i=0;i<4;i++){array[graph[i][0]][graph[i][1]]=1;if(graph[i][0]<4)return 1;}for(int i=H-1;i>=0; ){int j;for(j=0;j<L;j++)if(array[i][j]!=1)break;if(j==L){for(int k=i;k>0;k--)for(int l=0;l<L;l++)array[k][l]=array[k-1][l];}else i--;}return 0;}void Cout(){for(int i=5;i<H;i++){for(int j=0;j<L;j++){if(array[i][j]==0)printf(".");else if(array[i][j]==1){printf("#");}else printf("o");}printf("\n");}}

七、效果界面

超简易版的俄罗斯方块,没有积分,没有开始菜单。(但其实这些自己去加就可以了,开个变量记一下)

八、总结

作为一个已经学了两年编程的菜鸟来说,写这个东西还花了一天,确实有点丢人。不过因为刚开的博客想写点东西上来,就水了个俄罗斯方块。整个过程我已经很详细地介绍了,但如果还有什么疏漏或者错误的地方,欢迎在下方评论指出,一起探讨。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。