C语言俄罗斯方块游戏解析(图文+源码)

以下文章来源于嵌入式Linux ,作者写代码的篮球球痴

最近在看俄罗斯方块的游戏,看到一个大神写的俄罗斯方块代码,非常非常优秀,拿出来解析给大家看看,也希望大家自己尝试运行试试,从中能得到一些启发。

#先了解下俄罗斯方块的几个形状

一共分成7形状,有的形状有4种状态,有的形状有1种状态。

不管是多少种状态,一个方块需要一个2个字节来存储,也就是16bit来保存一个方块的信息。

基于上面的理论,我们可以使用4x4的数组来保存方块的信息。

注意,下面代码中的"■"占用的是2个字节。

#写代码来显示这个方块

方块数据,这两个数组其实是两种游戏模式的方块信息,我们只需要分析一种就可以了。

intTGM[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}};

intSRS[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}};

我们分析这段代码

/***********擦除显示*************/

intDisplay(intx,inty,intCAC,intMode)

{

for(j=0;j=3;j++){

P[j]=CAC0xF,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]=CAC0xF取到的是 4个bit,然后通过判断这 4个bit决定输出方块的位置。

我们拿0这个方块的数据0x4859对应的二进制0B0100100001011001来做个例子。

0100----对应坐标(1,0)

1000----对应坐标(2,0)

0101----对应坐标(1,1)

1001----对应坐标(2,1)

通过这个坐标,我们会输出这样一个方块

再举个例子

我们拿Z这个方块的数据0x0156对应的二进制0B0000000101010110来做个例子。

0000----对应坐标(0,0)

0001----对应坐标(0,1)

0101----对应坐标(1,1)

0110----对应坐标(1,2)

显示方块没有问题了

上面的代码中,如果mode等于0的话,也就是把某个方块从显示中擦除掉。

我们用devc++写的程序,需要知道几个细节。

#构建固定行列的窗口

正常情况,我们显示cmd是一个默认值的黑框「如下图」。

实际上,我们可以用代码来固定cmd的框框大小。

默认代码输出

示例代码:

#includeconio.h

#includestdio.h

#includestdlib.h

#includetime.h

#includeWindows.h

/**********Main主函数***********/

intmain()

{

system("colorF1modeconcols=35lines=25");

getchar();

return0;

}

程序输出:

#延迟函数的设计

跟其他不同的是,这个程序的延迟没有使用usleep,我觉得这也是非常值得称赞的地方,不过空跑cpu,哈哈,是有那么一点调皮。

把延迟放到键值获取的函数中。

/**********按键获取**************/

intGetkey(intN,intT)

{

intstart=clock();

if(KEY_V==115){return115;}

do{

if(kbhit()){

KEY_V=(int)(getch());

if(KEY_V97){KEY_V+=32;}

returnKEY_V;

}

for(i=0;i=N;i++);

}while((clock()-start)T);

dy=1;

return-1;

}

就先简单讲解下这些,至于得分机制,碰撞检测,消除的代码,还没有想好怎么讲明白,需要再花时间剖析剖析。

#试玩一下

#源码

#includeconio.h

#includestdio.h

#includestdlib.h

#includetime.h

#includeWindows.h

/**********初始化参数************/

inti,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};

intTGM[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}};

intSRS[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}};

/**********光标位置函数**********/

voidPos(intx,inty)

{

COORDpos;

HANDLEhOutput;

pos.X=2*x;

pos.Y=y;

hOutput=GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleCursorPosition(hOutput,pos);

}

voidHideCursor()

{

CONSOLE_CURSOR_INFOcursor_info={1,0};

SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),cursor_info);

}

/**********初始化界面************/

voidCreatUI()

{

inti,j,BOUNDARY;

printf("┏━━━━━━━━━━┓\n");

for(j=1;j=20;j++){

if(j==3){printf("┃┃LEVEL:1\n");}

elseif(j==5){printf("┃┃SCORE:0\n");}

elseif(j==7){printf("┃┃NEXT\n");}

else{printf("┃┃\n");}

}

printf("┗━━━━━━━━━━┛\n");

printf("CopyRight@2016~2018BYHAPPY\n");

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;

}

}

}

}

/**********按键获取**************/

intGetkey(intN,intT)

{

intstart=clock();

if(KEY_V==115){return115;}

do{

if(kbhit()){

KEY_V=(int)(getch());

if(KEY_V97){KEY_V+=32;}

returnKEY_V;

}

for(i=0;i=N;i++);

printf("%d\n",clock()-start);

}while((clock()-start)T);

dy=1;

return-1;

}

/***********块体转置*************/

intRote(intS,intI)

{

return(F==0)TGM[S][(I+4)%4]:SRS[S][(I+4)%4];

}

/***********擦除显示*************/

intDisplay(intx,inty,intCAC,intMode)

{

for(j=0;j=3;j++){

P[j]=CAC0xF,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;

}

/***********固化块体*************/

intDoBlocks()

{

//~~~游戏结束

if(Y2){

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_MAXP_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;

}

/***********碰撞检测*************/

intCheckCollision()

{

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

/***********循环核心*************/

intGameCycle(intN,intT,intF)

{

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主函数***********/

intmain()

{

system("colorF0modeconcols=35lines=25");

HideCursor();

CreatUI();

GameCycle(10,800,1);

return0;

}

#后记

里面涉及的很多东西,我都没有完全总结出来,作者的巧妙非常令我佩服,后面应该还会有文章分析。

大家有什么想法或者自己的解读,可以留言,欢迎一起讨论,共同进步,探索代码里面的奥秘和乐趣。

方块消除

准备下一个方块

得分机制

Game Over 判断

C语言俄罗斯方块游戏解析(图文+源码) 相关文章

C语言头文件math.h(cmath)

C语言头文件math.h(cmath) 如果已经看过算术运算符,也许你已经能进行加减乘除这些基本操作,但对于数学来说远远不够,甚至不能一下子计算一些常见函数的值,比如计算lg 10。 math头文件正是为了解决这一基础性的问题,在做PTA的时候如果适当引入math模块,

实体

!DOCTYPE html!-- 设置html的语言为英文网站 --html lang="en"head meta charset="UTF-8" titlehtml中的字符实体/title/headbody !-- 在网页中编写的多个空格默认情况会自动被浏览器解析为一个空格 在html页面中有些时候, 我们不能直接书写一些特殊符号 比如

C语言学习之我见-strncpy()字符串复制函数(可控制范围)

strncpy()函数,用于两个字符串值的复制。 (1)函数原型 char *strncpy(char * _Dest,const char * _Source,size_t _Count); (2)头文件 string.h (3)功能 将从const char * _Source到'\0'结尾的字符串(包括'\0')复制到char * _Dest所指的字符串处。siz

C语言学习之我见-strcpy()字符串复制函数

strcpy()函数,用于两个字符串值的复制。 (1)函数原型 char * strcpy(char * _Dest,const char * _Source); (2)头文件 string.h (3)功能 将从const char * _Source到'\0'结尾的字符串(包括'\0')复制到char * _Dest所指的字符串处。返回值char * = cha

C语言入门学习(第三天EX——定点数、浮点数以及如何确定取值范围)

镇楼图 之前没讲清楚,特此新开一个blog好好讲一下定点数、浮点数。 一、定点数 组成部分:符号位、整数部分、小数部分 如图所示,假设有n位整数部分,m位小数部分 在整数部分、小数部分之间确定的位置便是小数点 因为能够明确小数点的位置,这种小数称为定

c语言关于freopen函数最全使用方法

此文转载自:https://blog.csdn.net/weixin_53177536/article/details/113444511#commentBox hey,好久不见,最近沉迷游戏无法自拔,现在抽出时间来写写关于freopen函数的使用方法,这个freopen函数主要作用就是从文件读取函数同时写入文件,不像我们平常的控

R语言可视化学习笔记之ggridges包. crossed coverage

https://blog.csdn.net/woodcorpse/article/details/106554057 library(viridis)library(ggridges)head(lincoln_weather[ ,1:4])ggplot(lincoln_weather, aes(x=`Mean Temperature [F]`, y=`Month`, fill=..x..))+ geom_density_ridges_gradient(scale=3, re

五种C语言非数值计算的常用经典排序算法

摘要: 排序是计算机的一种操作方法,其目的是将一组“无序”的记录序列调整为“有序”的记录序列,主要分为内部排序和外部排序。 排序 排序是计算机的一种操作方法,其目的是将一组“无序”的记录序列调整为“有序”的记录序列,主要分为内部排序和外部排序

C/C++ 跳出多重循环方法

c语言的break语句只能跳出离它最近的一层循环,但是我们有时候需要跳出多层循环,以下有几种跳出多重循环的方法: 1. 使用goto for (int i = 0; i MAX1; i++){ for (int j = 0; j MAX2; j++) { if (condition) { symbol = 1; goto outloop; } }}outloop://so

JS简写技巧

任何编程语言的简写技巧都能够帮助你编写更简练的代码,让你用更少的代码实现你的目标。让我们一个个来看看 JavaScript 的简写技巧吧。 1. 声明变量 //Longhandlet x;let y = 20;//Shorthandlet x, y = 20; 2. 给多个变量赋值 我们可以使用数组解构来在一行

linux c语言俄罗斯方块,C语言俄罗斯方块游戏解析(图文+源码)相关推荐

  1. c/c++编程日记:用C语言实现消消乐游戏(附源码)

    描述 给定一个矩阵,判断移动哪一个格子,可以实现消除.(定义连续三个即可消除) 分析 先写一个函数,判断包含(i,j)的格子是否可能实现消除. 然后就是向右向下交换,然后调用上面写好的函数判断 被交换 ...

  2. 纯js 别踩白块游戏解析与源码

    (一)别踩白块 1.考虑游戏中有哪些对象,属性和方法?    别踩白块游戏仔细想想如果非要对象的话,游戏显示界面可以算是一个对象,下滑的区域算一个对象(每个小方格算对象的属性对象吧) 2.这里主要要思 ...

  3. 分享一个C语言矿井逃生迷宫小游戏【附源码】

    用C语言写的一个迷宫小游戏,游戏玩法是通过鼠标控制帽子上的灯走出迷宫 // 定义常量 #define PI 3.141592653589 // 圆周率 #define UNIT_GROUND 0 // ...

  4. 基于stm32、0.96寸OLED实现的俄罗斯方块小游戏(详细源码注释)

    概述:本实验基于stm32最小系统.0.96寸OLED(68*128)和摇杆实现一个经典的俄罗斯方块小游戏.项目源码地址:点击下载. 硬件要求: 普通摇杆,两个电位器和一个开关组成,左右摇动控制一个电 ...

  5. c语言小游戏跳一跳代码及注释,如何获得微信小游戏跳一跳源码以及源代码组合包括哪些...

    原标题:如何获得微信小游戏跳一跳源码以及源代码组合包括哪些 很多小游戏都是由源代码编写而成的,那大家知道源代码组合包括哪些吗?手机游戏源代码怎么使用的呢?还有,如何获得微信小游戏跳一跳源码?下面就由奇 ...

  6. C语言小游戏大全,C语言贪吃蛇小游戏(附源码)

    一.C语言小游戏大全,C语言贪吃蛇小游戏(附源码) 贪吃蛇小游戏源码和更多C语言课设项目小游戏源码免 费 下 载 链 接 如下: c语言项目课设小游戏源码资料压缩包.zip-C文档类资源-CSDN下载 ...

  7. c语言 临时文件作用,c语言函数mktemp()产生唯一临时文件名实例源码介绍

    c语言函数mktemp()产生唯一临时文件名实例源码介绍.有关的函数:tmpfile引入的头文件:#include 定义函数mktemp():char * mktemp(char * template ...

  8. 价值4500的国际版多语言点赞抖音分享点赞任务平台源码(十二种语言)

    介绍: 平台会员分享给我的,他自己搭建成功了,测试可用!我就不测试了,需要的拿! 九种语言 :西班牙语,泰语.日语,印度尼西亚语言.越南语言.英文.繁体中文,简体中文,印度语 前台支持更换5种颜色风格 ...

  9. C语言课设-----工资管理系统(附全部源码)

    C语言课设-----工资管理系统(附全部源码) 本系统分三个部分: 1.出售金鱼 2.数字菱形 3.工资管理系统 (ps:另外添加了登录界面 id:qwq password:123 可自己在代码里再更 ...

  10. mysql db模块下载_易语言MySql数据库操作类V1.0模块源码

    易语言MySql数据库操作类V1.0模块源码 易语言MySql数据库操作类V1.0模块源码 系统结构:MySql数据库连接类_测试子程序,置连接选项,连接,关闭,是否已连接,取连接句柄,置连接句柄,执 ...

最新文章

  1. 《电路分析导论(原书第12版)》一3.12 热敏电阻
  2. VPN之DSVPN的介绍
  3. linux jar命令找不到 -bash: jar: command not found
  4. C#基础_值类型引用类型(十一)
  5. Nginx upstream (一) 整体流程分析
  6. 如何生成 jMeter 结果分析统计图表
  7. acwing3132. 食物(BZOJ3028)
  8. Netty : writeAndFlush的线程安全及并发问题
  9. Spark Yarn-cluster与Yarn-client
  10. Java 7 最快要到 2012 年中发布
  11. jodconverter实现在线预览
  12. 虚拟机安装教程win10_Parallels Desktop如何安装windowns系统?PD虚拟机安装win10系统详细教程
  13. 微信小程序表格前后台分页
  14. Vercel部署个人博客
  15. 橙色优学:PS扣图技术讲解,六种方法你都知道吗?
  16. 报告显示,宝爸参与度不断提升,超三成男性提前服用营养品备孕
  17. 【jpa】简介和项目生成、API-初级入门
  18. 不一样的feign,获取返回code非200的响应
  19. 【数据结构】栈的应用-算术表达式求值#数据结构实验任务书
  20. 微信小程序开发—关于配置服务器域名

热门文章

  1. 美术基础——角色设计
  2. 给视频加上自己想要的水印,再也不用担心被盗图了
  3. OSChina 周日乱弹 ——请世界不要对好人太薄情
  4. 英特尔DAOS分布式异步存储系统
  5. 010-win10任务栏假死—重启“Windows资源管理器”。
  6. 邮箱 签名 / 电子名片 设置
  7. 微信公众号开发工具类
  8. AD9854+STM32正弦波信号发生器
  9. 微信java转盘抽奖代码_jquery手机端抽奖代码_微信jquery实现大转盘抽奖代码特效...
  10. oracle基础|什么是数据库操作语言|什么是DDL、DML、DCL