C++俄罗斯方块

C++的课题设计选择了写俄罗期方块,想了一下却不知道怎么下手去做,无从下手。。求高人指点一下~~
最新回答
矜持萝莉

2024-06-24 01:52:41

//类用到的函数所需的头文件
#include <windows.h>
#include <time.h>

//类用到的基本宏定义

#define SHAPENUM 7 //方块形状的数目
#define MAXBLOCKNUM 4 //不同形状方块的小方块的最大数

//类用到的类型定义
typedef struct
{
POINT pt[MAXBLOCKNUM];//各小方块在网格中的索引
int ncount;//小方块数
}RUSSIAN;

class Russian
{
public:

//类的公有函数
Russian();
void init(COLORREF blockcolor,COLORREF blocklinecolor,COLORREF removecolor,int blocksize,int xindex,int yindex);
int randomblock(int shapeindex);//随机产生一个方块
int drawblock(HDC hdc,int left,int top,COLORREF brushcolor,COLORREF pencolor);
int virtualmoveblock(int *falled,int m,int n,int incre,int *adjust,int hv);
int rotate(HDC hdc,int left,int top,int *falled,int m,int n);
int coordinaterotate(int *falled,int m,int n);
void trans(POINT *pt);
int linefinished(int *falled,int m,int n);
int minmax(int xy,int flag);
void mov(int incre,int flag);
int setfalled(int *falled,int m,int n);
int getblock(HDC hdc,int left,int top,int shapeindex);
~Russian();

private:
//类的私有属性
POINT block[MAXBLOCKNUM];//方块中各小方块的位置索引
int ncount;//方块可分成几个小方块
static RUSSIAN russianshape[SHAPENUM];//方块形状描述数组
COLORREF m_blocklinecolor;//方块边框颜色
COLORREF m_blockcolor;//方块颜色
COLORREF m_removecolor;//擦除方块所用颜色
int m_blocksize;//方块尺寸
int m_xindex;//方块x坐标偏移m_xindex个m_blocksize单位
int m_yindex;//方块y坐标偏移yindex个m_blocksize单位

};
void Russian::mov(int incre,int flag)
//功能:调整方块incre个基本单位
//参数:flag为1,水平方向上调整,为2垂直方向
{
POINT *p;
for(p=block;p<block+ncount;p++)
{
if(flag==1)
{
p->x+=incre;
}
else if(flag==2)
{
p->y+=incre;
}
else
{
}
}
}

int Russian::minmax(int xy,int flag)
//功能:返回当前方块(block ncount属性指定)的某些最值
//参数:
//1.xy 偶数表示返回X坐标 奇数表示Y坐标
//2.flag 1返回最大值,0返回最小值
{
int *p,*pint;
int temp;

pint=(int *)block+xy%2;
temp=*pint;
for(p=pint;p<pint+sizeof(POINT)/sizeof(int)*ncount;p+=2)
{
if(flag==1)
{
if(temp<*p)
{
temp=*p;
}
}
else
{
if(temp>*p)
{
temp=*p;
}
}
}
return temp;
}

int Russian::randomblock(int shapeindex)
//根据方块形状数组,随机产生一个方块,对产生的方块顺时针随机旋转0~270度
//返回值:下一个方块的索引
{
POINT *p1,*p2;
int i;

if(shapeindex<0||shapeindex>=SHAPENUM)//如果传入的方块索引不正确,产生当前方块的索引
{
srand(time(NULL));//随机数序列种子
shapeindex=rand()%SHAPENUM;//随机数除方块形状数目的余数,shapeindex范围为0~SHAPENUM-1
}

ncount=russianshape[shapeindex].ncount;//初始化全局变量加速倍数为1
//初始化block为各个小方块的网格索引
for(p1=block,p2=russianshape[shapeindex].pt;p1<block+ncount;p1++,p2++)
{
p1->x=p2->x+m_xindex;
p1->y=p2->y+m_yindex;
}

srand(time(NULL));//随机数序列种子
shapeindex=rand()%4;//随机数除4的余数,顺时针旋转90度0~3次度,实现方块的方向随机

for(i=0;i<shapeindex;i++)
{
trans(block);//旋转坐标变换
}

//产生下一个方块的索引
srand(time(NULL));
shapeindex=rand()%SHAPENUM;

return shapeindex;
}

int Russian::drawblock(HDC hdc,int left,int top,COLORREF brushcolor,COLORREF pencolor)
//在hdc,屏幕坐标为x,y处用brushcolor、pencolor绘制方块
//如果color参数为NULL,则用默认的方块画刷、方块边框实心笔
{
POINT *p;
int x,y;
HBRUSH hbrush;
HPEN hpen;

if(pencolor==NULL)
{
hpen=(HPEN)CreatePen(PS_SOLID,1,m_blocklinecolor);
}
else
{
hpen=(HPEN)CreatePen(PS_SOLID,1,pencolor);
}

if(brushcolor==NULL)
{
hbrush=(HBRUSH)CreateSolidBrush(m_blockcolor);
}
else
{
hbrush=(HBRUSH)CreateSolidBrush(brushcolor);
}

SelectObject(hdc,hbrush);
SelectObject(hdc,hpen);

for(p=block;p<block+ncount;p++)
{
x=p->x*m_blocksize+left;
y=p->y*m_blocksize+top;

Rectangle(hdc,x,y,x+m_blocksize,y+m_blocksize);//有边框
}

DeleteObject(hbrush);
DeleteObject(hpen);//释放对象内存
return 1;
}

int Russian::virtualmoveblock(int *falled,int m,int n,int incre,int *adjust,int hv)
//功能:假设水平或垂直方向移动方块incre增量,是否会遇到障碍(边界或者falled)
//参数:
//1.pt为POINT数组的起始地址
//判断n个POINT范围内是否有边界或者障碍(falled)
//3.incre 坐标增量
//4.adjust存储新的增量(单位为BLOCKSIZE),即实际可行的移动的网格数
//5.hv 0或1,分别表示水平方向、垂直方向
//返回值:-1表示参数错误,0表示可以移动,1表示水平有边界或者障碍,2表示垂直有边界或障碍(randomblock)
{
POINT *p;
int index;
int i;
int resflag=0;//返回值变量,初始为0
int temp;//临时存储变量
int direction;//移动方向,1或者 -1

incre=incre/m_blocksize;
if(adjust==NULL)
{
return -1;//参数错误
}
else
{
*adjust=incre;//默认值等于incre/BLOCKSIZE
}

if(incre==0)
{
return 0;
}

if(falled==NULL)
{
return -1;//参数错误
}
direction=abs(incre)/incre;//方向:1为向右向下 -1为向左向上

for(p=block;p<block+ncount;p++)
{
if(hv==0)//判断水平方向是否有边界或障碍
{
index=p->x+incre;

for(i=p->x;(i-index)*direction<=0;i+=direction)
{
if(*(falled+p->y*n+i)==1)//遇到障碍
{
resflag=3;

temp=(i-direction)-p->x;
if(direction*(*adjust-temp)>0)//取绝对值较小的偏移量
{
*adjust=temp;
}
break;
}
}

if(resflag!=3)
{
if(index<0)//遇到左边界
{
*adjust=-minmax(0,0);
resflag=1;
break;
}

if(p->x+incre>n-1)//遇到右边界
{
*adjust=(n-1)-minmax(0,1);//返回(NLINE-1)*BLOCKSIZE-x坐标最大值
resflag=2;
break;
}
}

}
else//判断垂直方向是否有边界或障碍
{
index=p->y+incre;

for(i=p->y;(i-index)*direction<=0;i+=abs(incre)/incre)
{

if(i>=0&&*(falled+i*n+p->x)==1)//遇到障碍
{
resflag=5;
temp=(i-direction)-p->y;

if(direction*(*adjust-temp)>0)//取ncount个小方块中绝对值最小的偏移量
{
*adjust=temp;
}
break;
}
}

if(resflag!=5)//没有遇到障碍才进行边界的判断,否则会出现加速下降穿过障碍物的情况
{
if(p->y+incre>m-1)//
{
*adjust=m-1-minmax(1,1);
resflag=4;
break;
}
}

}
}

return resflag;
}

int Russian::rotate(HDC hdc,int left,int top,int *falled,int m,int n)
//功能:将方块绕点(pt->x,pt->y)顺时针旋转90度,坐标变换(网格坐标系中)
//参数:
//1.hdc 设备上下文,用于绘图
//2.pt为方块各小方块网格索引数组
//3.n为小方块数目
//返回值:如果pt为NULL,则返回0,否则返回1
//注意:在函数中,进行坐标变换,覆盖pt所指向的数组

{

drawblock(hdc,left,top,m_removecolor,0);//擦除旧方块,无边框

coordinaterotate(falled,m,n);//坐标转换

drawblock(hdc,left,top,m_blockcolor,0);//新方块,无边框
return 1;
}

int Russian::coordinaterotate(int *falled,int m,int n)
//原理:(x1,y1)绕(x0,y0)顺时针旋转90度,新坐标为:(x0+y0-y1,y0-x0+x1)
//功能:将方块绕点(0+pt->x,0+pt->y)顺时针旋转90度,坐标变换(网格坐标系中)
//返回值,1 已转换,0不能转换
{
int resflag=1;
POINT *p1,*p2;

POINT pt[MAXBLOCKNUM];//临时存储旋转后的坐标
trans(pt);//转换坐标,存储到pt中

for(p2=pt;p2<pt+ncount;p2++)//旋转后坐标有效性判断
{
if(!(!(p2->x>n-1||p2->y>m||p2->x<0)&&*(falled+p2->y*n+p2->x)!=1))
{
resflag=0;//坐标不合法
break;
}
}

if(resflag!=0)//坐标合法,把临时存储的坐标复制到block
{
for(p1=block,p2=pt;p1<block+ncount;p1++,p2++)
{
p1->x=p2->x;
p1->y=p2->y;
}
}
return resflag;
}

void Russian::trans(POINT *pt)
//功能:无条件将方块坐标转换(网格坐标系中),存储在pt所指向的数组中
//pt的size不小于block
{
int temp;
POINT *p1,*p2;
int xindex,yindex;

xindex=block->x;
yindex=block->y;
for(p1=block,p2=pt;p1<block+ncount;p1++,p2++)
{
p2->x=p1->x-xindex;
p2->y=p1->y-yindex;

temp=p2->x;
p2->x=-p2->y;
p2->y=temp;

p2->x+=xindex;
p2->y+=yindex;
}
}

int Russian::setfalled(int *falled,int m,int n)
//功能:设置障碍
//返回值,-1为参数错误,0为设置障碍失败(方块y坐标<0,游戏结束),1为成功设置障碍
{
POINT *p;
if(falled==NULL)
{
return -1;
}

for(p=block;p<block+ncount;p++)
{
if(p->y>=0)
{
*(falled+p->y*n+p->x)=1;//设置障碍
}
else
{
return 0;
}
}
return 1;
}

int Russian::linefinished(int *falled,int m,int n)
//方块停止落下时判断,是否有行满,并进行处理
//返回值:填满的行数
{
int *p;
int *pline;//指向NLINE个元素的指针
int i=0;//满行计数器

// int res[MAXBLOCKNUM];//存放满行的index,最多消去的行数等于各种形状方块有的小方块的数目

for(pline=falled+(m-1)*n;pline>=falled;pline-=n)//从最底下一行开始
{
for(p=pline;p<pline+n;p++)//从最左边一列开始
{
if(*p!=1)
{
break;
}
}
if(p>=pline+n)//说明pline行的所有元素都是1,行满
{
i++;
// res[i++]=pline-falled;
}
else//行不满,复制到底层
{
if(i!=0)
{
memcpy(pline+i*n,pline,sizeof(int)*n);//不满的行下面有i个满的行,满的行不用理会
}
}
}

memset(falled,0,sizeof(int)*n*i);//清空最上面i行

return i;
}

void Russian::init(COLORREF blockcolor,COLORREF blocklinecolor,COLORREF removecolor,int blocksize,int xindex,int yindex)
//初始化方块的各项属性
{
m_blockcolor=blockcolor;
m_blocklinecolor=blocklinecolor;
m_removecolor=removecolor;

m_blocksize=blocksize;
m_xindex=xindex;
m_yindex=yindex;
}

int Russian::getblock(HDC hdc,int left,int top,int shapeindex)
{
POINT *p1,*p2;
POINT pt[MAXBLOCKNUM];
HPEN hpen;
HBRUSH hbrush;
int x,y;
if(shapeindex<0||shapeindex>=SHAPENUM)//如果传入的方块索引不正确
{
return 0;
}

for(p1=pt,p2=russianshape[shapeindex].pt;p1<pt+ncount;p1++,p2++)
{
p1->x=p2->x;
p1->y=p2->y;
}

hpen=CreatePen(PS_SOLID,1,m_blocklinecolor);
SelectObject(hdc,hpen);

hbrush=CreateSolidBrush(m_blockcolor);
SelectObject(hdc,hbrush);//创建DC对象,选入DC,并保存旧的DC对象

for(p1=pt;p1<pt+russianshape[shapeindex].ncount;p1++)
{
x=p1->x*m_blocksize+left;
y=p1->y*m_blocksize+top;

Rectangle(hdc,x,y,x+m_blocksize,y+m_blocksize);//有边框,若hpen为0,则边框与背景色一致
}

DeleteObject(hbrush);
DeleteObject(hpen);//释放内存
return 1;
}

RUSSIAN Russian::russianshape[SHAPENUM]=
//在类外初始化静态成员
/*
方块的各种形状描述,以中心点开始描述
△■■ ■■△ ■ △△■ △■△ ■■△ △■△
△■△ ■■△ △■△ △■■ △■■ △■△ △■■
△■△ △△△ △■△ △■△ △■△ △■△ △△■
△■△
*/
{
{
{
{0,0},//以0,0开始
{0,-1},
{1,-1},
{0,1}
},
4
},
{
{
{0,0},
{-1,-1},
{-1,0},
{0,-1}
},
4
},
{
{
{0,0},
{0,-1},
{0,1},
{0,-2}
},
4
},
{
{
{0,0},
{0,1},
{1,-1},
{1,0}
},
4
},
{
{
{0,0},
{1,0},
{0,-1},
{0,1}
},
4
},
{
{
{0,0},
{0,-1},
{-1,-1},
{0,1}
},
4
},
{
{
{0,0},
{0,-1},
{1,0},
{1,1}
},
4
}
};

Russian::Russian()
{
}

Russian::~Russian()
{
}
汏姐萌神

2024-06-24 16:45:48

有一本书叫C语言经典案例,有个俄罗斯方块,你可以参考一下
故事与谁

2024-06-24 06:20:33

我有完整代码,LZ要吗