C++实现俄罗斯方块

本文实例为大家分享了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;

}

分析项目:

1.必须要有欢迎界面

2.搭建合理的边界,就是游戏范围

3.逻辑1:先出现右上方的方块样式,等待一段时间,将右上方的样式在游戏区打印出

4.逻辑2,方块降落,要擦除原先印记,将1改为0

5.逻辑3,热键控制移动方向,暂停及变形,且不能移动出界,判断方块是否还能移动

6.逻辑4,方块凝固在下方不出界

7.逻辑5,最下面一行方块叠满了,消去它并把上面的行都下移(分两种情况),并且再次检查这一行

8.逻辑6,计算消除行数次数,统计分数,控制休眠时间长度

9.逻辑7,每次移动先判断是否能移动,默认结束程序,在合理游戏区返回false,结束界面

总结:从界面开始到完整的架构,功能后实现,一步一步,逻辑严谨,思路清晰,注释在代码里。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 C++实现俄罗斯方块 的全部内容, 来源链接: utcz.com/p/244748.html

回到顶部