您的位置:首页 > 编程语言 > C语言/C++

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

2014-03-11 20:33 357 查看
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
[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;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: