C++编写俄罗斯方块游戏

http://www.doc88.com/p-46113659969.html


头文件:

#if !defined(AFX_WNDMAIN_H__143E8EA9_9690_4B57_A53F_95071AE2ECB8__INCLUDED_)
#define AFX_WNDMAIN_H__143E8EA9_9690_4B57_A53F_95071AE2ECB8__INCLUDED_


#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// WndMain.h : header file
//


#include "DlgMain.h"


/
// CWndMain window


class CWndMain : public CWnd
{
// Construction
public:
CWndMain();


// Attributes
public:
//画网格线
void DrawLine(CDC* pDC);
//位图,方块
void DrawSquBmp(CDC* pDC);
//预备方块
void DrawWill();
//游戏开始
void Start();
//移动的方向
bool MoveDir(int direction);
//控制越界
bool Meet(int a[][4], int direction, CPoint p);
//方块变换
bool Change(int a[][4], CPoint p, int b[][100]);
//检查要不要消行
void LineDelete();
                 
//难度级别
void GameLevel(int level);

//显示位图
CBitmap m_bitmap;


//背景画刷
CBrush* BGBrush;
//网格区域画刷
CBrush* GridBrush;
//方格的画刷
CBrush* SquareBrush;
//画笔
CPen* penGrid;
CPen* penSquare;
//状态显示所用的字体
CFont m_font;
//字幕字体描述
LOGFONT m_lf;


//游戏区域左上角坐标
int m_startX;
int m_startY;
int m_col;
int m_row;
//大数组
int Russian[100][100];  
//4*4的大方格,小数组
int GameSquare[4][4];
int GameSquWill[4][4];
int GameSquAfter[4][4];


//当前可能出现的图形形状数
int Count;
//开始的标志
BOOL m_Start;
//暂停的标志
BOOL m_Pause;
//游戏结束
BOOL m_End;
//当前图形的左上角位置
CPoint NowPosition;
//级数
int m_Level;
//分数
int m_Score;
//速度
int m_Speed;


int m_nYIndex;
int m_nXIndex;
int nx, ny;
int cx, cy;
int m_nIndex[4][2];
//定时器
int m_nTimer;






// Operations
public:


// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWndMain)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
//}}AFX_VIRTUAL


// Implementation
public:
virtual ~CWndMain();


// Generated message map functions
protected:
//{{AFX_MSG(CWndMain)
afx_msg void OnPaint();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnDestroy();
afx_msg void OnOptionLevel1();
afx_msg void OnOptionLevel2();
afx_msg void OnOptionLevel3();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};


extern CWndMain g_wndMain;


/


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


#endif // !defined(AFX_WNDMAIN_H__143E8EA9_9690_4B57_A53F_95071AE2ECB8__INCLUDED_)


源文件:

// WndMain.cpp : implementation file
//


#include "stdafx.h"
#include "Russian.h"
#include "WndMain.h"


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


CWndMain g_wndMain;


/
// CWndMain


CWndMain::CWndMain()
{
m_startX = 0;
m_startY = 0;
m_col    = 14;
m_row = 20;

Count = 7;
m_Start = FALSE;
m_Pause = FALSE;
// NowPosition.x = 0;
// NowPosition.y = 0;
     m_Level = 1;
m_Score = 0;
m_Speed = 20;

m_nYIndex = 0;
m_nXIndex = 0;
m_nTimer = -1;


int i, j;
for (i=0; i<100; i++)
{
for(j=0; j<100; j++)
{
Russian[i][j] = 0;
}
}


//4*4的大方格,数组值初始化为0
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
GameSquare[i][j] = 0;
}
}


for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
GameSquWill[i][j] = 0;
}
}


for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
GameSquAfter[i][j] = 0;
}
}


for (i=0; i<4; i++)
{
for (j=0; j<2; j++)
{
m_nIndex[i][j] = 0;
}
}
}


CWndMain::~CWndMain()
{
}




BEGIN_MESSAGE_MAP(CWndMain, CWnd)
//{{AFX_MSG_MAP(CWndMain)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_SIZE()
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_KEYDOWN()
ON_WM_DESTROY()
ON_COMMAND(ID_OPTION_LEVEL1, OnOptionLevel1)
ON_COMMAND(ID_OPTION_LEVEL2, OnOptionLevel2)
ON_COMMAND(ID_OPTION_LEVEL3, OnOptionLevel3)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()




//sag///
// CWndMain mese handlers




BOOL CWndMain::OnEraseBkgnd(CDC* pDC) 
{
// CRect rc;
// GetClientRect(rc);
// pDC->FillSolidRect(rc, RGB(192, 192, 192));


return CWnd::OnEraseBkgnd(pDC);
}


int CWndMain::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;


memset(&m_lf, 0, sizeof(m_lf));
m_lf.lfHeight = 18;
m_lf.lfWidth  = 9;
m_lf.lfEscapement = 0;
m_lf.lfOrientation = 0;
m_lf.lfWeight = FW_NORMAL;
m_lf.lfItalic = FALSE;
m_lf.lfUnderline = FALSE;
m_lf.lfStrikeOut = FALSE;
m_lf.lfCharSet = GB2312_CHARSET;
m_lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
m_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
m_lf.lfQuality = DEFAULT_QUALITY;
m_lf.lfPitchAndFamily = DEFAULT_PITCH | FF_ROMAN;
strncpy(m_lf.lfFaceName, "宋体", LF_FACESIZE - 1);
m_lf.lfFaceName[LF_FACESIZE - 1] = 0;


return 0;
}
void CWndMain::OnDestroy() 
{
if (m_bitmap.m_hObject)
{
m_bitmap.DeleteObject();
}


CWnd::OnDestroy();
}


void CWndMain::OnPaint() 
{
CPaintDC dc(this); // device context for painting


DrawLine(&dc);


DrawSquBmp(&dc);


// Do not call CWnd::OnPaint() for painting messages
}




void CWndMain::OnSize(UINT nType, int cx, int cy) 
{
CWnd::OnSize(nType, cx, cy);


}


void CWndMain::DrawLine(CDC* pDC)
{
int i, j;
CRect rc;
GetClientRect(rc);
if (rc.Width() <= 0)
return;


//如位图不够大,则重新申请
if (m_bitmap.m_hObject)
{
BITMAP info;
m_bitmap.GetBitmap(&info);
//释放原来的小位图
if (info.bmWidth<rc.Width() || info.bmHeight<rc.Height())
{
m_bitmap.DeleteObject();
}
}


//创建位图
if (m_bitmap.m_hObject == NULL)
{
m_bitmap.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());
}


//如果还没有创建显示所用的字体,则创建
if (m_font.m_hObject == NULL)
{
m_font.CreateFontIndirect(&m_lf);
}

//双缓冲
CDC dcTemp;
dcTemp.CreateCompatibleDC(pDC);


//设置显示方式
CBitmap* pOldBitmap= dcTemp.SelectObject(&m_bitmap);
COLORREF oldColor = dcTemp.SetTextColor(RGB(0, 255, 255));
int nOldMode = dcTemp.SetBkMode(TRANSPARENT);
CFont *pOldFont = dcTemp.SelectObject(&m_font);


//填充背景图为黑色
dcTemp.FillRect(rc, &CBrush(BLACK));

CRect rcLine;
rcLine.CopyRect(rc); 

// CPen penGrid(PS_SOLID, 1, PINK);
// CPen* pOldGrid = dcTemp.SelectObject(&penGrid);


//画笔类型
penGrid = new CPen(PS_SOLID, 1, PINK);
penSquare = new CPen(PS_SOLID, 1, YELLO);


//画刷类型
GridBrush = new CBrush(GREEN);
SquareBrush = new CBrush(BLUE);

dcTemp.SelectObject(GridBrush);
dcTemp.Rectangle(0, 0, 420, 600);


//网格线:设置为20行15列,行距为30
int dist = 30;
dcTemp.SelectObject(penGrid);
for (i=0; i<15; i++)
{
dcTemp.MoveTo(rc.left + i*dist, rc.top);
dcTemp.LineTo(rc.left + i*dist, rc.bottom);
// TRACE("网格线x=%d, 网格线y=%d\n", rc.left + i*dist, rc.top);
// TRACE("网格线x=%d, 网格线y=%d\n", rc.left + i*dist, rc.bottom);
}


for(j=0; j<20; j++)
{
dcTemp.MoveTo(rc.left, rc.top + j*dist);
dcTemp.LineTo(rc.right- 180 , rc.top + j*dist);
}


//画分数
CString str;
str.Format("总分为:%d分", m_Score);
if (m_Score>=0)
{
dcTemp.TextOut(450, 500, str);
}


pDC->BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &dcTemp, rc.left, rc.top, SRCCOPY);


dcTemp.SelectObject(pOldBitmap);
dcTemp.SelectObject(penGrid);
dcTemp.SelectObject(penSquare);
dcTemp.SelectObject(GridBrush);
dcTemp.SelectObject(SquareBrush);


dcTemp.DeleteDC();
}


void CWndMain:: DrawSquBmp(CDC* pDC)
{
if (m_Start == FALSE )
{
return;
}
//方块位图
CBitmap SquareBmp;


//加载方块位图
SquareBmp.LoadBitmap(IDB_BITMAP1);

CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC);


int i, j,   
k=0;


// for (i=0; i<4; i++)
// {
// nx = m_nIndex[i][0];
// ny = m_nIndex[i][1];
// Russian[nx][ny] = 0;
// }
// //将小数组赋值给大数组
// for (i=0; i<4; i++)
// {
// nx = NowPosition.x + i;
// for (j=0; j<4; j++)
// {
// ny = NowPosition.y + j;
// Russian[nx][ny] = GameSquWill[i][j];
// 
// if (GameSquWill[i][j] == 1)
// {
// m_nIndex[k][0] = nx;
// m_nIndex[k][1] = ny;
// k++;
// }
// }
// }


//如果有方块则显示方块,否则不显示
for ( i=0; i<m_row; i++ )
{
for ( j=0; j<m_col; j++)
{

if (Russian[i][j] == 1 )    
{
dcCompatible.SelectObject(&SquareBmp);

CRect rect;
GetClientRect(&rect);
pDC->BitBlt(j* 30+ 1, i*30 + 1, 30, 30, &dcCompatible, 0, 0, SRCCOPY);
TRACE("i = %d, j = %d\n", i, j);
}
}
}

//预先图形方块
for (int n=0; n<4; n++)
{
for (int m=0; m<4; m++)
{
if (GameSquWill[n][m] == 1)
{
dcCompatible.SelectObject(&SquareBmp);
pDC->BitBlt(450 + m*30, 50 +n*30, 30, 30, &dcCompatible, 0, 0, SRCCOPY);
TRACE("n = %d, m = %d\n", m, n);
}
}
}

}


void CWndMain::Start()
{
int i, j;


m_End = FALSE;


SetTimer(1, 500, NULL);


//清空背景数组
for (i=0; i<m_row; i++)
{
for (j=0; j<m_col; j++)
{
Russian[i][j] = 0;
}
}


//清空方块数组
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
GameSquare[i][j]  = 0;
GameSquWill[i][j] = 0;
}
}


DrawWill();
}


void CWndMain::DrawWill()
{
int i, j, k, l;
k = 4;
l = 4;


//把将要出现的方块给当前数组,并把将要出现数组赋值为零
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
GameSquare[i][j] = GameSquWill[i][j];
GameSquWill[i][j] = 0;
}
}




// //初始化随机数种子
  srand (GetTickCount());
  int nTemp = rand() % Count;


//各种图形
switch(nTemp)
{
case 0:
GameSquWill[0][0] = 1;
GameSquWill[0][1] = 1;
GameSquWill[1][0] = 1;
GameSquWill[1][1] = 1;
break;
case 1:
GameSquWill[0][0] = 1;
GameSquWill[0][1] = 1;
GameSquWill[1][0] = 1;
GameSquWill[2][0] = 1;
break;
case 2:
GameSquWill[0][0] = 1;
GameSquWill[0][1] = 1;
GameSquWill[1][1] = 1;
GameSquWill[2][1] = 1;
break;
case 3:
GameSquWill[0][1] = 1;
GameSquWill[1][0] = 1;
GameSquWill[1][1] = 1;
GameSquWill[2][0] = 1;
break;
case 4:
GameSquWill[0][0] = 1;
GameSquWill[1][0] = 1;
GameSquWill[1][1] = 1;
GameSquWill[2][1] = 1;
break;
case 5:
GameSquWill[0][0] = 1;
GameSquWill[1][0] = 1;
GameSquWill[1][1] = 1;
GameSquWill[2][0] = 1;
break;
case 6:
GameSquWill[0][0] = 1;
GameSquWill[1][0] = 1;
GameSquWill[2][0] = 1;
GameSquWill[3][0] = 1;
break;


default:
ASSERT(0);
break;
}


//方块一开始的位置
NowPosition.x = 0;
NowPosition.y = m_col/2;
}


void CWndMain::OnTimer(UINT nIDEvent) 
{
MoveDir(3);

this->Invalidate();

CWnd::OnTimer(nIDEvent);
}




bool CWndMain::MoveDir(int direction)
{
if (m_End)
{
return false;
}
switch(direction)
{
//左
case 1:
if (Meet(GameSquare, 1, NowPosition)) break;
NowPosition.y--;
break;
//右
case 2:
if (Meet(GameSquare, 2, NowPosition)) break;
NowPosition.y++;
break;
//下
case 3:
if (Meet(GameSquare, 3, NowPosition)) 
{
LineDelete();
break;
}
NowPosition.x++;
break;
//上
case 4:
Meet(GameSquare, 4, NowPosition);
break;

  default:
ASSERT(0);
break;
}
return true;
}


bool CWndMain::Meet(int a[][4], int direction, CPoint p)
{
int i, j;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
a[i][j] = GameSquWill[i][j];
}
}
//先把原位置清0
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (a[i][j] == 1)
{
TRACE("i = %d, j = %d\n", i, j);
Russian[p.x+i][p.y+j] = 0;

}
}


for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (a[i][j] == 1)
{
TRACE("上下左右:i = %d, j = %d\n", i, j);
switch(direction)
{
//左移动
case 1:
if ((p.y+j-1)<0) 
goto exit;
if (Russian[p.x+i][p.y+j-1] == 1)
goto exit;
break;
//右移动
case 2:
if ((p.y+j+1)>=m_col) 
goto exit;
if (Russian[p.x+i][p.y+j+1] == 1) 
goto exit;
break;
//下移
case 3:
if ((p.x+i+1)>=m_row) 
goto exit;
if (Russian[p.x+i+1][p.y+j] == 1) 
goto exit;
break;
//变换
case 4:
if (!Change(a, p, Russian)) 
goto exit;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
GameSquare[i][j] = GameSquAfter[i][j];
a[i][j] = GameSquare[i][j];
}
}
return false;
break;

}
}

}
}

int x, y;
x = p.x;
y = p.y;
//移动位置,重新给数组赋值
switch(direction)
{
case 1:
y--;
break;
case 2:
y++;
break;
case 3:
x++; 
break;
case 4:
break;
}


for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (a[i][j] == 1)
{
Russian[x+i][y+j] = 1;
}
}
}
return false;


exit:
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (GameSquWill[i][j] == 1)
{
Russian[p.x+i][p.y+j] = 1;
TRACE("p.x+i = %d, p.y+j = %d\n", p.x+i, p.y+j);
}
}
}
return true;
}


bool CWndMain::Change(int a[][4], CPoint p, int b[][100])
{
int temp[4][4];
int i, j;
int k=4, l=4;


for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
a[i][j] = GameSquWill[i][j];
}
}


//存放变换后的方块矩阵
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
temp[i][j] = a[j][3-i];
}
}


for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (temp[i][j] == 1)
{
TRACE("111111:i = %d, j = %d\n", i, j);
TRACE("222222:k = %d, k = %d\n", k, l);
if (k>i) k=i;
if (l>j) l=j;
TRACE("333333:k = %d, k = %d\n", k, l);
}
}
}


for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
GameSquWill[i][j] = 0;
}
}


//把变换后的矩阵移到左上角
for (i=k; i<4; i++)
{
for (j=l; j<4; j++)
{
GameSquWill[i-k][j-l] = temp[i][j];
TRACE("4444444:i= %d, j = %d\n", i, j);
TRACE("5555555:i-k= %d, j-l = %d\n", i-k, j-l);
}
}


//判断是否接触,是:返回失败
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (GameSquAfter[i][j] == 0)  continue;
if (((p.x+i)>=m_row) || ((p.y+j)<0) ||((p.y+j)>m_col))
{
return false;
}
if (b[p.x+i][p.y+j] == 1)
{
return false;
}
}
}
return true;
}




void CWndMain::LineDelete()
{
int i,j, k, l;
//本次共消去的行数
int m=0; 
bool flag = 0;
for (i=0; i<m_row; i++)
{
//检查要不要消行
flag = true;
for (j=0; j<m_col; j++)
{
if (Russian[i][j] == 0)
{
TRACE("检查要不要消行:i = %d, j = %d\n", i, j);
flag = false;
}
}
//如果要消行
if (flag == true)
{
m++;
TRACE("///m = %d\n", m);
for (k=i; k>0; k--)
{
//上行给下行
for (l=0; l<m_col; l++)
{
TRACE("赋值前:k = %d, l = %d\n", k, l);
Russian[k][l] = Russian[k-1][l];
TRACE("赋值后:k = %d, l = %d\n", k, l);
}
}
//第一行为0
// for (l=0; l<m_col; l++)
// {
// Russian[0][1] = 0;
// }
}
}
DrawWill();


//加分
switch(m)
{
case 1:
m_Score++;
break;
case 2:
m_Score += 3;
break;
case 3:
m_Score += 6;
break;
case 4:
m_Score += 10;
break;
default:
break;
}


//速度
m_Speed = m_Score/50;


//游戏结束
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (GameSquare[i][j] == 1)
{
TRACE("消行:i = %d, j = %d\n", i, j);
//到了顶点
if (Russian[i+NowPosition.x][j+NowPosition.y] == 1)
{
TRACE("i+NowPosition.x = %d, j+NowPosition.y = %d\n", i+NowPosition.x, j+NowPosition.y);
m_End = TRUE;
MessageBox("游戏结束");
return;
}
}
}
}
}


void CWndMain::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
// switch(nChar)
// {
// case VK_LEFT:
// MessageBox("向左");
//
// // g_wndMain.MoveDir(1);
// break;
// case VK_RIGHT:
// // g_wndMain.MoveDir(2);
//
// MessageBox("向右");
// break;
// case VK_DOWN:
// // g_wndMain.MoveDir(3);
//
// MessageBox("向下");
// break;
// default:
// ASSERT(0);
// break;
// }

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


BOOL CWndMain::PreTranslateMessage(MSG* pMsg) 
{
if (!m_Start)
{
return FALSE;
}
//暂停
if (m_Pause == TRUE)
{
return FALSE;
}
if (pMsg->message == WM_KEYDOWN)
{
switch(pMsg->wParam)
{
case VK_LEFT:
MoveDir(1);
break;
case VK_RIGHT:
MoveDir(2);
break;
case VK_DOWN:
MoveDir(3);
break;
case VK_UP:
MoveDir(4);
break;
}
}
return CWnd::PreTranslateMessage(pMsg);
}




void CWndMain::OnOptionLevel1() 
{
GameLevel(1);
}


void CWndMain::OnOptionLevel2() 
{
GameLevel(2);
}


void CWndMain::OnOptionLevel3() 
{
GameLevel(3);
}


void CWndMain::GameLevel(int level)
{
switch(level)
{
//第一级,最简单,方块下落速度最慢,所以乘的数最大
case 1:
m_Speed = 20;
break;
//第二级
case 2:
m_Speed = 10;
break;
//第三级
case 3:
m_Speed = 1;
break;
default:
ASSERT(0);
break;
}
}


  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值