这里贴出主要源码如下:
#include "StdAfx.h"
#include "Snake.h"
Snake::Snake():m_NewDrection(m_right),m_OldDrection(m_right)
{
int i;
for (i = 0; i < 400; i++)
{
m_NewSnakePos[i].x = 1;
m_NewSnakePos[i].y = 1;
m_NewSnakePos[i].Status = 1;
m_NewLenth = 0;
}
Object::GetPosition(m_OldSnakePos);
m_OldLenth = Object::GetPosNum();
}
Snake::~Snake()
{
}
void
Snake::initSnake()
{
m_NewLenth = 6;
for (int i = 0; i < 6; i++)
{
m_NewSnakePos[i].x = i+1;
m_NewSnakePos[i].y = 1;
m_NewSnakePos[i].Status = 1;
}
}
void
Snake::GetNewSnakePos(Pos* pos)
{
int i;
for (i = 0; i < 400; ++i)
{
pos[i].Status = m_NewSnakePos[i].Status;
pos[i].x = m_NewSnakePos[i].x;
pos[i].y = m_NewSnakePos[i].y;
}
}
void
Snake::Move()
{
int i;
for (i = 0; i < m_NewLenth; ++i) // 把当前蛇的位置及蛇身长度拷贝到OldSnake中保存
{
m_OldSnakePos[i].x = m_NewSnakePos[i].x;
m_OldSnakePos[i].y = m_NewSnakePos[i].y;
m_OldSnakePos[i].Status = m_NewSnakePos[i].Status;
}
m_OldLenth = m_NewLenth;
switch (m_NewDrection)
{
case m_right:
m_NewSnakePos[m_NewLenth - 1].x = m_OldSnakePos[m_NewLenth - 1].x + 1;
break;
case m_left:
m_NewSnakePos[m_NewLenth - 1].x = m_OldSnakePos[m_NewLenth - 1].x - 1;
break;
case m_up:
m_NewSnakePos[m_NewLenth - 1].y = m_OldSnakePos[m_NewLenth - 1].y - 1;
break;
case m_down:
m_NewSnakePos[m_NewLenth - 1].y = m_OldSnakePos[m_NewLenth - 1].y + 1;
break;
}
m_NewSnakePos[m_NewLenth - 1].Status = 1;
m_NewSnakePos[m_NewLenth].x = m_OldSnakePos[0].x; // 在蛇身体数组后增加一个点,来记录蛇尾位置,并设置为空地状态,实现蛇尾的擦除
m_NewSnakePos[m_NewLenth].y = m_OldSnakePos[0].y;
m_NewSnakePos[m_NewLenth].Status = 0;
for (i = 1; i < m_NewLenth; ++i) // 从OldSnake获取除了蛇头蛇尾外的所有位置信息
{
m_NewSnakePos[i - 1].x = m_OldSnakePos[i].x;
m_NewSnakePos[i - 1].y = m_OldSnakePos[i].y;
}
}
void
Snake::AddLenth()
{
m_NewLenth = m_NewLenth + 1;
m_NewSnakePos[m_NewLenth].x = m_NewSnakePos[m_NewLenth - 1].x; // 记录需要擦除蛇尾的信息
m_NewSnakePos[m_NewLenth].y = m_NewSnakePos[m_NewLenth - 1].y;
m_NewSnakePos[m_NewLenth].Status = m_NewSnakePos[m_NewLenth - 1].Status;
m_NewSnakePos[m_NewLenth - 1].Status = 1;
switch (m_NewDrection) // 在蛇头前增加一个点,设置为新蛇头,来实现蛇身的增长
{
case m_right:
m_NewSnakePos[m_NewLenth - 1].x = m_NewSnakePos[m_NewLenth - 2].x + 1;
m_NewSnakePos[m_NewLenth - 1].y = m_NewSnakePos[m_NewLenth - 2].y;
break;
case m_left:
m_NewSnakePos[m_NewLenth - 1].x = m_NewSnakePos[m_NewLenth - 2].x - 1;
m_NewSnakePos[m_NewLenth - 1].y = m_NewSnakePos[m_NewLenth - 2].y;
break;
case m_up:
m_NewSnakePos[m_NewLenth - 1].x = m_NewSnakePos[m_NewLenth - 2].x;
m_NewSnakePos[m_NewLenth - 1].y = m_NewSnakePos[m_NewLenth - 2].y - 1;
break;
case m_down:
m_NewSnakePos[m_NewLenth - 1].x = m_NewSnakePos[m_NewLenth - 2].x;
m_NewSnakePos[m_NewLenth - 1].y = m_NewSnakePos[m_NewLenth - 2].y + 1;
break;
default:
break;
}
}
void
Snake::KeyInput(Drection m_drection)
{
switch(m_drection)
{
case m_right:
if (m_NewDrection == m_up || m_NewDrection == m_down)
{
m_OldDrection = m_NewDrection;
m_NewDrection = m_drection;
}
break;
case m_left:
if (m_NewDrection == m_up || m_NewDrection == m_down)
{
m_OldDrection = m_NewDrection;
m_NewDrection = m_drection;
}
break;
case m_up:
if (m_NewDrection == m_left || m_NewDrection == m_right)
{
m_OldDrection = m_NewDrection;
m_NewDrection = m_drection;
}
break;
case m_down:
if (m_NewDrection == m_left || m_NewDrection == m_right)
{
m_OldDrection = m_NewDrection;
m_NewDrection = m_drection;
}
break;
}
}
#include "StdAfx.h"
#include "Food.h"
Food::Food():isfoodexist(0)
{
}
Food::~Food()
{
}
void
Food::initFood()
{
Pos* m_Foodposition = new Pos[1];
m_Foodposition[0].x = 10;
m_Foodposition[0].y = 2;
m_Foodposition[0].Status = 3;
int num = 1;
Object::SetPosNum(num);
Object::SetPosition(m_Foodposition);
delete[] m_Foodposition;
m_Foodposition = NULL;
}
void
Food::CreatFood()
{
Pos* m_Foodposition = new Pos[1];
srand((unsigned) time(NULL));
m_Foodposition[0].x = rand()%30;
while ((m_Foodposition[0].x < 2) || (m_Foodposition[0].x >33))
{
m_Foodposition[0].x = rand()%30;
}
m_Foodposition[0].y = rand()%30;
while ((m_Foodposition[0].y < 2) || (m_Foodposition[0].y >33))
{
m_Foodposition[0].y = rand()%30;
}
m_Foodposition[0].Status = 3;
Object::SetPosition(m_Foodposition);
delete [1] m_Foodposition;
m_Foodposition = NULL;
}
void
Food::SetFlag(bool existflag)
{
isfoodexist = existflag;
}
bool
Food::GetFlag()
{
return isfoodexist;
}
#include "StdAfx.h"
#include "Wall.h"
Wall::Wall(void):
m_width(36),m_hight(36)
{
}
Wall::~Wall(void)
{
}
void
Wall::InitWall()
{
Pos* position = new Pos[400];
int x;
int y;
int num = 0;
for (x = 0; x < m_width; x++)
{
position[num].x = x;
position[num].y = 0;
position[num].Status = 2;
num++;
position[num].x = x;
position[num].y = m_width - 1;
position[num].Status = 2;
num++;
}
for (y = 0; y < m_hight; y++)
{
position[num].x = 0;
position[num].y = y;
position[num].Status = 2;
num++;
position[num].x = m_hight - 1;
position[num].y = y;
position[num].Status = 2;
num++;
}
Object::SetPosNum(num);
Object::SetPosition(position);
delete[] position;
position = NULL;
}
#include "StdAfx.h"
#ifndef CXX_OBJECT_H
#include "Object.h"
#endif
Object::Object():m_PosNum(0)
{
int i;
for (i = 0;i < 400; i++)
{
m_Position[i].x = 0;
m_Position[i].y = 0;
m_Position[i].Status = 0;
}
}
Object::~Object(void)
{
}
void
Object::SetPosNum(int num)
{
m_PosNum = num;
}
int
Object::GetPosNum()
{
return m_PosNum;
}
/// 通过传入的pos,设置m_Position的X,Y坐标及状态。
void
Object::SetPosition(Pos* pos)
{
int i;
for (i = 0; i < m_PosNum + 1; ++i)
{
m_Position[i].Status = pos[i].Status;
m_Position[i].x = pos[i].x;
m_Position[i].y = pos[i].y;
}
}
void
Object::GetPosition(Pos* pos)
{
int i;
for (i = 0; i < 400; ++i)
{
pos[i].Status = m_Position[i].Status;
pos[i].x = m_Position[i].x;
pos[i].y = m_Position[i].y;
}
}
#include "StdAfx.h"
#include "PlayGround.h"
PlayGround::PlayGround(void):m_live(0)
{
m_playground = new int*[36];
int i;
for (i = 0; i < 36; ++i)
{
m_playground[i] = new int[36];
}
int m;
int n;
for (m = 0; m < 36; ++m)
{
for (n = 0; n < 36; ++n)
{
m_playground[m][n] = 0;
}
}
}
PlayGround::~PlayGround(void)
{
}
void
PlayGround::SetStatues()
{
m_wall.InitWall();
Pos* position = new Pos[400];
m_wall.GetPosition(position);
int num;
for (num = 0;num < m_wall.GetPosNum();num++)
{
int x = position[num].x;
int y = position[num].y;
int status = position[num].Status;
m_playground[x][y] = status;
}
delete[400] position;
position = NULL;
m_snake.initSnake();
Pos* snakeposition = new Pos[400];
m_snake.GetNewSnakePos(snakeposition);
for (num = 0;num < m_snake.GetNewLenth();num++)
{
int x = snakeposition[num].x;
int y = snakeposition[num].y;
int status = snakeposition[num].Status;
m_playground[x][y] = status;
}
delete[400] snakeposition;
snakeposition = NULL;
m_food.initFood();
Pos* foodposition =new Pos[400];
m_food.GetPosition(foodposition);
int x = foodposition[0].x;
int y = foodposition[0].y;
int status = foodposition[0].Status;
m_playground[x][y] = status;
delete[400] foodposition;
foodposition = NULL;
}
int
PlayGround::GetStatus(Pos* pos,int len)
{
int i;
int j;
int status;
i = pos[len - 1].x;
j = pos[len - 1].y;
status = m_playground[i][j];
return status;
}
/// 返回m_Playground,提供给CSnakeView进行屏幕输出。
int**
PlayGround::GetPlayground()
{
return m_playground;
}
void
PlayGround::AddFood()
{
bool existflag;
existflag = m_food.GetFlag();
if (1 == existflag)
{
m_food.CreatFood();
Pos* fruit = new Pos[400];
m_food.GetPosition(fruit);
int fruitstatus = PlayGround::GetStatus(fruit,1);
if ((2 == fruitstatus) || (1 ==fruitstatus)) // 如果m_Playground中水果对应位置状态是墙或者蛇,则重新生成
{
m_food.CreatFood();
}
m_food.SetFlag(0);
delete[400] fruit;
fruit = NULL;
}
}
void
PlayGround::UpdatePosition()
{
Pos* position = new Pos[400]; // 获取蛇的坐标点,更新m_Playground
m_snake.GetNewSnakePos(position);
int num = m_snake.GetNewLenth();
int m;
for (m = 0; m < num + 1; ++m)
{
int x = position[m].x;
int y = position[m].y;
int status = position[m].Status;
m_playground[x][y] = status;
}
delete[400] position;
position = NULL;
Pos* fruitposition = new Pos[400]; // 获取水果的坐标点,更新m_Playground
m_food.GetPosition(fruitposition);
int x;
int y;
int status;
x = fruitposition[0].x;
y = fruitposition[0].y;
status = fruitposition[0].Status;
m_playground[x][y] = status;
delete[400] fruitposition;
fruitposition = NULL;
}
void
PlayGround::SnakeMove()
{
m_snake.Move(); // 蛇身坐标进行变化
Pos* snakehead = new Pos[400];
m_snake.GetNewSnakePos(snakehead);
int len;
int status;
len = m_snake.GetNewLenth();
status = PlayGround::GetStatus(snakehead,len);
if (3 == status) // 如果m_Playground中蛇头所在位置的状态为食物则增加蛇身长度,设置水果Flag为1,即不存在
{
m_snake.AddLenth();
m_food.SetFlag(1);
}
delete[400] snakehead;
snakehead = NULL;
}
void
PlayGround::ChangeDrection(Drection m_drection)
{
m_snake.KeyInput(m_drection);
}
bool
PlayGround::IsGameOver()
{
Pos* snakehead = new Pos[400];
m_snake.GetNewSnakePos(snakehead);
int len;
int status;
len = m_snake.GetNewLenth();
status = PlayGround::GetStatus(snakehead,len);
if (1 == status || 2 == status)
{
m_live = 1;
}
delete[400] snakehead;
snakehead = NULL;
return m_live;
}
int
PlayGround::GetScore()
{
return m_score;
}
void
PlayGround::SetScore()
{
m_score = (m_snake.GetNewLenth() - 6)*10;
}
// SnakeHTView.cpp : implementation of the CSnakeHTView class
//
#include "stdafx.h"
#include "SnakeHT.h"
#include "SnakeHTDoc.h"
#include "SnakeHTView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSnakeHTView
IMPLEMENT_DYNCREATE(CSnakeHTView, CView)
BEGIN_MESSAGE_MAP(CSnakeHTView, CView)
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
ON_COMMAND(ID_32771, &CSnakeHTView::OnStart)
ON_COMMAND(ID_32772, &CSnakeHTView::OnPause)
ON_COMMAND(ID_32773, &CSnakeHTView::OnContinue)
ON_COMMAND(ID_32774, &CSnakeHTView::OnGameOver)
ON_WM_KEYDOWN()
ON_WM_TIMER()
END_MESSAGE_MAP()
// CSnakeHTView construction/destruction
CSnakeHTView::CSnakeHTView()
{
// TODO: add construction code here
}
CSnakeHTView::~CSnakeHTView()
{
}
BOOL CSnakeHTView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
// CSnakeHTView drawing
void CSnakeHTView::OnDraw(CDC* /*pDC*/)
{
CSnakeHTDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
m_playground.SetStatues();
CSnakeHTView::OnInitialUpdate(m_playground.GetPlayground());
}
// CSnakeHTView printing
BOOL CSnakeHTView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CSnakeHTView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CSnakeHTView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
// CSnakeHTView diagnostics
#ifdef _DEBUG
void CSnakeHTView::AssertValid() const
{
CView::AssertValid();
}
void CSnakeHTView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CSnakeHTDoc* CSnakeHTView::GetDocument() const // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSnakeHTDoc)));
return (CSnakeHTDoc*)m_pDocument;
}
#endif //_DEBUG
void CSnakeHTView::OnStart()
{
SetTimer(1,300,NULL); // TODO: Add your command handler code here
}
void CSnakeHTView::OnPause()
{
// TODO: Add your command handler code here
}
void CSnakeHTView::OnContinue()
{
// TODO: Add your command handler code here
}
void CSnakeHTView::OnGameOver()
{
// TODO: Add your command handler code here
}
void CSnakeHTView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
Drection m_drection = m_right;
switch (nChar)
{
case VK_UP:
m_drection = m_up;
break;
case VK_DOWN:
m_drection = m_down;
break;
case VK_LEFT:
m_drection = m_left;
break;
case VK_RIGHT:
m_drection = m_right;
break;
}
m_playground.ChangeDrection(m_drection);
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CSnakeHTView::OnTimer(UINT_PTR nIDEvent)
{ // TODO: Add your message handler code here and/or call default
m_playground.UpdatePosition();
m_playground.AddFood();
CSnakeHTView::OnInitialUpdate(m_playground.GetPlayground());
m_playground.SnakeMove();
bool snakelive;
snakelive = m_playground.IsGameOver();
if (snakelive == 1)
{
KillTimer(1);
m_playground.SetScore();
int score = m_playground.GetScore();
CString message;
message.Format(_T("GameOver!Your Score Is: %d"),score);
AfxMessageBox(message);
}
CView::OnTimer(nIDEvent);
}
void
CSnakeHTView::OnInitialUpdate(int** Playground)
{
//CView::OnInitialUpdate();
int x;
int y;
x = 0;
y = 0;
CDC* pDC = GetDC();
CBrush DrawBrushEmpty = (RGB(255, 255, 255)); // 设置空白地的颜色
CBrush DrawBrushWall = (RGB(180, 60, 45)); // 设置墙及障碍物的颜色
CBrush DrawBrushSnake = (RGB(0, 255, 0)); // 设置蛇的颜色
CBrush DrawBrushFruit = (RGB(220, 120, 60)); // 设置水果的颜色
CPen pen(PS_SOLID, 1, RGB(255, 255, 255)); // 矩形边框设置白色
for (y = 0; y < 36; ++y)
{
for (x = 0; x < 36; ++x)
{
pDC->SelectObject(&pen);
pDC->Rectangle(x * 20, y * 20, (x + 1) * 20, (y + 1) * 20); // 绘制矩形边框为白色
switch (Playground[x][y]) // 根据playground中各个坐标的状态来绘制不同的颜色
{
case 0:
pDC->SelectObject(DrawBrushEmpty);
pDC->Rectangle(x * 20, y * 20, (x + 1) * 20, (y + 1) * 20);
break;
case 1:
pDC->SelectObject(DrawBrushSnake);
pDC->Rectangle(x * 20, y * 20, (x + 1) * 20, (y + 1) * 20);
break;
case 2:
pDC->SelectObject(DrawBrushWall);
pDC->Rectangle(x * 20, y * 20, (x + 1) * 20, (y + 1) * 20);
break;
case 3:
pDC->SelectObject(DrawBrushFruit);
pDC->Rectangle(x * 20, y * 20, (x + 1) * 20, (y + 1) * 20);
break;
default:
break;
}
}
}
}