// snakeView.cpp : implementation of the CSnakeView class
/*
* 作者:薛长明
* 运行环境:WINXP
* 开发工具:VC6.0
* 时间:2008年12月19日
* 写作目的:无聊
* 制作背景:突发奇想。。。想看自己能不能用自己会的仅有
* 一点MFC知识来做这个贪吃蛇游戏,结果还真做出来了(尽管
* 做的不是很完美)。我没经过大量的测试,不过有的时候会出现
* 内存问题,可能跟DC的申请和释放有关。游戏做的还不是很完善
* 把它发出来的目的就是想和大家交流下,此程序哪里写的不好啊、
* 算法实现的不好什么的,都希望大家和我交流!
* QQ:45695481
* MSN:4624330@163.com
* EMAIL:4624330@163.com
* 希望结交程序员朋友!~
*/
#include "stdafx.h"
#include "snake.h"
#include "snakeDoc.h"
#include "snakeView.h"
#include<ctime>
#include "math.h"
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
#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_START, OnStart)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSnakeView construction/destruction
CSnakeView::CSnakeView()
{
// TODO: add construction code here
remove = 14;
up = FALSE;
down = FALSE;
left = FALSE;
right = TRUE;
start = FALSE;
moveCount = FALSE;
pointNum = 0;
timeNum = 300;
score = 0;
level = 1;
scoreStr = "0";
levelStr = "1";
CountForLevel = 0;
}
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);
CRect rect;
pDC->MoveTo(13, 27);
pDC->LineTo(13, 296);
pDC->LineTo(296, 296);
pDC->LineTo(296, 27);
pDC->LineTo(13, 27);
pDC->TextOut(14, 5, "SCORE:");
pDC->TextOut(90, 5, "0");
pDC->TextOut(220, 5, "LEVEL:");
pDC->TextOut(280, 5, "1");
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// 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)
{
if(!start)/* 在没开始前不进行监听 */
{
return;
}
switch(nChar)
{
case VK_DOWN:
if (!up&&!moveCount)/* 这里的moveCount是为了避免BUG的 */
{
down = TRUE;
moveCount = TRUE;
left = FALSE;
right = FALSE;
}
break;
case VK_UP:
if (!down&&!moveCount)
{
up = TRUE;
moveCount = TRUE;
left = FALSE;
right = FALSE;
}
break;
case VK_LEFT:
if (!right&&!moveCount)
{
left = TRUE;
moveCount = TRUE;
down = FALSE;
up = FALSE;
}
break;
case VK_RIGHT:
if (!left&&!moveCount)
{
right = TRUE;
moveCount = TRUE;
down = FALSE;
up = FALSE;
}
break;
default:
break;
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
/**************
* *
* -=画蛇头=- *
* *
**************/
void CSnakeView::OnDrawHead()
{
CDC *pDC = GetDC();
pDC->TextOut(head[0], head[1], "■");
pDC->DeleteDC();
}
/*****************************************************
* *
* -=删除蛇尾,实际上是将蛇尾的点用反色覆盖(*^_^*)=- *
* *
*****************************************************/
void CSnakeView::OnDeleteTail()
{
CDC *pDC = GetDC();
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,255,255));
pDC->TextOut(tail[0], tail[1], "■");
pDC->DeleteDC();
}
/********************************
* *
* -=计时器,处理蛇移动的函数=- *
* *
********************************/
void CSnakeView::OnTimer(UINT nIDEvent)
{
/* 判断移动方向,并改变蛇头坐标 */
if (up)
head[1] -= remove;
if (down)
head[1] += remove;
if (right)
head[0] += remove;
if (left)
head[0] -= remove;
if (!OnCheck())
{
OnDrawHead();
if((head[0] == random[0]&&head[1] == random[1]))
{
sndPlaySound("23.wav", SND_ASYNC);/* 播放吃东西的音效,没花时间去找好的。 */
score += 10; /* 记分 */
CountForLevel++; /* 为level记次数的,我定的是如果吃了十个豆level就+1 */
CDC *pDC = GetDC();
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,255,255)); /* 设置字体颜色为背景色 */
pDC->TextOut(90,5,scoreStr);/* 覆盖原分数 */
scoreStr.Format("%d", score);
pDC->SetTextColor(RGB(0,0,0));/* 恢复字体颜色 */
pDC->TextOut(90,5,scoreStr);/* 写新的分数 */
pDC->DeleteDC();
SavePoint();
OnRandom();
if (CountForLevel == 10)
{
KillTimer(1);/* KILL掉计时器 */
timeNum -= 50; /* 重新设置计时器的时间 */
SetTimer(1, timeNum, NULL);/* 重新启动计时器 */
/* 上面的代码实现了level+1的时候速度变快 */
/* 下面的代码更新界面上的level后的数字 */
level++;
CountForLevel = 0;
CDC *pDC = GetDC();
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,255,255));
pDC->TextOut(280,5,levelStr);
levelStr.Format("%d", level);
pDC->SetTextColor(RGB(0,0,0));
pDC->TextOut(280,5,levelStr);
pDC->DeleteDC();
}
}else
{
MovePoint();
OnDeleteTail();
}
moveCount = FALSE;
}else
{
CDC *pDC = GetDC();
CRect rc(14,28,295,295);
pDC->FillSolidRect(&rc, RGB(255, 255, 255));
pDC->TextOut(120, 130, "Game Over!");
ReleaseDC(pDC);
}
CView::OnTimer(nIDEvent);
}
/*******************************************************************
* *
* -=当蛇头吃随机点的时候将随即点的坐标加入到蛇身数组index[][]中=- *
* *
*******************************************************************/
void CSnakeView::SavePoint()
{
pointNum++;
index[pointNum-1][0] = random[0];
index[pointNum-1][1] = random[1];
}
/*********************************************************************
* -=行进的时候将蛇身数组的每个值进行移动=- *
* -=假设现在蛇身有三个节点为3(index[0]),2(index[1]),1(index[2])=- *
* -=那么移动的顺序为 3<=2, 2<=1, 1<=新的蛇头坐标=- *
*********************************************************************/
void CSnakeView::MovePoint()
{
tail[0] = index[0][0];
tail[1] = index[0][1];
for (int i = 0; i < pointNum; i++)
{
index[i][0] = index[i+1][0];
index[i][1] = index[i+1][1];
}
index[pointNum-1][0] = head[0];
index[pointNum-1][1] = head[1];
}
void CSnakeView::OnStart()
{
Init();
OnRandom();
SetTimer(1, timeNum, NULL);
CDC *pDC = GetDC();
pDC->TextOut(14, 28, "■");
ReleaseDC(pDC);
// TODO: Add your command handler code here
}
void CSnakeView::Init()
{
start = TRUE;
for(int i = 0; i < 100; i++)
{
index[i][0] = 0;
index[i][1] = 0;
}
head[0] = 14;
head[1] = 28;
index[0][0] = tail[0] = head[0];
index[0][1] = tail[1] = head[1];
random[0] = 0;
random[1] = 0;
pointNum = 1;
}
/*
*这个函数是产生随即数的
*/
/******************************
* *
* -=这个函数是产生随即数的=- *
* *
******************************/
void CSnakeView::OnRandom()
{
CDC *pDC = GetDC();