解析一个C语言俄罗斯方块游戏,包你看了就会
#写代码来显示这个方块
方块数据,这两个数组其实是两种游戏模式的方块信息,我们只需要分析一种就可以了。
int TGM[7][4]={{0x159D,0x89AB,0x159D,0x89AB},{0x126A,0x4856,0x159A,0x4526},{0x926A,0x456A,0x1592,0x0456},{0x4859,0x4859,0x4859,0x4859},{0x5926,0x0156,0x5926,0x0156},{0x4159,0x4596,0x1596,0x4156},{0x156A,0x4152,0x156A,0x4152}};
int SRS[7][4]={{0x159D,0x89AB,0x26AE,0x4567},{0x0159,0x4856,0x159A,0x4526},{0x8159,0x456A,0x1592,0x0456},{0x4859,0x4859,0x4859,0x4859},{0x4815,0x459A,0x5926,0x0156},{0x4159,0x4596,0x1596,0x4156},{0x0459,0x8596,0x156A,0x4152}};
我们分析这段代码
/***********擦除显示*************/
int Display(int x, int y, int CAC, int Mode)
{
for(j=0;j<=3;j++){
P[j]=CAC&0xF, CAC>>=4;
if(Mode==1){Pos((P[j]>>2)+x,(P[j]&0x3)+y); printf( "■");}
elseif(Mode==0){Pos((P[j]>>2)+x,(P[j]&0x3)+y); printf( " ");}
}
return0;
}
P[j]=CAC&0xF 取到的是 4个bit,然后通过判断这 4个bit决定输出方块的位置。
0100 ----> 对应坐标(1,0)
1000 ----> 对应坐标(2,0)
0101 ----> 对应坐标(1,1)
1001 ----> 对应坐标(2,1)
通过这个坐标,我们会输出这样一个方块
再举个例子
0000 ----> 对应坐标(0,0)
0001 ----> 对应坐标(0,1)
0101 ----> 对应坐标(1,1)
0110 ----> 对应坐标(1,2)
显示方块没有问题了
上面的代码中,如果mode等于0的话,也就是把某个方块从显示中擦除掉。
我们用devc++写的程序,需要知道几个细节。
#构建固定行列的窗口
正常情况,我们显示cmd是一个默认值的黑框「如下图」。
实际上,我们可以用代码来固定cmd的框框大小。
默认代码输出
示例代码:
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>
/**********Main主函数***********/
int main
{
system( "color F1&mode con cols=35 lines=25");
getchar;
return0;
}
程序输出:
#延迟函数的设计
跟其他不同的是,这个程序的延迟没有使用 usleep ,我觉得这也是非常值得称赞的地方,不过空跑cpu,哈哈,是有那么一点调皮。
把延迟放到键值获取的函数中。
/**********按键获取**************/
int Getkey(int N,int T)
{
int start=clock;
if(KEY_V==115){ return115;}
do{
if(kbhit){
KEY_V=(int)(getch);
if(KEY_V<97){KEY_V+=32;}
returnKEY_V;
}
for(i=0;i<=N;i++);
} while((clock-start)<T);
dy=1;
return-1;
}
就先简单讲解下这些,至于得分机制,碰撞检测,消除的代码,还没有想好怎么讲明白,需要再花时间剖析剖析。
#试玩一下
#源码 #include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>
/**********初始化参数************/
int i,j,N,T,F,J,X,Y,dx,dy, KEY_V, Cache1,Cache2,NU,NI,RU,RI, P_X,P_Y,POS_H_MAX, LEVEL=1,SCORE=0, P[4], POINT_V[12][22], MARK[21], FLAG[5]={0,0,0,1,0};
int TGM[7][4]={{0x159D,0x89AB,0x159D,0x89AB},{0x126A,0x4856,0x159A,0x4526},{0x926A,0x456A,0x1592,0x0456},{0x4859,0x4859,0x4859,0x4859},{0x5926,0x0156,0x5926,0x0156},{0x4159,0x4596,0x1596,0x4156},{0x156A,0x4152,0x156A,0x4152}};
int SRS[7][4]={{0x159D,0x89AB,0x26AE,0x4567},{0x0159,0x4856,0x159A,0x4526},{0x8159,0x456A,0x1592,0x0456},{0x4859,0x4859,0x4859,0x4859},{0x4815,0x459A,0x5926,0x0156},{0x4159,0x4596,0x1596,0x4156},{0x0459,0x8596,0x156A,0x4152}};
/**********光标位置函数**********/
void Pos(int x,int y)
{
COORD pos;
HANDLE hOutput;
pos.X=2*x;
pos.Y=y;
hOutput=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOutput,pos);
}
void HideCursor
{
CONSOLE_CURSOR_INFO cursor_info={1,0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
}
/**********初始化界面************/
void CreatUI
{
int i,j,BOUNDARY;
printf( "┏━━━━━━━━━━┓n");
for(j=1;j<=20;j++) {
if(j==3){ printf( "┃ ┃LEVEL:1n");}
elseif(j==5){ printf( "┃ ┃SCORE:0n");}
elseif(j==7){ printf( "┃ ┃NEXT n");}
else{ printf( "┃ ┃n");}
}
printf( "┗━━━━━━━━━━┛n");
printf( " CopyRight@2016~2018 BY HAPPYn");
for(j=1;j<=21;j++){
for(i=0;i<=11;i++){
BOUNDARY=i*(i-11)*(j-21);
if(BOUNDARY==0){
POINT_V[i][j]=1;
} else{
POINT_V[i][j]=0;
}
}
}
}
/**********按键获取**************/
int Getkey(int N,int T)
{
int start=clock;
if(KEY_V==115){ return115;}
do{
if(kbhit){
KEY_V=(int)(getch);
if(KEY_V<97){KEY_V+=32;}
returnKEY_V;
}
for(i=0;i<=N;i++);
printf( "%dn",clock-start);
} while((clock-start)<T);
dy=1;
return-1;
}
/***********块体转置*************/
int Rote(int S, int I)
{
return(F==0)?TGM[S][(I+4)%4]:SRS[S][(I+4)%4];
}
/***********擦除显示*************/
int Display(int x, int y, int CAC, int Mode)
{
for(j=0;j<=3;j++){
P[j]=CAC&0xF, CAC>>=4;
if(Mode==1){Pos((P[j]>>2)+x,(P[j]&0x3)+y); printf( "■");}
elseif(Mode==0){Pos((P[j]>>2)+x,(P[j]&0x3)+y); printf( " ");}
}
return0;
}
/***********固化块体*************/
int DoBlocks
{
//~~~游戏结束
if(Y<2){
Pos(1,22); printf( "GAME OVER!");
exit(0);
}
//~~~固化块体
POS_H_MAX=0, FLAG[3]=1;
for(j=0;j<=3;j++){
P_X=(P[j]>>2)+X,P_Y=(P[j]&0x3)+Y;
if(POS_H_MAX<P_Y){POS_H_MAX=P_Y;}
POINT_V[P_X][P_Y]=1;
}
//~~~关卡得分
for(j=Y;j<=POS_H_MAX;j++){
FLAG[2]=1;
for(i=1;i<=10;i++){
if(POINT_V[i][j]==0){FLAG[2]=0;}
}
if(FLAG[2]){
SCORE+=10,MARK[j]=1;
if(SCORE==400){
SCORE=0,LEVEL+=1,T-=100;
FLAG[4]=1;
}
}
}
//~~~极品消行
for(j=20;j>=5;j--){
if(FLAG[4]){
for(i=1;i<=10;i++){
POINT_V[i][j]=0;
Pos(i,j); printf( " ");
}
}
elseif(MARK[j])
{
MARK[j]=0,J=j-1;
for(N=1;N<=3;N++){
if(MARK[J]){J--;}
}
MARK[J]=1;
for(i=1;i<=10;i++){
Pos(i,j);
if(POINT_V[i][j]=POINT_V[i][J]){
printf( "■");
} else{
printf( " ");
}
}
}
}
FLAG[4]=0;
return0;
}
/***********碰撞检测*************/
int CheckCollision
{
for(j=0;j<=3;j++){
P_X=(P[j]>>2)+X+dx,P_Y=(P[j]&0x3)+Y+dy;
if(POINT_V[P_X][P_Y]){
if(dx!=0){ return1;}
if(dy){
DoBlocks;
Pos(12,3); printf( "LEVEL:%-3d",LEVEL);
Pos(12,5); printf( "SCORE:%-3d",SCORE);
return2;
}
if(KEY_V==119){FLAG[0]=1;}
}
}
return0;
}
unsigned
/***********循环核心*************/
int GameCycle(int N, int T, int F)
{
srand((unsigned)time(NULL));RU=rand%7,RI=(rand%4);
while(1){
if(FLAG[3]){
Display(12,8,Rote(RU,RI),0);
X=4,Y=1, NU=RU,NI=RI, RU=rand%7,RI=(rand%4), FLAG[3]=0,KEY_V=0;
Display(12,8,Rote(RU,RI),1);
Display(X, Y,Rote(NU,NI),1);
}
dx=0,dy=0;
KEY_V=Getkey(N,T);
if(KEY_V==119){
NI++;
Display(X,Y,Rote(NU,NI),2);
}//旋W
elseif(KEY_V==115){dy= 1;}//下S
elseif(KEY_V==97 ){dx=-1;}//左A
elseif(KEY_V==100){dx= 1;}//右D
elseif(KEY_V==112){getch; }//暂停P
elseif(KEY_V==113){ return0;}//退出Q
if(dx!=0 || dy!=0 || KEY_V==119){
if(!CheckCollision){
if(FLAG[0]){
NI--,FLAG[0]=0;
Display(X,Y,Rote(NU,NI),0);
}
elseif(KEY_V==119){
Display(X,Y,Rote(NU,NI-1),0);
} else{
Display(X,Y,Rote(NU,NI),0);
}
Display(X+dx,Y+dy,Rote(NU,NI),1);
X+=dx,Y+=dy;
}
}
}
return0;
}
/**********Main主函数***********/
int main
{
system( "color F0&mode con cols=35 lines=25");
HideCursor;
CreatUI;
GameCycle(10,800,1);
return0;
}
#后记
热门曲谱
- 刘德华喊话四大天王合体做节目:他们愿意我 彭于晏带违规水果过海关被罚 据台湾媒体报道,彭于晏7月1日返回台北在松山机场过海关的时候,因为不小心带了水果,被海关查获并罚款3000元台币 。有台湾媒体询问机场工作人...[详情]分类:知识库时间:12:37
- led和节能灯哪个好
概括:这道题是贲友颗同学的课后练习题,主要是关于led和节能灯哪个好,指导老师为黎老师。LED节能灯是继紧凑型荧光灯(即普通节能灯...
[详情]分类:知识库时间:14:47 - 个人所得税税率
概括:这道题是蒲值暇同学的课后练习题,主要是关于个人所得税税率,指导老师为阚老师。
题目:个人所得税税率
解:<...[详情]分类:知识库时间:14:51 - 个税计算方法
概括:这道题是文缘卣同学的课后练习题,主要是关于个税计算方法,指导老师为惠老师。负所得税制度的意义财税部门出台了给予弱势群...
[详情]分类:知识库时间:14:51 - 李光洁宣布结婚 彭于晏带违规水果过海关被罚 据台湾媒体报道,彭于晏7月1日返回台北在松山机场过海关的时候,因为不小心带了水果,被海关查获并罚款3000元台币 。有台湾媒体询问机场工作人...[详情]分类:知识库时间:12:37
- 什么可以美白牙齿
概括:这道题是贡泼俊同学的课后练习题,主要是关于什么可以美白牙齿,指导老师为井老师。冷光美白牙齿顾名思义就是用冷光来美白牙...
[详情]分类:知识库时间:14:58 - 什么是连带责任
概括:这道题是满澄檬同学的课后政治练习题,主要是关于什么是连带责任,指导老师为宦老师。
题目:什么是连带责任
...[详情]分类:知识库时间:14:58 - 趣头条与江苏卫视达成战略合作 彭于晏带违规水果过海关被罚 据台湾媒体报道,彭于晏7月1日返回台北在松山机场过海关的时候,因为不小心带了水果,被海关查获并罚款3000元台币 。有台湾媒体询问机场工作人...[详情]分类:知识库时间:12:37
- 利率怎么算
概括:这道题是从纲凑同学的课后练习题,主要是关于利率怎么算,指导老师为殳老师。银行利率表示一定时期内利息量与本金的比率,通...
[详情]分类:知识库时间:14:58 - 名贵树种
概括:这道题是山翁灿同学的课后练习题,主要是关于名贵树种,指导老师为谈老师。
题目:名贵树种
解: ...[详情]分类:知识库时间:14:56 - 埃利斯
概括:这道题是苏似涡同学的课后政治练习题,主要是关于埃利斯,指导老师为裴老师。
题目:埃利斯
解: ...[详情]分类:知识库时间:14:54 - 差异
概括:这道题是巫唐抖同学的课后练习题,主要是关于差异,指导老师为左老师。暂时性差异是由税收法规与会计准则确认时间或计税基础...
[详情]分类:知识库时间:14:53 - 平衡梁
概括:这道题是浦晓淖同学的课后练习题,主要是关于平衡梁,指导老师为赵老师。平衡梁为吊装机具的重要组成部分,可用于保持被吊设...
[详情]分类:知识库时间:14:54 - 建筑图集
概括:这道题是蓟侠位同学的课后政治练习题,主要是关于建筑图集,指导老师为焦老师。《新疆传统建筑图集》是2009年新疆科学技术出...
[详情]分类:知识库时间:14:54 - 成分分析
概括:这道题是颜仑徽同学的课后练习题,主要是关于成分分析,指导老师为戈老师。
题目:成分分析
解: ...[详情]分类:知识库时间:14:56 - 无坚不摧之力
概括:这道题是路婆掖同学的课后政治练习题,主要是关于无坚不摧之力,指导老师为祁老师。
题目:无坚不摧之力
解:<...[详情]分类:知识库时间:14:54 - 气垫船原理
概括:这道题是席洞朴同学的课后练习题,主要是关于气垫船原理,指导老师为毛老师。通风工程是送风、排风、除尘、气力输送以及防、...
[详情]分类:知识库时间:14:54 - 海狸
概括:这道题是项筛卦同学的课后练习题,主要是关于海狸,指导老师为钱老师。
题目:海狸
解: ...[详情]分类:知识库时间:14:56 - 38译码器
知识点:《38译码器》 收集:瞿收霉 编辑:桂花
[详情]分类:知识库时间:10:57
本知识点包括:1、38译码器在单片机系统中的作用是什么? 2、求vh... - aidma
知识点:《aidma》 收集:蒯超峦 编辑:栀子花女孩
[详情]分类:知识库时间:12:08
本知识点包括:1、SOV/SOM是什么?AIDMA和AIDAS理论代表什么...