实训:俄罗斯方块

本来是一天上传一点的,结果一次性上传了( ̄▽ ̄)",尴尬。

HANDLE Output;
void printPrompting();                                                  //显示提示信息
void gotoxyWithFullwidth(short x,short y);                              //进行全角定位
void printScore(const Manager *manager);                                //显示分数
void printPoolBorder();                                                 //显示游戏池边界
void initGame(Manager *manager,Control *control);                       //初始化游戏
void startGame(Manager *manager,Control *control);                      //开始游戏
void printNextTetris(const Manager *manager);                           //显示下一个和下下一个方块
void printTetrisPool(const Manager *manager,const Control *control);    //显示游戏池
void initTetris(Manager *manager);                                      //方块初始化,构造当前方块
void insertTetris(Manager *manager);                                    //把当前方块插入游戏池中
void setPoolColor(const Manager *manager,Control *control);             //设置颜色
void printCurrentTetris(const Manager *manager,const Control *control); //显示当前方块
bool checkCollision(const Manager *manager);                            //碰撞检测
void runGame(Manager *manager,Control *control);                        //运行游戏
void moveDownTetris(Manager *manager,Control *control);                 //向下移动方块
void removeTetris(Manager *manager);                                    //移去方块
bool checkErasing(Manager *manager,Control *control);                   //检测消行
void horzMoveTetris(Manager *manager,Control *control);                 //左右移动
void rotateTetris(Manager *manager,Control *control);                   //旋转方块
void keydownControl(Manager *manager,Control *control,int key);         //键入指令
void dropDownTetris(Manager *manager,Control *control);                 //消行
bool ifPlayAgain();                                                     //重新游戏

这是所有的函数。

 

#include 
#include 
#include"day8.h"
int main()
{
    Manager manager;
    Control control;
    //初始化函数
    initGame(&manager,&control);
    //initTetris(&manager);
    //runGame(&manager,&control);
    //初始化结构体
   // Output=GetStdHandle(STD_OUTPUT_HANDLE);



    do
    {   printPrompting();
        //printScore(&manager);
        printPoolBorder();
        // printNextTetris(&manager);//显示下一个和下下一个方块
        // printTetrisPool(&manager,&control);//显示游戏池
        // setPoolColor(&manager,&control);
        // insertTetris(&manager);
        // setPoolColor(&manager,&control);
        runGame(&manager,&control);
        if(ifPlayAgain())
        {
            SetConsoleTextAttribute(Output,0x7);
            system("cls");//清屏
            startGame(&manager,&control);
        }
        else
        {
            break;
        }

    }while(1);

}



//进行全角定位
void gotoxyWithFullwidth(short x,short y)
{
        static COORD cd;
        cd.X=(x*2);
        cd.Y=y;
        SetConsoleCursorPosition(Output,cd);
}



//显示提示信息
void printPrompting()
{
    SetConsoleTextAttribute(Output,11);
    gotoxyWithFullwidth(26,10);
    printf("■控制:");
    SetConsoleTextAttribute(Output,11);
    gotoxyWithFullwidth(27,12);
    printf("□向左移动:← A 4");
    SetConsoleTextAttribute(Output,11);
    gotoxyWithFullwidth(27,13);
    printf("□向右移动:→ D 6");
    SetConsoleTextAttribute(Output,11);
    gotoxyWithFullwidth(27,14);
    printf("□向下移动:↓ S 2");
    SetConsoleTextAttribute(Output,11);
    gotoxyWithFullwidth(27,15);
    printf("□顺时针转:↑ W 8");
    SetConsoleTextAttribute(Output,11);
    gotoxyWithFullwidth(27,16);
    printf("□逆时针转:0");
    SetConsoleTextAttribute(Output,11);
    gotoxyWithFullwidth(27,17);
    printf("□直接落地:空格");
    SetConsoleTextAttribute(Output,11);
    gotoxyWithFullwidth(27,18);
    printf("□暂停游戏:回车");

}



//显示分数
void printScore(const Manager *manager)
{
    static const char *tetrisbName="ITLJZSO";
  int i;
  SetConsoleTextAttribute(Output,14);
  gotoxyWithFullwidth(2,2);
  printf("■得分:%u",manager->score);
  //显示消行总数
  gotoxyWithFullwidth(1,6);
  printf("■消行总数:%u",manager->erasedTotal);
  for(i=0;i<4;++i)
  {
      gotoxyWithFullwidth(2,8+i);
      printf("□消%d:%u",i+1,manager->erasedCount[i]);
  }
  //输出方块总数
  gotoxyWithFullwidth(1,15);
  printf("■方块总数:%u",manager->tetrisTotal);
  //输出每一行方块数
  for(i=0;i<7;++i)
  {
     gotoxyWithFullwidth(2,17+i);
     printf("□%c形:%u",tetrisbName[i],manager->tetrisCount[i]);
  }

}



//显示游戏池边界
void printPoolBorder()
{   int j;
    //背景高亮白     11110000
    SetConsoleTextAttribute(Output,0xf0);
/*  //显示纵线
for(i=1;i<24;++i)
    {
       gotoxyWithFullwidth(10,i);
       printf("%2s","");

       gotoxyWithFullwidth(23,i);
       printf("%2s","");
    }
    //显示横线
    for(j=0;j<12;++j)
    {gotoxyWithFullwidth(11+j,23);
    printf("%2s","");
    }
*/
for(j=4;j<26;++j)
    {
        //显示纵线
       gotoxyWithFullwidth(10,j-3);
       printf("%2s","");

       gotoxyWithFullwidth(23,j-3);
       printf("%2s","");
    }
        //显示横线

    gotoxyWithFullwidth(10,j-3);
    printf("%28s","");


}



//初始化游戏
void initGame(Manager *manager,Control *control)
{
    //设置一个光标隐藏变量并初始化
    CONSOLE_CURSOR_INFO cursorInfo={1,FALSE};
    //获取控制台输入句柄
    Output=GetStdHandle(STD_OUTPUT_HANDLE);
    //设置光标隐藏
    SetConsoleCursorInfo(Output,&cursorInfo);
    //设置控制台标题
    SetConsoleTitle("俄罗斯方块");
    //调用一个游戏开始函数
    startGame(manager,control);
}



//开始游戏
void startGame(Manager *manager,Control *control)
{
    //初始化结构体
    memset(manager,0,sizeof(Manager));
    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 printNextTetris(const Manager *manager)
{
    unsigned int tetris;
    int i;
    //边框
    SetConsoleTextAttribute(Output,15);
    gotoxyWithFullwidth(26,1);
    printf("■■■■■■■■■■■");
    gotoxyWithFullwidth(26,2);
    printf("■%8s■%8s■","","");
    gotoxyWithFullwidth(26,3);
    printf("■%8s■%8s■","","");
    gotoxyWithFullwidth(26,4);
    printf("■%8s■%8s■","","");
    gotoxyWithFullwidth(26,5);
    printf("■%8s■%8s■","","");
    gotoxyWithFullwidth(26,6);
    printf("■■■■■■■■■■■");
     //显示下一个方块
     tetris=TetrisTable[manager->type[1]][manager->orientation[1]];
     SetConsoleTextAttribute(Output,manager->type[1]|8);
     for(i=0;i<16;++i)
     {
         gotoxyWithFullwidth((i&3)+27,(i>>2)+2);
         ((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((i&3)+32,(i>>2)+2);
         ((tetris>>i)&1)?(printf("■")):printf("%2s","");
     };
     gotoxyWithFullwidth(50,27);
     printf("by:yaoe");


}


//显示游戏池  gotoxyInPool(2,4)等价于gotoxyWithFullwidth(11,1)
#define gotoxyInPool(x,y) gotoxyWithFullwidth(x+9,y-3)
void printTetrisPool(const Manager *manager,const Control *control)
{
    int x,y;
    for (y=4;y<=25;++y)
    {
        gotoxyInPool(2,y);//把光标打到每行的开头
        for(x=2;x<=13;++x)
        {
            if((manager->pool[y]>>x)&1)//将每一行都遍历一遍
            {
                //用相应颜色,显示一个实心方块
                SetConsoleTextAttribute(Output,control->color[y][x]);
                printf("■");
            }
            else//没有方块,显示空白
            {
                SetConsoleTextAttribute(Output,0);
                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->y=0;
    manager->x=6;
    if(checkCollision(manager))
    {
        manager->dead=true;
    }
    else
    {
        insertTetris(manager);//将当前方块加入游戏池
    }
    ++manager->tetrisTotal;//方块总数
    ++manager->tetrisCount[manager->type[0]];//对应方块数
    printScore(manager);
    printNextTetris(manager);//显示下一个方块

}



//把当前方块插入游戏池中
void insertTetris(Manager *manager)
{
    unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
    //当前方块每4位取出,位或到游戏池相应位置,即完成插入方块
    manager->pool[manager->y+0]|=(((tetris>>0x0)&0x000f)<x);//取方块的最低4位,放入游戏池中,取4
    manager->pool[manager->y+1]|=(((tetris>>0x4)&0x000f)<x);//取方块的次低4位,放入游戏池中,取3
    manager->pool[manager->y+2]|=(((tetris>>0x8)&0x000f)<x);//取方块的最高4位,放入游戏池中,取2
    manager->pool[manager->y+3]|=(((tetris>>0xc)&0x000f)<x);//取方块的最高4位,放入游戏池中,取1
}



//设置颜色
void setPoolColor( const Manager *manager, Control *control)
{
    int i,x,y;
    //当前方块
    unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
    for(i=0;i<16;++i)
    {
        y=(i>>2)+manager->y;//待设置的列
            if(y>26)//超过底部限制
        {
            break;
        }
        x=(i&3)+manager->x;//待设置的行
            if((tetris>>i)&1)//检测的到消方格属于当前方块区域
        {
            control->color[y][x]=(manager->type[0]|8);//设置颜色

        }
    }

}



//显示当前方块
void printCurrentTetris(const Manager *manager,const Control *control)
{
    int x,y;
    y=(manager->y>4)?(manager->y-1):4;//向上扩展一行
    for(;y<26&&yy+4;++y)
    {
        x=(manager->x>2)?(manager->x-1):2;//向左扩展一列
        for(;x<14&&xx+5;++x)
        {
            gotoxyInPool(x,y);
            if((manager->pool[y]>>x)&1)
            {
                SetConsoleTextAttribute(Output,control->color[y][x]);
                printf("■");
            }
            else
            {
                SetConsoleTextAttribute(Output,0);
                printf("%2s","");
            }
        }
    }

}



//碰撞检测
bool checkCollision(const Manager *manager)
{
    unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
    unsigned int dest=0;//存放我们在新的位置取出来的16位数
    //取dest的最低4位
    dest|=(((manager->pool[manager->y+0]>>manager->x)<<0x0)&0x000f);
    //取dest的次低4位
    dest|=(((manager->pool[manager->y+1]>>manager->x)<<0x4)&0x00f0);
    //取dest的次高4位
    dest|=(((manager->pool[manager->y+2]>>manager->x)<<0x8)&0x0f00);
    //取dest的最高4位
    dest|=(((manager->pool[manager->y+3]>>manager->x)<<0xc)&0xf000);
    return((dest&tetris)!=0);

}



//运行游戏
void runGame(Manager *manager,Control *control)
{
    clock_t clockLast,clockNow;//这里的clock_t为长整型,clock_t是用来保存时间
    clockLast=clock();//计时
    printTetrisPool(manager,control);//显示游戏池
    while(!manager->dead)//没挂
    {
        while(_kbhit())//有键按下
        {
            keydownControl(manager,control,getch());//处理按键
        }
        if(!control->pause)//未暂停
        {
            clockNow=clock();//计时
            //两次计时的间隔超过0.45秒
            if(clockNow-clockLast>0.45F*CLOCKS_PER_SEC)//CLOCKS_PER_SER为常量,值为1000
            {
               clockLast=clockNow;
               moveDownTetris(manager,control);
            }
        }
    }
}



//向下移动方块
void moveDownTetris(Manager *manager,Control *control)
{
    int y=manager->y;
    removeTetris(manager);//移去当前方块
    ++manager->y;
    if(checkCollision(manager))
    {
        manager->y=y;
        insertTetris(manager);//放入当前方块,不需要设置颜色
        if(checkErasing(manager,control))
        {
            printTetrisPool(manager,control);
        }
    }
    else
    {
        insertTetris(manager);
        setPoolColor(manager,control);
        printCurrentTetris(manager,control);

    }


}



//移去方块
void removeTetris(Manager *manager)
{
    //当前方块
    unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
    //当前方块每4位取出,按位取反后位与到游戏池相应位置,即完成移除方块
    manager->pool[manager->y+0]&=~(((tetris>>0x0)&0x000F)<x);
    manager->pool[manager->y+1]&=~(((tetris>>0x4)&0x000F)<x);
    manager->pool[manager->y+2]&=~(((tetris>>0x8)&0x000F)<x);
    manager->pool[manager->y+3]&=~(((tetris>>0xc)&0x000F)<x);
}



bool checkErasing(Manager *manager,Control *control)
{
    static const unsigned scores[5]={0,10,30,90,150};
    int count=0;//本次的消行数
    int y=manager->y+3;//从下往上检测
    do
    {
        if(y<26&&manager->pool[y]==0xffff)//有效区域内
        {
            ++count;//
            memmove(manager->pool+1,manager->pool,sizeof(unsigned int )*y);
            memmove(control->color[1],control->color[0],sizeof(int [16])*y);
        }
        else
        {
            --y;
        }
    }while(y>=manager->y);
    manager->erasedTotal+=count;//消行总分
    manager->score+=scores[count];//得分
    if(count>0)
    {
        ++manager->erasedCount[count-1];//消行
    }
    initTetris(manager);//初始化方块
    setPoolColor(manager,control);//设置颜色
    return(count>0);

}



void horzMoveTetris(Manager *manager,Control *control)
{
    int x=manager->x;//记录原列位置
    removeTetris(manager);//在原来的位置移除方块
    control->direction==0?(--manager->x):(++manager->x);//选择移动
    if(checkCollision(manager))
    {
        manager->x=x;//恢复原来的位置
        insertTetris(manager);//放入当前方块,由于位置未变,不需要设置颜色
    }
    else
    {
        insertTetris(manager);//在新位置放入方块
        setPoolColor(manager,control);//设置颜色
        printCurrentTetris(manager,control);//显示当前方块
    }
}



void rotateTetris(Manager *manager,Control *control)
{
    int ori=manager->orientation[0];//记录原旋转状态
    removeTetris(manager);//
    manager->orientation[0]=(control->clockwise)?((ori+1)&3):((ori+3)&3);
    if(checkCollision(manager))
    {
        manager->orientation[0]=ori;//恢复原来的位置
        insertTetris(manager);//放入当前方块,由于位置未变,不需要设置颜色
    }
    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 72://上
        rotateTetris(manager,control);//旋转方块
        break;
    case 80://下
        moveDownTetris(manager,control);//向下移动方块
        break;
    case 75://左
        control->direction=0;
        horzMoveTetris(manager,control);//水平移动方块
        break;
    case 77://右
        control->direction=1;
        horzMoveTetris(manager,control);//水平移动方块
        break;
    case ' '://直接落地
        dropDownTetris(manager,control);
        break;
    default:
        break;
    }

}



void dropDownTetris(Manager *manager,Control *control)
{
    removeTetris(manager);//移走当前方块
    for(;manager->y<26;++manager->y)
    {
        if(checkCollision(manager))//检测到碰撞
        {
            break;
        }
    }
    --manager->y;
    insertTetris(manager);
    setPoolColor(manager,control);
    checkErasing(manager,control);
    printTetrisPool(manager,control);
}


//重玩一次
bool ifPlayAgain()
{
    int ch;
    SetConsoleTextAttribute(Output,0xf0);
    gotoxyWithFullwidth(15,10);
    printf("游戏结束");
    gotoxyWithFullwidth(13,11);
    printf("按Y重玩,按N退出");
    do
    {
        ch=_getch();
        if(ch=='Y'||ch=='y')
        {
            return true;
        }
        else if(ch=='N'||ch=='n')
        {
            return false;
        }

    }while(1);

}

容我偷回懒O(∩_∩)O

 

 

#ifndef DAY8_H_INCLUDED
#define DAY8_H_INCLUDED
#include
#include 
#include
#include
#include
#include
#include

typedef struct TetrisManager
{
    unsigned int pool[28];                                              //游戏池                                             //游戏池
    int x;                                                              //当前方块横坐标,此处坐标为X轴左上角横坐标
    int y;                                                              //当前方块纵坐标,此处坐标为Y轴左上角纵坐标
    int type[3];                                                        //当前、下一个和下下一个方块的类型
    int orientation[3];                                                 //当前、下一个和下下一个方块的旋转状态
    unsigned score;                                                     //得分
    unsigned erasedCount[4];                                            //消行数
    unsigned erasedTotal;                                               //消行总数
    unsigned tetrisCount[7];                                            //消方块数
    unsigned tetrisTotal;                                               //方块总数
    bool dead;                                                          //游戏是否结束
}Manager;

typedef struct TetrisControl
{
    bool pause;          //暂停
    bool clockwise;      //旋转方向:顺时针为true
    int direction;       //移动方向:0向左运动,1向右运动
    int color[28][16];
}Control;

static const unsigned int TetrisTable[7][4]=
{
    {0x00f0,0x2222,0x00F0,0x2222},                                      //I型
    {0x0072,0x0262,0x0270,0x0232},                                      //T型
    {0x0223,0x0074,0x0622,0x0170},                                      //L型
    {0x0226,0x0470,0x0322,0x0071},                                      //J型
    {0x0063,0x0264,0x0063,0x0264},                                      //Z型
    {0x006C,0x0462,0x006c,0x0462},                                      //S型
    {0x0660,0x0660,0x0660,0x0660}                                       //O型
};


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

HANDLE Output;
void printPrompting();                                                  //显示提示信息
void gotoxyWithFullwidth(short x,short y);                              //进行全角定位
void printScore(const Manager *manager);                                //显示分数
void printPoolBorder();                                                 //显示游戏池边界
void initGame(Manager *manager,Control *control);                       //初始化游戏
void startGame(Manager *manager,Control *control);                      //开始游戏
void printNextTetris(const Manager *manager);                           //显示下一个和下下一个方块
void printTetrisPool(const Manager *manager,const Control *control);    //显示游戏池
void initTetris(Manager *manager);                                      //方块初始化,构造当前方块
void insertTetris(Manager *manager);                                    //把当前方块插入游戏池中
void setPoolColor(const Manager *manager,Control *control);             //设置颜色
void printCurrentTetris(const Manager *manager,const Control *control); //显示当前方块
bool checkCollision(const Manager *manager);                            //碰撞检测
void runGame(Manager *manager,Control *control);                        //运行游戏
void moveDownTetris(Manager *manager,Control *control);                 //向下移动方块
void removeTetris(Manager *manager);                                    //移去方块
bool checkErasing(Manager *manager,Control *control);
void horzMoveTetris(Manager *manager,Control *control);
void rotateTetris(Manager *manager,Control *control);
void keydownControl(Manager *manager,Control *control,int key);         
void dropDownTetris(Manager *manager,Control *control);
bool ifPlayAgain();

#endif // DAY8_H_INCLUDED

头文件   ↑

暂且写这些以后再改(o゚v゚)ノ

2018.6

 

你可能感兴趣的:(私人)