俄罗斯方块(c++)

    科技2022-07-10  160

    代码拷贝完,可以直接运行游戏哦

    #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 }, };
    Processed: 0.026, SQL: 8