C++编写俄罗斯方块游戏源码
12617 点击·1 回帖
![]() | ![]() | |
![]() | 头文件:
#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 //pw_AFX_VIRTUAL(CWndMain) public: virtual BOOL PreTranslateMessage(MSG* pMsg); //AFX_VIRTUAL // Implementation public: virtual ~CWndMain(); // Generated message map functions protected: //pw_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; ///////////////////////////////////////////////////////////////////////////// //pw_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[j] = 0; } } //4*4的大方格,数组值初始化为0 for (i=0; i<4; i++) { for (j=0; j<4; j++) { GameSquare[j] = 0; } } for (i=0; i<4; i++) { for (j=0; j<4; j++) { GameSquWill[j] = 0; } } for (i=0; i<4; i++) { for (j=0; j<4; j++) { GameSquAfter[j] = 0; } } for (i=0; i<4; i++) { for (j=0; j<2; j++) { m_nIndex[j] = 0; } } } CWndMain::~CWndMain() { } BEGIN_MESSAGE_MAP(CWndMain, CWnd) //pw_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 { 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=%dn", rc.left + i*dist, rc.top); // TRACE("网格线x=%d, 网格线y=%dn", 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[0]; // ny = m_nIndex[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[j]; // // if (GameSquWill[j] == 1) // { // m_nIndex[k][0] = nx; // m_nIndex[k][1] = ny; // k++; // } // } // } //如果有方块则显示方块,否则不显示 for ( i=0; i { for ( j=0; j { if (Russian[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 = %dn", 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 = %dn", m, n); } } } } void CWndMain::Start() { int i, j; m_End = FALSE; SetTimer(1, 500, NULL); //清空背景数组 for (i=0; i { for (j=0; j { Russian[j] = 0; } } //清空方块数组 for (i=0; i<4; i++) { for (j=0; j<4; j++) { GameSquare[j] = 0; GameSquWill[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[j] = GameSquWill[j]; GameSquWill[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[j] = GameSquWill[j]; } } //先把原位置清0 for (i=0; i<4; i++) { for (j=0; j<4; j++) { if (a[j] == 1) { TRACE("i = %d, j = %dn", i, j); Russian[p.x+i][p.y+j] = 0; } } } for (i=0; i<4; i++) { for (j=0; j<4; j++) { if (a[j] == 1) { TRACE("上下左右:i = %d, j = %dn", 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[j] = GameSquAfter[j]; a[j] = GameSquare[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[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[j] == 1) { Russian[p.x+i][p.y+j] = 1; TRACE("p.x+i = %d, p.y+j = %dn", 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[j] = GameSquWill[j]; } } //存放变换后的方块矩阵 for (i=0; i<4; i++) { for (j=0; j<4; j++) { temp[j] = a[j][3-i]; } } for (i=0; i<4; i++) { for (j=0; j<4; j++) { if (temp[j] == 1) { TRACE("111111:i = %d, j = %dn", i, j); TRACE("222222:k = %d, k = %dn", k, l); if (k>i) k=i; if (l>j) l=j; TRACE("333333:k = %d, k = %dn", k, l); } } } for (i=0; i<4; i++) { for (j=0; j<4; j++) { GameSquWill[j] = 0; } } //把变换后的矩阵移到左上角 for (i=k; i<4; i++) { for (j=l; j<4; j++) { GameSquWill[i-k][j-l] = temp[j]; TRACE("4444444:i= %d, j = %dn", i, j); TRACE("5555555:i-k= %d, j-l = %dn", i-k, j-l); } } //判断是否接触,是:返回失败 for (i=0; i<4; i++) { for (j=0; j<4; j++) { if (GameSquAfter[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 { //检查要不要消行 flag = true; for (j=0; j { if (Russian[j] == 0) { TRACE("检查要不要消行:i = %d, j = %dn", i, j); flag = false; } } //如果要消行 if (flag == true) { m++; TRACE("///////m = %dn", m); for (k=i; k>0; k--) { //上行给下行 for (l=0; l { TRACE("赋值前:k = %d, l = %dn", k, l); Russian[k][l] = Russian[k-1][l]; TRACE("赋值后:k = %d, l = %dn", k, l); } } //第一行为0 // for (l=0; 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[j] == 1) { TRACE("消行:i = %d, j = %dn", i, j); //到了顶点 if (Russian[i+NowPosition.x][j+NowPosition.y] == 1) { TRACE("i+NowPosition.x = %d, j+NowPosition.y = %dn", 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; } } | |
![]() | ![]() |