貪吃蛇游戲的實作
一、前期準備
類的定義
1、位置(點)類的定義
class Point
{
public:
Point(int x = 0, int y = 0);
int getPointx(); //獲得X軸位置
int getPointy(); //獲得Y軸位置
bool changex(int a); //改變X軸位置
bool changey(int b); //改變Y軸位置
bool cmp(Point &a); //比較
private:
int x, y; //X、Y軸
};
2、食物類的定義
class Food
{
public:
Food();
void draw(CDC* dc); //畫食物
Point init(); //初始化位置
friend class Snake;
private:
Point x;
};
3、蛇類的定義
class Snake
{
public:
friend class CTCSnakeView;
Snake(Point head, int d = 2, int len = 1);
~Snake() {
}
void drawSnake(CDC *dc); //畫蛇
bool eatFood(int x, int y); //吃食物
bool move(Food &food); //游走
void changeD(int); //改變方向
bool isHit();
int getD() {
return direct;
} // 獲取方向
Point getH() {
return head;
} //獲取頭位置
private:
Point head; //蛇頭位置
int direct; //前進方向
vector<Point> body; // 蛇身位置
int length; //蛇長
bool isEat(); //判斷是否吃到自己
//蛇身寬度為10像素
};
開發工具 VS2019
二、實作思路
1、建立一個單檔案檔案


2、完成對類的宣告和實作
點類的實作
Point::Point(int x, int y)
{
this->x = x;
this->y = y;
}
int Point::getPointx() {
return x;
}
int Point::getPointy() {
return y;
}
bool Point::changex(int a)
{
x = a;
return true;
}
bool Point::changey(int b)
{
y = b;
return true;
}
bool Point::cmp(Point& a) {
if (a.x == x && a.y == y)
return true;
return false;
}
食物類的實作
Food::Food()
{
srand(time(NULL));
int a = rand() % 320 + 100;
a -= a % 10;
int b = rand() % 320 + 100;
b -= b % 10;
x.changex(a);
x.changey(b);
}
void Food::draw(CDC* dc)
{
CBrush brush;
brush.CreateSolidBrush(RGB(0, 0, 255));
dc->FillRect(CRect(x.getPointx(), x.getPointy(), x.getPointx() + 10, x.getPointy() + 10), &brush);
brush.DeleteObject();
}
Point Food::init()
{
srand(time(NULL)); //設定種子
//生成40-420之間的亂數
int a = rand() % 380 + 40;
a -= a % 10;
int b = rand() % 380 + 40;
b -= b % 10;
x.changex(a);
x.changey(b);
return x;
}
貪吃蛇類的定義
Snake::Snake(Point head, int d, int len):head(60, 60), direct(d), length(len)
{
body.push_back(Point(50, 60));
}
void Snake::drawSnake(CDC * dc)
{
CBrush brush;
brush.CreateSolidBrush(RGB(0, 255, 0));
dc->FillRect(CRect(head.getPointx(), head.getPointy(), head.getPointx()+10, head.getPointy()+10), &brush);
brush.DeleteObject();
brush.CreateSolidBrush(RGB(255, 0, 0));
for (int i = length - 1; i >= 0; i--) {
dc->FillRect(CRect(body[i].getPointx(), body[i].getPointy(), body[i].getPointx() + 10, body[i].getPointy() + 10), &brush);
}
brush.DeleteObject();
}
bool Snake::isHit() {
if (head.getPointx() <= 30 || head.getPointx() >= 420)
return true;
if (head.getPointy() <= 30 || head.getPointy() >= 420)
return true;
return false;
}
bool Snake::move(Food &food)
{
int i = length;
if (isEat())
{
return false;
}
if (isHit())
{
return false;
}
if (eatFood(food.x.getPointx(), food.x.getPointy())) {
Point n = food.init();
if (n.cmp(head))
n = food.init();
while (1) {
i = length;
for (i--; i >= 0; i--) {
if (body[i].cmp((n))) {
n = food.init();
break;
}
}
if (i < 0)
break;
}
Point t(body[length - 1].getPointx(), body[length - 1].getPointy());
body.push_back(t);
length++;
return true;
}
i = length;
switch (direct)
{
case 1: {
for (i--; i >= 1; i--)
{
body[i].changex(body[i - 1].getPointx());
body[i].changey(body[i - 1].getPointy());
}
body[0].changex(head.getPointx());
body[0].changey(head.getPointy());
head.changey(head.getPointy() - 10);
break;
}
case 2: {
for (i--; i >= 1; i--)
{
body[i].changex(body[i - 1].getPointx());
body[i].changey(body[i - 1].getPointy());
}
body[0].changex(head.getPointx());
body[0].changey(head.getPointy());
head.changex(head.getPointx() + 10);
break;
}
case 3: {
for (i--; i >= 1; i--)
{
body[i].changex(body[i - 1].getPointx());
body[i].changey(body[i - 1].getPointy());
}
body[0].changex(head.getPointx());
body[0].changey(head.getPointy());
head.changey(head.getPointy() + 10);
break;
}
case 4: {
for (i--; i >= 1; i--)
{
body[i].changex(body[i - 1].getPointx());
body[i].changey(body[i - 1].getPointy());
}
body[0].changex(head.getPointx());
body[0].changey(head.getPointy());
head.changex(head.getPointx() - 10);
break;
}
}
return true;
}
bool Snake::isEat()
{
int x = head.getPointx();
int y = head.getPointy();
int i = length;
if (i > 3) {
for (i-- ; i >= 0; i--)
{
if (head.getPointx() == body[i].getPointx() && head.getPointy() == body[i].getPointy())
return true;
}
}
return false;
}
bool Snake::eatFood(int x, int y)
{
if (head.getPointx() == x && head.getPointy() == y)
return true;
return false;
}
void Snake::changeD(int a)
{
direct = a;
}
3、對貪吃蛇、食物、界面的繪制
建立類向導

對ondraw()虛函式進行撰寫


在繪制程序中還需要使用雙快取技術,可以自行了解一下,
4、初始化游戲
我對初始化游戲有兩種方法
方法一: 在OnInitialUpdate()函式內用SetTimer(1, 1000, NULL);

方法二 :在選單內加入開始游戲

實作:
在資源管理器內雙擊TCsnake.rc


對選單進行編輯

可以寫入自己想要的,然后添加事件處理程式

類串列選擇CTCSnakeView,訊息型別COMMAND,函式名自定義

在生成的函式內用settimer()達到開始游戲的效果

5、實作蛇的移動效果
通過OnTimer()、SetTimer()、Invalidate()和KillTimer()的配合實作
6、通過按鍵改變蛇的移動方向
首先添加一個OnKeyDown()函式

再在函式內判斷按下的鍵所對應的方向,最后進行一個改變方向的操作,
以上就是我實作貪吃蛇的基礎步驟,初學MFC,很多地方沒有考慮周全,內容很多只是粗略介紹實作程序,具體的實作程序還需要查看原始碼,用到的一些虛函式和訊息的詳解大家應該可以自行查到,作品僅作記錄
下面附上原始碼
原始碼地址: https://gitee.com/gg_8_0/the-greedy-snake-of-mfc.git
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/287820.html
標籤:其他
上一篇:生物細胞繁衍生存模擬仿真實驗
下一篇:C語言初階《三子棋》
