当前位置 主页 > 服务器问题 > Linux/apache问题 >

    C++实现俄罗斯方块

    栏目:Linux/apache问题 时间:2020-01-27 11:51

    本文实例为大家分享了C++实现俄罗斯方块的具体代码,供大家参考,具体内容如下

    工具:vc++2010,图库:EasyX

    先看效果图片

    纯手写,没有面向对象思想,看全部源码

    #include <stdio.h>
    #include <graphics.h>
    #include <time.h>
    #include <conio.h>
    
    #define BLOCK_COUNT 5
    #define BLOCK_WIDTH 5
    #define BLOCK_HEIGHT 5
    #define UNIT_SIZE 20
    #define START_X  130
    
    #define START_Y  30
    #define KEY_UP  72
    #define KEY_RIGHT 77
    #define KEY_LEFT  75
    #define KEY_SPACE 32
    #define KEY_DOWN  76
    typedef enum{
     BLOCK_UP,
     BLOCK_RIGHT,
     BLOCK_DOWN, 
     BLOCK_LEFT
    }block_dir_t;
    typedef enum{
     MOVE_DOWN,
     MOVE_LEFT,
     MOVE_RIGHT
    
    }move_dir_t;
    int speed = 500;
    int NextIndex = -1;//下一个方块种类
    int BlockIndex = -1;//当前方块种类
    int score = 0;//分数
    int rank = 0;//等级
    int visit[30][15];//访问数组
    int markcolor[30][15];//表示颜色
    int minX = 30;
    int minY = 30;
    int color[BLOCK_COUNT]={
     GREEN,CYAN,MAGENTA,BROWN,YELLOW
    };
    int block[BLOCK_COUNT*4][BLOCK_HEIGHT][BLOCK_WIDTH] = {
     //条形方块
     {
     0,0,0,0,0,
     0,0,1,0,0,
     0,0,1,0,0,
     0,0,1,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,0,0,0,0,
     0,1,1,1,0,
     0,0,0,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,0,1,0,0,
     0,0,1,0,0,
     0,0,1,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,0,0,0,0,
     0,1,1,1,0,
     0,0,0,0,0,
     0,0,0,0,0},
     //L形方块
     {
     0,0,0,0,0,
     0,0,1,0,0,
     0,0,1,0,0,
     0,0,1,1,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,0,0,0,0,
     0,1,1,1,0,
     0,1,0,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,1,1,0,0,
     0,0,1,0,0,
     0,0,1,0,0,
     0,0,0,0,0}, 
     {
     0,0,0,0,0,
     0,0,0,1,0,
     0,1,1,1,0,
     0,0,0,0,0,
     0,0,0,0,0}, 
     //田字型
     {
     0,0,0,0,0,
     0,1,1,0,0,
     0,1,1,0,0,
     0,0,0,0,0,
     0,0,0,0,0}, 
     {
     0,0,0,0,0,
     0,1,1,0,0,
     0,1,1,0,0,
     0,0,0,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,1,1,0,0,
     0,1,1,0,0,
     0,0,0,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,1,1,0,0,
     0,1,1,0,0,
     0,0,0,0,0,
     0,0,0,0,0},
     //T字形方块
     {
     0,0,0,0,0,
     0,1,1,1,0,
     0,0,1,0,0,
     0,0,0,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,0,0,1,0,
     0,0,1,1,0,
     0,0,0,1,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,0,1,0,0,
     0,1,1,1,0,
     0,0,0,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,0,1,0,0,
     0,0,1,1,0,
     0,0,1,0,0,
     0,0,0,0,0},
     //Z字形方块
     {
     0,0,0,0,0,
     0,1,1,0,0,
     0,0,1,1,0,
     0,0,0,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,0,0,1,0,
     0,0,1,1,0,
     0,0,1,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,1,1,0,0,
     0,0,1,1,0,
     0,0,0,0,0,
     0,0,0,0,0},
     {
     0,0,0,0,0,
     0,0,0,1,0,
     0,0,1,1,0,
     0,0,1,0,0,
     0,0,0,0,0}
    };
    
    //欢迎界面
    void welcome(){
     //初始化画布
     initgraph(550,660);
    
     //设置窗口标题
     HWND window = GetHWnd();//获取窗口
     SetWindowText(window,_T("俄罗斯方块 GWF"));//设置窗口标题
    
    
     //设置文本字体样式
     setfont(0,30,_T("微软雅黑"));
     setcolor(YELLOW);
     outtextxy(150,200,_T("俄罗斯方块"));
     setfont(0,10,_T("微软雅黑"));
     outtextxy(175,300,_T("IT编程从俄罗斯方块开始"));
     Sleep(3000);
     
    }
    //初始化游戏屏幕
    void initGameScene(){
     char str[16];
     //清除屏幕
     cleardevice();
    
     rectangle(27,27,336,635);
     rectangle(29,29,334,633);
     rectangle(370,50,515,195);
     setfont(24,0,_T("楷体"));
     setcolor(LIGHTGRAY);
     outtextxy(405,215,_T("下一个"));
     setcolor(RED);
     outtextxy(405,280,_T("分数"));
     sprintf(str,"%d",score);
     outtextxy(415,310,str);
     outtextxy(405,375,_T("等级"));
     sprintf(str,"%d",rank);
     outtextxy(415,405,str);
     setcolor(LIGHTBLUE);
     outtextxy(390,475,"操作说明");
     outtextxy(390,500,"↑:旋转");
     outtextxy(390,525,"↓:下降");
     outtextxy(390,550,"→:向右");
     outtextxy(390,575,"←:向左");
     outtextxy(390,600,"空格:暂停");
    
    
    
    }
    void drawBlock(int x,int y){//右上角画出方块
     setcolor(color[NextIndex]);
     setfont(23,0,"楷体");
     for(int i= 0;i<BLOCK_HEIGHT;i++){
     for(int j= 0;j<BLOCK_WIDTH;j++){
     if(block[NextIndex*4][i][j] == 1){
     outtextxy(x+UNIT_SIZE*j,y+UNIT_SIZE*i,"■");
     }
      }
     }
    }
    void drawBlock(int x,int y,int blockIndex,block_dir_t dir){//按索引画出什么方块指定位置方块指定方向
     setcolor(color[blockIndex]);
     setfont(23,0,"楷体");
     int id = blockIndex*4+dir;
     for(int i= 0;i<BLOCK_HEIGHT;i++){
     for(int j= 0;j<BLOCK_WIDTH;j++){
     if(block[id][i][j] == 1){
     outtextxy(x+UNIT_SIZE*j,y+UNIT_SIZE*i,"■");
     }
      }
     }
    }
    
    void clearBlock(int x, int y){
     setcolor(BLACK);
     setfont(23,0,"楷体");
     for(int i= 0;i<BLOCK_HEIGHT;i++){
     for(int j= 0;j<BLOCK_WIDTH;j++){
     outtextxy(x+UNIT_SIZE*j,y+UNIT_SIZE*i,"■");
      }
     }
    }
    void clearBlock(int x, int y,block_dir_t dir){
     setcolor(BLACK);
     int id = BlockIndex *4+dir;
     y+=START_Y;
     for(int i= 0;i<BLOCK_HEIGHT;i++){
     for(int j= 0;j<BLOCK_WIDTH;j++){
     if(block[id][i][j] == 1){
     outtextxy(x+UNIT_SIZE*j,y+UNIT_SIZE*i,"■");
     }
      }
     }
    }
    void nextblock(){
     clearBlock(391,71);//清除右上角方块
     //随机选择一种方块
     srand(time(NULL));//时间函数的返回值产生随机数种子
     NextIndex = rand()%BLOCK_COUNT;
     drawBlock(391,71);//画出方块
    
    }
    //如果在指定位置可以向方向移动
    int moveable(int x0,int y0,move_dir_t moveDir,block_dir_t blockDir){
     int x = (y0 - minY)/UNIT_SIZE;
     int y = (x0 - minX)/UNIT_SIZE;
     int id = BlockIndex * 4+blockDir;
     int ret = 1;
     if(moveDir == MOVE_DOWN){
     for(int i = 0;i<5;i++){
     for(int j = 0;j<5;j++){
     if(block[id][i][j] == 1 &&(x+i+1>=30 || visit[x+i+1][y+j]==1)){
      ret=0;
     }
     }
     }
     }else if(moveDir == MOVE_LEFT){
     for(int i = 0;i<5;i++){
     for(int j = 0;j<5;j++){
     if(block[id][i][j] == 1 &&(y+j==0 || visit[x+i][y+j-1]==1)){
      ret=0;
     }
     }
     }
     }else if(moveDir == MOVE_RIGHT){
     for(int i = 0;i<5;i++){
     for(int j = 0;j<5;j++){
     if(block[id][i][j] == 1 &&(y+j+1>=15 || visit[x+i][y+j+1]==1)){
      ret=0;
     }
     }
     }
     }
     return ret;
    }
    void failCheck(){//游戏是否结束
     if(!moveable(START_X,START_Y,MOVE_DOWN,BLOCK_UP)){
     setcolor(WHITE);
     setfont(45,0,"隶体");
     outtextxy(75,300,"GAME OVER!");
     Sleep(1000);
     system("pause");
     closegraph();
     exit(0);
     }
    }
    int wait(int interval){//等待
     int count = interval/5;
     for(int i = 0;i<count;i++){
     Sleep(5);
     if(kbhit()){
     return 0;
     }
     }
    }//判断当前方向是否可以转到指定方向
    int rotatable(int x,int y,block_dir_t dir){
     int id= BlockIndex * 4 +dir;
     int xIndex = (y-minY)/20;
     int yIndex = (x-minX)/20;
    
     if(!moveable(x,y,MOVE_DOWN,dir)){
     return 0 ;
     }
     for(int i = 0;i<5;i++){
     for(int j = 0;j<5;j++){
     if(block[id][i][j] ==1&&(yIndex+j<0||yIndex+j>=15||visit[xIndex+i][yIndex+j] ==1)){
     return 0 ;
     }
     }
     }
     return 1;
    }
    void mark(int x,int y,int blockIndex,block_dir_t dir){
     int id = blockIndex*4+dir;
     int x2 = (y-minY)/20;
     int y2 = (x-minX)/20;
     for(int i=0;i<5;i++){
     for(int j=0;j<5;j++){
     if(block[id][i][j] ==1){
     visit[x2+i][y2+j]=1;
     markcolor[x2+i][y2+j]=color[blockIndex];
     }
     }
     }
    }
    void clear_down(int x){//消除第x行,并把上面的行都下移
     for(int i = x;i>0;i--){
     for(int j=0;j<15;j++){
     if(visit[i-1][j]){//上面有东西
     visit[i][j]=1;
     markcolor[i][j]=markcolor[i-1][j];
     setcolor(markcolor[i][j]); 
     outtextxy(20*j+minX,20*i+minY,"■");
     }else{
     visit[i][j] =0;
     setcolor(BLACK);
     outtextxy(20*j+minX,20*i+minY,"■");
     }
     }
     }
     //清除最顶层那一行,就是行标位0的哪一行
     setcolor(BLACK);
     for(int j = 0;j<15;j++){
     visit[0][j] = 0;
     outtextxy(20*j+minX,minY,"■");
     }
    }
    void updataGrade(){
    //更新等级提示
    //假设:50分一级
     char str[10];
     rank = score/50;
     sprintf(str,"%d",rank);
     outtextxy(425,405,str);
     //更新速度,等级越高速度越快,speed越小
     //最慢是500,最快是50
     speed = 500-rank*50;
     if(speed<=0){
     speed = 50;
     }
    }
    void addScore(int lines){//更新分数,line表示消除的行数
     char str[32];
     setcolor(RED);
     score+=lines*10;
     sprintf(str,"%d",score);
     outtextxy(415,310,str);
    }
    void check(){//消去方块
     int i,j;
     int clearLines =0;
     for(i=29;i>=0;i--){
     for(j=0;j<15 && visit[i][j];j++);
     //执行到此处有两种情况,
     //1.第I行没有满,即表示有空位,此时j<15
     //2.第i行已经满了,j就大于等于15
     if(j>=15){
     //此时第i行已经满了,就需要消除第i行
     clear_down(i);//清除第i行,并把上面的行都下移动
     i++;
     clearLines++;
     }
     }
     //更新分数
     addScore(clearLines);
     //更新等级
     updataGrade();
    }
    void move(){
     int x = START_X;
     int y = START_Y;
     int k = 0;
     int curSpeed = speed;
     block_dir_t blockDir = BLOCK_UP;
    
     //检查游戏是否结束
     failCheck();
     while(1){
     if(kbhit()){
     int key = getch();
     if(KEY_SPACE == key){
     getch();
     }
     }
     //清除当前方块
     clearBlock(x,k,blockDir);
     if(kbhit()){
     int key = getch();
     
     if(KEY_UP == key){//变形
     block_dir_t nextDir = (block_dir_t)((blockDir+1)%4);
     if(rotatable(x,y+k,nextDir)){
      blockDir= nextDir;
     }
     }else if(KEY_DOWN == key){//乡下加速
     curSpeed = 50;
     }else if(KEY_RIGHT == key){//右移动
     if(moveable(x,y+k+20,MOVE_RIGHT,blockDir)){
      x+=20;
     }
     }else if(KEY_LEFT == key){//左移动
     if(moveable(x,y+k+20,MOVE_LEFT,blockDir)){
      x-=20; 
     }
     }
     }
     k+=20;
     //绘制当前方块
     drawBlock(x,y+k,BlockIndex,blockDir);
     wait(curSpeed);
     
     //方块降落到底层的固化处理
     if(!moveable(x,y+k,MOVE_DOWN,blockDir)){
     mark(x,y+k,BlockIndex,blockDir);
     break;
     }
     }
    }
    void newblock(){
     //确定即将使用的方块
     BlockIndex = NextIndex;
     //绘制方块从顶部掉下来
     drawBlock(START_X,START_Y);
     //新出现的方块等一下
     Sleep(100);
     //右上角绘制下一个方块
     nextblock();
     //向下降落的动作
     move();
    }
    
    int main (void){
     welcome(); 
     initGameScene();
     //产生新方块 
     nextblock();
     Sleep(500);
     memset(visit,0,sizeof(visit));
     while(1){
     newblock();
     //消除满行,并更新分数和速度
     check();
     }
     
     system("pause");
     closegraph();
     
     return 0;
    }