📄 board.cpp
字号:
}
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 + -