⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snakeframe.cpp

📁 这是用VC编写的贪食蛇游戏
💻 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 + -