VC++60俄罗斯方块代码讲解.docx
《VC++60俄罗斯方块代码讲解.docx》由会员分享,可在线阅读,更多相关《VC++60俄罗斯方块代码讲解.docx(67页珍藏版)》请在冰豆网上搜索。
VC++60俄罗斯方块代码讲解
俄罗斯方块
俄罗斯方块是我大学一年级刚学VC++时的课程设计,当时的课程设计有三种,单文档、多文档和俄罗斯方块。
我选择俄罗斯方块,就是因为它是游戏。
之前我是玩过俄罗斯方块的,一种是单人的(单人版),一种是两人对战的(对战版),还有一种是网络版的,由于我还不了解网络,所以就决定编前两种。
可是,这样没有新意,我就想到了另外一种,配合游戏,或者称为情侣版。
这里我先介绍三种,而网络版,由于我们将介绍五子棋的网络游戏,鉴于它的简单性,我们将不介绍。
说明:
以下三部分,可以以三章看待。
一、单人版
1、游戏实现
俄罗斯方块,或称积木游戏,它是利用一些形状各异却又是用正方形组成的方块,经过不同位置不同角度的变化之后,堆积在一起的一种智力游戏。
而从我们编程的角度讲,我们只需要提供各种方块的图形,提供几个键盘操作键以供方块的形状和位置的变化,提供几个功能函数以供游戏的正常进行。
各种方块图形:
利用数组定形,然后利用随机函数随机地不按顺序地按游戏的需要而出现。
键盘操作键:
就是四个方向键。
其中左、右、下三个键意思一样,上键的功能不是使方块向上,而是使方块的下落角度改变。
功能函数将在变量函数里面介绍。
新建单文档工程4_1。
2、资源编辑
添加位图:
封面:
IDB_BITMAP1
背景:
IDB_BITMAP2
方块:
IDB_BITMAP4
添加菜单:
开始:
ID_MENU_START
3、变量函数
接着就是定义变量了,但是,由于这个游戏要添加的变量和函数太多了,我们要建一个新类。
是否应该先添加应该类呢?
最好是这样。
因为新类将会涉及到变量。
添加普通类Crussia,见下图。
图4-1-1
添加变量函数:
由于两个类一共有很多变量函数,列举如下:
//4_1View.h:
//俄罗斯类
CRussiarussia;
//开始标志
boolstart;
//封面
CBitmapfenmian;
//暂停
BOOLm_bPause;
//开始菜单
afx_msgvoidOnMenuStart();
//计时器
afx_msgvoidOnTimer(UINTnIDEvent);
//键盘操作
afx_msgvoidOnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags);
//Russia.h:
//游戏数组
intRussia[100][100];
//当前图形
intNow[4][4];
//上一图形
intWill[4][4];
//变换后的图形
intAfter[4][4];
//当前图形的左上角位置
CPointNowPosition;
//当前可能出现的图形形状数,
intCount;
//游戏结束
boolend;
//级别
intm_Level;
//速度
intm_Speed;
//分数
intm_Score;
//行列数
intm_RowCount,m_ColCount;
//方块
CBitmapfangkuai;
//背景
CBitmapjiemian;
//显示分数等内容
voidDrawScore(CDC*pDC);
//消行
voidLineDelete();
//方块移动
voidMove(intdirection);
//方块变化,即方向键上键操作
boolChange(inta[][4],CPointp,intb[][100]);
//是否与原来方块接触,或与边界接触
boolMeet(inta[][4],intdirection,CPointp);
//显示下一个方块
voidDrawWill();
//显示界面
voidDrawJiemian(CDC*pDC);
//开始
voidStart();
4、具体实现
然后,我们就可以一步一步地实现游戏了。
函数依然是一个一个添加,如果有还没定义的函数,添加空函数。
以保证程序的条理性和可运行性。
构造函数:
CMy4_1View:
:
CMy4_1View()
{
//TODO:
addconstructioncodehere
fenmian.LoadBitmap(IDB_BITMAP1);
start=false;
m_bPause=false;
}
CRussia:
:
CRussia()
{
jiemian.LoadBitmap(IDB_BITMAP2);
fangkuai.LoadBitmap(IDB_BITMAP4);
}
画图函数:
voidCMy4_1View:
:
OnDraw(CDC*pDC)
{
CMy4_1Doc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
CDCDc;
if(Dc.CreateCompatibleDC(pDC)==FALSE)
AfxMessageBox("Can'tcreateDC");
//没有开始,显示封面
if(!
start)
{
Dc.SelectObject(fenmian);
pDC->BitBlt(0,0,500,550,&Dc,0,0,SRCCOPY);
}
//显示背景
else
russia.DrawJiemian(pDC);
}
开始时我们是设start为假,它就会在OnDraw()函数中画封面,而当我们开始游戏,start为真,那么,它干什么呢?
画背景!
其函数如下:
界面函数:
还是那个道理,当有一些客户区生效(被挡住或最小化)时,它必须重画,而如果游戏只是玩了一半,它必然在重画时必须把原先已经出现的方块、分数等也显示出来,怎么办?
就必须在画封面的同时也画出它们。
当然,刚开始时它们是不会符合条件的。
voidCRussia:
:
DrawJiemian(CDC*pDC)
{
CDCDc;
if(Dc.CreateCompatibleDC(pDC)==FALSE)
AfxMessageBox("Can'tcreateDC");
//画背景
Dc.SelectObject(jiemian);
pDC->BitBlt(0,0,500,550,&Dc,0,0,SRCCOPY);
//画分数,速度,难度
DrawScore(pDC);
//如果有方块,显示方块
//游戏区
for(inti=0;ifor(intj=0;jif(Russia[i][j]==1)
{
Dc.SelectObject(fangkuai);
pDC->BitBlt(j*30,i*30,30,30,&Dc,0,0,SRCCOPY);
}
//预先图形方块
for(intn=0;n<4;n++)
for(intm=0;m<4;m++)
if(Will[n][m]==1)
{
Dc.SelectObject(fangkuai);
pDC->BitBlt(365+m*30,240+n*30,30,30,&Dc,0,0,SRCCOPY);
}
}
信息函数:
其中还涉及另外一个函数DrawScore(pDC),它是画分数、速度、难度(本程序省略)的。
由于它的代码不是太少,另外用了一个函数,这样有利于理解。
voidCRussia:
:
DrawScore(CDC*pDC)
{
intnOldDC=pDC->SaveDC();
//设置字体
CFontfont;
if(0==font.CreatePointFont(300,"ComicSansMS"))
{
AfxMessageBox("Can'tCreateFont");
}
pDC->SelectObject(&font);
//设置字体颜色及其背景颜色
CStringstr;
pDC->SetTextColor(RGB(39,244,10));
pDC->SetBkColor(RGB(255,255,0));
//输出数字
str.Format("%d",m_Level);
if(m_Level>=0)
pDC->TextOut(440,120,str);
str.Format("%d",m_Speed);
if(m_Speed>=0)
pDC->TextOut(440,64,str);
str.Format("%d",m_Score);
if(m_Score>=0)
pDC->TextOut(440,2,str);
pDC->RestoreDC(nOldDC);
}
至此,可以看的都画完了。
程序一般都是会先处理图形界面,因为这样在编核心内容时能够让人有一个检查的机会。
菜单开始函数:
现在,游戏总该开始了吧。
添加菜单开始函数:
ID_MENU_START
其函数如下:
voidCMy4_1View:
:
OnMenuStart()
{
//TODO:
Addyourcommandhandlercodehere
start=true;
russia.Start();
SetTimer(1,50*(11-russia.m_Speed),NULL);
}
先把start赋值为true,再调用russia.Start()函数,让它对俄罗斯方块游戏的相应变量赋值,为了使游戏能够调整速度,设置一个可变的计数器。
那么,russia.Start()函数做了什么呢?
开始函数:
voidCRussia:
:
Start()
{
end=false;//运行结束标志
m_Score=0;//初始分数
m_Speed=0;//初始速度
m_Level=1;//初始难度
m_RowCount=18;//行数
m_ColCount=12;//列数
Count=7;//方块种类
//清空背景数组
for(inti=0;ifor(intj=0;j{
Russia[i][j]=0;
}
//清空方块数组Now[][]Will[][]
for(i=0;i<4;i++)
for(intj=0;j<4;j++)
{
Now[i][j]=0;
Will[i][j]=0;
}
//先画Will[][]
DrawWill();
//再画Now[][]&Will[][]
DrawWill();
}
预备方块:
DrawWill()的作用是,把预备方块给当前方块,再生成一个预备方块。
由于开始时预备方块自己都没有