Bootstrap

俄罗斯方块(c++)

在这里插入图片描述
代码拷贝完,可以直接运行游戏哦

#include<stdio.h>
#include<graphics.h>
#include<Windows.h>
#include<time.h>
#include<conio.h>
int score = 0;//总分
int rank =0;//等级
int NextIndex=-1;  //下一个要降落方块的种类
int BlockIndex =1; //本次降落方块的种类
#define  BLOCK_COUNT     5
#define  BLOCK_WIDTH  5
#define  BLOCK_HEIGHT       5
#define  START_X          130
#define  START_Y     30
#define  UNIT_SIZE         20
#define KEY_UP             72
#define KEY_RIGHT          77
#define KEY_LEFT     75
#define KEY_DOWN           80
#define KEY_SPACE          32
int speed=500;
int minX = 30;
int minY =30;
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 visit[30][15];    
int markColor[30][15];  //对应的数组颜色
int color[BLOCK_COUNT]=
 {GREEN ,CYAN ,MAGENTA ,BROWN ,YELLOW };
extern  int block[BLOCK_COUNT * 4][BLOCK_HEIGHT][BLOCK_WIDTH];
int main(){
void welcome();    //欢迎界面
void initGameScene();//游戏大体框架
void clearBlock();//清除方块
void clearBlock(int x,int y,block_dir_t dir);
void drawBlock(int x,int y);//画方块
void drawBlock(int x,int y,int blockIndex,block_dir_t dir);
void nextblock();//下一个方块
int moveable(int x0,int y0,move_dir_t moveDir,block_dir_t blockDir);
//检查游戏是否结束
void failCheck(); //检查是否失败
void wait(int interval);
//判断当前位置是否可以转到指定方向
//注意现在这步并没有真正的转向,只是预览一下是否真的可以
int rotatable(int x,int y,block_dir_t dir);//查看是否能旋转
void mark(int x,int y,int BlockIndex,block_dir_t dir);//固定数组
void move(); //核心移动
void newblock();//新方块
void down(int x);//消除第x行的方块,并把上面的全部下移
void Showscore();//用于显示当前分数
void update();//等级更新
void check(); //检查是否满了一行的方块
/*以上为函数声明*/








welcome();    //欢迎界面
 initGameScene();  //绘制游戏基本框架
 nextblock();   //右上角下一个方块
 Sleep(500);
 memset(visit,0,sizeof(visit));//初始化访问数组
 while(1){
  newblock();
  check();
 }
 system("pause");
 closegraph();
 return 0;
}
void welcome(){
 initgraph(550,660);
 //设置窗口标题
 HWND hwnd = GetHWnd();   //获取窗口
 SetWindowText(hwnd,_T("小猪猪的俄罗斯方块"));
 //设置游戏标题
 setfont(40,0,_T("雅黑"));
 setcolor(WHITE);
 outtextxy(205,200,_T("俄罗斯方块"));
 setfont(22,0,_T("楷体"));
 outtextxy(175,300,_T("请开始你的表演!"));
 Sleep(3000);
}
void initGameScene(void){
 //清除屏幕
 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(425,405,str);
 //操作说明
 setcolor(LIGHTBLUE);
 outtextxy(390,475,"操作说明");
 outtextxy(390,500,"↑:旋转");
 outtextxy(390,525,"↓:下降");
 outtextxy(390,550,"←:左移");
 outtextxy(390,575,"→:右移");
 outtextxy(390,600,"空格 暂停");
}
void clearBlock(){
 setcolor(BLACK);
 setfont(23,0,"楷体");
 for(int i=0;i<BLOCK_HEIGHT;i++){
  for(int j=0;j<BLOCK_WIDTH;j++){
   int x = 391+j*UNIT_SIZE;
   int y =71+i*UNIT_SIZE;
   outtextxy(x,y,"■");
  }
 }
}
void clearBlock(int x,int y,block_dir_t dir){
 int id = BlockIndex*4+dir;
 y+=START_Y;
 setcolor(BLACK);
 for(int i=0;i<5;i++){
  for(int j=0;j<5;j++){
   if(block[id][i][j] == 1){
    //擦除该方块的地i行的第j列
    outtextxy(x+j*20,y+i*20,"■");
   }
  }
 }
}
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+j*UNIT_SIZE,y+i*UNIT_SIZE,"■");
   }
  }
 }
}
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+j*UNIT_SIZE,y+i*UNIT_SIZE,"■");
   }
  }
 }
}
void nextblock(){
 int x = 391, y = 71;
 clearBlock();
 srand(time(NULL));
 NextIndex = rand()%BLOCK_COUNT;
 drawBlock(x,y);
}
//如果在指定位置可以向指定方向移动。就返回1,否则就返回0
int moveable(int x0,int y0,move_dir_t moveDir,block_dir_t blockDir){
 int id = BlockIndex *4 +blockDir;
 //计算当前方块的左上角在30 x 15的游戏去中的位置(第几行,第几列)
 int x = (y0 - minY)/UNIT_SIZE;
 int y = (x0-minX)/UNIT_SIZE;
 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,_T("GAME OVER!!!"));
  Sleep(1000);
  system("pause");
  closegraph();
  exit(0);
 }
}
void wait(int interval){ //500
 int count = interval/10;
 for(int i=0;i<count;i++)
 {
  Sleep(10);
  if(kbhit()){
  return ;
  }
 }
}
//判断当前位置是否可以转到指定方向
//注意现在这步并没有真正的转向,只是预览一下是否真的可以
int rotatable(int x,int y,block_dir_t dir){
 if(!moveable(x,y,MOVE_DOWN,dir)){
  return 0;
 }
 int id= BlockIndex*4+dir;
 int x2 = (y - minY)/UNIT_SIZE;
 int y2 = (x-minX)/UNIT_SIZE;
 for(int i = 0;i<5;i++){
  for(int j = 0;j<5;j++){
   if(block[id][i][j] == 1&&
    (y2+j < 0||y2+j >= 15 ||visit[x2+i][y2+j] == 1)){
    return 0;
   }
  }
 }
 return 1;
}
void mark(int x,int y,int BlockIndex,block_dir_t dir){
 int x2 =(y-minY)/UNIT_SIZE;
 int y2 = (x-minX)/UNIT_SIZE;
 int id = BlockIndex*4+dir;
 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 move(){
 int x = START_X;
 int y = START_Y;
 int k=0;
 block_dir_t blockDir =BLOCK_UP;
 int curSpeed = speed;
 failCheck();  //检查游戏是否结束
 //持续下降
 while(1){
  if(kbhit()){
   int key = getch();
   if(key == KEY_SPACE){
    getch();
   }
  }
  //清除当前方块
  clearBlock(x,k,blockDir);
  if(kbhit()){
   int key = getch();
   if(key == KEY_UP){
    block_dir_t nextDir = (block_dir_t)((blockDir+1)%4);
    if(rotatable(x,y+k,nextDir)){
     blockDir = nextDir;
    }
   }else if(key == KEY_DOWN){
    curSpeed =50;
   }else if(key == KEY_LEFT){
    if(moveable(x,y+k+20,MOVE_LEFT,blockDir)){
        x-=20;
    }
   }else if(key == KEY_RIGHT){
    if(moveable(x,y+k+20,MOVE_RIGHT,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();  //方块下落
}
//消除第x行的方块,并把上面的全部下移
void down(int 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(minX+j*20,minY+i*20,"■");
   }else{
    visit[i][j] = 0;
    setcolor(BLACK);
    outtextxy(minX+j*20,minY+i*20,"■");
   }
  }
 }
 if(x == 0){
  for(int j=0;j<15;j++){
   visit[0][j]=0;
   setcolor(BLACK);
   outtextxy(minX+j*20,0,"■");
  }
 }
}
//用于显示当前分数
void Showscore(){
 char str[32];
 sprintf(str,"%d",score);
 setcolor(RED);
 outtextxy(415,310,str);
}
void update(){//本函数实现两个功能
 //实现显示等级
 rank = score/50;
 char str[16];
 sprintf(str,"%d",rank);
 outtextxy(425,405,str);
 //随着等级提升改变速度
 speed = 500 - rank*100;
 if(speed <=100){
  speed=100;
 }
}
void check(){ //检查是否一行全部占满
 int i,j;
 for(i=29;i>=0;i--){
  //检查第i行有没有满
  for(j=0;j<15&&visit[i][j];j++);
  //此时有两种情况
  //第一种:一行未满 即j<15
  //第二种:一行全部占满j= = 15
  if(j==15){
  //此时已经满了,就需要消除第i行
   down(i);//实现消除第i行,并把上面的行都下移
   i++;//特别注意,因为最外层的循环 中有i--,
    //所以我们必须在下次循环时再检查一遍这一行
   score+=10;
   //显示积分
   Showscore();
   //显示等级以及更新速度
   update();
  }
 }
}
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,1,0,0,0,
 0,1,1,0,0,
 0,1,0,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,1,0,0,
 0,1,1,0,0,
 0,1,0,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,1,0,0,
 0,1,1,0,0,
 0,1,0,0,0,
 0,0,0,0,0 },
};
;