找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 8075|回复: 4

【C语言】控制台界面的俄罗斯方块

[复制链接]

1112

主题

1653

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
245
威望
744 点
宅币
24263 个
贡献
46222 次
宅之契约
0 份
在线时间
2298 小时
注册时间
2014-1-26
发表于 2015-8-17 02:12:44 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
来源:http://www.0xaa55.com/thread-1477-1-1.html
转载请注明出处。

也就是所谓“DOS窗口”的控制台程序。我写的这个是全平台的,只用了C语言的库(不过貌似有些函数好像只有微软有提供,比如_sleep这种,不过可以将其定义为void _sleep(int iTime){};来解决跨平台的兼容性问题(但是这么弄会导致这个游戏很占CPU)。
20150817020408.png
20150817020514.png
我当时写这个程序的时候我忘记了它应该叫“Tetris”而不是“Russian Blocks”(中式英语,大概可以翻译成“俄罗斯的方块”)
代码不算很复杂,一些游戏逻辑判断的函数,一些画面的逻辑判断的函数,以及整个游戏的组织函数。
  1. #include<stdint.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<time.h>
  5. #include<conio.h>
  6. #include<string.h>
  7. #include<signal.h>

  8. const int8_t g_BlockTypes[]=//方块组合
  9. {
  10.         //格式:1个字节表示组合所需方块数,后面的字节是偏移坐标
  11.         1,
  12.         0,0,        //        口

  13.         4,
  14.         0,0,
  15.         0,1,        //        口口
  16.         1,0,        //        口口
  17.         1,1,

  18.         4,
  19.         -1,0,
  20.         0,0,        //        口口口口
  21.         1,0,
  22.         2,0,

  23.         4,
  24.         -1,1,
  25.         -1,0,        //        口口口
  26.         0,0,        //        口
  27.         1,0,

  28.         4,
  29.         -1,-1,
  30.         -1,0,        //        口
  31.         0,0,        //        口口口
  32.         1,0,
  33.        
  34.         4,
  35.         -1,0,
  36.         0,0,        //        口口口
  37.         1,0,        //          口
  38.         0,-1,

  39.         4,
  40.         -1,0,
  41.         0,0,        //        口口
  42.         0,1,        //          口口
  43.         1,1,

  44.         4,
  45.         1,0,
  46.         0,0,        //          口口
  47.         0,1,        //        口口
  48.         -1,1,

  49.         0
  50. };
  51. //目前共8种组合
  52. #define NbTypes 8

  53. typedef int32_t pos_t,*pos_p;//坐标
  54. typedef uint8_t block_t,*block_p;//方块状态

  55. //方块缓冲区
  56. #define BlockBufWidth        12
  57. #define BlockBufHeight        23
  58. block_t g_BlockBuf[BlockBufWidth*BlockBufHeight]={0};
  59. #define ReDirToBBuf(x,y) ((x)+(y)*BlockBufWidth)

  60. //游戏界面显示的字符
  61. #define BlockChar '\xB1'
  62. #define BlankChar ' '
  63. #define ClientAreaChar '\xDB'

  64. //当前方块的中心位置
  65. pos_t g_CurX,g_CurY;
  66. uint8_t g_CurRot;//当前旋转
  67. uint8_t g_GameOver;
  68. uint8_t g_QuitGame;
  69. uint16_t g_CurrentBlock;

  70. typedef uint32_t score_t,*score_p;//用来计算分数的变量类型
  71. #define MaxScore 999999999L
  72. score_t g_Score=0,g_HighScore=0;

  73. //方块视口的位置
  74. #define VP_X 20
  75. #define VP_Y 1
  76. #define VP_W (BlockBufWidth*2)
  77. #define VP_H BlockBufHeight

  78. //“下一个方块”的提示框位置
  79. #define NextBlockAreaX 2
  80. #define NextBlockAreaY 2
  81. #define NextBlockAreaW 12
  82. #define NextBlockAreaH 6
  83. #define NextBlockAreaR (NextBlockAreaX+NextBlockAreaW)
  84. #define NextBlockAreaB (NextBlockAreaY+NextBlockAreaH)
  85. #define NextBlockAreaCX (NextBlockAreaX+NextBlockAreaW/2)
  86. #define NextBlockAreaCY (NextBlockAreaY+NextBlockAreaH/2)

  87. #define ShowScoreAreaX 2
  88. #define ShowScoreAreaY 9
  89. #define ShowScoreAreaW 12
  90. #define ShowScoreAreaH 4
  91. #define ShowScoreAreaR (ShowScoreAreaX+ShowScoreAreaW)
  92. #define ShowScoreAreaB (ShowScoreAreaY+ShowScoreAreaH)

  93. #define GameOverDlgBoxAreaX 20
  94. #define GameOverDlgBoxAreaY 4
  95. #define GameOverDlgBoxAreaW 40
  96. #define GameOverDlgBoxAreaH 10
  97. #define GameOverDlgBoxAreaR (GameOverDlgBoxAreaX+GameOverDlgBoxAreaW)
  98. #define GameOverDlgBoxAreaB (GameOverDlgBoxAreaY+GameOverDlgBoxAreaH)

  99. #define Rot_0 0
  100. #define Rot_90 1
  101. #define Rot_180 2
  102. #define Rot_270 3
  103. uint8_t g_NextRot;//当前旋转
  104. uint16_t g_NextBlock;

  105. clock_t g_CurClock=0;//当前时钟计数
  106. clock_t g_Interval=1000;//每次移动的时钟数

  107. //“画板”
  108. #define ScrBufWidth                80
  109. #define ScrBufHeight        25
  110. #define ScrBufSize (ScrBufWidth*ScrBufHeight)
  111. char g_ScrBuf[ScrBufSize]={0};//显示缓冲区
  112. #define ReDirToScr(x,y) ((x)+(y)*ScrBufWidth)

  113. void TranslateRotateCoord(pos_t x,pos_t y,uint8_t Rot,pos_p px,pos_p py);
  114. void ClearBuf(char cChar);
  115. void DrawStaticBlocks(char cBL,char cBR,char cBlank);
  116. uint16_t GetBlockTypeData(uint16_t BlockType);
  117. void DrawFallingComb(pos_t x,pos_t y,uint16_t BlockData,uint8_t Rot,char cBL,char cBR);

  118. void InitGame();
  119. void NewGame();
  120. void MoveLeft();
  121. void MoveRight();
  122. void Rotate();
  123. void FixBlock();
  124. void NewBlock();
  125. void FallDown();
  126. void CheckupBlockFall();
  127. void EraseLines();
  128. void GameOverBox();
  129. void FrameMove();

  130. void InitScrBuf();
  131. void DrawNextBlockType();
  132. void DrawCurrentFallingBlock();
  133. void RenderScene();
  134. void FlushScene();

  135. void GameMenu();
  136. void GameLoop();

  137. //=============================================================================
  138. //函数:TranslateRotateCoord
  139. //描述:翻译相对旋转坐标
  140. //-----------------------------------------------------------------------------
  141. void TranslateRotateCoord(pos_t x,pos_t y,uint8_t Rot,pos_p px,pos_p py)
  142. {
  143.         //判断是哪种旋转
  144.         switch(Rot)
  145.         {
  146.         default://默认:不旋转
  147.                 *px=x;*py=y;
  148.                 break;
  149.         case Rot_90://旋转90度,x=-y y=x
  150.                 *px=-y;*py=x;
  151.                 break;
  152.         case Rot_180://旋转180度,x=-x y=-y
  153.                 *px=-x;*py=-y;
  154.                 break;
  155.         case Rot_270://旋转270度,x=y y=-x
  156.                 *px=y;*py=-x;
  157.                 break;
  158.         }
  159. }

  160. //=============================================================================
  161. //函数:ClearBuf
  162. //描述:将“画板”用cChar填充
  163. //-----------------------------------------------------------------------------
  164. void ClearBuf(char cChar)
  165. {
  166.         memset(g_ScrBuf,cChar,sizeof(g_ScrBuf));//每一行都用cChar来填
  167. }

  168. //=============================================================================
  169. //函数:FillRectangle
  170. //描述:在“画板”上填充举行
  171. //-----------------------------------------------------------------------------
  172. void FillRectangle(pos_t x,pos_t y,pos_t r,pos_t b,char cChar)
  173. {
  174.         pos_t cbLine,i;

  175.         if(x>ScrBufWidth || y>ScrBufHeight)
  176.                 return;
  177.         if(r>ScrBufWidth)
  178.                 r=ScrBufWidth;
  179.         if(b>ScrBufHeight)
  180.                 b=ScrBufHeight;

  181.         cbLine=r-x;
  182.         i=ReDirToScr(x,y);//“画布”上的对应位置
  183.         for(;y<b;y++)
  184.         {
  185.                 memset(&g_ScrBuf[i],cChar,cbLine);//每一行都用cChar来填
  186.                 i+=ScrBufWidth;//转到下一行
  187.         }
  188. }

  189. //=============================================================================
  190. //函数:DrawStaticBlocks
  191. //描述:在“画板”上将所有的静态方块都绘制上去(也就是画好已经落下的方块)
  192. //-----------------------------------------------------------------------------
  193. void DrawStaticBlocks
  194. (
  195.         char cBL,//方块左半边的字符
  196.         char cBR,//方块右半边的字符
  197.         char cBlank//没有方块时的字符
  198. )
  199. {
  200.         pos_t x,y,i;

  201.         //擦除背景
  202.         FillRectangle(VP_X,VP_Y,VP_X+BlockBufWidth*2,VP_Y+BlockBufHeight,cBlank);

  203.         //一行行的画方块
  204.         for(y=i=0;y<BlockBufHeight;y++)//遍历每一行方块槽
  205.         {
  206.                 for(x=0;x<BlockBufWidth;x++,i++)//遍历每一列方块槽
  207.                 {
  208.                         pos_t uIndex=ReDirToScr(VP_X+x*2,VP_Y+y);//方块在“画布”对应位置
  209.                         //方块槽每个格子相当于画布上的两个字符
  210.                         //一个字符是长方形,两个就是正方形了
  211.                         if(g_BlockBuf[i])//有方块
  212.                         {
  213.                                 g_ScrBuf[uIndex+0]=cBL;//方块左半边的字符
  214.                                 g_ScrBuf[uIndex+1]=cBR;//方块右半边的字符
  215.                         }
  216.                 }
  217.         }
  218. }

  219. //=============================================================================
  220. //函数:GetBlockTypeData
  221. //描述:取得方块类型数据
  222. //-----------------------------------------------------------------------------
  223. uint16_t GetBlockTypeData(uint16_t BlockType)
  224. {
  225.         uint16_t BlockIndex=0;
  226.         while(BlockType--)
  227.                 BlockIndex+=g_BlockTypes[BlockIndex]*2+1;
  228.         return BlockIndex;
  229. }

  230. //=============================================================================
  231. //函数:DrawFallingComb
  232. //描述:在“画板”上绘制落下的方块组合
  233. //-----------------------------------------------------------------------------
  234. void DrawFallingComb
  235. (
  236.         pos_t x,//画布上的位置横坐标
  237.         pos_t y,//画布上的位置纵坐标
  238.         uint16_t BlockType,//方块种类
  239.         uint8_t Rot,//方向
  240.         char cBL,//方块左半边的字符
  241.         char cBR//方块右半边的字符
  242. )
  243. {
  244.         uint16_t BlockIndex=GetBlockTypeData(BlockType);
  245.         uint8_t NbBlocks=g_BlockTypes[BlockIndex];
  246.         BlockIndex++;//这是坐标索引
  247.         while(NbBlocks--)
  248.         {
  249.                 pos_t BlockX,BlockY,uIndex;//这是转换后的相对坐标
  250.                 TranslateRotateCoord(g_BlockTypes[BlockIndex+0],
  251.                                                          g_BlockTypes[BlockIndex+1],
  252.                                                          Rot,&BlockX,&BlockY);
  253.                 //取得绝对坐标
  254.                 BlockX=BlockX*2+x;
  255.                 BlockY=BlockY+y;

  256.                 uIndex=ReDirToScr(BlockX,BlockY);//方块在“画布”对应位置
  257.                
  258.                 g_ScrBuf[uIndex+0]=cBL;//方块左半边的字符
  259.                 g_ScrBuf[uIndex+1]=cBR;//方块右半边的字符

  260.                 BlockIndex+=2;
  261.         }
  262. }

  263. //=============================================================================
  264. //函数:DrawString
  265. //描述:“画板”上写字
  266. //-----------------------------------------------------------------------------
  267. void DrawString(pos_t x,pos_t y,char*szString)
  268. {
  269.         size_t cbString=strlen(szString);
  270.         memcpy(&g_ScrBuf[ReDirToScr(x,y)],szString,cbString);
  271. }

  272. //=============================================================================
  273. //函数:InitGame
  274. //描述:初始化游戏
  275. //-----------------------------------------------------------------------------
  276. void InitGame()
  277. {
  278.         g_CurClock=clock();
  279.         srand((unsigned)g_CurClock);

  280.         InitScrBuf();

  281.         g_HighScore=0;
  282. }

  283. //=============================================================================
  284. //函数:NewGame
  285. //描述:开始新游戏
  286. //-----------------------------------------------------------------------------
  287. void NewGame()
  288. {
  289.         g_Score=0;
  290.         g_QuitGame=0;
  291.         g_GameOver=0;
  292.         g_NextRot=rand()%4;
  293.         g_NextBlock=rand()%NbTypes;
  294.         memset(g_BlockBuf,0,sizeof(g_BlockBuf));
  295.         NewBlock();
  296.         RenderScene();
  297.         FlushScene();
  298. }

  299. //=============================================================================
  300. //函数:MoveLeft
  301. //描述:将方块往左移
  302. //-----------------------------------------------------------------------------
  303. void MoveLeft()
  304. {
  305.         uint16_t BlockIndex=GetBlockTypeData(g_CurrentBlock);
  306.         uint8_t NbBlocks=g_BlockTypes[BlockIndex];
  307.         BlockIndex++;//这是坐标索引
  308.         g_CurX--;//先左移
  309.         while(NbBlocks--)
  310.         {
  311.                 pos_t BlockX,BlockY;//这是转换后的相对坐标
  312.                 TranslateRotateCoord(g_BlockTypes[BlockIndex+0],
  313.                                                          g_BlockTypes[BlockIndex+1],
  314.                                                          g_CurRot,&BlockX,&BlockY);

  315.                 //左边没有空间可以移动,退出。
  316.                 if(g_CurX+BlockX<0 ||
  317.                    g_BlockBuf[ReDirToBBuf(g_CurX+BlockX,g_CurY+BlockY)])
  318.                 {
  319.                         g_CurX++;//移回来
  320.                         return;
  321.                 }

  322.                 BlockIndex+=2;
  323.         }
  324. }

  325. //=============================================================================
  326. //函数:MoveRight
  327. //描述:将方块往右移
  328. //-----------------------------------------------------------------------------
  329. void MoveRight()
  330. {
  331.         uint16_t BlockIndex=GetBlockTypeData(g_CurrentBlock);
  332.         uint8_t NbBlocks=g_BlockTypes[BlockIndex];
  333.         BlockIndex++;//这是坐标索引
  334.         g_CurX++;
  335.         while(NbBlocks--)
  336.         {
  337.                 pos_t BlockX,BlockY;//这是转换后的相对坐标
  338.                 TranslateRotateCoord(g_BlockTypes[BlockIndex+0],
  339.                                                          g_BlockTypes[BlockIndex+1],
  340.                                                          g_CurRot,&BlockX,&BlockY);

  341.                 //左边没有空间可以移动,退出。
  342.                 if(g_CurX+BlockX>BlockBufWidth-1||
  343.                    g_BlockBuf[ReDirToBBuf(g_CurX+BlockX,g_CurY+BlockY)])
  344.                 {
  345.                         g_CurX--;
  346.                         return;
  347.                 }

  348.                 BlockIndex+=2;
  349.         }
  350. }

  351. //=============================================================================
  352. //函数:RotateForward
  353. //描述:向前旋转,不带判断
  354. //-----------------------------------------------------------------------------
  355. static void RotateForward()
  356. {
  357.         switch(g_CurRot)
  358.         {
  359.         default:                g_CurRot=Rot_90;break;
  360.         case Rot_90:        g_CurRot=Rot_180;break;
  361.         case Rot_180:        g_CurRot=Rot_270;break;
  362.         case Rot_270:        g_CurRot=Rot_0;break;
  363.         }
  364. }

  365. //=============================================================================
  366. //函数:RotateBackward
  367. //描述:向后旋转,不带判断
  368. //-----------------------------------------------------------------------------
  369. static void RotateBackward()
  370. {
  371.         switch(g_CurRot)
  372.         {
  373.         default:                g_CurRot=Rot_270;break;
  374.         case Rot_270:        g_CurRot=Rot_180;break;
  375.         case Rot_180:        g_CurRot=Rot_90;break;
  376.         case Rot_90:        g_CurRot=Rot_0;break;
  377.         }
  378. }

  379. //=============================================================================
  380. //函数:Rotate
  381. //描述:旋转方块
  382. //-----------------------------------------------------------------------------
  383. void Rotate()
  384. {
  385.         uint16_t BlockIndex=GetBlockTypeData(g_CurrentBlock);
  386.         uint8_t NbBlocks=g_BlockTypes[BlockIndex];
  387.         BlockIndex++;//这是坐标索引

  388.         //先向前旋转
  389.         RotateForward();

  390.         while(NbBlocks--)
  391.         {
  392.                 pos_t BlockX,BlockY;//这是转换后的相对坐标
  393.                 TranslateRotateCoord(g_BlockTypes[BlockIndex+0],
  394.                                                          g_BlockTypes[BlockIndex+1],
  395.                                                          g_CurRot,&BlockX,&BlockY);

  396.                 //如果旋转后有方块会跑出,那么就转回来。
  397.                 BlockX+=g_CurX;
  398.                 BlockY+=g_CurY;
  399.                 if(BlockX<0 || BlockY<0 ||
  400.                    BlockX>BlockBufWidth-1 ||
  401.                    BlockY>BlockBufHeight-1 ||
  402.                    g_BlockBuf[ReDirToBBuf(BlockX,BlockY)])
  403.                 {
  404.                         RotateBackward();
  405.                         return;
  406.                 }

  407.                 BlockIndex+=2;
  408.         }
  409. }

  410. //=============================================================================
  411. //函数:FixBlock
  412. //描述:将方块固定到槽里
  413. //-----------------------------------------------------------------------------
  414. void FixBlock()
  415. {
  416.         uint16_t BlockIndex=GetBlockTypeData(g_CurrentBlock);
  417.         uint8_t NbBlocks=g_BlockTypes[BlockIndex];
  418.         BlockIndex++;//这是坐标索引
  419.         while(NbBlocks--)
  420.         {
  421.                 pos_t BlockX,BlockY;//这是转换后的相对坐标
  422.                 TranslateRotateCoord(g_BlockTypes[BlockIndex+0],
  423.                                                          g_BlockTypes[BlockIndex+1],
  424.                                                          g_CurRot,&BlockX,&BlockY);

  425.                 g_BlockBuf[ReDirToBBuf(g_CurX+BlockX,g_CurY+BlockY)]=1;

  426.                 BlockIndex+=2;
  427.         }
  428. }

  429. //=============================================================================
  430. //函数:NewBlock
  431. //描述:设置下一个方块
  432. //-----------------------------------------------------------------------------
  433. void NewBlock()
  434. {
  435.         uint16_t BlockIndex,BIStart;
  436.         uint8_t NbBlocks,i;
  437.        
  438.         g_CurrentBlock=g_NextBlock;
  439.         g_CurRot=g_NextRot;
  440.         g_NextBlock=rand()%NbTypes;
  441.         g_CurX=BlockBufWidth/2;
  442.         g_CurY=0;
  443.         g_NextRot=rand()%4;

  444.         BlockIndex=GetBlockTypeData(g_CurrentBlock);
  445.         NbBlocks=g_BlockTypes[BlockIndex];
  446.         BIStart=++BlockIndex;//这是坐标索引
  447.         for(i=0;i<NbBlocks;i++)
  448.         {
  449.                 pos_t BlockX,BlockY;//这是转换后的相对坐标
  450.                 TranslateRotateCoord(g_BlockTypes[BlockIndex+0],
  451.                                                          g_BlockTypes[BlockIndex+1],
  452.                                                          g_CurRot,&BlockX,&BlockY);

  453.                 //先保证方块完全进入区域
  454.                 if(g_CurY+BlockY<0)
  455.                         g_CurY-=BlockY;

  456.                 BlockIndex+=2;
  457.         }
  458.         //然后判断是否有重合方块
  459.         BlockIndex=BIStart;
  460.         for(i=0;i<NbBlocks;i++)
  461.         {
  462.                 pos_t BlockX,BlockY;//这是转换后的相对坐标
  463.                 TranslateRotateCoord(g_BlockTypes[BlockIndex+0],
  464.                                                          g_BlockTypes[BlockIndex+1],
  465.                                                          g_CurRot,&BlockX,&BlockY);
  466.                
  467.                 //如果现在的位置有方块重合了
  468.                 if(g_BlockBuf[ReDirToBBuf(g_CurX+BlockX,g_CurY+BlockY)])
  469.                         g_GameOver=1;

  470.                 BlockIndex+=2;
  471.         }
  472. }

  473. //=============================================================================
  474. //函数:FallDown
  475. //描述:坠下方块
  476. //-----------------------------------------------------------------------------
  477. void FallDown()
  478. {
  479.         g_CurY++;
  480. }

  481. //=============================================================================
  482. //函数:CheckupBlockFall
  483. //描述:检查方块状态(当前方块是否已经沉底)
  484. //-----------------------------------------------------------------------------
  485. void CheckupBlockFall()
  486. {
  487.         uint16_t BlockIndex=GetBlockTypeData(g_CurrentBlock);
  488.         uint8_t NbBlocks=g_BlockTypes[BlockIndex];

  489.         BlockIndex++;//这是坐标索引
  490.         while(NbBlocks--)
  491.         {
  492.                 pos_t BlockX,BlockY;//这是转换后的相对坐标
  493.                 TranslateRotateCoord(g_BlockTypes[BlockIndex+0],
  494.                                                          g_BlockTypes[BlockIndex+1],
  495.                                                          g_CurRot,&BlockX,&BlockY);

  496.                 if(g_CurY+BlockY>BlockBufHeight-1 ||
  497.                    g_BlockBuf[ReDirToBBuf(g_CurX+BlockX,g_CurY+BlockY)])
  498.                 {
  499.                         g_CurY--;
  500.                         FixBlock();
  501.                         NewBlock();
  502.                 }

  503.                 BlockIndex+=2;
  504.         }
  505. }

  506. //=============================================================================
  507. //函数:FallDownFixedBlocks
  508. //描述:从第0行开始到第y行坠下固定的方块
  509. //-----------------------------------------------------------------------------
  510. void FallDownFixedBlocks(pos_t y)
  511. {
  512.         pos_t i;
  513.         if(!y)
  514.                 return;
  515.         i=y*BlockBufWidth;
  516.         while(--y)
  517.         {
  518.                 memcpy(&g_BlockBuf[i],&g_BlockBuf[i-BlockBufWidth],BlockBufWidth*sizeof(block_t));
  519.                 i-=BlockBufWidth;
  520.         }
  521. }

  522. //=============================================================================
  523. //函数:EraseLines
  524. //描述:消除填满的行
  525. //-----------------------------------------------------------------------------
  526. void EraseLines()
  527. {
  528.         pos_t y,i,LineBlockIndex;
  529.         score_t AddScore=1;//加分(每多消除一行,多加一分)
  530.         uint8_t CouldNotErase;

  531.         //判断是否有已经填满的一行,并给用户统计积分
  532.         //从最后一行开始判断
  533.         y=BlockBufHeight-1;
  534.         LineBlockIndex=y*BlockBufWidth;
  535.         for(;y;y--,LineBlockIndex-=BlockBufWidth)
  536.         {
  537.                 CouldNotErase=0;
  538.                 for(i=0;i<BlockBufWidth;i++)
  539.                 {
  540.                         if(!g_BlockBuf[LineBlockIndex+i])
  541.                         {
  542.                                 CouldNotErase=1;
  543.                                 break;
  544.                         }
  545.                 }
  546.                 if(!CouldNotErase)
  547.                 {
  548.                         FallDownFixedBlocks(y);
  549.                         g_Score+=AddScore++;//加分到总分里,并且同时消除的行数会增加加分量
  550.                 }
  551.         }
  552.         if(g_Score>g_HighScore)
  553.                 g_HighScore=g_Score;//统计最高分
  554. }

  555. //=============================================================================
  556. //函数:FrameMove
  557. //描述:判断是否在降落的时候碰到已有的方块、计算积分等
  558. //-----------------------------------------------------------------------------
  559. void FrameMove()
  560. {
  561.         char chKey;
  562.         for(;;_sleep(1))//节省CPU的游戏循环
  563.         {
  564.                 if(clock()-g_CurClock>=g_Interval)//超时
  565.                 {
  566.                         //向下移动方块
  567.                         g_CurY++;
  568.                         g_CurClock=clock();//更新时钟
  569.                         break;
  570.                 }
  571.                 if(_kbhit())
  572.                 {
  573.                         chKey=_getch();
  574.                         switch(chKey)
  575.                         {
  576.                         case'W':
  577.                         case'w':
  578.                                 Rotate();
  579.                                 break;
  580.                         case'A':
  581.                         case'a':
  582.                                 MoveLeft();
  583.                                 break;
  584.                         case'S':
  585.                         case's':
  586.                                 FallDown();
  587.                                 break;
  588.                         case'D':
  589.                         case'd':
  590.                                 MoveRight();
  591.                                 break;
  592.                         }
  593.                         break;
  594.                 }
  595.         }

  596.         CheckupBlockFall();
  597.         EraseLines();
  598. }

  599. //=============================================================================
  600. //函数:InitScrBuf
  601. //描述:初始化“画板”
  602. //-----------------------------------------------------------------------------
  603. void InitScrBuf()
  604. {
  605.         ClearBuf(ClientAreaChar);
  606. }

  607. //=============================================================================
  608. //函数:DrawNextBlockType
  609. //描述:在画布上绘制“下一个方块”
  610. //-----------------------------------------------------------------------------
  611. void DrawNextBlockType()
  612. {
  613.         FillRectangle(NextBlockAreaX,NextBlockAreaY,
  614.                                   NextBlockAreaR,NextBlockAreaB,BlankChar);
  615.         DrawString(NextBlockAreaX,NextBlockAreaY," Next Block:");
  616.         DrawFallingComb(NextBlockAreaCX,NextBlockAreaCY,
  617.                 g_NextBlock,g_NextRot,BlockChar,BlockChar);
  618. }

  619. //=============================================================================
  620. //函数:DrawTotalScore
  621. //描述:在画布上绘制“总分”
  622. //-----------------------------------------------------------------------------
  623. void DrawTotalScore()
  624. {
  625.         char Buf[ShowScoreAreaW+1];//字符串缓冲区
  626.         FillRectangle(ShowScoreAreaX,ShowScoreAreaY,
  627.                                   ShowScoreAreaR,ShowScoreAreaB,BlankChar);
  628.        
  629.         DrawString(ShowScoreAreaX,ShowScoreAreaY,"Total score:");
  630.         sprintf(Buf,"%u",g_Score);
  631.         DrawString(ShowScoreAreaX,ShowScoreAreaY+1,Buf);
  632.         DrawString(ShowScoreAreaX,ShowScoreAreaY+2,"High score:");
  633.         sprintf(Buf,"%u",g_HighScore);
  634.         DrawString(ShowScoreAreaX,ShowScoreAreaY+3,Buf);
  635. }

  636. //=============================================================================
  637. //函数:DrawCurrentFallingBlock
  638. //描述:绘制当前正在掉落的方块
  639. //-----------------------------------------------------------------------------
  640. void DrawCurrentFallingBlock()
  641. {
  642.         DrawFallingComb(VP_X+g_CurX*2,VP_Y+g_CurY,
  643.                 g_CurrentBlock,g_CurRot,BlockChar,BlockChar);
  644. }

  645. //=============================================================================
  646. //函数:RenderScene
  647. //描述:渲染整个场景
  648. //-----------------------------------------------------------------------------
  649. void RenderScene()
  650. {
  651.         ClearBuf(ClientAreaChar);
  652.         DrawNextBlockType();
  653.         DrawTotalScore();
  654.         DrawStaticBlocks(BlockChar,BlockChar,BlankChar);
  655.         DrawCurrentFallingBlock();
  656. }

  657. //=============================================================================
  658. //函数:FlushScene
  659. //描述:将场景显示出来
  660. //-----------------------------------------------------------------------------
  661. void FlushScene()
  662. {
  663.         //强行换行
  664.         pos_t y,i;
  665.         for(y=0,i=0;y<ScrBufHeight-1;y++)
  666.         {
  667.                 g_ScrBuf[i+ScrBufWidth-1]='\n';//然后在行末加一个换行符
  668.                 i+=ScrBufWidth;//转到下一行
  669.         }

  670.         fputc('\n',stdout);//插入一个新行,以让“画板”从新行输出
  671.         fwrite(g_ScrBuf,1,ScrBufSize-1,stdout);//减去1是为了防止自动换行
  672. }

  673. //=============================================================================
  674. //函数:GameMenu
  675. //描述:游戏菜单
  676. //-----------------------------------------------------------------------------
  677. void GameMenu()
  678. {
  679.         //清屏
  680.         system("cls");

  681.         //显示LOGO
  682.         fputs("\n"
  683. "     TTTTTTTTTT  EEEEEEEEEE  TTTTTTTTTT  RRRRRRRR    IIIIIIIIII    SSSSSSSS\n"
  684. "     TT  TT  TT    EE    EE  TT  TT  TT    RR    RR      II      SS      SS\n"
  685. "         TT        EE  EE        TT        RR    RR      II      SS\n"
  686. "         TT        EEEEEE        TT        RRRRRR        II        SSSS\n"
  687. "         TT        EE  EE        TT        RR  RR        II            SS\n"
  688. "         TT        EE            TT        RR    RR      II              SS\n"
  689. "         TT        EE    EE      TT        RR    RR      II      SS      SS\n"
  690. "       TTTTTT    EEEEEEEEEE    TTTTTT    RRRRRR  RRRRIIIIIIIIII  SSSSSSSS\n"
  691. "       \n"
  692. "    BBBBBB    YY    YY      00000000          AAAAAA  AAAAAA  555555  555555\n"
  693. "    BB    BB  YY    YY  ::  00    00          AA  AA  AA  AA  55      55\n"
  694. "    BBBBBB    YY    YY      00    00          AAAAAA  AAAAAA  555555  555555\n"
  695. "    BB    BB    YYYYYY      00    00  XX  XX  AA  AA  AA  AA      55      55\n"
  696. "    BB    BB        YY  ::  00    00    XX    AA  AA  AA  AA      55      55\n"
  697. "    BBBBBB    YYYYYY        00000000  XX  XX  AA  AA  AA  AA  555555  555555\n"
  698. "\n"
  699. "    http://www.0xaa55.com\n"
  700. "\n",stdout);

  701.         //显示最高分
  702.         printf("    HIGH SCORE:%u\n\n",g_HighScore);

  703.         //闪烁显示“按键开始游戏”
  704.         for(;!g_QuitGame;_sleep(1))
  705.         {
  706.                 if(clock()%1000 > 500)//根据时钟来判断显示字符还是抹掉字符
  707.                         fputs("    Press 'B' to start the game.\r",stdout);
  708.                 else
  709.                         fputs("                                \r",stdout);

  710.                 //判断按键输入
  711.                 if(_kbhit())
  712.                 {
  713.                         char ch=_getch();
  714.                         if(ch=='B'||ch=='b')//B键开始游戏,其它键没用。Ctrl+C退出游戏。
  715.                         {
  716.                                 NewGame();
  717.                                 break;
  718.                         }
  719.                 }
  720.         }
  721. }

  722. //=============================================================================
  723. //函数:GameOverBox
  724. //描述:显示“游戏结束”框
  725. //-----------------------------------------------------------------------------
  726. void GameOverBox()
  727. {
  728.         uint8_t ShowScene=0;
  729.         char szBuf[GameOverDlgBoxAreaW+1];

  730.         //渲染一次场景
  731.         RenderScene();

  732.         //画出对话框边框
  733.         FillRectangle(GameOverDlgBoxAreaX,GameOverDlgBoxAreaY,
  734.                 GameOverDlgBoxAreaR,GameOverDlgBoxAreaB,ClientAreaChar);
  735.         FillRectangle(GameOverDlgBoxAreaX+2,GameOverDlgBoxAreaY+1,
  736.                 GameOverDlgBoxAreaR-2,GameOverDlgBoxAreaB-1,BlankChar);

  737.         //显示字符串
  738.         DrawString(GameOverDlgBoxAreaX+2,GameOverDlgBoxAreaY+1,
  739.                 "Game Over");

  740.         //显示分数
  741.         sprintf(szBuf,"Total score:%u",g_Score);
  742.         DrawString(GameOverDlgBoxAreaX+2,GameOverDlgBoxAreaY+3,szBuf);

  743.         //显示最高分
  744.         sprintf(szBuf,"High score:%u",g_HighScore);
  745.         DrawString(GameOverDlgBoxAreaX+2,GameOverDlgBoxAreaY+5,szBuf);
  746.                
  747.         //闪烁提示按任意键继续,并判断按键
  748.         for(;;_sleep(10))
  749.         {
  750.                 if(clock()%1000<500)
  751.                 {
  752.                         if(!ShowScene)
  753.                         {
  754.                                 DrawString(GameOverDlgBoxAreaX+2,GameOverDlgBoxAreaY+7,
  755.                                         "Press 'C' to continue. . .");

  756.                                 //显示已经绘制好的场景
  757.                                 FlushScene();
  758.                                 ShowScene=1;//防止重复刷屏
  759.                         }
  760.                 }
  761.                 else
  762.                 {
  763.                         if(ShowScene)
  764.                         {
  765.                                 DrawString(GameOverDlgBoxAreaX+2,GameOverDlgBoxAreaY+7,
  766.                                         "                              ");

  767.                                 //显示已经绘制好的场景
  768.                                 FlushScene();
  769.                                 ShowScene=0;//防止重复刷屏
  770.                         }
  771.                 }

  772.                 //如果按下了键,就退出这个循环
  773.                 if(_kbhit())
  774.                 {
  775.                         char chKey=_getch();
  776.                         if(chKey=='C'||chKey=='c')
  777.                                 break;
  778.                 }
  779.         }
  780. }

  781. //=============================================================================
  782. //函数:GameLoop
  783. //描述:游戏逻辑循环
  784. //-----------------------------------------------------------------------------
  785. void GameLoop()
  786. {
  787.         //游戏循环
  788.         while(!g_GameOver)
  789.         {
  790.                 FrameMove();
  791.                 RenderScene();
  792.                 FlushScene();
  793.         }

  794.         //游戏结束
  795.         GameOverBox();
  796. }

  797. //=============================================================================
  798. //函数:SigProc
  799. //描述:信号处理程序
  800. //-----------------------------------------------------------------------------
  801. void SigProc(int Signal)
  802. {
  803.         switch(Signal)
  804.         {
  805.         case SIGINT:
  806.                 g_QuitGame=1;
  807.                 break;
  808.         }
  809. }

  810. //=============================================================================
  811. //函数:main
  812. //描述:程序入口点
  813. //-----------------------------------------------------------------------------
  814. int main(int argc,char**Argv)
  815. {
  816.         signal(SIGINT,SigProc);

  817.         system("chcp 437");
  818.         system("mode con cols=80 lines=25");
  819.         system("cls");

  820.         InitGame();

  821.         do
  822.         {
  823.                 GameMenu();
  824.                 if(g_QuitGame)
  825.                         break;
  826.                 GameLoop();
  827.         }while(!g_QuitGame);
  828.         return 0;
  829. }
复制代码
BIN: RussianBlocks.exe (14 KB, 下载次数: 32)
SRC: RussianBlocks.7z (6.54 KB, 下载次数: 28)
其实名字应该叫Tetris。

本帖被以下淘专辑推荐:

回复

使用道具 举报

13

主题

63

回帖

1326

积分

用户组: 上·技术宅

UID
888
精华
0
威望
0 点
宅币
302 个
贡献
948 次
宅之契约
0 份
在线时间
36 小时
注册时间
2015-5-31
发表于 2015-8-17 02:18:27 | 显示全部楼层
棒棒哒!!
回复

使用道具 举报

55

主题

275

回帖

9358

积分

用户组: 管理员

UID
77
精华
16
威望
237 点
宅币
8223 个
贡献
251 次
宅之契约
0 份
在线时间
255 小时
注册时间
2014-2-22
发表于 2015-8-17 08:33:56 | 显示全部楼层
代码我要了。
回复 赞! 靠!

使用道具 举报

0

主题

2

回帖

20

积分

用户组: 初·技术宅

UID
1035
精华
0
威望
2 点
宅币
14 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2015-8-10
发表于 2015-8-17 09:25:49 | 显示全部楼层
先占个位置..
回复 赞! 靠!

使用道具 举报

0

主题

76

回帖

6758

积分

用户组: 真·技术宅

UID
604
精华
0
威望
2 点
宅币
825 个
贡献
5853 次
宅之契约
0 份
在线时间
101 小时
注册时间
2014-12-20
发表于 2015-8-20 20:43:06 | 显示全部楼层
坐标设计太有才了. 这样就可以很容易实现旋转了. 大赞
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-5-2 17:11 , Processed in 0.052140 second(s), 36 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表