📄 snakeview.cpp
字号:
// SnakeView.cpp : implementation of the CSnakeView class
//
#include "stdafx.h"
#include "Snake.h"
#include "SnakeDoc.h"
#include "SnakeView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSnakeView
IMPLEMENT_DYNCREATE(CSnakeView, CView)
BEGIN_MESSAGE_MAP(CSnakeView, CView)
//{{AFX_MSG_MAP(CSnakeView)
ON_WM_KEYDOWN()
ON_WM_TIMER()
ON_COMMAND(ID_GAME_START, OnGameStart)
//}}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()
/////////////////////////////////////////////////////////////////////////////
// CSnakeView construction/destruction
CSnakeView::CSnakeView()
{
IniGame();
}
CSnakeView::~CSnakeView()
{
}
BOOL CSnakeView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CSnakeView drawing
void CSnakeView::OnDraw(CDC* pDC)
{
CSnakeDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap *pOldBitmap=MemDC.SelectObject(&bitmap);
BITMAP bm;
bitmap.GetBitmap(&bm);
pDC->BitBlt(0,0,bm.bmWidth,bm.bmHeight,&MemDC,0,0,SRCCOPY);
MemDC.SelectObject(pOldBitmap);
// 画游戏区域
pDC->SelectStockObject(WHITE_BRUSH);
pDC->Rectangle(CRect(m_nLeft-1,m_nTop-1,m_nLeft+m_nWidth*m_nSize+1,
m_nTop+m_nHeight*m_nSize+1));
//显示当前用时
CString uStr;
uStr.Format("当前用时:%d",m_nTime);
pDC->TextOut(m_nLeft+m_nWidth*m_nSize+30,40,uStr);
//显示当前得分
uStr.Format("当前得分:%d",m_nCount);
pDC->TextOut(m_nLeft+m_nWidth*m_nSize+30,140,uStr);
//显示目标
pDC->SelectStockObject(LTGRAY_BRUSH);
pDC->Rectangle(CRect(m_nLeft+m_pAim.y*m_nSize,m_nTop+m_pAim.x*m_nSize,
m_nLeft+(m_pAim.y+1)*m_nSize,m_nTop+(m_pAim.x+1)*m_nSize));
//draw snake
for(int i=0;i<=m_aBody.GetUpperBound();i++)
{
CPoint uPoint=m_aBody.GetAt(i);
pDC->Rectangle(CRect(m_nLeft+uPoint.y*m_nSize,m_nTop+uPoint.x*m_nSize,
m_nLeft+(uPoint.y+1)*m_nSize,m_nTop+(uPoint.x+1)*m_nSize));
}
}
/////////////////////////////////////////////////////////////////////////////
// CSnakeView printing
BOOL CSnakeView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CSnakeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CSnakeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CSnakeView diagnostics
#ifdef _DEBUG
void CSnakeView::AssertValid() const
{
CView::AssertValid();
}
void CSnakeView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CSnakeDoc* CSnakeView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSnakeDoc)));
return (CSnakeDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CSnakeView message handlers
void CSnakeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// 设置各方向的值
switch(nChar){
case 38:
if(m_nDirect!=3)
m_nDirect=4;
break;
case 40:
if(m_nDirect!=4)
m_nDirect=3;
break;
case 37:
if(m_nDirect!=1)
m_nDirect=2;
break;
case 39:
if(m_nDirect!=2)
m_nDirect=1;
break;
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CSnakeView::OnTimer(UINT nIDEvent)
{
m_nTime1++; //计时
if(m_nTime1==10) //达到1秒
{
m_nTime++;
m_nTime1=0;
Invalidate();
}
CPoint uPoint=m_aBody.GetAt(0); //sanke head
int uTag=0;
switch(m_nDirect)
{
case 1: //right
uPoint.y++;
if(uPoint.y>=m_nWidth)
uTag=1;
break;
case 2: //left
uPoint.y--;
if(uPoint.y<0)
uTag=1;
break;
case 3: //down
uPoint.x++;
if(uPoint.x>=m_nHeight)
uTag=1;
break;
case 4: //up
uPoint.x--;
if(uPoint.x<0)
uTag=1;
break;
}
if(uTag==0)
{
for(int i=0; i<=m_aBody.GetUpperBound();i++)
{
CPoint uPoint1=m_aBody.GetAt(i);
if(uPoint1.x==uPoint.x&& uPoint1.y==uPoint.y)
{
uTag=1;
break;
}
}
}
if(uTag==0)
{
m_aBody.InsertAt(0,uPoint);
ReDisplay(uPoint);
if(uPoint.x==m_pAim.x&&uPoint.y==m_pAim.y)
{
m_nCount++;
IniAim();
Invalidate();
}
else
{
CPoint uPoint1=m_aBody.GetAt(m_aBody.GetUpperBound());
m_aBody.RemoveAt(m_aBody.GetUpperBound());
ReDisplay(uPoint1);
}
}
else //Game Over
{
KillTimer(1);
AfxMessageBox("Fail!");
}
CView::OnTimer(nIDEvent);
}
void CSnakeView::OnGameStart()
{
IniGame();
m_nGameStatus=1;
SetTimer(1,100,NULL); //启动定时器
Invalidate();
}
//该随机函数产生一个供蛇吃的目标,如与蛇身重合,则重新产生一个
void CSnakeView::IniAim()
{
int uX,uY; //目标位置
while(1)
{
uX=rand()%m_nHeight;
uY=rand()%m_nWidth;
int uTag=0; //0:不与蛇身重合;1:重合
for(int i=0;i<=m_aBody.GetUpperBound();i++)
{
CPoint uPoint=m_aBody.GetAt(i);
if(uPoint.x==uX||uPoint.y==uY) //重合
{
uTag=1;
break;
}
}
if(uTag==0)
break;
}
m_pAim=CPoint(uX,uY); //目标保存于成员变量中
}
//初始化游戏
void CSnakeView::IniGame() //这个类中的方法
{
//initialize game area
m_nLeft=20;
m_nTop=20;
m_nWidth=40;
m_nHeight=30;
m_nSize=10;
//initialize game status
m_nGameStatus=0;
m_nDirect=1;
m_nCount=0;
//initialize snake body
m_aBody.RemoveAll();
m_aBody.Add(CPoint(2,7));
m_aBody.Add(CPoint(2,6));
m_aBody.Add(CPoint(2,5));
m_aBody.Add(CPoint(2,4));
//clean timer
m_nTime=0;
m_nTime1=0;
srand((unsigned)time(NULL)); //初始化随机数发生器
IniAim(); //产生一个目标
}
//刷新游戏区域中pPoint处的一个小方格
void CSnakeView::ReDisplay(CPoint pPoint)
{
InvalidateRect(CRect(m_nLeft+pPoint.y*m_nSize,m_nTop+pPoint.x*m_nSize,
m_nLeft+(pPoint.y+1)*m_nSize,m_nTop+(pPoint.x+1)*m_nSize));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -