📄 snakeframe.cpp
字号:
// snakeFrame.cpp : implementation file
//
#include "stdafx.h"
#include "resource.h"
#include "snakeFrame.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// snakeFrame
IMPLEMENT_DYNCREATE(snakeFrame, CFrameWnd)
snakeFrame::snakeFrame()
{
CRect rt;
Create(NULL, "贪吃蛇", WS_OVERLAPPED | WS_SYSMENU | WS_THICKFRAME,
CRect(0 , 0, 800, 675));
//将窗口移到屏幕中央显示
CClientDC dc(this);
int nWidth = dc.GetDeviceCaps(HORZRES);
int nHeight = dc.GetDeviceCaps(VERTRES);
GetClientRect(&rt);
nWidth = (nWidth - (rt.right - rt.left))/2;
nHeight = (nHeight - (rt.bottom - rt.top))/2;
MoveWindow(nWidth, nHeight, (rt.right - rt.left), (rt.bottom - rt.top), true);
m_snakeHead = m_snakeTail = NULL;
m_nScore = 0;
m_nElapse = 200;
m_gameState = ST_PRE;
}
snakeFrame::~snakeFrame()
{
}
BEGIN_MESSAGE_MAP(snakeFrame, CFrameWnd)
//{{AFX_MSG_MAP(snakeFrame)
ON_WM_PAINT()
ON_WM_TIMER()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// snakeFrame message handlers
void snakeFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
if (m_gameState == ST_PLAY){
DrawSnake(&dc);
m_foodNode.DrawCell(&dc);
int rgbPart = 51;
int baseX = 601;
for (int nIndex = 0; nIndex < 5; nIndex++)
{
CPen pnDraw(PS_SOLID, 1, RGB(rgbPart, rgbPart, rgbPart));
dc.SelectObject(&pnDraw);
dc.MoveTo(baseX, 0);
dc.LineTo(baseX, 600);
rgbPart += 51;
baseX++;
pnDraw.DeleteObject();
}
// TODO: Add your message handler code here
CRect rt(640, 70, 750, 120);
CString str;
str.Format("score: %d", m_nScore);
dc.SetBkMode(0);
dc.DrawText(str, rt, DT_CENTER);
}
if (m_gameState == ST_PRE) {
CRect rt(250, 250, 500, 500);
CString str = "Press any key to start!";
dc.SetBkMode(0);
dc.DrawText(str, &rt, DT_CENTER);
}
// Do not call CFrameWnd::OnPaint() for painting messages
}
void snakeFrame::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
MoveTo(m_state);
CFrameWnd::OnTimer(nIDEvent);
}
bool snakeFrame::NodeValid(Node *skNode)
{
if ((skNode->m_ptBase.x < 0) || (skNode->m_ptBase.x >= 60) ||
(skNode->m_ptBase.y < 0) || (skNode->m_ptBase.y >= 60))
return false;
Node *temp = m_snakeHead->m_pNext;
while (temp != NULL)
{
if (skNode->m_ptBase == temp->m_ptBase)
return false;
else
temp = temp->m_pNext;
}
return true;
}
void snakeFrame::GameBegin()
{
m_gameState = ST_PLAY;
m_state = LEFT;
CClientDC dc(this);
m_snakeTail = new Node(TAIL, CPoint(15, 0), NULL, NULL);
m_snakeHead = m_snakeTail;
AddHead(LEFT);
AddHead(LEFT);
AddHead(LEFT);
SetTimer(1, m_nElapse, NULL);
NewFood();
Invalidate();
}
void snakeFrame::GameOver()
{
CClientDC dc(this);
// Draw gameover
CRect rt(250, 250, 500, 500);
CString str = "GAME OVER !";
dc.SetBkMode(0);
dc.DrawText(str, rt, DT_CENTER);
CRect rtClient;
GetClientRect(&rtClient);
dc.FillRect(&rtClient, &CBrush(RGB(255, 255, 255)));
Node *temp = m_snakeHead;
while (temp != NULL)
{
m_snakeHead = m_snakeHead->m_pNext;
delete temp;
temp = m_snakeHead;
}
_sleep(800);
m_nScore = 0;
m_nElapse = 200;
m_gameState = ST_PRE;
m_foodNode.m_nID = -1;
m_state = -1;
Invalidate();
}
void snakeFrame::MoveTo(int st)
{
switch (st)
{
case UP:
if (m_state == DOWN)
break;
else {
if ((m_foodNode.m_ptBase.y == m_snakeHead->m_ptBase.y - 1) && (m_foodNode.m_ptBase.x == m_snakeHead->m_ptBase.x))
EatFood();
else {
if (AddHead(UP))
DeleteTail();
else
GameOver();
}
}
break;
case DOWN:
if (m_state == UP)
break;
else {
if ((m_foodNode.m_ptBase.y == m_snakeHead->m_ptBase.y + 1) && (m_foodNode.m_ptBase.x == m_snakeHead->m_ptBase.x))
EatFood();
else {
if (AddHead(DOWN))
DeleteTail();
else
GameOver();
}
}
break;
case LEFT:
if (m_state == RIGHT)
break;
else{
if ((m_foodNode.m_ptBase.x == m_snakeHead->m_ptBase.x - 1) && (m_foodNode.m_ptBase.y == m_snakeHead->m_ptBase.y))
EatFood();
else {
if (AddHead(LEFT))
DeleteTail();
else GameOver();
}
}
break;
case RIGHT:
if (m_state == LEFT)
break;
else {
if ((m_foodNode.m_ptBase.x == m_snakeHead->m_ptBase.x + 1) && (m_foodNode.m_ptBase.y == m_snakeHead->m_ptBase.y))
EatFood();
else {
if (AddHead(RIGHT))
DeleteTail();
else GameOver();
}
}
break;
}
}
void snakeFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
if ((m_gameState == ST_PRE) && nChar)
GameBegin();
if (m_gameState == ST_PLAY){
switch (nChar)
{
case VK_UP:
MoveTo(UP);
if (m_state != DOWN)
m_state = UP;
break;
case VK_DOWN:
MoveTo(DOWN);
if (m_state != UP)
m_state = DOWN;
break;
case VK_LEFT:
MoveTo(LEFT);
if (m_state != RIGHT)
m_state = LEFT;
break;
case VK_RIGHT:
MoveTo(RIGHT);
if (m_state != LEFT)
m_state = RIGHT;
break;
}
}
CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
void snakeFrame::DeleteTail()
{
CClientDC dc(this);
m_snakeTail->DrawCell(&dc, true);
m_snakeTail->m_pPre->DrawCell(&dc, true);
Node *temp = m_snakeTail->m_pPre;
temp->m_nID = TAIL;
delete m_snakeTail;
temp->m_pNext = NULL;
m_snakeTail = temp;
m_snakeTail->DrawCell(&dc);
}
bool snakeFrame::AddHead(int orient)
{
CClientDC dc(this);
CPoint ptTemp;
Node *temp = NULL;
switch (orient)
{
case UP:
ptTemp.x = m_snakeHead->m_ptBase.x;
ptTemp.y = m_snakeHead->m_ptBase.y - 1;
temp = new Node(HEAD, ptTemp, NULL, m_snakeHead);
if (!NodeValid(temp)) {
delete temp;
return false;
}
else {
m_snakeHead->DrawCell(&dc ,true);
m_snakeHead->m_pPre = temp;
m_snakeHead->m_nID = BODY;
m_snakeHead = temp;
m_snakeHead->DrawCell(&dc);
return true;
}
case DOWN:
ptTemp.x = m_snakeHead->m_ptBase.x;
ptTemp.y = m_snakeHead->m_ptBase.y + 1;
temp = new Node(HEAD, ptTemp, NULL, m_snakeHead);
if (!NodeValid(temp))
{ delete temp;
return false;
}
else {
m_snakeHead->DrawCell(&dc, true);
m_snakeHead->m_pPre = temp;
m_snakeHead->m_nID = BODY;
m_snakeHead = temp;
m_snakeHead->DrawCell(&dc);
return true;
}
case LEFT:
ptTemp.x = m_snakeHead->m_ptBase.x - 1;
ptTemp.y = m_snakeHead->m_ptBase.y;
temp = new Node(HEAD, ptTemp, NULL, m_snakeHead);
if (!NodeValid(temp)) {
delete temp;
return false;
}
else{
m_snakeHead->DrawCell(&dc, true);
m_snakeHead->m_pPre = temp;
m_snakeHead->m_nID = BODY;
m_snakeHead = temp;
m_snakeHead->DrawCell(&dc);;
return true;
}
case RIGHT:
ptTemp.x = m_snakeHead->m_ptBase.x + 1;
ptTemp.y = m_snakeHead->m_ptBase.y;
temp = new Node(HEAD, ptTemp, NULL, m_snakeHead);
if (!NodeValid(temp)) {
delete temp;
return false;
}
else{
m_snakeHead->DrawCell(&dc, true);
m_snakeHead->m_pPre = temp;
m_snakeHead->m_nID = BODY;
m_snakeHead = temp;
m_snakeHead->DrawCell(&dc);
return true;
}
default :return false;
}
}
void snakeFrame::DrawSnake(CDC *pDC)
{
Node * temp = m_snakeHead;
while (temp != NULL)
{
if (temp == m_snakeTail)
temp->m_nID = TAIL;
temp->DrawCell(pDC);
temp = temp->m_pNext;
}
}
void snakeFrame::EatFood()
{
CClientDC dc(this);
m_snakeHead->DrawCell(&dc, true);
Node *pFood = new Node(m_foodNode);
pFood->m_nID = HEAD;
m_snakeHead->m_pPre = pFood;
pFood->m_pNext = m_snakeHead;
m_snakeHead->m_nID = BODY;
m_snakeHead = pFood;
m_snakeHead->DrawCell(&dc);
m_nScore += 10;
if (m_nElapse >= 50){
m_nElapse--;
SetTimer(1, m_nElapse, NULL);
}
CRect rt(640, 70, 750, 120);
dc.FillRect(&rt, &CBrush(RGB(255, 255, 255)));
CString str;
str.Format("score: %d", m_nScore);
dc.SetBkMode(0);
dc.DrawText(str, rt, DT_CENTER);
NewFood();
m_foodNode.DrawCell(&dc);
}
void snakeFrame::NewFood()
{
CClientDC dc(this);
m_foodNode.m_nID = FOOD;
srand(time(NULL));
m_foodNode.m_ptBase.x = rand() % 60;
m_foodNode.m_ptBase.y = rand() % 60;
m_foodNode.m_pNext = m_foodNode.m_pPre = NULL;
while (!foodValid(m_foodNode)) {
srand(time(NULL));
m_foodNode.m_ptBase.x = rand() % 60;
m_foodNode.m_ptBase.y = rand() % 60;
}
}
bool snakeFrame::foodValid(Node fdNode)
{
Node *temp = m_snakeHead;
while (temp != NULL)
{
if (fdNode.m_ptBase == temp->m_ptBase)
return false;
else temp = temp->m_pNext;
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -