东阿网站建设公司,新都区建设局网站,如何登入 WORDPRESS 后台,搬家公司收费价格表最近在看俄罗斯方块的游戏#xff0c;看到一个大神写的俄罗斯方块代码#xff0c;非常非常优秀#xff0c;拿出来解析给大家看看#xff0c;也希望大家自己尝试运行试试#xff0c;从中能得到一些启发。#先了解下俄罗斯方块的几个形状一共分成 7 形状#xff0c;有的形状… 最近在看俄罗斯方块的游戏看到一个大神写的俄罗斯方块代码非常非常优秀拿出来解析给大家看看也希望大家自己尝试运行试试从中能得到一些启发。#先了解下俄罗斯方块的几个形状一共分成 7 形状有的形状有 4种状态有的形状有1种状态。不管是多少种状态一个方块需要一个2个字节来存储也就是16bit来保存一个方块的信息。基于上面的理论我们可以使用4x4的数组来保存方块的信息。注意下面代码中的 ■ 占用的是2个字节。#写代码来显示这个方块方块数据这两个数组其实是两种游戏模式的方块信息我们只需要分析一种就可以了。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(j0;j3;j){P[j]CAC0xF, CAC4;if (Mode1){Pos((P[j]2)x,(P[j]0x3)y);printf(■);}else if(Mode0){Pos((P[j]2)x,(P[j]0x3)y);printf( );}}return 0;
}
P[j]CAC0xF 取到的是 4个bit然后通过判断这 4个bit决定输出方块的位置。我们拿 0这个方块的数据0x4859 对应的二进制 0B0100100001011001来做个例子。0100 ---- 对应坐标10
1000 ---- 对应坐标20
0101 ---- 对应坐标11
1001 ---- 对应坐标21
通过这个坐标我们会输出这样一个方块再举个例子我们拿 Z这个方块的数据0x0156 对应的二进制 0B0000000101010110来做个例子。0000 ---- 对应坐标00
0001 ---- 对应坐标01
0101 ---- 对应坐标11
0110 ---- 对应坐标12
显示方块没有问题了上面的代码中如果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 F1mode con cols35 lines25);getchar();return 0;
}
程序输出#延迟函数的设计跟其他不同的是这个程序的延迟没有使用usleep我觉得这也是非常值得称赞的地方不过空跑cpu哈哈是有那么一点调皮。把延迟放到键值获取的函数中。/**********按键获取**************/
int Getkey(int N,int T)
{int startclock();if(KEY_V115){return 115;}do{if(kbhit()){KEY_V(int)(getch());if(KEY_V97){KEY_V32;}return KEY_V;}for(i0;iN;i);}while((clock()-start)T);dy1;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, LEVEL1,SCORE0, 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.X2*x;pos.Yy;hOutputGetStdHandle(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(j1;j20;j) {if (j3){printf(┃ ┃LEVEL1\n);}else if(j5){printf(┃ ┃SCORE0\n);}else if(j7){printf(┃ ┃NEXT \n);}else {printf(┃ ┃\n);}}printf(┗━━━━━━━━━━┛\n);printf( CopyRight2016~2018 BY HAPPY\n);for(j1;j21;j){for(i0;i11;i){BOUNDARYi*(i-11)*(j-21);if(BOUNDARY0){POINT_V[i][j]1;}else{POINT_V[i][j]0;} }}
}/**********按键获取**************/
int Getkey(int N,int T)
{int startclock();if(KEY_V115){return 115;}do{if(kbhit()){KEY_V(int)(getch());if(KEY_V97){KEY_V32;}return KEY_V;}for(i0;iN;i);printf(%d\n,clock()-start);}while((clock()-start)T);dy1;return -1;
}/***********块体转置*************/
int Rote(int S, int I)
{return (F0)?TGM[S][(I4)%4]:SRS[S][(I4)%4];
}/***********擦除显示*************/
int Display(int x, int y, int CAC, int Mode)
{for(j0;j3;j){P[j]CAC0xF, CAC4;if (Mode1){Pos((P[j]2)x,(P[j]0x3)y);printf(■);}else if(Mode0){Pos((P[j]2)x,(P[j]0x3)y);printf( );}}return 0;
}/***********固化块体*************/
int DoBlocks()
{//~~~游戏结束if(Y2){Pos(1,22);printf(GAME OVER);exit(0);}//~~~固化块体POS_H_MAX0, FLAG[3]1;for(j0;j3;j){P_X(P[j]2)X,P_Y(P[j]0x3)Y;if(POS_H_MAXP_Y){POS_H_MAXP_Y;}POINT_V[P_X][P_Y]1;}//~~~关卡得分for(jY;jPOS_H_MAX;j){FLAG[2]1;for(i1;i10;i){if(POINT_V[i][j]0){FLAG[2]0;}}if(FLAG[2]){SCORE10,MARK[j]1;if(SCORE400){SCORE0,LEVEL1,T-100;FLAG[4]1; }}}//~~~极品消行for(j20;j5;j--){if(FLAG[4]){for(i1;i10;i){POINT_V[i][j]0;Pos(i,j);printf( );}}else if(MARK[j]){MARK[j]0,Jj-1;for(N1;N3;N){if(MARK[J]){J--;}}MARK[J]1;for(i1;i10;i){Pos(i,j);if(POINT_V[i][j]POINT_V[i][J]){printf(■);}else{printf( );}}}}FLAG[4]0;return 0;
}/***********碰撞检测*************/
int CheckCollision()
{ for(j0;j3;j){P_X(P[j]2)Xdx,P_Y(P[j]0x3)Ydy;if(POINT_V[P_X][P_Y]){if(dx!0){return 1;}if(dy){DoBlocks();Pos(12,3);printf(LEVEL%-3d,LEVEL);Pos(12,5);printf(SCORE%-3d,SCORE);return 2;}if(KEY_V119){FLAG[0]1;}}}return 0;
}
unsigned
/***********循环核心*************/
int GameCycle(int N, int T, int F)
{srand((unsigned)time(NULL));RUrand()%7,RI(rand()%4);while(1){if(FLAG[3]){Display(12,8,Rote(RU,RI),0);X4,Y1, NURU,NIRI, RUrand()%7,RI(rand()%4), FLAG[3]0,KEY_V0;Display(12,8,Rote(RU,RI),1);Display(X, Y,Rote(NU,NI),1);}dx0,dy0; KEY_VGetkey(N,T);if(KEY_V119){NI;Display(X,Y,Rote(NU,NI),2);}//旋Welse if(KEY_V115){dy 1;}//下Selse if(KEY_V97 ){dx-1;}//左Aelse if(KEY_V100){dx 1;}//右Delse if(KEY_V112){getch(); }//暂停Pelse if(KEY_V113){return 0;}//退出Qif(dx!0 || dy!0 || KEY_V119){if(!CheckCollision()){if(FLAG[0]){NI--,FLAG[0]0;Display(X,Y,Rote(NU,NI),0);}else if(KEY_V119){Display(X,Y,Rote(NU,NI-1),0);}else{Display(X,Y,Rote(NU,NI),0);}Display(Xdx,Ydy,Rote(NU,NI),1);Xdx,Ydy;}}}return 0;
}/**********Main主函数***********/
int main()
{system(color F0mode con cols35 lines25);HideCursor();CreatUI();GameCycle(10,800,1);return 0;
}
#后记里面涉及的很多东西我都没有完全总结出来作者的巧妙非常令我佩服后面应该还会有文章分析。大家有什么想法或者自己的解读可以留言欢迎一起讨论共同进步探索代码里面的奥秘和乐趣。方块消除准备下一个方块得分机制Game Over 判断推荐阅读专辑|Linux文章汇总专辑|程序人生专辑|C语言我的知识小密圈