您的位置:首页 > 其它

vc项目开发:俄罗斯方块制作日志 [上]

2010-10-21 22:15 393 查看
vc项目日志,俄罗斯方块开发

----July

mfc初学一个月时,所写的俄罗斯方块。共享下源码。

July、2010/10/21

-------------------------------------------------------------

此为View.h文件

/*-------------------------------------
View.h文件
July\2010、10月
--------------------------------------*/

// skyjuly_RecTTView.h : interface of the CSkyjuly_RecTTView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_SKYJULY_RECTTVIEW_H__BBD13113_594E_4BE6_9DA5_1DAE3EC53ED8__INCLUDED_)
#define AFX_SKYJULY_RECTTVIEW_H__BBD13113_594E_4BE6_9DA5_1DAE3EC53ED8__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// 宏变量:白色和黑色
#define WHITE RGB(255,255,255)
#define BLACK RGB(0,0,0)
#define BLUE RGB(0,0,255)

//中断操作的运动趋势
#define LEFT  0      //向左移动
#define RIGHT 1      //向左移动
#define UP    2		//向上(变形)
#define DOWN  3      //向下移动(加速)

//游戏区域地图最大限制
#define  MAX_ROW    100     //地图的最大行数
#define  MAX_COL    100      //地图的最大列数

//地图状态
#define MAP_STATE_EMPTY             0    //空(未被占据)
#define MAP_STATE_NOT_EMPTY         1    //被占据

class CSkyjuly_RecTTView : public CView
{
protected: // create from serialization only
CSkyjuly_RecTTView();
DECLARE_DYNCREATE(CSkyjuly_RecTTView)

// Attributes
public:
CSkyjuly_RecTTDoc* GetDocument();

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSkyblue_RectView)
public:
virtual void OnDraw(CDC* pDC);  // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CSkyjuly_RecTTView();

protected:
int m_nWidth;  //子窗口的宽度
int m_nHeight; //子窗口的高度

//列与行的数量
int m_iCol;
int m_iRow;

//小方块的大小,它会随着行与列的不同而不同,具体为:
// 12行10列,30个象素的正方形
// 18行15列,20
// 24行20列,15
// 30行25列,12
int m_iLarge;

//当前的级别,换算成速度的算法为:1500 - m_iLevel*200
int m_iLevel;
//当前选择的方块显示样式
int m_iBlockSytle;

//游戏区域左上角的坐标
int m_iStartX;
int m_iStartY;

BOOL IsLeftLimit();       //下坠物件是否可向左移动
BOOL IsRightLimit();

//接触面二维数组,记录1~7种下坠物的1~4种形态的接触面信息
//我们把该下坠物的某种形态种的4个方块,有接触面则记录方位,无则为-1标识。
int InterFace[74][4];

//当前的方块形状
int m_currentRect;

//判断当前方块是否到底

void IsBottom();
//当前方块下降
void RectDown();

//当前方块加速:UP,左移:LEFT,右移:RIGHT
void RectArrow(int m_Type);

//根据下坠物的类型映射出它的具体形态  功能组
//根据旧的下一下坠物映射出当前激活状态下的下坠物形态
void RectStatusToActiveStatus(int m_which);
//根据下坠物形态映射出下一下坠物的形态
void RectStatusToNextStatus(int m_which);
//将当前的状态映射到地图游戏区域
void ActiveStatusToGameStatus();

int Random(int MaxNumber);
//标识方块已到底的变量,到底为TRUE
BOOL m_isBottom;

//用于标志方块状态的数组,大小由横格与竖格数据决定,为1表示该方块显示,或者不显示
//画形状只需要修改数组中相应元素的状态值即可
//由时钟控制,定时在OnPaint函数中根据数组画方块
int GameStatus[MAX_ROW][MAX_COL];

//用于保存当前方块的动态位置,4个小方块分别在大数组中的位置
//存放位置为先左后右,每一列又遵循先上后下的原则
int ActiveStatus[4][2];

//存入下一次要出来的方块的模样的数组
int NextStatus[4][2];

// Generated message map functions
protected:
BOOL m_bGamePaush;
void StopMid();
void PlayMid();
void CurrentAreaAndLevel();
//用于记录当前区域大小与当前级别的字符串,用于显示在屏幕上提示用户当前状态
CString m_strArea;
CString m_strLevel;

//当前的样式 ,下一个将会出现的样式
int m_icurrentStatus;
int m_inextStatus;

//OnDraw中需要用到的设备名称
CPen *m_pBlackPen;
CBrush *m_pGrayBrush;
CBrush *m_pBlackBrush;

//是否画网格线
BOOL m_bDrawGrid;

//是否插放背景音乐
BOOL m_bMusic;

//游戏总成绩
int m_iPerformance;

//游戏是否已结束,为FALSE表示开始,否则为结束
BOOL m_bGameEnd;

//刷新指定的区域,它的大小为:四个小方块所在的正方形的大小
void InvalidateCurrent();

//内存绘图设备的处理
CDC m_memDC;                   //内存设备环境
CBitmap m_memBmp;              //内存位图

CDC m_memRectDC;       //方块内存设备环境
HBITMAP m_hMemRectBmp;  //方块内存位图句柄

int m_bFistPlay;               //是否是第一次开始游戏
void DcEnvInitial(void);
void DCEnvClear(void);
void DrawGame(CDC *pDC);

// Generated message map functions
protected:
void RectChange();
//{{AFX_MSG(CSkyjuly_RecTTView)
afx_msg void OnGameStart();
afx_msg void OnGamePaush();
afx_msg void OnGameEnd();
afx_msg void OnGameExit();
afx_msg void OnGameOption();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

#ifndef _DEBUG  // debug version in skyjuly_RecTTView.cpp
inline CSkyjuly_RecTTDoc* CSkyjuly_RecTTView::GetDocument()
{ return (CSkyjuly_RecTTDoc*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_SKYJULY_RECTTVIEW_H__BBD13113_594E_4BE6_9DA5_1DAE3EC53ED8__INCLUDED_)


以下为View.cpp文件。

/*--------------------------------------
View.cpp文件。
July、2010/10月
--------------------------------------*/

// skyjuly_RecTTView.cpp : implementation of the CSkyjuly_RecTTView class
//

#include "stdafx.h"
#include "skyjuly_RecTT.h"

#include "skyjuly_RecTTDoc.h"
#include "skyjuly_RecTTView.h"
#include "OptionDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSkyjuly_RecTTView

IMPLEMENT_DYNCREATE(CSkyjuly_RecTTView, CView)

BEGIN_MESSAGE_MAP(CSkyjuly_RecTTView, CView)
//{{AFX_MSG_MAP(CSkyjuly_RecTTView)
ON_COMMAND(ID_GAME_START, OnGameStart)
ON_COMMAND(ID_GAME_PAUSH, OnGamePaush)
ON_COMMAND(ID_GAME_END, OnGameEnd)
ON_COMMAND(ID_GAME_EXIT, OnGameExit)
ON_COMMAND(ID_GAME_OPTION, OnGameOption)
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSkyjuly_RecTTView construction/destruction

CSkyjuly_RecTTView::CSkyjuly_RecTTView()
{
// TODO: add construction code here
//第一次开始游戏
m_bFistPlay = TRUE;

//缺省为不是游戏暂停状态
m_bGamePaush = FALSE;

//缺省为不插放背景音乐
m_bMusic = FALSE;

//缺省为画网格线
m_bDrawGrid = TRUE;

//总分值清零
m_iPerformance = 0;

//测试值:为12行,10列
m_iRow = 12;
m_iCol = 10;

//左上角X,Y坐标
m_iStartX = 10;
m_iStartY = 10;

//缺省级别为3级
m_iLevel = 2;
//第一种样式
m_iBlockSytle = 0;

//缺省方块大小为m_iLarge个象素
m_iLarge = 30;

//缺省游戏是结束的
m_bGameEnd = TRUE;

int i,j;

//赋初值
for (i=0;i<100;i++)
for (j=0;j<100;j++)
GameStatus[i][j]=0;

//各种形状方块的接触面数据,参见设计书的接触面表格,
//如果某种形状的方块没有4个接触面,则后面的数据填-1
for (i=0;i<74;i++)
for (j=0;j<4;j++)
InterFace[i][j] = -1;
/*
1  ----
*/
InterFace[1][0] = 3;

InterFace[11][0] = 0;	InterFace[11][1] = 1;	InterFace[11][2] = 2;	InterFace[11][3] = 3;
/*
2	--
--
*/
InterFace[2][0] = 1;	InterFace[2][1] = 3;
/*
3   -
---

*/
InterFace[3][0] = 0;	InterFace[3][1] = 2;	InterFace[3][2] = 3;

InterFace[31][0] = 2;	InterFace[31][1] = 3;

InterFace[32][0] = 0;	InterFace[32][1] = 2;	InterFace[32][2] = 3;

InterFace[33][0] = 0;	InterFace[33][1] = 3;
/*
4  --
--
*/
InterFace[4][0] = 1;	InterFace[4][1] = 3;

InterFace[41][0] = 0;	InterFace[41][1] = 2;	InterFace[41][2] = 3;
/*
5  --
--
*/
InterFace[5][0] = 1;	InterFace[5][1] = 3;

InterFace[51][0] = 0;	InterFace[51][1] = 2;	InterFace[51][2] = 3;
/*
6  --
-
-
*/
InterFace[6][0] = 0;	InterFace[6][1] = 3;

InterFace[61][0] = 1;	InterFace[61][1] = 2;	InterFace[61][2] = 3;

InterFace[62][0] = 2;	InterFace[62][1] = 3;

InterFace[63][0] = 0;	InterFace[63][1] = 1;	InterFace[63][2] = 3;
/*
7  --
-
-
*/
InterFace[7][0] = 2;	InterFace[7][1] = 3;
InterFace[71][0] = 1;	InterFace[71][1] = 2;	InterFace[71][2] = 3;

InterFace[72][0] = 0;	InterFace[72][1] = 3;

InterFace[73][0] = 0;	InterFace[73][1] = 1;	InterFace[73][2] = 3;

}

CSkyjuly_RecTTView::~CSkyjuly_RecTTView()
{
}

BOOL CSkyjuly_RecTTView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
//  the CREATESTRUCT cs

return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CSkyjuly_RecTTView drawing

void CSkyjuly_RecTTView::OnDraw(CDC* pDC)
{
/*CSkyjuly_RecTTDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);*/
// TODO: add draw code for native data here
DcEnvInitial();
DrawGame(&m_memDC);  //在内存位图的游戏区域绘制

pDC->BitBlt(0,0,m_nWidth,m_nHeight,&m_memDC,0,0,SRCCOPY);
}

/////////////////////////////////////////////////////////////////////////////
// CSkyjuly_RecTTView diagnostics

#ifdef _DEBUG
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CSkyjuly_RecTTView message handlers

void CSkyjuly_RecTTView::OnGameStart()
{
// TODO: Add your command handler code here
if (!m_bGamePaush)  //如果不是游戏暂停状态,则必须作些初始工作
{
m_bGameEnd = FALSE;
//总分值清零, 并显示总分记分牌
m_iPerformance = 0;

//显示当前的区域及游戏级别的汉字描述
//	CurrentAreaAndLevel();

CRect rect(m_iStartY, m_iStartX, m_iStartY+440, m_iStartX+370);
InvalidateRect(&rect);
}

m_bGamePaush = FALSE;
SetTimer(1,1500-250*m_iLevel,NULL);

}

void CSkyjuly_RecTTView::OnGamePaush()
{
// TODO: Add your command handler code here
m_bGamePaush = TRUE;

KillTimer(1);

}

void CSkyjuly_RecTTView::OnGameEnd()
{
// TODO: Add your command handler code here
m_bGameEnd = TRUE;

int i,j;
for (i=0;i<m_iRow;i++)
for (j=0;j<m_iCol;j++)
GameStatus[i][j]=0;

CRect rect(m_iStartY, m_iStartX, m_iStartY+440, m_iStartX+370);
InvalidateRect(&rect);

m_bGamePaush = FALSE;  //清除游戏暂停状态

KillTimer(1);
}

void CSkyjuly_RecTTView::OnGameExit()
{
// TODO: Add your command handler code here

}

void CSkyjuly_RecTTView::OnGameOption()
{
// TODO: Add your command handler code here
//参数顺序: 区域大小代码:0-3,分别为:12X10,18X15,24X20,m_iLargeX25
//级别:0-5,分别为:1500,1200,1000,800,600,400
//背景音乐:TRUE 或者 FALSE
int m_lsArea;
/*	switch(m_iRow)
{
case 12:
m_lsArea = 0;
break;
case 18:
m_lsArea = 1;
break;
case 24:
m_lsArea = 2;
break;
case 30:
m_lsArea = 3;
break;
}*/

COptionDlg dlg(m_lsArea,m_iLevel,m_iBlockSytle,m_bMusic,m_bDrawGrid);

if (dlg.DoModal()==IDOK)
{
//确定区域的大小
/*	switch(dlg.m_iArea)
{
case 0:
m_iRow = 12;
m_iCol = 10;
m_iLarge = 30;
break;
case 1:
m_iRow = 18;
m_iCol = 15;
m_iLarge = 20;
break;
case 2:
m_iRow = 24;
m_iCol = 20;
m_iLarge = 15;
break;
case 3:
m_iRow = 30;
m_iCol = 25;
m_iLarge = 12;
break;
}

//确定级别
m_iLevel = dlg.m_iLevel;
//选择的样式
m_iBlockSytle = dlg.m_iBlockStyle;

//确定是否绘网格背景
m_bDrawGrid = dlg.m_bDrawGrid;

//检查是否插放音乐
m_bMusic = dlg.m_bMusic;
//	if (m_bMusic)
//			PlayMid();
//	else
//		StopMid();

Invalidate();*/
}

}

void CSkyjuly_RecTTView::DrawGame(CDC *pDC)
{
int i,j;
//选用黑色画刷,绘制整个游戏所在窗口的背景
pDC -> SelectObject(m_pBlackBrush);
CRect rect;
GetClientRect(&rect);
pDC -> Rectangle(rect);

//选用灰色画刷,绘制游戏区域的背景
pDC -> SelectObject(m_pGrayBrush);
pDC -> Rectangle(m_iStartY ,m_iStartX, m_iStartY + 301, m_iStartX + 360);

pDC->SelectObject(m_pBlackPen);
//画网格线
if (m_bDrawGrid)
{
//画横线
for (i=0;i<m_iRow;i++)
{
pDC->MoveTo(m_iStartY, m_iStartX + i*m_iLarge);
pDC->LineTo(m_iStartY+300, m_iStartX +i*m_iLarge);
}

//画竖线
for (i=0;i<m_iCol;i++)
{
pDC->MoveTo(m_iStartY+i*m_iLarge, m_iStartX);
pDC->LineTo(m_iStartY+i*m_iLarge, m_iStartX+360);
}
}

int x,y,nW,nH;

//小方块的绘制
for (i=0;i<m_iRow;i++)
for (j=0;j<m_iCol;j++)
{
if (GameStatus[i][j]==MAP_STATE_NOT_EMPTY)
{
//在游戏区域中状态为被占用状态的区域绘制小方块
x = m_iStartY+j*m_iLarge +2;
y = m_iStartX+i*m_iLarge +2;
nW = m_iLarge-4;
nH = m_iLarge-4;
pDC->BitBlt(x,y,nW,nH,&m_memRectDC,m_iBlockSytle*30,0,SRCCOPY);
}
}

//显示游戏区域及游戏级别的汉字描述
if (!m_bGameEnd)
{
pDC -> SetBkColor(BLACK);
pDC -> SetTextColor(WHITE);
pDC -> TextOut(m_iStartY+320, m_iStartX+220, "游戏区域大小:");
pDC -> TextOut(m_iStartY+320, m_iStartX+240,m_strArea);

pDC -> TextOut(m_iStartY+320, m_iStartX+280, "游戏级别:");
pDC -> TextOut(m_iStartY+320, m_iStartX+300,m_strLevel);
}

//显示总分
if (!m_bGameEnd)
{
CString lsStr;
lsStr.Format("总分为:%d 分",m_iPerformance);
pDC -> SetBkColor(BLACK);
pDC -> SetTextColor(WHITE);
pDC -> TextOut(m_iStartY+320, m_iStartX+180,lsStr);
}

//画下一次将要出现的方块,用于提示用户
if (!m_bGameEnd)
{
pDC -> SetBkColor(BLACK);
pDC -> SetTextColor(WHITE);
pDC -> TextOut(m_iStartY+320, m_iStartX,"下一个方块:");

int x,y,nW,nH;
for (UINT k=0;k<4;k++)
{
i = NextStatus[k][0];
j = NextStatus[k][1];

x = m_iStartY+j*30 +2+320;
y = m_iStartX+i*30 +2+30;
nW = m_iLarge-4;
nH = m_iLarge-4;
pDC->BitBlt(x,y,nW,nH,&m_memRectDC,m_iBlockSytle*30,0,SRCCOPY);
}
}

}

void CSkyjuly_RecTTView::DcEnvInitial()
{
if(m_bFistPlay)
{
m_bFistPlay = FALSE;
//用默认的参数,获取当前屏幕设备环境
CDC *pWindowDC = GetDC();

//1.用于映射屏幕的内存设备环境
//获取游戏窗口的大小用于下面设置内存位图的尺寸
CRect windowRect;
GetClientRect(&windowRect);
m_nWidth = windowRect.Width();
m_nHeight = windowRect.Height();

//内存设备环境与屏幕设备环境关联(兼容)
m_memDC.CreateCompatibleDC(pWindowDC);
//内存位图与与屏幕关联(兼容),大小为游戏窗口的尺寸
m_memBmp.CreateCompatibleBitmap(pWindowDC,m_nWidth,m_nHeight);
//内存设备环境与内存位图关联,以便通过m_memDC在内存位图上作画
m_memDC.SelectObject(&m_memBmp);

//2.存储方块位图的内存资源
//内存设备环境与屏幕设备环境关联(兼容)
m_memRectDC.CreateCompatibleDC(pWindowDC);
//相当于将外部位图rect.bmp动态载入m_hMemRectBmp中
m_hMemRectBmp=(HBITMAP)LoadImage(NULL,"rect.bmp",IMAGE_BITMAP,150,30,LR_LOADFROMFILE);
//内存设备环境与内存位图关联,以便通过m_memDC在内存位图上作画
SelectObject(m_memRectDC.m_hDC, m_hMemRectBmp);

//黑色的黑笔
m_pBlackPen  = new CPen(PS_SOLID,1,BLACK);

//画刷,
m_pGrayBrush  = new CBrush(RGB(0,60,0));
m_pBlackBrush  = new CBrush(BLACK);
}

}

void CSkyjuly_RecTTView::DCEnvClear()
{
//设备环境
m_memDC.DeleteDC();
m_memRectDC.DeleteDC();
//位图资源
DeleteObject(m_memBmp);
DeleteObject(m_hMemRectBmp);

delete(m_pBlackPen);
delete(m_pGrayBrush);
delete(m_pBlackBrush);
}

int CSkyjuly_RecTTView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;

//决定第一次掉下来的方块的样式
m_inextStatus = Random(7);

return 0;
}

int CSkyjuly_RecTTView::Random(int MaxNumber)
{
//部下随机种子
srand( (unsigned)time( NULL ) );
//产生随机数
int random = rand() % MaxNumber;

//保证非0
if(random == 0 )
random++;
return random;
}

void CSkyjuly_RecTTView::RectDown()
{
IsBottom();
if (!m_isBottom)
{
//清除以前的方块
int x1,x2,x3,x4,y1,y2,y3,y4;
x1 = ActiveStatus[0][0];
x2 = ActiveStatus[1][0];
x3 = ActiveStatus[2][0];
x4 = ActiveStatus[3][0];
y1 = ActiveStatus[0][1];
y2 = ActiveStatus[1][1];
y3 = ActiveStatus[2][1];
y4 = ActiveStatus[3][1];
GameStatus[x1][y1]=MAP_STATE_EMPTY;
GameStatus[x2][y2]=MAP_STATE_EMPTY;
GameStatus[x3][y3]=MAP_STATE_EMPTY;
GameStatus[x4][y4]=MAP_STATE_EMPTY;
InvalidateCurrent();

//方块下落
ActiveStatus[0][0] += 1;
ActiveStatus[1][0] += 1;
ActiveStatus[2][0] += 1;
ActiveStatus[3][0] += 1;
GameStatus[x1+1][y1]=MAP_STATE_NOT_EMPTY;
GameStatus[x2+1][y2]=MAP_STATE_NOT_EMPTY;
GameStatus[x3+1][y3]=MAP_STATE_NOT_EMPTY;
GameStatus[x4+1][y4]=MAP_STATE_NOT_EMPTY;

InvalidateCurrent();
}
}

void CSkyjuly_RecTTView::InvalidateCurrent()
{
int i;
for (i=0;i<4;i++)
{
CRect rect(m_iStartX+ActiveStatus[i][1]*m_iLarge,
m_iStartY+ActiveStatus[i][0]*m_iLarge,
m_iStartX+(ActiveStatus[i][1]+1)*m_iLarge+5,
m_iStartY+(ActiveStatus[i][0]+1)*m_iLarge);
//InvalidateRect(&rect);
Invalidate(FALSE);
}

}

void CSkyjuly_RecTTView::IsBottom()
{
//到底有两种概念:1是已到底部,2是下面碰到了另外的方块
int x1,x2,x3,x4;
int x,xx,yy,i;

x1 = ActiveStatus[0][0];
x2 = ActiveStatus[1][0];
x3 = ActiveStatus[2][0];
x4 = ActiveStatus[3][0];

//是否为底部的判断
//1。到达游戏区域的底部
//2。与接触面正下方的小方块区域为被占用状态
if (x1>=m_iRow-1 || x2>=m_iRow-1 || x3>=m_iRow-1 || x4>=m_iRow-1)
m_isBottom = TRUE;
else
{
for (i=0;i<4;i++)
{
if (InterFace[m_currentRect][i] > -1)
{//取当前下坠物有接触面的方块

//获取有接触面的小方块的编号
x=InterFace[m_currentRect][i];
//根据编号获取ActiveStatus中该小方块的整下方的坐标
xx=ActiveStatus[x][0]+1;
yy=ActiveStatus[x][1];
//判断该接触面整下方的小方块区域是否为被占用状态
if (GameStatus[xx][yy]==MAP_STATE_NOT_EMPTY)
m_isBottom = TRUE;
}
}
}

BOOL m_bIsSucced;
int k,j;
int m_iMuch=0; //本次销掉的行数

//计分规则:一次销掉一行,加100分,一次销掉两行,加400分,三行,900分
//例如销掉x行,则分数为:x*(x*100)

if (m_isBottom)
{
//判断是否已得分
for (i=0;i<m_iRow;i++)
{
m_bIsSucced = TRUE;
for (j=0;j<m_iCol;j++)
if (GameStatus[i][j]==MAP_STATE_EMPTY)
m_bIsSucced = FALSE;

//如果得分,则销掉此行
if (m_bIsSucced)
{
for (k=i;k>0;k--)
for (j=0;j<m_iCol;j++)
GameStatus[k][j] = GameStatus[k-1][j];
//第1行清零
for (j=0;j<m_iCol;j++)
GameStatus[0][j]=MAP_STATE_EMPTY;

m_iMuch += 1;
}
}

if (m_iMuch>0)
{
m_iPerformance += m_iMuch * m_iMuch * 100;
//刷新游戏区域
CRect rect1(m_iStartY, m_iStartX, m_iStartY+300, m_iStartX+360);
//InvalidateRect(&rect1);

//刷新分数区域
CRect rect2(m_iStartY+320, m_iStartX+180, m_iStartY+440, m_iStartX+200);
//InvalidateRect(&rect2);
Invalidate(FALSE);
}

}

}

//映射下一个方快,显示下一个降落的方块
void CSkyjuly_RecTTView::RectStatusToActiveStatus(int m_which)
{
switch(m_which)
{
case 1:
ActiveStatus[0][0] = 0;	ActiveStatus[0][1] = 5;	ActiveStatus[1][0] = 1;	ActiveStatus[1][1] = 5;
ActiveStatus[2][0] = 2;	ActiveStatus[2][1] = 5;	ActiveStatus[3][0] = 3;	ActiveStatus[3][1] = 5;
break;
case 2:
ActiveStatus[0][0] = 0;	ActiveStatus[0][1] = 5;	ActiveStatus[1][0] = 1;	ActiveStatus[1][1] = 5;
ActiveStatus[2][0] = 0;	ActiveStatus[2][1] = 6;	ActiveStatus[3][0] = 1;	ActiveStatus[3][1] = 6;
break;
case 3:
ActiveStatus[0][0] = 1;	ActiveStatus[0][1] = 4;	ActiveStatus[1][0] = 0;	ActiveStatus[1][1] = 5;
ActiveStatus[2][0] = 1;	ActiveStatus[2][1] = 5;	ActiveStatus[3][0] = 1;	ActiveStatus[3][1] = 6;
break;
case 4:
ActiveStatus[0][0] = 0;	ActiveStatus[0][1] = 5;	ActiveStatus[1][0] = 1;	ActiveStatus[1][1] = 5;
ActiveStatus[2][0] = 1;	ActiveStatus[2][1] = 6;	ActiveStatus[3][0] = 2;	ActiveStatus[3][1] = 6;
break;
case 5:
ActiveStatus[0][0] = 1;	ActiveStatus[0][1] = 5;	ActiveStatus[1][0] = 2;	ActiveStatus[1][1] = 5;
ActiveStatus[2][0] = 0;	ActiveStatus[2][1] = 6;	ActiveStatus[3][0] = 1;	ActiveStatus[3][1] = 6;
break;
case 6:
ActiveStatus[0][0] = 0;	ActiveStatus[0][1] = 5;	ActiveStatus[1][0] = 0;	ActiveStatus[1][1] = 6;
ActiveStatus[2][0] = 1;	ActiveStatus[2][1] = 6;	ActiveStatus[3][0] = 2;	ActiveStatus[3][1] = 6;
break;
case 7:
ActiveStatus[0][0] = 0;	ActiveStatus[0][1] = 5;	ActiveStatus[1][0] = 1;	ActiveStatus[1][1] = 5;
ActiveStatus[2][0] = 2;	ActiveStatus[2][1] = 5;	ActiveStatus[3][0] = 0;	ActiveStatus[3][1] = 6;
break;
}

}

void CSkyjuly_RecTTView::OnTimer(UINT nIDEvent)
{
//如果原来的方块已到底或游戏刚开始,则掉下一个新的方块
int i,j,k;
if (m_isBottom)
{
//1.产生下一个随机下坠物
m_icurrentStatus = m_inextStatus;
m_inextStatus = Random(7);  //得到下一次的方块样式
//	if (m_inextStatus==0) m_inextStatus++;

//2.修改新的“下一下坠物”
RectStatusToNextStatus( m_inextStatus );
//	CRect rect(m_iStartY+320, m_iStartX, m_iStartY+440, m_iStartX+160);
//	InvalidateRect(&rect);
//	Invalidate(FALSE);

//3.将旧的“下一下坠物”用作当前使用
m_currentRect = m_icurrentStatus;
//根据当前下坠物的形状去初始化激活状态下的下坠物坐标
RectStatusToActiveStatus( m_icurrentStatus );
//将当前动态数组中的数据反映到大数组中
ActiveStatusToGameStatus();
m_isBottom = FALSE;

//4.判断当前方块是否已到底
IsBottom();

//5.判断游戏是否已结束: 碰了底,且第1行有小方块
if (m_isBottom)
for (i=0;i<m_iCol;i++)
if (GameStatus[0][i])
{
KillTimer(1);
AfxMessageBox("游戏已结束!");
for (j=0;j<m_iRow;j++)
for (k=0;k<m_iCol;k++)
GameStatus[j][k]=0;
Invalidate(FALSE);
m_bGameEnd = TRUE;
break;
}

}
else  //当前方块下降
{
RectDown();
}
CView::OnTimer(nIDEvent);
}

void CSkyjuly_RecTTView::ActiveStatusToGameStatus()
{
int x1,x2,x3,x4,y1,y2,y3,y4;
x1 = ActiveStatus[0][0];
x2 = ActiveStatus[1][0];
x3 = ActiveStatus[2][0];
x4 = ActiveStatus[3][0];
y1 = ActiveStatus[0][1];
y2 = ActiveStatus[1][1];
y3 = ActiveStatus[2][1];
y4 = ActiveStatus[3][1];
GameStatus[x1][y1]=MAP_STATE_NOT_EMPTY;
GameStatus[x2][y2]=MAP_STATE_NOT_EMPTY;
GameStatus[x3][y3]=MAP_STATE_NOT_EMPTY;
GameStatus[x4][y4]=MAP_STATE_NOT_EMPTY;
}

void CSkyjuly_RecTTView::RectStatusToNextStatus(int m_which)
{
switch(m_which)
{
case 1:
NextStatus[0][0] = 0;	NextStatus[0][1] = 1;	NextStatus[1][0] = 1;	NextStatus[1][1] = 1;
NextStatus[2][0] = 2;	NextStatus[2][1] = 1;	NextStatus[3][0] = 3;	NextStatus[3][1] = 1;
break;
case 2:
NextStatus[0][0] = 0;	NextStatus[0][1] = 1;	NextStatus[1][0] = 1;	NextStatus[1][1] = 1;
NextStatus[2][0] = 0;	NextStatus[2][1] = 2;	NextStatus[3][0] = 1;	NextStatus[3][1] = 2;
break;
case 3:
NextStatus[0][0] = 1;	NextStatus[0][1] = 0;	NextStatus[1][0] = 0;	NextStatus[1][1] = 1;
NextStatus[2][0] = 1;	NextStatus[2][1] = 1;	NextStatus[3][0] = 1;	NextStatus[3][1] = 2;
break;
case 4:
NextStatus[0][0] = 0;	NextStatus[0][1] = 1;	NextStatus[1][0] = 1;	NextStatus[1][1] = 1;
NextStatus[2][0] = 1;	NextStatus[2][1] = 2;	NextStatus[3][0] = 2;	NextStatus[3][1] = 2;
break;
case 5:
NextStatus[0][0] = 1;	NextStatus[0][1] = 1;	NextStatus[1][0] = 2;	NextStatus[1][1] = 1;
NextStatus[2][0] = 0;	NextStatus[2][1] = 2;	NextStatus[3][0] = 1;	NextStatus[3][1] = 2;
break;
case 6:
NextStatus[0][0] = 0;	NextStatus[0][1] = 1;	NextStatus[1][0] = 0;	NextStatus[1][1] = 2;
NextStatus[2][0] = 1;	NextStatus[2][1] = 2;	NextStatus[3][0] = 2;	NextStatus[3][1] = 2;
break;
case 7:
NextStatus[0][0] = 0;	NextStatus[0][1] = 1;	NextStatus[1][0] = 1;	NextStatus[1][1] = 1;
NextStatus[2][0] = 2;	NextStatus[2][1] = 1;	NextStatus[3][0] = 0;	NextStatus[3][1] = 2;
break;
}

}

void CSkyjuly_RecTTView::RectArrow(int m_Type)
{
//获取当前下坠物4个小方块的位置坐标
int x1,x2,x3,x4,y1,y2,y3,y4;
x1 = ActiveStatus[0][0];
x2 = ActiveStatus[1][0];
x3 = ActiveStatus[2][0];
x4 = ActiveStatus[3][0];
y1 = ActiveStatus[0][1];
y2 = ActiveStatus[1][1];
y3 = ActiveStatus[2][1];
y4 = ActiveStatus[3][1];

//对不同的移动命令指示进行分类实现
switch(m_Type)
{
case LEFT:
//对每种不同的移动命令指示特性作相应的可移动分析
if ( (ActiveStatus[0][1]>0) && IsLeftLimit() && !m_isBottom)
{
//清原来的方块
GameStatus[x1][y1]=MAP_STATE_EMPTY;
GameStatus[x2][y2]=MAP_STATE_EMPTY;
GameStatus[x3][y3]=MAP_STATE_EMPTY;
GameStatus[x4][y4]=MAP_STATE_EMPTY;

//	InvalidateCurrent();
//添加新的移动后数据状态
ActiveStatus[0][1] -= 1;
ActiveStatus[1][1] -= 1;
ActiveStatus[2][1] -= 1;
ActiveStatus[3][1] -= 1;
GameStatus[x1][y1-1]=MAP_STATE_NOT_EMPTY;
GameStatus[x2][y2-1]=MAP_STATE_NOT_EMPTY;
GameStatus[x3][y3-1]=MAP_STATE_NOT_EMPTY;
GameStatus[x4][y4-1]=MAP_STATE_NOT_EMPTY;

InvalidateCurrent();
}
break;

case RIGHT:
if ( (ActiveStatus[3][1]< m_iCol-1) && IsRightLimit() && !m_isBottom)
{
//清原来的方块
GameStatus[x1][y1]=MAP_STATE_EMPTY;
GameStatus[x2][y2]=MAP_STATE_EMPTY;
GameStatus[x3][y3]=MAP_STATE_EMPTY;
GameStatus[x4][y4]=MAP_STATE_EMPTY;

//	InvalidateCurrent();
//添加新的移动后数据状态
ActiveStatus[0][1] += 1;
ActiveStatus[1][1] += 1;
ActiveStatus[2][1] += 1;
ActiveStatus[3][1] += 1;
GameStatus[x1][y1+1]=MAP_STATE_NOT_EMPTY;
GameStatus[x2][y2+1]=MAP_STATE_NOT_EMPTY;
GameStatus[x3][y3+1]=MAP_STATE_NOT_EMPTY;
GameStatus[x4][y4+1]=MAP_STATE_NOT_EMPTY;

InvalidateCurrent();
}
break;

case DOWN:
RectDown();
break;
}
}

void CSkyjuly_RecTTView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch(nChar)
{
case VK_LEFT:
RectArrow(LEFT);
break;
case VK_RIGHT:
RectArrow(RIGHT);
break;
case VK_UP:
RectChange();
break;
case VK_DOWN:
RectArrow(DOWN);
break;
}

CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

BOOL CSkyjuly_RecTTView::IsLeftLimit()
{
int x1,x2,x3,x4,y1,y2,y3,y4;
x1 = ActiveStatus[0][0];
x2 = ActiveStatus[1][0];
x3 = ActiveStatus[2][0];
x4 = ActiveStatus[3][0];
y1 = ActiveStatus[0][1];
y2 = ActiveStatus[1][1];
y3 = ActiveStatus[2][1];
y4 = ActiveStatus[3][1];

//根据当前下坠物的具体形态,分析判断其是否有向左移动的空间
switch(m_currentRect)
{
// "1"字形形态类型,判断其四个方块的正左边都没有任何物件(空间没有被占据)
case 1:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1] || GameStatus[x4][y4-1])
return FALSE;
break;
case 11:
if (GameStatus[x1][y1-1])
return FALSE;
break;
case 2:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1])
return FALSE;
break;
case 3:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1])
return FALSE;
break;
case 31:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1])
return FALSE;
break;
case 32:
if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1])
return FALSE;
break;
case 33:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x4][y4-1])
return FALSE;
break;
case 4:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x4][y4-1])
return FALSE;
break;
case 41:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1])
return FALSE;
break;
case 5:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1])
return FALSE;
break;
case 51:
if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1])
return FALSE;
break;
case 6:
if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1] || GameStatus[x4][y4-1])
return FALSE;
break;
case 61:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1])
return FALSE;
break;
case 62:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1])
return FALSE;
break;
case 63:
if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1])
return FALSE;
break;
case 7:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1])
return FALSE;
break;
case 71:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1])
return FALSE;
break;
case 72:
if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1])
return FALSE;
break;
case 73:
if (GameStatus[x1][y1-1] || GameStatus[x4][y4-1])
return FALSE;
break;
}

return TRUE;

}

BOOL CSkyjuly_RecTTView::IsRightLimit()
{
int x1,x2,x3,x4,y1,y2,y3,y4;
x1 = ActiveStatus[0][0];
x2 = ActiveStatus[1][0];
x3 = ActiveStatus[2][0];
x4 = ActiveStatus[3][0];
y1 = ActiveStatus[0][1];
y2 = ActiveStatus[1][1];
y3 = ActiveStatus[2][1];
y4 = ActiveStatus[3][1];

switch(m_currentRect)
{
case 1:
if (GameStatus[x1][y1+1] || GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 11:
if (GameStatus[x4][y4+1])
return FALSE;
break;
case 2:
if (GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 3:
if (GameStatus[x2][y2+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 31:
if (GameStatus[x1][y1+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 32:
if (GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 33:
if (GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 4:
if (GameStatus[x1][y1+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 41:
if (GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 5:
if (GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 51:
if (GameStatus[x2][y2+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 6:
if (GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 61:
if (GameStatus[x2][y2+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 62:
if (GameStatus[x1][y1+1] || GameStatus[x2][y2+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 63:
if (GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 7:
if (GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 71:
if (GameStatus[x1][y1+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 72:
if (GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
case 73:
if (GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
return FALSE;
break;
}

return TRUE;

}

void CSkyjuly_RecTTView::RectChange()
{

//先预先变形,然后判断变形后的方块是否有空间,如有足够空间,则进行实际变形,否则不变
int xx1,xx2,xx3,xx4,yy1,yy2,yy3,yy4;
int m_lscurrentRect;

CString lsStr;

int x1,x2,x3,x4,y1,y2,y3,y4;
x1 = ActiveStatus[0][0];
x2 = ActiveStatus[1][0];
x3 = ActiveStatus[2][0];
x4 = ActiveStatus[3][0];
y1 = ActiveStatus[0][1];
y2 = ActiveStatus[1][1];
y3 = ActiveStatus[2][1];
y4 = ActiveStatus[3][1];

//变形后位置在数组中的存放顺序仍需遵循先左后右,在同一列中先上后下
xx1=x1; xx2=x2; xx3=x3; xx4=x4; yy1=y1; yy2=y2; yy3=y3; yy4=y4;
switch(m_currentRect)
{
case 1:
xx1=x1+1; yy1=y1-1; xx3=x3-1; yy3=y3+1; xx4=x4-2; yy4=y4+2;
m_lscurrentRect = 11;
break;
case 11:
xx1=x1-1; yy1=y1+1; xx3=x3+1; yy3=y3-1; xx4=x4+2; yy4=y4-2;
m_lscurrentRect = 1;
break;
case 2:
m_lscurrentRect=2;
break;
case 3:
xx1=x1-2; yy1=y1+1; xx4=x4-1; yy4=y4;
m_lscurrentRect = 31;
break;
case 31:
xx1=x1+1; yy1=y1-1;
m_lscurrentRect = 32;
break;
case 32:
xx1=x1+1; yy1=y1; xx4=x4+2; yy4=y4-1;
m_lscurrentRect=33;
break;
case 33:
xx4=x4-1; yy4=y4+1;
m_lscurrentRect=3;
break;
case 4:
xx1=x1+2; yy1=y1-1; xx3=x3+1; yy3=y3-1; xx4=x4-1;
m_lscurrentRect = 41;
break;
case 41:
xx1=x1-2; yy1=y1+1; xx3=x3-1; yy3=y3+1; xx4=x4+1;
m_lscurrentRect = 4;
break;
case 5:
xx1=x1-1; xx2=x2-2; yy2=y2+1; xx3=x3+1; yy4=y4+1;
m_lscurrentRect = 51;
break;
case 51:
xx1=x1+1; xx2=x2+2; yy2=y2-1; xx3=x3-1; yy4=y4-1;
m_lscurrentRect = 5;
break;
case 6:
xx2=x1+1; yy2=y2-1; xx3=x3-1; xx4=x4-2; yy4 = yy4+1;
m_lscurrentRect = 61;
break;
case 61:
xx3=x3+2; yy3=y3-1; xx4=x4+2; yy4=y4-1;
m_lscurrentRect = 62;
break;
case 62:
xx1=x1+1; yy1=y1-1; xx3=x3-2; yy3=y3+1; xx4=x4-1;
m_lscurrentRect = 63;
break;
case 63:
xx1=x1-2; yy1=y1+1; xx2=x2-2; yy2=y2+1;
m_lscurrentRect = 6;
break;
case 7:
xx3=x3-1; yy3=y3+1; xx4=x4+1; yy4=y4+1;
m_lscurrentRect = 71;
break;
case 71:
xx1=x1+2; xx2=x2-1; yy2=y2+1; xx4=x4+1; yy4=y4-1;
m_lscurrentRect = 72;
break;
case 72:
xx1=x1-2; xx3=x3-1; yy3=y3+1; xx4=x4-1; yy4=y4+1;
m_lscurrentRect = 73;
break;
case 73:
xx2=x2+1; yy2=y2-1; xx3=x3+2; yy3=y3-2; xx4=x4-1; yy4=y4-1;
m_lscurrentRect = 7;
break;
}

//如果变形后所在的区域内无其他方块,则表示有足够空间,可以变形
//且不能超越边界
GameStatus[x1][y1] = MAP_STATE_EMPTY;
GameStatus[x2][y2] = MAP_STATE_EMPTY;
GameStatus[x3][y3] = MAP_STATE_EMPTY;
GameStatus[x4][y4] = MAP_STATE_EMPTY;
if (GameStatus[xx1][yy1]==MAP_STATE_EMPTY &&
GameStatus[xx2][yy2]==MAP_STATE_EMPTY &&
GameStatus[xx3][yy3]==MAP_STATE_EMPTY &&
GameStatus[xx4][yy4]==MAP_STATE_EMPTY
&& yy1>=0 && yy4<=m_iCol-1
&& !(xx1<0 || xx2<0 || xx3<0 || xx4<0)
&& !(xx1>m_iRow-1 || xx2>m_iRow-1 || xx3>m_iRow-1 || xx4>m_iRow-1) )
{
InvalidateCurrent();

ActiveStatus[0][0]=xx1;
ActiveStatus[1][0]=xx2;
ActiveStatus[2][0]=xx3;
ActiveStatus[3][0]=xx4;
ActiveStatus[0][1]=yy1;
ActiveStatus[1][1]=yy2;
ActiveStatus[2][1]=yy3;
ActiveStatus[3][1]=yy4;

GameStatus[xx1][yy1] = MAP_STATE_NOT_EMPTY;
GameStatus[xx2][yy2] = MAP_STATE_NOT_EMPTY;
GameStatus[xx3][yy3] = MAP_STATE_NOT_EMPTY;
GameStatus[xx4][yy4] = MAP_STATE_NOT_EMPTY;

InvalidateCurrent();

//改变形状代码
m_currentRect = m_lscurrentRect;
}
else
{//恢复原来状态
GameStatus[x1][y1] = MAP_STATE_NOT_EMPTY;
GameStatus[x2][y2] = MAP_STATE_NOT_EMPTY;
GameStatus[x3][y3] = MAP_STATE_NOT_EMPTY;
GameStatus[x4][y4] = MAP_STATE_NOT_EMPTY;
}

//判断是否已到底
IsBottom();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: