📄 game_yyllkview.cpp
字号:
// Game_YYLLKView.cpp : implementation of the CGame_YYLLKView class
//
#include "stdafx.h"
#include <stdlib.h>
#include "Game_YYLLK.h"
#include "Game_YYLLKDefs.h"
#include "Game_YYLLKDoc.h"
#include "Game_YYLLKView.h"
#include "SettingDlg.h"
#include<windows.h>
#include<mmsystem.h> //音乐MCI播放API接口函数的声明
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define BKCOLOR RGB(128,128,128) //背景颜色
#define ROWCOUNT 8 //行数
#define COLCOUNT 10 //列数
#define FRONTWIDTH 50 //前面方块的宽度
#define FRONTHEIGHT 50 //前面方块的高度
#define BKWIDTH 56 //背景方块的宽度
#define BKHEIGHT 56 //背景方块的高度
#define BLANK_STATE -1 //空方块
/////////////////////////////////////////////////////////////////////////////
// CGame_YYLLKView
IMPLEMENT_DYNCREATE(CGame_YYLLKView, CView)
BEGIN_MESSAGE_MAP(CGame_YYLLKView, CView)
//{{AFX_MSG_MAP(CGame_YYLLKView)
ON_WM_CREATE()
ON_COMMAND(IDM_START, OnStart)
ON_WM_LBUTTONDOWN()
ON_COMMAND(IDM_PAUSE, OnPause)
ON_COMMAND(IDM_EXIT, OnExit)
ON_COMMAND(IDM_END, OnEnd)
ON_UPDATE_COMMAND_UI(IDM_NUM, OnUpdateNum)
ON_UPDATE_COMMAND_UI(IDM_ANIMAL, OnUpdateAnimal)
ON_UPDATE_COMMAND_UI(IDM_PLANT, OnUpdatePlant)
ON_WM_TIMER()
ON_UPDATE_COMMAND_UI(IDM_START, OnUpdateStart)
ON_UPDATE_COMMAND_UI(IDM_PAUSE, OnUpdatePause)
ON_UPDATE_COMMAND_UI(IDM_END, OnUpdateEnd)
ON_UPDATE_COMMAND_UI(IDM_SET, OnUpdateSet)
ON_UPDATE_COMMAND_UI(IDM_EXIT, OnUpdateExit)
ON_UPDATE_COMMAND_UI(ID_APP_ABOUT, OnUpdateAppAbout)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGame_YYLLKView construction/destruction
CGame_YYLLKView::CGame_YYLLKView()
{
}
CGame_YYLLKView::~CGame_YYLLKView()
{
//释放动态数组空间
delete[] m_map;
}
BOOL CGame_YYLLKView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CGame_YYLLKView drawing
/////////////////////////////////////////////////////////////////////////////
// CGame_YYLLKView diagnostics
#ifdef _DEBUG
void CGame_YYLLKView::AssertValid() const
{
CView::AssertValid();
}
void CGame_YYLLKView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CGame_YYLLKDoc* CGame_YYLLKView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGame_YYLLKDoc)));
return (CGame_YYLLKDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CGame_YYLLKView message handlers
int CGame_YYLLKView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
//初始化行列数
m_nRow=ROWCOUNT;
m_nCol=COLCOUNT;
//根据行列数动态分配内核数据数组空间
m_map=new int[m_nRow*m_nCol];
//第一次开始游戏
m_bFistPlay = TRUE;
//缺省为不是游戏暂停状态
m_bGamePaush = FALSE;
//缺省为不插放背景音乐
m_bMusic = FALSE;
//左上角X,Y坐标
m_iStartX = 40;
m_iStartY = 20;
//缺省级别为3级
m_iLevel = 0;
//缺省游戏是结束的
m_bGameEnd = TRUE;
//记录方块置为无效状态
m_nY1= BLANK_STATE;
m_nX1= BLANK_STATE;
m_b_GAME_STATE = true;//欢迎界面是否显示:是
return 0;
}
//OnDraw(CDC* pDC);承担所有绘制屏幕工作
void CGame_YYLLKView::OnDraw(CDC* pDC)
{
DcEnvInitial();
DrawGame(&m_memDC); //在内存位图的游戏区域绘制
pDC->BitBlt(0,0,m_nWidth,m_nHeight,&m_memDC,0,0,SRCCOPY);
}
//绘图设备环境的初始化
void CGame_YYLLKView::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);
//动物图样内存位图
m_memPictureDC1.CreateCompatibleDC(pWindowDC);
m_memPictureBmp1.LoadBitmap(IDB_BMP_ANIMAL1);
m_memPictureDC1.SelectObject(&m_memPictureBmp1);
//放在最桌面的前面显示
HWND hWnd = ::AfxGetMainWnd()->m_hWnd;
::SetWindowPos(hWnd,HWND_TOPMOST,m_iStartY, m_iStartX,0,0,SWP_NOMOVE|SWP_NOSIZE);
//黑色的黑笔
m_pBlackPen = new CPen(PS_SOLID,1,BLACK);
//画刷
m_pGrayBrush = new CBrush(RGB(66,66,66));
m_pBlackBrush = new CBrush(BLACK);
}
}
//释放绘图资源
void CGame_YYLLKView::DCEnvClear()
{
//设备环境
m_memDC.DeleteDC();
//位图资源
DeleteObject(m_memBmp);
//画刷和画笔
delete(m_pBlackPen);
delete(m_pGrayBrush);
delete(m_pBlackBrush);
}
//绘制游戏区域
void CGame_YYLLKView::DrawGame(CDC *pDC)
{
//选用黑色画刷,绘制整个游戏所在窗口的背景
pDC -> SelectObject(m_pBlackBrush);
CRect rect;
CListBox m_listbox;
GetClientRect(&rect);
pDC -> Rectangle(rect);
//显示游戏区域及游戏级别的汉字描述
if (!m_bGameEnd)
{
pDC -> SetBkColor(BLACK);
pDC -> SetTextColor(WHITE);
pDC -> TextOut(m_iStartY+610, m_iStartX, "游戏类型:");
pDC -> TextOut(m_iStartY+680, m_iStartX,m_strLevel);
}
for(int i=0;i<m_nRow;i++)
{
for(int j=0;j<m_nCol;j++)
{
if(m_map[i*m_nCol+j]==BLANK_STATE)
{
continue;
}
//绘制方块边框
pDC->BitBlt(m_iStartY+j*FRONTWIDTH,m_iStartX+i*FRONTHEIGHT,
BKWIDTH,BKHEIGHT,
0,
0,BKHEIGHT,
SRCCOPY);
//绘制方块
pDC->BitBlt(m_iStartY+j*FRONTWIDTH,m_iStartX+i*FRONTHEIGHT,
FRONTWIDTH,FRONTHEIGHT,
&m_memPictureDC1,
0,m_map[i*m_nCol+j]*(FRONTHEIGHT),
SRCPAINT);
}
}
}
//游戏开始
void CGame_YYLLKView::OnStart()
{
if (!m_bGamePaush) //如果不是游戏暂停状态,则必须作些初始工作
{
m_bGameEnd = FALSE;
//显示当前的区域及游戏级别的汉字描述
CurrentAreaAndLevel();
CRect rect(m_iStartY, m_iStartX, m_iStartY+800, m_iStartX+600);
InvalidateRect(&rect);
}
//初始化地图,将地图中所有方块区域位置置为空方块状态
for(int iNum=0;iNum<(m_nCol*m_nRow);iNum++)
{
m_map[iNum] = BLANK_STATE;
}
//部下随机种子
srand(time(NULL));
//生成随机地图
//将所有匹配成对的动物物种放进一个临时的地图中
CDWordArray tmpMap;
for(int i=0;i<(m_nCol*m_nRow)/2;i++)
for(int j=0;j<2;j++)
tmpMap.Add(i);
//每次从上面的临时地图中取走(获取后并在临时地图删除)
//一个动物放到地图的空方块上
for(i=0;i<m_nRow*m_nCol;i++)
{
//随机挑选一个位置
int nIndex=(int(rand()*0.1+rand()*0.01+rand()))%tmpMap.GetSize();
//获取该选定物件放到地图的空方块
m_map[i]=tmpMap.GetAt(nIndex);
//在临时地图除去该动物
tmpMap.RemoveAt(nIndex);
}
//更新显示
Invalidate(TRUE);
m_bGamePaush = FALSE;
}
//用于生成当前区域大小与级别所对应的汉字描述
void CGame_YYLLKView::CurrentAreaAndLevel()
{
switch(m_iLevel)
{
case 0:
m_strLevel = "动物"; break;
case 1:
m_strLevel = ""; break;
case 2:
m_strLevel = "植物"; break;
}
}
// 鼠标左键消息处理
void CGame_YYLLKView::OnLButtonDown(UINT nFlags, CPoint point)
{
//1.计算鼠标点击方块的的位置
int x=(point.x-m_iStartY)/FRONTWIDTH+((point.x-m_iStartY)%FRONTWIDTH?1:0)-1;
int y=(point.y-m_iStartX)/FRONTHEIGHT+((point.y-m_iStartX)%FRONTHEIGHT?1:0)-1;
//2.在游戏区域内并且该区域还有该区域不是空的区域
if(x<m_nCol&&y<m_nRow&&m_map[y*m_nCol+x]!= BLANK_STATE)
{
//3.假设尚未记录第一个方块
if(m_nX1==BLANK_STATE)
{
//4.记录第一个方块的位置
m_nX1=x;
m_nY1=y;
//获取程序框架的设备环境
CDC *pWinDC = GetDC();
//临时绘制点中的方块外框
//只绘屏幕不载入内存位图
CPen myPen;
CPen *pOldPen;
myPen.CreatePen(PS_SOLID, 4, RGB(255,0,0));
pOldPen = pWinDC->SelectObject(&myPen);
//方块外框绘制,线条环绕绘制框架
pWinDC->MoveTo(m_iStartY+x*FRONTWIDTH,m_iStartX+y*FRONTHEIGHT);
pWinDC->LineTo(m_iStartY+x*FRONTWIDTH,m_iStartX+(y+1)*FRONTHEIGHT);
pWinDC->LineTo(m_iStartY+(x+1)*FRONTWIDTH,m_iStartX+(y+1)*FRONTHEIGHT);
pWinDC->LineTo(m_iStartY+(x+1)*FRONTWIDTH,m_iStartX+y*FRONTHEIGHT);
pWinDC->LineTo(m_iStartY+x*FRONTWIDTH,m_iStartX+y*FRONTHEIGHT);
//现场恢复
pWinDC->SelectObject(pOldPen);
}
else
{
//5.判断是否点击的方块非本身, 是否点击同一种动物
if((m_nX1!=x||m_nY1!=y)&&
m_map[m_nY1*m_nCol+m_nX1]==m_map[y*m_nCol+x]+20||
(m_map[m_nY1*m_nCol+m_nX1]==m_map[y*m_nCol+x]-20))
//m_map[m_nY1*m_nCol+m_nX1]==m_map[y*m_nCol+x])
{
//6.检测是否可以消除
if(IsLink(m_nX1,m_nY1,x,y))
{
//7.数据清理
m_map[m_nY1*m_nCol+m_nX1]=BLANK_STATE;
m_map[y*m_nCol+x]=BLANK_STATE;
}
}
//8.清空记录方块的值
m_nX1=BLANK_STATE;
m_nY1=BLANK_STATE;
//通知重绘
Invalidate(FALSE);
}
}
//察看是否已经胜利
if(IsWin())
{
MessageBox("恭喜您胜利闯关,即将开始新局");
OnStart();
}
}
//判断选中的两个方块是否可以消除
BOOL CGame_YYLLKView::IsLink(int x1, int y1, int x2, int y2)
{
//X直连方式
if(x1==x2)
{
if(X1_Link_X2(x1,y1,y2))
return TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -