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

📄 sgameview.cpp

📁 自己写的贪吃蛇的MFC源代码
💻 CPP
字号:
// SGameView.cpp : implementation of the CSGameView class
//

#include "stdafx.h"
#include "SGame.h"

#include "SGameDoc.h"
#include "SGameView.h"

#include "NewRecordDlg.h"
#include "HeroDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//分数
int score=0;

//蛇的结构体
struct Snake 
{
	int x,y; //左上角坐标
	int dir; //蛇头方向
	int nLen; //蛇的长度
}Snake[50];  

//Snake[0]是蛇头那一格
//吃的格子
struct EatedFood
{
	int x,y;
	BOOL isEated; //被吃了没有
}food;
/////////////////////////////////////////////////////////////////////////////
// CSGameView

IMPLEMENT_DYNCREATE(CSGameView, CView)

BEGIN_MESSAGE_MAP(CSGameView, CView)
	//{{AFX_MSG_MAP(CSGameView)
	ON_WM_TIMER()
	ON_COMMAND(ID_NEWGAME, OnNewGame)
	ON_WM_KEYDOWN()
	ON_COMMAND(ID_LEVEL1, OnLevel1)
	ON_COMMAND(ID_LEVEL2, OnLevel2)
	ON_COMMAND(ID_LEVEL3, OnLevel3)
	ON_COMMAND(ID_LEVEL4, OnLevel4)
	ON_COMMAND(ID_LEVEL5, OnLevel5)
	ON_UPDATE_COMMAND_UI(ID_LEVEL1, OnUpdateLevel1)
	ON_UPDATE_COMMAND_UI(ID_LEVEL2, OnUpdateLevel2)
	ON_UPDATE_COMMAND_UI(ID_LEVEL3, OnUpdateLevel3)
	ON_UPDATE_COMMAND_UI(ID_LEVEL4, OnUpdateLevel4)
	ON_UPDATE_COMMAND_UI(ID_LEVEL5, OnUpdateLevel5)
	ON_COMMAND(ID_MRHERO, OnMrhero)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSGameView construction/destruction

CSGameView::CSGameView()
{
	m_level=1;
}

CSGameView::~CSGameView()
{
}

BOOL CSGameView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs
	//设置背景色,光标
    cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
		LoadCursor(NULL,IDC_CROSS),(HBRUSH)GetStockObject(BLACK_BRUSH));   
	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CSGameView drawing

void CSGameView::OnDraw(CDC* pDC)
{
	m_score.Format("%d",score);
	m_strLevel.Format("%d",m_level);

	CSGameDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	//矩形活动区 能容纳40格
	pDC->Rectangle(0,0,401,401);
    pDC->SetBkColor(RGB(0,0,0));
	pDC->SetTextColor(RGB(255,255,255));
	pDC->DrawText(_T("分数"),CRect(400,100,500,120),DT_CENTER );
	pDC->DrawText(m_score,CRect(400,120,500,140),DT_CENTER );

	pDC->DrawText(_T("等级"),CRect(400,140,500,160),DT_CENTER );
	pDC->DrawText(m_strLevel,CRect(400,160,500,180),DT_CENTER );
	this->InitSnake();
}

/////////////////////////////////////////////////////////////////////////////
// CSGameView diagnostics

#ifdef _DEBUG
void CSGameView::AssertValid() const
{
	CView::AssertValid();
}

void CSGameView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CSGameDoc* CSGameView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSGameDoc)));
	return (CSGameDoc*)m_pDocument;
}
#endif //_DEBUG

void CSGameView::InitSnake()
{
	CDC *pDC=GetDC();
	CBrush SBrush=(RGB(255,215,0));
	CBrush *pOldBR=pDC->SelectObject(&SBrush);

	//画蛇的一格
	CPen pen(PS_SOLID,1,RGB(255,255,255)); //白色画笔
	CPen *pOldPen=pDC->SelectObject(&pen);
	pDC->Rectangle(Snake[0].x*10,Snake[0].y*10,(Snake[0].x+1)*10,(Snake[0].y+1)*10);
    pDC->Rectangle(food.x*10,food.y*10,(food.x+1)*10,(food.y+1)*10); //食物 
	pDC->SelectObject(pOldBR);
	pDC->SelectObject(pOldPen);
}

void CSGameView::OnTimer(UINT nIDEvent) 
{
	CDC* pDC=GetDC();
	//如果食物没有被吃
	if (nIDEvent==2 && !food.isEated) 
	{
		//檫除原来的食物
		pDC->SelectStockObject(WHITE_PEN);
	    pDC->Rectangle(food.x*10,food.y*10,(food.x+1)*10,(food.y+1)*10);
		this->CreateFood();
	}
	//檫除蛇尾的那一格
	pDC->SelectStockObject(WHITE_PEN);
	pDC->Rectangle(Snake[Snake[0].nLen-1].x*10,Snake[Snake[0].nLen-1].y*10,(Snake[Snake[0].nLen-1].x+1)*10,(Snake[Snake[0].nLen-1].y+1)*10);
	for(int i=Snake[0].nLen-1;i>0;i--)
	{
		Snake[i].x=Snake[i-1].x;
		Snake[i].y=Snake[i-1].y;
	}	
	//方向
	if(Snake[0].dir==1)//向上
		Snake[0].y--;
	if(Snake[0].dir==2)//向右
		Snake[0].x++;
	if(Snake[0].dir==3)//向下
		Snake[0].y++;
	if(Snake[0].dir==4)//向左
		Snake[0].x--;
    //如果食物被吃了 
	if(Snake[0].x==food.x && Snake[0].y==food.y)
	{
		Snake[0].nLen++;
		score+=10; //分数加
		m_score.Format("%d",score);
		pDC->SetBkColor(RGB(0,0,0));
		pDC->SetTextColor(RGB(255,255,255));
		pDC->DrawText(m_score,CRect(400,120,500,140),DT_CENTER );

		Snake[Snake[0].nLen-1].x=Snake[Snake[0].nLen-2].x;
		Snake[Snake[0].nLen-1].y=Snake[Snake[0].nLen-2].y;
		this->CreateFood(); //生成另一个
	}	
	//是否撞到自己身体了
	if(Snake[0].nLen>2)
	{
		for(int sn=Snake[0].nLen-1;sn>0;sn--)
		{
			if(Snake[0].x==Snake[sn].x && Snake[0].y==Snake[sn].y)
			{
				this->GameOver();
				return;
			}
		}
	}
	//判断是否撞到墙了
	if (Snake[0].x>39 || Snake[0].x<0 || Snake[0].y<0 || Snake[0].y>39)
	{
		this->GameOver();
		return;
	}
	
	//画新的一格
	CBrush SBrush=(RGB(255,215,0));
	CBrush*	pOldBR=pDC->SelectObject(&SBrush);
	pDC->Rectangle(Snake[0].x*10,Snake[0].y*10,(Snake[0].x+1)*10,(Snake[0].y+1)*10);
	pDC->SelectObject(pOldBR);	
	///////////////////////////////////////////////////////////////////
	if (m_level>4)
	{
		if (score>600)
		{
			KillTimer(1);
    		KillTimer(2);
			MessageBox("牛B,通关了");
			return;
		}
	}
	//每吃到8格是一关
    //if (Snake[0].nLen>=(m_level*2))
	else if (Snake[0].nLen>=m_level*8)
	{
		KillTimer(1);
		KillTimer(2);
		this->LevelUpdate();

		pDC->SetBkColor(RGB(0,0,0));
		pDC->SetTextColor(RGB(255,255,255));
       	pDC->DrawText(m_strLevel,CRect(400,160,500,180),DT_CENTER );
		this->OnNewGame();
	}
	
	CView::OnTimer(nIDEvent);
}

void CSGameView::OnNewGame() 
{
	//画等级
	CDC* pDC=GetDC(); 
	m_strLevel.Format("%d",m_level);
    pDC->SetBkColor(RGB(0,0,0));
	pDC->SetTextColor(RGB(255,255,255));
	pDC->DrawText(_T("等级"),CRect(400,140,500,160),DT_CENTER );
	pDC->DrawText(m_strLevel,CRect(400,160,500,180),DT_CENTER );

	int ntime1,ntime2;
	switch (m_level)
	{
	case 1:
		ntime1=100;ntime2=8000;
		break;
	case 2:
		ntime1=70;ntime2=7500;
		break;
	case 3:
		ntime1=50;ntime2=6500;
		break;
	case 4:
		ntime1=40;ntime2=5000;
		break;
	case 5:
		ntime1=30;ntime2=3000;
		break;
	}
	//计时器的时间就是蛇的速度
	SetTimer(1,ntime1,NULL);
	//食物的计时器
	SetTimer(2,ntime2,NULL);
}
//初始化函数,第一个格子
void CSGameView::OnInitialUpdate() 
{
	Snake[0].x=20;
	Snake[0].y=20;
	Snake[0].nLen=1;
	Snake[0].dir=2;
	//
	food.x=30;
	food.y=30;
	food.isEated=FALSE;

	CView::OnInitialUpdate();	
}
//键盘方向键
void CSGameView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	switch(nChar)
	{
	case VK_UP:
		if (Snake[0].dir==3)
			break;   //不能反向行走
		Snake[0].dir=1;
		break;
	case VK_RIGHT:
		if(Snake[0].dir==4)
			break;
		Snake[0].dir=2;
		break;
	case VK_DOWN:
		if(Snake[0].dir==1)
			break;
		Snake[0].dir=3;
		break;
	case VK_LEFT:
		if(Snake[0].dir==2)
			break;
		Snake[0].dir=4;
		break;
	}
	
	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}


void CSGameView::CreateFood()
{
	CDC* pDC=GetDC();
	//
	CPen pen(PS_SOLID,1,RGB(255,255,255)); //白色画笔
	CPen *pOldPen=pDC->SelectObject(&pen);

	srand((unsigned)time(NULL));
	int i=0;
	do
	{   //生成的蛇不能与原来的蛇身体重叠
		food.x=rand()%40;
		food.y=rand()%40;
		for(i=0;i<Snake[0].nLen;i++)
		{
			if(food.x==Snake[i].x || food.y==Snake[i].y)
				break;
		}
		//如果i>=nLen那么跟蛇的全部的节点都比较完了,没有重叠的
        if (i>=Snake[0].nLen)
        {
			break;
        }
         
	}while(1);

	CBrush SBrush=(RGB(255,215,0));
	CBrush*	pOldBR=pDC->SelectObject(&SBrush);
	pDC->Rectangle(food.x*10,food.y*10,(food.x+1)*10,(food.y+1)*10);
	food.isEated=FALSE;
	pDC->SelectObject(pOldBR);
	pDC->SelectObject(pOldPen);
	ReleaseDC(pDC);
}

void CSGameView::GameOver()
{
	KillTimer(1);
	KillTimer(2);
	MessageBox("游戏结束");
	CHeroDlg dlg;
	int tmp=_ttoi(m_strTopScore);
	if (score>tmp)
	{
		CNewRecordDlg dlg1;
	    dlg1.DoModal();
        m_strTopName=dlg1.m_strInName;
		m_strTopLevel=m_strLevel;
		m_strTopScore=m_score;
		this->LoadData();

		dlg.m_strScore1=m_strTopScore;
		dlg.m_strName1=m_strTopName;
		dlg.m_strHeroLevel1=m_strTopLevel;
    	dlg.DoModal();
	}

	this->OnInitialUpdate();
	score=0;
	m_level=1;
}


void CSGameView::OnLevel1() 
{
	m_level=1;
}
void CSGameView::OnLevel2() 
{
	m_level=2;
}
void CSGameView::OnLevel3() 
{
	m_level=3;
}
void CSGameView::OnLevel4() 
{
	m_level=4;
}
void CSGameView::OnLevel5() 
{
	m_level=5;
}

void CSGameView::OnUpdateLevel1(CCmdUI* pCmdUI) 
{
	if (m_level == 1)
		pCmdUI -> SetCheck(TRUE);
	else
		pCmdUI -> SetCheck(FALSE);	
}

void CSGameView::OnUpdateLevel2(CCmdUI* pCmdUI) 
{
	if (m_level == 2)
		pCmdUI -> SetCheck(TRUE);
	else
		pCmdUI -> SetCheck(FALSE);	
}

void CSGameView::OnUpdateLevel3(CCmdUI* pCmdUI) 
{
	if (m_level == 3)
		pCmdUI -> SetCheck(TRUE);
	else
		pCmdUI -> SetCheck(FALSE);	
}

void CSGameView::OnUpdateLevel4(CCmdUI* pCmdUI) 
{
	if (m_level == 4)
		pCmdUI -> SetCheck(TRUE);
	else
		pCmdUI -> SetCheck(FALSE);	
}

void CSGameView::OnUpdateLevel5(CCmdUI* pCmdUI) 
{
	if (m_level == 5)
		pCmdUI -> SetCheck(TRUE);
	else
		pCmdUI -> SetCheck(FALSE);	
}

void CSGameView::LevelUpdate()
{
	MessageBox(_T("恭喜,进入下一关"));
	m_level++;
	
	Snake[0].x=20;
	Snake[0].y=20;
	Snake[0].dir=2;
	food.x=30;
	food.y=30;
	food.isEated=FALSE;
	m_strLevel.Format("%d",m_level);
}

void CSGameView::OnMrhero() 
{
	this->GetData();
	CHeroDlg dlg2;
	dlg2.m_strName1=m_strTopName;
	dlg2.m_strScore1=m_strTopScore;
	dlg2.m_strHeroLevel1=m_strTopLevel;
	dlg2.DoModal(); 
}

void CSGameView::LoadData()
{	
	WritePrivateProfileString("HeroData","姓名",m_strTopName,".\\myini.ini");
	WritePrivateProfileString("HeroData","分数",m_strTopScore,".\\myini.ini");
	WritePrivateProfileString("HeroData","等级",m_strTopLevel,".\\myini.ini");
}

void CSGameView::GetData()
{
	int nsize=8; // 大小为8
	GetPrivateProfileString("HeroData","姓名","匿名",m_strTopName.GetBuffer(nsize),nsize,".\\myini.ini");
	GetPrivateProfileString("HeroData","分数","默认",m_strTopScore.GetBuffer(nsize),nsize,".\\myini.ini");
	GetPrivateProfileString("HeroData","等级","默认",m_strTopLevel.GetBuffer(nsize),nsize,".\\myini.ini");
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -