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

📄 board.cpp

📁 一款自已开发的贪吃蛇游戏
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	}

	return true;
}
void CBoard::InitSnake()
{
	m_Snake.RemoveAll();
	CPoint ele;
	ele.x = COLS / 2;
	ele.y = ROWS / 2 - 3;
	m_ptHead.x = COLS / 2;
	m_ptHead.y = ROWS / 2 - 3;
	m_Snake.AddHead(ele);
}

CPoint CBoard::RandomSelCell()
{
	bool bFind = false;
	int	 nCount = 0;
	int nX, nY;
	CPoint pt;
	
	while (!bFind)
	{
		nX = rand() % COLS;
		nY = rand() % ROWS;
		nCount = 0;
		POSITION pos;
		for (int i = 0; i < m_nSnakeCount; i ++)
		{
			pos = m_Snake.FindIndex(i);
			pt = m_Snake.GetAt(pos);
			if (pt.x == nX && pt.y == nY){
				bFind = false;
				break;
			} // end if
			else
				nCount ++;
		} // end for

		if (nCount == m_nSnakeCount)
			bFind = true;
	} // end while
	m_ptFlashCell.x = nX;
	m_ptFlashCell.y = nY;

	return CPoint(nX,nY);
}

// ============================================================
// 判断 pt 是否是正在闪烁的方格,若是则变为蛇头,返回 true
// 否则返回 false
// ============================================================
bool CBoard::EatAgg(CPoint pt)
{
	if (pt.x == m_ptFlashCell.x && pt.y == m_ptFlashCell.y)
	{
		KillTimer(TIMER_CELL);
		RandomSelCell();
		SetTimer(TIMER_CELL, 400, NULL);			// flash the egg
		CPoint ele;
		ele.x = pt.x;
		ele.y = pt.y;
		m_Snake.AddHead(ele);
		m_nSnakeCount ++;
		m_nScores += 100;
		m_dpScore.SetNumber(m_nScores);
		m_ptHead.x = pt.x;
		m_ptHead.y = pt.y;
		
		if (m_nSnakeCount >= SNAKE_COUNT){
			WinGame();
			EndGame(true);
			SpeedUp();
		}
	}
	else
		return false;
	
	return true;
}

void CBoard::SwapSnakeCell(CPoint pt)
{
	//  add to head, delete from tail
	m_Snake.AddHead(pt);
	m_Snake.RemoveTail();

	m_ptHead.x = pt.x;
	m_ptHead.y = pt.y;
}

void CBoard::MoveBackword()
{
	int nCnt = m_Snake.GetCount();
	if (nCnt == 1) // the snake only have one element
	{
		return;
	}

	CPoint ptTmp, ptLast;
	POSITION pos;
	
	ptLast = m_Snake.GetTail();
	pos = m_Snake.FindIndex(nCnt - 2);
	ptTmp  = m_Snake.GetAt(pos); // get the second last element
	
	// When use the tail to move, set the new current movetype
	if (ptLast.x == ptTmp.x) // vertical
	{
		if (ptLast.y == ptTmp.y + 1) // last at bottom
			m_mtCurrent = MOVE_DOWN;
		else
			m_mtCurrent = MOVE_UP;
	}						// horizontal
	else
	{
		if (ptLast.x > ptLast.x) // last at right
			m_mtCurrent = MOVE_RIGHT;
		else
			m_mtCurrent = MOVE_LEFT;
	}

	m_ptHead.x = ptLast.x;
	m_ptHead.y = ptLast.y;

	// reverse the snake element
	int nEnd = (nCnt / 2); // the circle number
	POSITION psLast;
	
	for (int i = 0; i < nEnd; i ++)
	{
		pos = m_Snake.FindIndex(i);
		psLast = m_Snake.FindIndex(nCnt - i - 1);
		ptTmp = m_Snake.GetAt(pos);
		m_Snake.GetAt(pos) = m_Snake.GetAt(psLast);
		m_Snake.GetAt(psLast) = ptTmp;
	}

}

void CBoard::SpeedUp(bool bRestart /* = true */)
{
	if (bRestart)
	{
		KillTimer(TIMER_SNAKE);
		m_nSpeedLevel = (m_nSpeedLevel + 1) % 10;
		m_dpSpeed.SetNumber(m_nSpeedLevel);
		m_nSpeed = (10 - m_nSpeedLevel) * TIME_SPAN;
		m_nSnakeCount = 1;
		m_bWinGame    = true;
		
		m_Snake.RemoveAll();
		InitSnake();
		m_mtCurrent = MOVE_DOWN;
		SetTimer(TIMER_SNAKE, m_nSpeed, NULL);
	}
	else
	{
		KillTimer(TIMER_SNAKE);
		m_nSpeedLevel = (m_nSpeedLevel + 1) % 10;
		m_dpSpeed.SetNumber(m_nSpeedLevel);
		m_nSpeed = (10 - m_nSpeedLevel) * TIME_SPAN;
		SetTimer(TIMER_SNAKE, m_nSpeed, NULL);
	}
}
// ************************************************************
//						Game Processor Procedure
// ************************************************************

void CBoard::StartGame()
{
	// Initiate game data
	ReadyGame(true);
	//InvalidateRect(m_rtClientLeft);
//	if (!m_bWinGame)
//		m_nScores	= 0;
	if (m_nDeadSum < GAME_SUM)
	{
		if (!m_bWinGame)      // the player dead 
			m_nDeadSum ++;
	}
	else
	{
		m_nDeadSum = 0;
		m_nScores  = 0;
	}

	m_nSnakeCount	= 1;
	m_nSpeed		= (10 - m_nSpeedLevel) * TIME_SPAN;
	m_nState		= GAME_PLAYING;
	m_mtCurrent		= MOVE_DOWN;
	m_dpScore.SetNumber(m_nScores);
	m_dpSpeed.SetNumber(m_nSpeedLevel);
	DrawPlayers(GAME_SUM - m_nDeadSum + 1);

	for (int nRow = 0; nRow < ROWS; nRow ++)
		for (int nCol = 0; nCol < COLS; nCol ++)
		{
			m_bData[nRow][nCol] = 0;
		}

	InitSnake();
	RandomSelCell();
	SetTimer(TIMER_CELL, 400, NULL);			// flash the egg
	SetTimer(TIMER_SNAKE, m_nSpeed, NULL);	// the snake moving
}

void CBoard::ResumeGame()
{
	EndGame();
	m_nSpeedLevel = 0;
	m_bWinGame = true;
	m_nDeadSum	  = 0;	
	StartGame();
}

void CBoard::EndGame(bool bWinGame, bool bGameOver)
{
	KillTimer(TIMER_SNAKE);
	KillTimer(TIMER_CELL);
	CDC *pDC = GetDC();
	DrawSnake(pDC, false, true);
	ReleaseDC(pDC);
	InvalidateRect(m_rtClientLeft);
	DrawPlayers(4, false);

	if (bGameOver)	// end the game 
	{
		LostGame(2);
		m_nState = GAME_READY;
		return;
	}

	m_bWinGame = bWinGame;
	if (bWinGame){
		StartGame();
		return;
	}
	if (m_nDeadSum < GAME_SUM){
		LostGame(1);
		StartGame();
	}
	else
	{
		m_nState = GAME_READY;
		LostGame(2);
	}
	
}

void CBoard::PauseGame()
{
	if (m_nState == GAME_PLAYING)
	{
		KillTimer(TIMER_SNAKE);
		m_nState = GAME_PAUSE;
		m_btnPause.SetWindowText("CONTINUE");
	}
	else if (m_nState == GAME_PAUSE)
	{
		SetTimer(TIMER_SNAKE, m_nSpeed, NULL);
		m_nState = GAME_PLAYING;
		m_btnPause.SetWindowText("PAUSE");
	}
}

void CBoard::WinGame()
{
	int nRow, nCol;
	CPoint pt;
	long lDelay = 50;
	CDC *pDC = GetDC();

	// Flash the snake
	DrawSnake(pDC, false, true);
	_sleep(200);
	DrawSnake(pDC, true, true);
	_sleep(200);
	DrawSnake(pDC, false,true);

	for (nCol = 0; nCol < COLS; nCol ++) // ||
	{
		for (nRow = 0; nRow < ROWS; nRow ++){
			pt.x = nCol;
			pt.y = nRow;
			DrawCell(pDC, pt, true);
			pt.x = COLS - nCol - 1;
			DrawCell(pDC, pt, true);
		}
		_sleep(lDelay);
		for (nRow = 0; nRow < ROWS; nRow ++){
			pt.x = nCol;
			pt.y = nRow;
			DrawCell(pDC, pt, false);
			pt.x = COLS - nCol - 1;
			DrawCell(pDC, pt, false);
		}
		if (lDelay > 10)
			lDelay -=3;
	}

	for (nCol = 0; nCol < COLS; nCol ++) // ||
	{
		for (nRow = 0; nRow < ROWS; nRow ++){
			pt.x = nCol;
			pt.y = nRow;
			DrawCell(pDC, pt, true);
			pt.x = COLS - nCol - 1;
			DrawCell(pDC, pt, true);
		}
		_sleep(lDelay);
		for (nRow = 0; nRow < ROWS; nRow ++){
			pt.x = nCol;
			pt.y = nRow;
			DrawCell(pDC, pt, false);
			pt.x = COLS - nCol - 1;
			DrawCell(pDC, pt, false);
		}
		if (lDelay < 50)
			lDelay +=3;
	}

	ReleaseDC(pDC);
	InvalidateRect(m_rtClientLeft);
}

// 1 round over, 2 game over
void CBoard::LostGame(int nEvent/* = 1*/)
{
	int nRow, nCol;
	CPoint pt;
	CDC *pDC = GetDC();

	KillTimer(TIMER_CELL);
	DrawCell(pDC, m_ptFlashCell, false);
	// =========================================================
	// Draw the outside rectangle

	pt.y = 0; // the first top line
	for (nCol = 0; nCol < COLS; nCol ++){
		pt.x = nCol;
		DrawCell(pDC, pt);
	}
	pt.y = ROWS - 1;
	for (nCol = 0; nCol < COLS; nCol ++){
		pt.x = nCol;
		DrawCell(pDC, pt);
	}
	pt.x = 0;
	for (nRow = 0; nRow < ROWS; nRow ++){
		pt.y = nRow;
		DrawCell(pDC, pt);
	}
	pt.x = COLS - 1;
	for (nRow = 0; nRow < ROWS; nRow ++){
		pt.y = nRow;
		DrawCell(pDC, pt);
	}
	_sleep(200);

	pt.y = 0; // the first top line
	for (nCol = 0; nCol < COLS; nCol ++){
		pt.x = nCol;
		DrawCell(pDC, pt, false);
	}
	pt.y = ROWS - 1;
	for (nCol = 0; nCol < COLS; nCol ++){
		pt.x = nCol;
		DrawCell(pDC, pt, false);
	}
	pt.x = 0;
	for (nRow = 0; nRow < ROWS; nRow ++){
		pt.y = nRow;
		DrawCell(pDC, pt, false);
	}
	pt.x = COLS - 1;
	for (nRow = 0; nRow < ROWS; nRow ++){
		pt.y = nRow;
		DrawCell(pDC, pt, false);
	}

	// ========================================================
	// Draw the second outside rectangle

	pt.y = 3; // the second top line
	for (nCol = 1; nCol < COLS - 1; nCol ++){
		pt.x = nCol;
		DrawCell(pDC, pt);
	}
	pt.y = ROWS - 4;
	for (nCol = 1; nCol < COLS - 1; nCol ++){
		pt.x = nCol;
		DrawCell(pDC, pt);
	}
	pt.x = 1;
	for (nRow = 3; nRow < ROWS - 3; nRow ++){
		pt.y = nRow;
		DrawCell(pDC, pt);
	}
	pt.x = COLS - 2;
	for (nRow = 3; nRow < ROWS - 3; nRow ++){
		pt.y = nRow;
		DrawCell(pDC, pt);
	}
	_sleep(200);
	
	pt.y = 3; // the second top line
	for (nCol = 1; nCol < COLS - 1; nCol ++){
		pt.x = nCol;
		DrawCell(pDC, pt, false);
	}
	pt.y = ROWS - 4;
	for (nCol = 1; nCol < COLS - 1; nCol ++){
		pt.x = nCol;
		DrawCell(pDC, pt, false);
	}
	pt.x = 1;
	for (nRow = 3; nRow < ROWS - 3; nRow ++){
		pt.y = nRow;
		DrawCell(pDC, pt, false);
	}
	pt.x = COLS - 2;
	for (nRow = 3; nRow < ROWS - 3; nRow ++){
		pt.y = nRow;
		DrawCell(pDC, pt, false);
	}

	// ========================================================
	// Draw the third outside rectangle

	pt.y = 6; // the third top line
	for (nCol = 2; nCol < COLS - 2; nCol ++){
		pt.x = nCol;
		DrawCell(pDC, pt);
	}
	pt.y = ROWS - 8;
	for (nCol = 2; nCol < COLS - 2; nCol ++){
		pt.x = nCol;
		DrawCell(pDC, pt);
	}
	pt.x = 2;
	for (nRow = 6; nRow < ROWS - 7; nRow ++){
		pt.y = nRow;
		DrawCell(pDC, pt);
	}
	pt.x = COLS - 3;
	for (nRow = 6; nRow < ROWS - 7; nRow ++){
		pt.y = nRow;
		DrawCell(pDC, pt);
	}

	CString sTop, sBottom;
	CRect rtTop(3 * WIDTH, 7 * WIDTH, 7 * WIDTH, 8 * WIDTH + 10);
	CRect rtBottom(3 * WIDTH, 8 * WIDTH + 10, 7 * WIDTH, 10 * WIDTH);

	if (nEvent == 1)
	{
		sTop	 = "YOU";
		sBottom	 = "LOST";
	}
	else if (nEvent == 2)
	{
		sTop	 = "GAME";
		sBottom  = "OVER";
	}
	DrawMyText(pDC, sTop, rtTop, 11);
	DrawMyText(pDC, sBottom, rtBottom, 11);

	_sleep(1000);

	ReleaseDC(pDC);
	InvalidateRect(m_rtClientLeft);
}

void CBoard::ReadyGame(bool bOver /*= false*/)
{
	if (bOver)
	{
		KillTimer(TIMER_READY);
		for (int nRow = 0; nRow < ROWS; nRow ++)
			for (int nCol = 0; nCol < COLS; nCol ++)
			{
				m_bData[nRow][nCol] = 0;
			}
		InvalidateRect(m_rtClientLeft);
	}

	int i;
	for (i = 0; i < COLS; i ++){ // set the first row
		if (i % 2 == 0)
			m_bData[0][i] = 1;
		else
			m_bData[0][i] = 2;
	}

	for (i = 0; i < COLS; i ++){ // set the last row
		if (i % 2 != 0)
			m_bData[ROWS - 1][i] = 1;
		else
			m_bData[ROWS - 1][i] = 2;
	}

	for (i = 0; i < ROWS; i ++){ // set the first col
		if (i % 2 == 0)
			m_bData[i][0] = 1;
		else
			m_bData[i][0] = 2;
	}

	for (i = 0; i < ROWS; i ++){ // set the last col
		if (i % 2 != 0)
			m_bData[i][COLS - 1] = 1;
		else
			m_bData[i][COLS - 1] = 2;
	}

	// Fill a rectangle with 1 to include "Ready"
	for (i = 2; i < COLS - 2; i ++){
		m_bData[ROWS/3][i] = 1;
	}
	for (i = 2; i < COLS -2; i ++){
		m_bData[ROWS/3+3][i] = 1;
	}
	for (i = ROWS/3; i < ROWS/3 + 3; i ++){
		m_bData[i][2] = 1;
	}
	for (i = ROWS/3; i < ROWS/3 + 3; i ++){
		m_bData[i][COLS-3] = 1;
	}
	
	SetTimer(TIMER_READY, 350, NULL);
}

// ************************************************************
//						Annex Function
// ************************************************************

void CBoard::DrawMyText(CDC *pDC, CString sText, CRect rtClient, int nSize, COLORREF cr)
{
	pDC->SetBkMode(0);
	pDC->SetTextColor(RGB(255,255,255));    // back text

	CFont fnBig;
	fnBig.CreateFont(3 * nSize,				// nHeight
					0,						// nWidth
					0,						// nEscapement
					0,						// nOrientation
					100,					// nWeight
					FALSE,					// bItalic
					FALSE,					// bUnderline
					FALSE,					// cStrikeOut
					ANSI_CHARSET,			// nCharSet
					OUT_DEFAULT_PRECIS,		// nOutPrecision
					CLIP_DEFAULT_PRECIS,	// nClipPrecision
					PROOF_QUALITY,			// nQuality
					DEFAULT_PITCH+FF_DONTCARE,// nPitchAndFamily
					"Arail");				// lpszFacename 

	ASSERT_VALID(&fnBig);
	CFont *pOldFont = pDC->SelectObject(&fnBig);
	pDC->DrawText( sText, rtClient, DT_CENTER );

	rtClient.OffsetRect(1, 1 );
	pDC->SetTextColor( cr );   // fore text
	pDC->DrawText( sText, rtClient, DT_CENTER );

	pDC->SelectObject(pOldFont);
}

bool CBoard::EnableSound(bool bSound /*= true*/)
{
	bool bPrevious = m_bSound;
	m_bSound = bSound;

	return bPrevious;
}

void CBoard::OnBtnSound()
{
	bool b = EnableSound();
	if (b)
		m_bSound = false;
	else
		m_bSound = true;

	if (m_bSound)
		//m_hMusic = AfxBeginThread(PlayBkMusic, this);
		//DWORD d = ::ResumeThread(m_hMusic);
		m_nMidState = 2; //continue
	else{
		//m_MidBk.Stop(false);
		//::SuspendThread(m_hMusic);
		//DWORD d = GetLastError();
		m_nMidState = 1; // pause
	}
}

void CBoard::OnBtnStart()
{
	if (GetGameState() == GAME_READY)
		StartGame();
}

void CBoard::OnBtnPause()
{
	if (GetGameState() != GAME_READY)
		PauseGame();
}

void CBoard::OnBtnRestart()
{
	ResumeGame();
}

void CBoard::OnBtnEnd()
{
	if (GetGameState() != GAME_READY)
		EndGame(false, true);
}

UINT CBoard::PlayBkMusic(LPVOID pParam)
{
	((CBoard*)pParam)->m_MidBk.Play(true);
	while (1)
	{
		if (m_nMidState == 2)
			((CBoard*)pParam)->m_MidBk.Continue();
		else if (m_nMidState == 1)
			((CBoard*)pParam)->m_MidBk.Pause();
	}
	return 0;
}

⌨️ 快捷键说明

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