这是上大学敲得第一个完整的项目,使用的开发工具是codeblock,是用纯C语言编写的。效果如下

Python 小游戏俄罗斯方块 编程俄罗斯方块_sed

现在把完整的整合出来

主体部分代码

#include "Tetris.h"
void gotoxyWithFullWidth(short x,short y)
{
    static COORD pos;
    pos.X=x*2;
    pos.Y=y;
    SetConsoleCursorPosition(Output,pos);
}//显示提示信息
void printPrompting()
{
    SetConsoleTextAttribute(Output,0x0B);
    //gotoxyWithFullWidth(0,1);
    //printf("请输入等级 1-1000:dj=");
    gotoxyWithFullWidth(26,8);
    printf(" 下一方块     下下一方块");
    gotoxyWithFullWidth(26,10);
    printf("■控制");
    gotoxyWithFullWidth(27,12);
    printf("□向左移动:← A 4");
    gotoxyWithFullWidth(27,13);
    printf("□向右移动:→ D 6");
    gotoxyWithFullWidth(27,14);
    printf("□向下移动:↓ S 2");
    gotoxyWithFullWidth(27,15);
    printf("□顺时针转:↑ W 8");
    gotoxyWithFullWidth(27,16);
    printf("□逆时针转:0");
    gotoxyWithFullWidth(27,17);
    printf("□直接落地:空格");
    gotoxyWithFullWidth(27,18);
    printf("□暂停游戏:回车");
    gotoxyWithFullWidth(26,22);
    printf("■作者 :       ");    //gotoxyWithFullWidth(28,22);
   // printf("★★版权所有,仿冒必究★★");
}
//==========================================================================================
//显示游戏池边界()
void printPoolBorder()
{
    int x,y;
    SetConsoleTextAttribute(Output,0xF0);//背景色高亮白色
    for(y=4;y<26;++y)
    {
        gotoxyWithFullWidth(10,y-3);
        SetConsoleTextAttribute(Output,0xBB);
        printf("%2s","◆");
        gotoxyWithFullWidth(23,y-3);
        SetConsoleTextAttribute(Output,0xBB);
        printf("%2s","◆");    }
    for(x=10;x<=23;x++)
    {
      gotoxyWithFullWidth(10,22);
        SetConsoleTextAttribute(Output,0xBB);
        printf("%2s","◆");
    }
   for (y=0;y<26;++y)
    {
       gotoxyWithFullWidth(0,y);
        SetConsoleTextAttribute(Output,0xCE);
        printf ("%2s","●");
        gotoxyWithFullWidth(39,y);
        SetConsoleTextAttribute(Output,0xCE);
        printf ("%2s","●");
    }
   for (x=0;x<=39;++x)
   {
     gotoxyWithFullWidth(x,1);
        SetConsoleTextAttribute(Output,0xCE);
        printf ("%2s","●");
        gotoxyWithFullWidth(x,26);
        SetConsoleTextAttribute(Output,0xCE);
        printf ("%2s","●");
    }    gotoxyWithFullWidth(10,y-3);
    SetConsoleTextAttribute(Output,0xBB);
    printf("%28s","");}
//==================================================================================================
//显示得分信息
void printScore(const Manager *manager)
{
    SetConsoleTextAttribute(Output,0X0B);
    gotoxyWithFullWidth(2,2);
    printf("■得分:%u",manager->score);
    gotoxyWithFullWidth(1,6);
    printf("■消行总数:%u",manager->erasedTotal);
    int i;
    for(i=1;i<=4;++i)
    {
        SetConsoleTextAttribute(Output,0X0C);
        gotoxyWithFullWidth(2,8+i);
        printf("□消%d:%u",i,manager->erasedCount[i-1]);
    }
    gotoxyWithFullWidth(1,15);
    printf("■方块总数:%u",manager->tetrisTotal);
    static const char * tetirsName="ITLJZSO";
    for(i=0;i<7;++i)
    {
        SetConsoleTextAttribute(Output,0X0E);
        gotoxyWithFullWidth(2,17+i);
        printf("□%c形:%u",tetirsName[i],manager->tetrisCount[i]);
    }
}
//===========================================================================================================
//显示下个及下下个方块的显示边框
 void printNextBorder()
 {     SetConsoleTextAttribute(Output,0X0F);
     gotoxyWithFullWidth(26,2);
     printf("┌────┬─────┐");
     gotoxyWithFullWidth(26,3);
     printf("│        │          │");
     gotoxyWithFullWidth(26,4);
     printf("│        │          │");
     gotoxyWithFullWidth(26,5);
     printf("│        │          │");
     gotoxyWithFullWidth(26,6);
     printf("│        │          │");
     gotoxyWithFullWidth(26,7);
     printf("└────┴─────┘");
     gotoxyWithFullWidth(1,28); 
 }
 //============================================================================
 void startGame(Manager *manager,Control *control)
 {     memset(manager,0,sizeof(Manager));//游戏相关数据结构体全部清0
     memset(control,0,sizeof(Control));
     memcpy(manager->pool,gs_uInitialTetrisPool,sizeof(unsigned int [28]));
     srand((unsigned)time(NULL));//设置随机数种子
     manager->type[1]=rand()%7;//初始化下一个方块的形状
     manager->orientation[1]=rand()%4;//初始化下一个方块的状态
     manager->type[2]=rand()%7;//初始化下下一个方块的形状
     manager->orientation[2]=rand()%4;//初始化下下一个方块的状态
     //memset(control,0,sizeof(Control));
     initTetris(manager);
     setPoolColor(manager,control);
 }
 //==============================================================================================
 void initGame(Manager *manager,Control *control)//控制台标题,光标隐藏,游戏池初始化
 {
     SetConsoleTitle("俄罗斯方块");
     CONSOLE_CURSOR_INFO cursorInfo={1,FALSE};
     Output=GetStdHandle(STD_OUTPUT_HANDLE);
     SetConsoleCursorInfo(Output,&cursorInfo);
     startGame(manager,control);
 }
 //================================================================================
 void printNextTetirs(const Manager *manager)
 {
     unsigned int tetris;
     tetris=TetrisTable[manager->type[1]][manager->orientation[1]];
     SetConsoleTextAttribute(Output,manager->type[1]| 8);
     int i;
     for (i=0;i<16;++i)
     {
         gotoxyWithFullWidth(30-(i&3),(i>>2)+3);
        ((tetris>>i)&1)? printf("■"):printf("%2s","");     }
     tetris=TetrisTable[manager->type[2]][manager->orientation[2]];
     SetConsoleTextAttribute(Output,manager->type[2]| 8);
     for (i=0;i<16;++i)
     {
          gotoxyWithFullWidth(35-(i&3),(i>>2)+3);
        ((tetris>>i)&1)? printf("■"):printf("%2s","");
     }
 }
 //==============================================================================================
 //初始化方块
 void initTetris(Manager *manager)
 {
     unsigned int tetris;
     manager->type[0]=manager->type[1];//当前类型=下一方块类型
     manager->orientation[0]=manager->orientation[1];//当前状态=下一方块状态
     manager->type[1]=manager->type[2];//下一类型=下下一方块类型
     manager->orientation[1]=manager->orientation[2];//下一状态=下下一方块状态
     manager->type[2]=rand()%7;//下下一方块随机产生
     manager->orientation[2]=rand()%4;
     tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
     manager->x=6;//定义方块位置
     manager->y=0;
    if (checkCollision(manager))
        manager->dead=true;//有碰撞,游戏结束
     else
      {
        insertTetris(manager);//没有碰撞,插入方块,
      }
     ++manager->tetrisTotal;//方块总数增加
     ++manager->tetrisCount[manager->type[0]];//相应方块数增加
     printNextBorder();
     printScore(manager);
     printNextTetirs(manager);//显示下一个,下下一个方块
     //显示得分信息
 }
 //================================================================================
 //插入方块
 void insertTetris(Manager *manager)
 {
     unsigned int tetris;
     int z;
     z=12-manager->x;
     tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
     manager->pool[manager->y+0]|=((tetris>>0x0 & 0x000F)<<z);
     manager->pool[manager->y+1]|=((tetris>>0x4 & 0x000F)<<z);
     manager->pool[manager->y+2]|=((tetris>>0x8 & 0x000F)<<z);
     manager->pool[manager->y+3]|=((tetris>>0xC & 0x000F)<<z);
 }
 //===================================================================================
 //显示当前方块
 void printCurrentTetris(const Manager *manager,const Control *control)
 {
     //显示当前方块是在移动后调用的,要擦去移动前的方块,需要扩展
     //向上扩展一行manager->y 向左,向右扩张 manager->x
     int x,y;
     y=(manager->y>4) ? (manager->y-1):4;
     for(;y<26 && y<(manager->y+4);++y)
     {
       //x=manager->x;
       x=(manager->x>2) ? (manager->x-1):2;
       for(;x<14 && x<(manager->x+5);++x)
       {
           gotoxyWithFullWidth(x+9,y-3);
          if (manager->pool[y]<<x&0x8000)
          {SetConsoleTextAttribute(Output,control->color[y][x]);
           printf("■");
            }
            else
            {
                SetConsoleTextAttribute(Output,0x00);
                printf("%2s","");
            }
     }
 }
 }
 //====================================================================================
 //检测碰撞
bool checkCollision(const Manager *manager)
{
    unsigned int tetris;
    tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
    int z;
    z=12-manager->x;
    unsigned int dest=0;
    dest|=(((manager->pool[manager->y+0]>>z)<<0x0)& 0x000F);
    dest|=(((manager->pool[manager->y+1]>>z)<<0x4)& 0x00F0);
    dest|=(((manager->pool[manager->y+2]>>z)<<0x8)& 0x0F00);
    dest|=(((manager->pool[manager->y+3]>>z)<<0xC)& 0xF000);
    return ((dest & tetris)!=0);
}
//===========================================================================================
//改变游戏池中每个方块的颜色
void setPoolColor(const Manager *manager,Control *control)
{
   unsigned int tetris;
   tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
   int i,x,y;
   for(i=0;i<16;++i)
   {
       y=(i>>2)+manager->y;//待设置的列
       if(y>26)
       {
           break;
       }
       x=manager->x+3-(i&3);
       if(tetris>>i&1)
       {
           control->color[y][x]=(manager->type[0]|8);//设置颜色
       }   }
}
//======================================================================================================
void printTetrisPool(const Manager *manager,const Control *control)
{
    int x,y;
    for (y=4;y<26;++y)
    {
        gotoxyWithFullWidth(11,y-3);
        for(x=2;x<14;++x)
        {
           if((manager->pool[y]<<x)&0x8000)
           {SetConsoleTextAttribute(Output,control->color[y][x]);
               printf("■");}        else
            {
                SetConsoleTextAttribute(Output,0);
                printf("%2s","");
            }        }
    }
}
//=================================================================================================================
//移除当前方块,其余保持不变
void removeTetris(Manager *manager)
 {
     unsigned  int tetris;
     tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
    int z;
    int y;
    z=12-manager->x;
    manager->pool[manager->y+0]&=~(((tetris>>0x0)&0x000F)<<z);
    manager->pool[manager->y+1]&=~(((tetris>>0x4)&0x000F)<<z);
    manager->pool[manager->y+2]&=~(((tetris>>0x8)&0x000F)<<z);
    manager->pool[manager->y+3]&=~(((tetris>>0xC)&0x000F)<<z); }
 //===============================================================================================
 //向下移动方块
void moveDownTetris(Manager *manager,Control *control)
 {
     int y=manager->y;//原来位置 manager->y
     removeTetris(manager);
     //manager->y=manager->y+1;//manager-> 变化
     ++manager->y;
     if(checkCollision(manager))//有碰撞 恢复原来位置 插入当前方块
     {
        manager->y=y;
        insertTetris(manager);
        //initTetris(manager);
        if(checkFrasing(manager,control))//有消行
        {
            printTetrisPool(manager,control);
        }
     }
     else//无碰撞 插入当前方块
     {
         insertTetris(manager);
         setPoolColor(manager,control);
         printCurrentTetris(manager,control);
     }
 }
 //============================================================================================
 void runGame(Manager *manager,Control *control)
 {
  clock_t clockLast,clockNow;
  clockLast=clock();
  printTetrisPool(manager,control);  while(!manager->dead)//没挂
  {
      while(_kbhit())
    {
        keydownControl(manager,control,getch());
    }
    if(!control->pause)
    {
        clockNow=clock();
        if(clockNow-clockLast>=450)//
  {
     clockLast=clockNow;
     moveDownTetris(manager,control);
  } 
 }
 }
 } //=================================================================================================
 void hozeMoveTetris(Manager *manager,Control  *control)
 {
     int x=manager->x;//记录原来X位置
     removeTetris(manager);
     control->direction==0 ? (--manager->x):(++manager->x);//左移或右移
     if(checkCollision(manager))//检测到碰撞
     {
         manager->x=x;//恢复原来位置
         insertTetris(manager);
         //initTetris(manage);
     }
     else //没有碰撞
        {
            insertTetris(manager);
            setPoolColor(manager,control);
            printCurrentTetris(manager,control);
        }
 }
 //===================================================================
 //按键控制
 void keydownControl(Manager *manager,Control *control,int  key)
 {
    //处理暂停
    if(key == 13)
    {
        control->pause=!control->pause;
    }
    if(control->pause)//暂停状态
    {
        return;
    }
    switch(key)
    {
     case 75:    //左移
     case'A':
     case'a':
     case'4':
         control->direction=0;
         hozeMoveTetris(manager,control);
         break;
     case 77://右移
     case 'D':
     case'd':
     case '6':
        control->direction=1;
        hozeMoveTetris(manager,control);
        break;
    case 80:  //下移
    case 'S':
    case's' :
    case '2':
        moveDownTetris(manager,control);
        break;
    case 72://顺时针转
    case 'W':
    case 'w':
    case '8':
        control->chockwise=true;
        rotateTetris(manager,control);
        break;
    case '0'://逆时针转
        control->chockwise=false;
        rotateTetris(manager,control);
        break;
     case ' '://直接落地
         dropDownTetris(manager,control);
         break;
    default:
        break;    }
 }
 //========================================================================================
 //旋转方块
 void rotateTetris(Manager *manager,Control *control)
 {
     int ori=manager->orientation[0];//记录当前方块状态
     removeTetris(manager) ;//移走当前方块
     manager->orientation[0]=(control->chockwise)?(ori+1)&3:(ori+3)&3;//顺指针改变状态
     if(checkCollision(manager))//有碰撞
    {
        manager->orientation[0]=ori;//恢复原来状态
        insertTetris(manager);//插入当前方块
    }
    else//无碰撞 放入当前方块
    {
        insertTetris(manager);
        setPoolColor(manager,control);//设置颜色,显示当前方块
        printCurrentTetris(manager,control);
    } }
 //==============================================================
 //消行检测
 bool checkFrasing(Manager *manager,Control *control)
 {
    static const unsigned int score[5]={0,1,3,6,9};//定义数组存分数 消0,1,2,3,4
     int count=0;//定义变量用于存很消行数 0
    int y=manager->y+3;//从下往上检测 y=manager->y+3
     do
     {
         if(y<26 && manager->pool[y]==0xFFFFU)//游戏池底部不能消且一行的值全为1
         {
             count++;//增加消行数
             memmove(manager->pool+1,manager->pool,sizeof(unsigned int)*y);
             memmove(control->color[1],control->color[0],sizeof(int[16])*y);//游戏池整体下移一行,颜色下移一行
             gotoxyWithFullWidth(15,18);
             SetConsoleTextAttribute(Output,0xF0);
             printf ("GOOD");
         }
         else
         {
             --y;
         }
        } while(y>=manager->y); //循环最多4次
        manager->erasedTotal+=count;//消行总数增加
        manager->score+=score[count];//得分增加
        if(count>0)
        {
            ++manager->erasedCount[count-1];//相应消行数增加
        }
        initTetris(manager);//初始化方块
        setPoolColor(manager,control);//设置游戏池颜色 
        return (count>0);
 }
 //=======================================================
 //直接落地
 void dropDownTetris(Manager *manager,Control *control)
 {
     int y;
     removeTetris(manager);//移走当前方块
     for(;manager->y<26;++manager->y)
     {
         if(checkCollision(manager))
         {
           break;
       }
     }
    //循环 y<26  ++manager->y
     --manager->y;//--manager->y 恢复位置
    insertTetris(manager);//插入当前方块
     setPoolColor(manager,control);//设置颜色
     checkFrasing(manager,control); //检测消行
     printTetrisPool(manager,control);//显示游戏池
 }
 //==============================================================
 //再来一次
 bool ifPlayAgain()
 {
     int  Y,y ,n, N;
     int ch; //定义整形变量,用于接受键盘输入的字符
    SetConsoleTextAttribute(Output,0xF0); //设置颜色, 前景色为黑色,背景色白色
      gotoxyWithFullWidth(15,10); //设置位置15,10
      printf("Game over"); //打印游戏结束
      gotoxyWithFullWidth(13,11);//设置位置13,11
      printf("按Y重玩,按N退出");//打印按y重玩, 按n退出
     do{              //do
          ch=_getch() ;          //变量=从键盘接受字符
          if(ch=='y' ||ch== 'Y')
          {
              return true;
          }           //判断是yY return true
          else  if(ch=='n'||ch=='N')
           {
               return false;
           }        //判断是nN return false;
            }while(1);
             }       //while(1)
//=============================================================
//游戏等级
//void youxidengji()
//{
   // int a;
   // SetConsoleTextAttribute(output,0xF0);
   // gotoxyWithFullWidth(16,11);
   // printf("请选择等级123");//}
 
Tetris.h文件
#ifndef TETRIS_H_INCLUDED
#define TETRIS_H_INCLUDED
#include <stdio.h>//标准输入输出头文件
#include <string.h>//标准字符串头文件
#include<stdlib.h>//标准库头文件
#include <time.h>//日期和时间头文件
#include <conio.h>//控制台输入输出头文件
#include<windows.h>//windows控制台头文件
#include<stdbool.h>//标准库尔函数头文件
//定义7种的方块的4种状态
static const unsigned int TetrisTable[7][4]=
{
   //==================================
   //正常状态
    {0x00F0,0x2222,0x00F0,0x2222},//I形方块的4个状态
    {0x7200,0x8C80,0x004E,0x0131},//T形方块的4个状态
    {0x6440,0x08E0,0x0226,0x0710},//L形方块的4个状态
    {0x4460,0x02E0,0x0622,0x0740},//J形方块的4个状态
   {0x3600,0x8C40,0x006C,0x0231},//Z形方块的4个状态
   {0x2640,0x0C60,0x0264,0x0630},//S形方块的4个状态
   {0x0660,0x0660,0x0660,0x0660},//O形方块的4个状态
    //==================================
    //全I形
    {0x0F00,0x4444,0x00F0,0x2222},
    {0x0F00,0x4444,0x00F0,0x2222},
    {0x0F00,0x4444,0x00F0,0x2222},
    {0x0F00,0x4444,0x00F0,0x2222},
    {0x0F00,0x4444,0x00F0,0x2222},
    {0x0F00,0x4444,0x00F0,0x2222},
    {0x0F00,0x4444,0x00F0,0x2222},
    //====================================
    //全O形
    {0x0660,0x0660,0x0660,0x0660},
    {0x0660,0x0660,0x0660,0x0660},
    {0x0660,0x0660,0x0660,0x0660},
    {0x0660,0x0660,0x0660,0x0660},
    {0x0660,0x0660,0x0660,0x0660},
    {0x0660,0x0660,0x0660,0x0660},
   {0x0660,0x0660,0x0660,0x0660},
    {0x0660,0x0660,0x0660,0x0660},
};
//初始化游戏池
//28行每行16位,前26行每行16位,每行前2位,最后两位均为1,其余为0,用于检测碰撞
//最后2行全部为1,用于检测碰撞
//当某一行为0xFFFF时,该行已满,可以消行
static const unsigned int gs_uInitialTetrisPool[28]=
{
    0xC003,0xC003,0xC003,0xC003,
    0xC003,0xC003,0xC003,0xC003,
    0xC003,0xC003,0xC003,0xC003,
    0xC003,0xC003,0xC003,0xC003,
    0xC003,0xC003,0xC003,0xC003,
    0xC003,0xC003,0xC003,0xC003,
    0xC003,0xC003,0xFFFF,0xFFFF,
};
typedef struct TetrisManager //这个结构体存储游戏相关数据
{
  unsigned int pool[28];//记录游戏池,28行,每行16位
  int x;//记录方块的x坐标,左上角坐标
  int y;//记录方块的y坐标
  int type[3];//当前,下一个,下下以一个方块的形状
  int orientation[3];//当前,下一个,下下一个的状态
  unsigned int score;//得分
  unsigned int erasedTotal;//消行总数
  unsigned int erasedCount[4];//消1,2,3,4的数目
  unsigned int tetrisTotal;//方块总数
  unsigned int tetrisCount [7];//7种方块的数目
  bool dead;//游戏结束
}Manager ;
typedef struct TetrisControl//这个结构体存储控制相关数据
{
  bool pause;//暂停
  bool chockwise;//旋转方向 顺时针位true
  int direction;//移动方向,0;向左移动;1; 向右移动
  int color[28][16];//游戏池中每个点的颜色
}Control;
HANDLE Output;
void gotoxyWithFullWidth(short x,short y);
void printPrompting();//显示提示信息
void printPoolBorder();//显示游戏池边界
void printScore();//显示得分信息
void printNextBorder();//显示下一个,下下一个边框
void startGame(Manager *manager,Control *Control);
void initGame (Manager *manager,Control *control);
void printNextTetirs(const Manager *manager);//显示下一个下下一个方块
void initTetris(Manager *manager);//初始化当前方块,下一个,下下一个
void insertTetris(Manager *manager);//插入当前方块
void printCurrentTetris(const Manager *manager,const Control *Control);//显示当前方块
bool checkCollision(const Manager *manager);//碰撞检测
void setPoolColor(const Manager *manager,Control *control);//设置游戏池当前方块颜色
void printTetrisPool(const Manager *manager,const Control *control);
void removeTetris(Manager *manager);//移除当前方块,游戏池中有方块的清零
void moveDownTetris(Manager *manager,Control *control);
void runGame(Manager *manager,Control *control);//运行游戏
void hozeMoveTetris(Manager *manager,Control  *control);//水平移动方块
void keydownControl(Manager *manager,Control *control,int  key);//按键控制
void rotateTetris(Manager *manager,Control *control);//旋转方块
bool checkFrasing(Manager *manager,Control *control);//消行检测
void dropDownTetris(Manager *manager,Control *control);//方块直接落地
bool ifPlayAgain();//再来一次//void  youxidengji();//游戏等级
#endif // TETRIS_H_INCLUDED
 
主函数
#include <stdio.h>
#include <stdlib.h>
#include "Tetris.h"
int main()
{    Manager manager;
    Control control;
    //printNextBorder();
    initGame(&manager,&control);
    //initTetris(&manager);
    printPoolBorder();
    printPrompting();
do
    {
    //printNextBorder();
    //printNextTetirs(&manager);
     printPrompting();
    printPoolBorder();
    //setPoolColor(&manager,&control);
    //printScore(&manager);
    //printCurrentTetris(&manager,&control);
    //insertTetris(&manager);
    //printTetrisPool(&manager,&control);
    //moveDownTetris(&manager,&control);
    runGame(&manager,&control);
    if(ifPlayAgain())//判断重玩函数是真,假
     {
         SetConsoleTextAttribute(Output,0x07);//真值,重玩 颜色设置为0x07
         system("cls");//system("cls")清屏
         startGame(&manager,&control);//重新开始游戏 startGame
     }     else
     {
         break;
         }//假值 break
           //}    while(1);
    gotoxyWithFullWidth(0,0);
    CloseHandle(Output);
    return 0;
}