Shun 发表于 2021-12-27 22:55:55

贪吃蛇实现

0.实现效果
模式选择:普通模式,穿墙模式,无敌模式。

进入游戏,有背景音乐。


1.准备工作:
easyx图形库安装,NSIS打包软件。
这两个在网上能找到教程安装。

2.关于贪吃蛇实现
在网上有很多教程,或多或少细节方面是有不同之处的,这里我借助easyx图形库进行实现,一是色彩不显得那么单调;二是不使用windows的光标控制函数等函数,这样就避免后面涉及线程的东西,上手方面会更简单一些。(线程这块不是太明白)

3.进入实战
注意:VS2019中.cpp才能运行easyx图形库,.c是不行的。
1.首先先绘个背景:

#include<iostream>
#include<easyx.h>
int main()
{
initgraph(640,480);//设置窗口大小,为640*480
setbkcolor(WHITE);//设置窗口背景色为白色
cleardevice();//刷新屏幕
setbkmode(TRANSPARENT); //设置字体背景色为透明
settextcolor(RED);    //设置字体颜色为红色
outtextxy(200, 240, L"Enter键进入游戏");
outtextxy(200, 280, L"字母键 W,S,A,D 方向键 上下左右 控制方向");
getchar(); //按任意键继续
return 0;
}


关于函数怎么使用,网上有详细说明,这里就不一一具体说明了。
这里getchar()是为了不让图片加载就消失。
这样,我们就得到了一个窗口

当然,这个就比较单调,我们加个背景图(这个找张喜欢的图片)上去。
#include<iostream>
#include<easyx.h>
IMAGE img;
int main()
{
cleardevice();//刷新屏幕
loadimage(&img, L"Image0.jpg", 640, 480);//保存图片
putimage(0, 0, &img);//显示图片
setbkmode(TRANSPARENT); //设置字体背景色为透明
settextcolor(WHITE);    //设置字体颜色为红色
outtextxy(170, 200, L"模式选择");
outtextxy(170, 240, L"1.普通模式");
outtextxy(170, 280, L"2.穿墙模式");
outtextxy(170, 320, L"3.无敌模式");
outtextxy(380, 220, L"游戏说明:");
outtextxy(360, 280, L"Enter键进入游戏");
outtextxy(300, 320, L"字母键 W,S,A,D 方向键 上下左右 控制方向");
outtextxy(350, 360, L"长按方向加速,空格暂停");
getchar(); //按任意键继续
return 0;
}


loadimage里的Image.jpg我是放在了项目所在的位置,就可以直接调用了。写绝对路径也是可以的,有一点要注意,就是路径要\\,比如D:\要写成D:\\
这里我踩的一个坑就是putimage的前两个参数,这两个参数代表的是图片左上角的坐标,全部设为0,图片才能全部加载出来。

然后我们把上面这个图片代码放在start函数中,在main中调用这个函数。
2.模式选择
void chose()
{
while (1)
{
    switch (_getch())
    {
    case '1':
      start();
      outtextxy(160, 240, L"->");
      mode = 0;//全局变量mode表示模式
      break;
    case '2':
      start();
      outtextxy(160, 280, L"->");
      mode = 1;
      break;
    case '3':
      start();
      outtextxy(160, 320, L"->");
      mode = 2;
      break;
    case 13://Enter键进入游戏
      return;
    deault:
      break;
    }
}
}


这里的13表示enter键对应的数字。这里我踩的大坑就是开始写的这个'1'是1,导致键盘上的1对应的数值不是1,也就是按不动。一定要注意,键盘上数字和对应的数字不是一回事。

然后就可以在这三个模式进行切换,按Enter键进入游戏。
3.初始化游戏数据
游戏数据的话,我们需要一个围墙,一条蛇,分数显示。
围墙这里我们借用Map元素把整个框框包含在里面,然后分四类,分别是SPACE(空地),墙(WALL),蛇身(SNAKE),蛇头(HEAD),食物(FOOD)。
enum {
SPACE, WALL, SNAKE, HEAD,FOOD//依次代表空地,墙,蛇身,头,食物
};
#define ROW 48
#define COL 64
int map;
int mode; //模式
int score; //分数
void DrawMap();//绘画界面
void Init();//初始化游戏界面


绘画:
void DrawMap()
{
BeginBatchDraw(); //开始绘图
settextcolor(RGB(238, 0, 0)); //设置字体颜色为红色
cleardevice(); //刷新屏幕
loadimage(&img, L"Image.jpg", 640, 480);//保存图片
putimage(0, 0, &img);//显示图片
WCHAR arr; //保存分数
wsprintf(arr, L"得分:%d", score); //分数放在arr中
outtextxy(0, 0, arr); //显示分数
for(int y=0;y<ROW;y++)
    for (int x = 0; x < COL; x++)
    {
      switch (map)
      {
      case SPACE:
      break;
      case WALL:
      setlinecolor(RED);//边框线条颜色
      setfillcolor(RGB(187, 255, 255));//填充颜色
      fillrectangle(x*10, y*10, x*10 + 10, y*10 + 10);//画矩形
      break;
      case SNAKE:
      setlinecolor(RGB(78, 238, 148));
      setfillcolor(WHITE);
      fillrectangle(x * 10, y * 10, x * 10 + 10, y * 10 + 10);
      break;
      case HEAD:
      switch (rand() % 7)
      {
      case 0:
          setlinecolor(RGB(78, 238, 148));
          setfillcolor(RED);
          fillrectangle(x * 10, y * 10, x * 10 + 10, y * 10 + 10);
          break;
      case 1:
          setlinecolor(RGB(78, 238, 148));
          setfillcolor(WHITE);
          fillrectangle(x * 10, y * 10, x * 10 + 10, y * 10 + 10);
          break;
      case 2:
          setlinecolor(RGB(78, 238, 148));
          setfillcolor(RGB(100,149,237));
          fillrectangle(x * 10, y * 10, x * 10 + 10, y * 10 + 10);
          break;
      case 3:
          setlinecolor(RGB(78, 238, 148));
          setfillcolor(RGB(127,255,0));
          fillrectangle(x * 10, y * 10, x * 10 + 10, y * 10 + 10);
          break;
      case 4:
          setlinecolor(RGB(78, 238, 148));
          setfillcolor(RGB(176,224,230));
          fillrectangle(x * 10, y * 10, x * 10 + 10, y * 10 + 10);
          break;
      case 5:
          setlinecolor(RGB(78, 238, 148));
          setfillcolor(RGB(102,139,139));
          fillrectangle(x * 10, y * 10, x * 10 + 10, y * 10 + 10);
          break;
      case 6:
          setlinecolor(RGB(78, 238, 148));
          setfillcolor(RGB(46,139,87));
          fillrectangle(x * 10, y * 10, x * 10 + 10, y * 10 + 10);
          break;
      default:
          break;
      }
      break;
      }
    }
EndBatchDraw(); //结束绘图
}


然后写初始化界面
void Init()
{
srand((unsigned)time(NULL));//随机种子,给后面DrawMap中画蛇头使用
memset(map, SPACE, sizeof(map));//初始化数组map为SPACE
for (int x =0; x < COL; x++)
    map = map = WALL;
for (int y = 0; y < ROW; y++)
    map = map = WALL;

}


先显示看看:
然后发现不对劲,怎么会怎样?这也是一个坑,坑在哪,在我们设置地图数组的时候,如果直接按原地就搬尺寸就会发现原来的得分被覆盖了,那怎么改?
一是把原来的DrawMap给Wall的初始坐标修改,二是对Init中的两个for进行调整,x,y不再是从0,0开始,而是从0,2开始。(注意:二维数组左边代表纵坐标,右边代表横坐标)。
void Init()
{
srand((unsigned)time(NULL));//随机种子,给后面DrawMap中画蛇头使用
memset(map, SPACE, sizeof(map));//初始化数组map为SPACE
for (int x =0; x < COL; x++)
    map = map = WALL;
for (int y = 2; y < ROW; y++)
    map = map = WALL;
}


这样改到也可以,至少目前来说是可以,但是产生食物需要一个边界。这里我们的map[]和map[]是浪费了的。所以为了后续更好使用,这里我们干脆来个大修改:
#define ROW 46
#define COL 64
...
void Init()
{
    srand((unsigned)time(NULL));//随机种子,给后面DrawMap中画蛇头使用
    memset(map, SPACE, sizeof(map));//初始化数组map为SPACE
    for (int x =0; x < COL; x++)
      map = map = WALL;
    for (int y = 0; y < ROW; y++)
      map = map = WALL;

}

void DrawMap()
{
    BeginBatchDraw(); //开始绘图
    settextcolor(RGB(238, 0, 0)); //设置字体颜色为红色
    cleardevice(); //刷新屏幕
    loadimage(&img, L"Image.jpg", 640, 480);//保存图片
    putimage(0, 0, &img);//显示图片
    WCHAR arr; //保存分数
    wsprintf(arr, L"得分:%d", score); //分数放在arr中
    outtextxy(0, 0, arr); //显示分数
    for (int y = 0; y < ROW; y++)
      for (int x = 0; x < COL; x++)
      {
            switch (map)
            {
            case SPACE:
                break;
            case WALL:
                setlinecolor(RED);//边框线条颜色
                setfillcolor(RGB(187, 255, 255));//填充颜色
                fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);//画矩形
                break;
            case SNAKE:
                setlinecolor(RGB(78, 238, 148));
                setfillcolor(WHITE);
                fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
                break;
            case HEAD:
                switch (rand() % 7)
                {
                case 0:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RED);
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
                  break;
                case 1:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(WHITE);
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
                  break;
                case 2:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RGB(100, 149, 237));
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
                  break;
                case 3:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RGB(127, 255, 0));
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
                  break;
                case 4:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RGB(176, 224, 230));
                  fillrectangle(x * 10, y * 10+20, x * 10 + 10, y * 10 + 30);
                  break;
                case 5:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RGB(102, 139, 139));
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 +30);
                  break;
                case 6:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RGB(46, 139, 87));
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 +30);
                  break;
                default:
                  break;
                }
                break;
            }
      }
    EndBatchDraw(); //结束绘图
    }


这里特别要注意的是这个矩形四个角的坐标,要调对来。

这样,就得到了一个进去后的游戏界面。
4.造蛇
那蛇呢?对,现在开始造蛇,造蛇的话?可以用数组,但是超过数组区间就会崩溃,这里我们使用链表。
struct snake
{
    COORD pos;    //typedef struct _COORD {SHORT X;   SHORT Y;} COORD
    struct snake* next; //连接结点
};
struct snake* Head; //表示蛇头
void AddPoint(int x, int y); //增加结点
...
void AddPoint(int x, int y)
{
    struct snake* point = (struct snake*)malloc(sizeof(struct snake));
    if (point == NULL)
    {
      return;
    }
    else
    {
      point->pos.X = x;//这里X,Y分别代表纵坐标,横坐标
      point->pos.Y = y;
      if (Head == NULL)
      {
            Head = point;
            map = HEAD;
      }
      else
      {
            map = SNAKE;
            point->next = Head;
            Head = point;
            map = HEAD;
      }
    }
}


然后就可以得到这样的:

那蛇要怎么动呢,就是蛇头移动一个位置,然后那个新坐标就是蛇头,原蛇头为SNAKE,后面蛇尾释放置SPACE。
void DelPoint(); //删除结点
void ChangeDir(); //调整方向
void move(); //蛇动起来
char SnakeDir;//蛇的方向
int t1, t2; //代表时间

void DelPoint()
{
    if (Head == NULL || Head->next == NULL)
    {
      return;
    }
    struct snake* p = (struct snake*)malloc(sizeof(struct snake));
    struct snake* q = (struct snake*)malloc(sizeof(struct snake));
    if (p == NULL || q == NULL)
    {
      return;
    }
    p = Head;
    q = p->next;
    while (q->next)
    {
      p = p->next;
      q = p->next;
    }
    map = SPACE;
    free(q);
    q = NULL;
    p->next = NULL;
}
void move()
{
    struct snake* newpoint = (struct snake*)malloc(sizeof(struct snake));
    if (newpoint == NULL)
    {
      return;
    }
    switch (SnakeDir)
    {
    case 'D':
      newpoint->pos.X = Head->pos.X;
      newpoint->pos.Y = Head->pos.Y + 1; //理清X,Y代表什么
      break;
    case 'A':
      newpoint->pos.X = Head->pos.X;
      newpoint->pos.Y = Head->pos.Y - 1;
      break;
    case 'W':
      newpoint->pos.X = Head->pos.X - 1;
      newpoint->pos.Y = Head->pos.Y;
      break;
    case 'S':
      newpoint->pos.X = Head->pos.X + 1;
      newpoint->pos.Y = Head->pos.Y;
      break;
    default:
      break;
    }
    AddPoint(newpoint->pos.X, newpoint->pos.Y);
    DelPoint();
}
void ChangeDir()
{
    switch (_getch())
    {
    case 'A':
    case 'a':
    case 75:
      if (SnakeDir != 'D')
            SnakeDir = 'A';
      break;
    case 'D':
    case 'd':
    case 77:
      if (SnakeDir != 'A')
            SnakeDir = 'D';
      break;
    case 'W':
    case 'w':
    case 72:
      if (SnakeDir != 'S')
            SnakeDir = 'W';
      break;
    case 'S':
    case 's':
    case 80:
      if (SnakeDir != 'W')
            SnakeDir = 'S';
      break;
    case 32://空格
      _getch();
      break;
    default:
      break;
    }
}


这里的键盘上上、下、左、右分别对应数值72,80,75,77.
因为蛇动起来,自然就是while循环内一直走,碰到限制条件结束,然后我们这里要让他动起来,借助GetTickCount()函数,这个函数精度高
int main()
{
    initgraph(640, 480);
    start();
    outtextxy(160, 240, L"->");
    chose();
    Init();
    while (1)
    {
      DrawMap();
                if (_kbhit())
            {
                ChangeDir();
                move();
                t2 = GetTickCount();
                t1 = t2;
            }
            t2 = GetTickCount();
            if (t2 - t1 > 100)
            {
                move();
                t1 = t2;
            }
    }
    getchar();
    closegraph();
    return 0;
}


然后蛇就可以简单的动了。
5.加食物和模式选择
接下来就是造食物,顺便把限制条件给加上,就普通模式下撞墙或者撞到自己身体游戏结束,另外两个模式就是屏蔽游戏结束。
void Addfood()
{
    int x, y;
    do
    {
      x = rand() % (ROW-1)+1;
      y = rand() % (COL - 1) + 1;
    } while (map != SPACE);
    map = FOOD;
}
void move()
{
    struct snake* newpoint = (struct snake*)malloc(sizeof(struct snake));
    if (newpoint == NULL)
    {
      return;
    }
    switch (SnakeDir)
    {
    case 'D':
      newpoint->pos.X = Head->pos.X;
      newpoint->pos.Y = Head->pos.Y + 1; //理清X,Y代表什么
      break;
    case 'A':
      newpoint->pos.X = Head->pos.X;
      newpoint->pos.Y = Head->pos.Y - 1;
      break;
    case 'W':
      newpoint->pos.X = Head->pos.X - 1;
      newpoint->pos.Y = Head->pos.Y;
      break;
    case 'S':
      newpoint->pos.X = Head->pos.X + 1;
      newpoint->pos.Y = Head->pos.Y;
      break;
    default:
      break;
    }
    switch (map)
    {
    case SPACE:
      AddPoint(newpoint->pos.X, newpoint->pos.Y);
      DelPoint();
      break;
    case SNAKE:
      if (mode==2)
      {
            AddPoint(newpoint->pos.X, newpoint->pos.Y);
            DelPoint();
      }
      else
      {
          PlaySound(NULL,0,0);
            MessageBox(GetHWnd(), L"游戏结束,继续努力", L"结果", MB_OK);
                exit(0);
      }
      break;
    case WALL:
      if (mode)
      {
            switch (SnakeDir)
            {
            case 'A':
                newpoint->pos.Y = COL - 2;
                break;
            case 'D':
                newpoint->pos.Y = 1;
                break;
            case 'W':
                newpoint->pos.X = ROW - 2;
                break;
            case 'S':
                newpoint->pos.X = 1;
                break;
            default:
                break;
            }
            AddPoint(newpoint->pos.X, newpoint->pos.Y);
            DelPoint();
      }
      else
      {
      PlaySound(NULL,0,0);
            MessageBox(GetHWnd(), L"游戏结束,继续努力", L"结果", MB_OK);
            exit(0);
      }
      break;
    case FOOD:
      score++;
      AddPoint(newpoint->pos.X, newpoint->pos.Y);
      Addfood();
      break;
    default:
      break;
    }
}


然后就是把main函数中进行调用一下。
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")

int main()
{
    initgraph(640, 480);
    start();
    outtextxy(160, 240, L"->");
    chose();
    Init();
    while (1)
    {
      PlaySound(L"彩豆森林.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT | SND_LOOP);
      while (1)
      {
            DrawMap();
            if (_kbhit())
            {
                ChangeDir();
                move();
                t2 = GetTickCount();
                t1 = t2;
            }
            t2 = GetTickCount();
            if (t2 - t1 > 100)
            {
                move();
                t1 = t2;
            }
      }
    }
    getchar();
    closegraph();
    return 0;
    }


然后加了个背景音乐进去,游戏结束把背景音乐停了。

6.源码
#include<iostream>
#include<easyx.h>
#include<conio.h>
#include<time.h>
#include<Windows.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
using namespace std;

void start(); //开始界面
void Init(); //初始化游戏数据
void chose(); //选择界面
void DrawMap();//绘画界面
void Init();//初始化游戏界面
void Addfood();//添加食物
enum {
    SPACE, WALL, SNAKE, HEAD,FOOD//依次代表空地,墙,蛇身,头
};
IMAGE img;
#define ROW 46
#define COL 64
int map;
int mode; //模式
int score; //分数
char SnakeDir;//蛇的方向
int t1, t2; //代表时间
struct snake
{
    COORD pos;    //typedef struct _COORD {SHORT X;   SHORT Y;} COORD
    struct snake* next; //连接结点
};
struct snake* Head; //表示蛇头
void AddPoint(int x, int y); //增加结点
void DelPoint(); //删除结点
void ChangeDir(); //调整方向
void move(); //蛇动起来
int main()
{
    initgraph(640, 480);
    start();
    outtextxy(160, 240, L"->");
    chose();
    Init();
    while (1)
    {
      PlaySound(L"彩豆森林.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT | SND_LOOP);
      while (1)
      {
            DrawMap();
            if (_kbhit())
            {
                ChangeDir();
                move();
                t2 = GetTickCount();
                t1 = t2;
            }
            t2 = GetTickCount();
            if (t2 - t1 > 100)
            {
                move();
                t1 = t2;
            }
      }
    }
    getchar();
    closegraph();
    return 0;
}
void start()
{
    cleardevice();
    loadimage(&img, L"Image0.jpg", 640, 480);//保存图片
    putimage(0, 0, &img);//显示图片
    setbkmode(TRANSPARENT); //设置字体背景色为透明
    settextcolor(WHITE);      //设置字体颜色为白色
    outtextxy(170, 200, L"模式选择");
    outtextxy(170, 240, L"1.普通模式");
    outtextxy(170, 280, L"2.穿墙模式");
    outtextxy(170, 320, L"3.无敌模式");
    outtextxy(380, 220, L"游戏说明:");
    outtextxy(360, 280, L"Enter键进入游戏");
    outtextxy(300, 320, L"字母键 W,S,A,D 方向键 上下左右 控制方向");
    outtextxy(350, 360, L"长按方向加速,空格暂停");
}
void chose()
{
    while (1)
    {
      switch (_getch())
      {
      case '1':
            start();
            outtextxy(160, 240, L"->");
            mode = 0;
            break;
      case '2':
            start();
            outtextxy(160, 280, L"->");
            mode = 1;
            break;
      case '3':
            start();
            outtextxy(160, 320, L"->");
            mode = 2;
            break;
      case 13://Enter键进入游戏
            return;
      deault:
            break;
      }
    }
}
void Init()
{
    srand((unsigned)time(NULL));//随机种子,给后面DrawMap中画蛇头使用
    memset(map, SPACE, sizeof(map));//初始化数组map为SPACE
    for (int x =0; x < COL; x++)
      map = map = WALL;
    for (int y = 0; y < ROW; y++)
      map = map = WALL;
    SnakeDir = 'D';
    AddPoint(5, 3);
    AddPoint(5, 4);
    AddPoint(5, 5);
    AddPoint(5, 6);
    Addfood();
}
void ChangeDir()
{
    switch (_getch())
    {
    case 'A':
    case 'a':
    case 75:
      if (SnakeDir != 'D')
            SnakeDir = 'A';
      break;
    case 'D':
    case 'd':
    case 77:
      if (SnakeDir != 'A')
            SnakeDir = 'D';
      break;
    case 'W':
    case 'w':
    case 72:
      if (SnakeDir != 'S')
            SnakeDir = 'W';
      break;
    case 'S':
    case 's':
    case 80:
      if (SnakeDir != 'W')
            SnakeDir = 'S';
      break;
    case 32:
      _getch();
      break;
    default:
      break;
    }
}
void AddPoint(int x, int y)
{
    struct snake* point = (struct snake*)malloc(sizeof(struct snake));
    if (point == NULL)
    {
      return;
    }
    else
    {
      point->pos.X = x;
      point->pos.Y = y;
      if (Head != NULL)
      {
            map = SNAKE;//这里X,Y分别代表纵坐标,横坐标
      }
         point->next = Head;
         Head = point;
         map = HEAD;
    }
}
void DelPoint()
{
    if (Head == NULL || Head->next == NULL)
    {
      return;
    }
    struct snake* p = (struct snake*)malloc(sizeof(struct snake));
    struct snake* q = (struct snake*)malloc(sizeof(struct snake));
    if (p == NULL || q == NULL)
    {
      return;
    }
    p = Head;
    q = p->next;
    while (q->next)
    {
      p = p->next;
      q = p->next;
    }
    map = SPACE;
    free(q);
    q = NULL;
    p->next = NULL;
}
void Addfood()
{
    int x, y;
    do
    {
      x = rand() % (ROW-1)+1;
      y = rand() % (COL - 1) + 1;
    } while (map != SPACE);
    map = FOOD;
}
void move()
{
    struct snake* newpoint = (struct snake*)malloc(sizeof(struct snake));
    if (newpoint == NULL)
    {
      return;
    }
    switch (SnakeDir)
    {
    case 'D':
      newpoint->pos.X = Head->pos.X;
      newpoint->pos.Y = Head->pos.Y + 1; //理清X,Y代表什么
      break;
    case 'A':
      newpoint->pos.X = Head->pos.X;
      newpoint->pos.Y = Head->pos.Y - 1;
      break;
    case 'W':
      newpoint->pos.X = Head->pos.X - 1;
      newpoint->pos.Y = Head->pos.Y;
      break;
    case 'S':
      newpoint->pos.X = Head->pos.X + 1;
      newpoint->pos.Y = Head->pos.Y;
      break;
    default:
      break;
    }
    switch (map)
    {
    case SPACE:
      AddPoint(newpoint->pos.X, newpoint->pos.Y);
      DelPoint();
      break;
    case SNAKE:
      if (mode==2)
      {
            AddPoint(newpoint->pos.X, newpoint->pos.Y);
            DelPoint();
      }
      else
      {
            MessageBox(GetHWnd(), L"游戏结束,继续努力", L"结果", MB_OK);
                exit(0);
      }
      break;
    case WALL:
      if (mode)
      {
            switch (SnakeDir)
            {
            case 'A':
                newpoint->pos.Y = COL - 2;
                break;
            case 'D':
                newpoint->pos.Y = 1;
                break;
            case 'W':
                newpoint->pos.X = ROW - 2;
                break;
            case 'S':
                newpoint->pos.X = 1;
                break;
            default:
                break;
            }
            AddPoint(newpoint->pos.X, newpoint->pos.Y);
            DelPoint();
      }
      else
      {
            MessageBox(GetHWnd(), L"游戏结束,继续努力", L"结果", MB_OK);
            exit(0);
      }
      break;
    case FOOD:
      score++;
      AddPoint(newpoint->pos.X, newpoint->pos.Y);
      Addfood();
      break;
    default:
      break;
    }
}
void DrawMap()
{
    BeginBatchDraw(); //开始绘图
    settextcolor(RGB(238, 0, 0)); //设置字体颜色为红色
    cleardevice(); //刷新屏幕
    loadimage(&img, L"Image.jpg", 640, 480);//保存图片
    putimage(0, 0, &img);//显示图片
    WCHAR arr; //保存分数
    wsprintf(arr, L"得分:%d", score); //分数放在arr中
    outtextxy(0, 0, arr); //显示分数
    for (int y = 0; y < ROW; y++)
      for (int x = 0; x < COL; x++)
      {
            switch (map)
            {
            case SPACE:
                break;
            case WALL:
                setlinecolor(RED);//边框线条颜色
                setfillcolor(RGB(187, 255, 255));//填充颜色
                fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);//画矩形
                break;
            case SNAKE:
                setlinecolor(RGB(78, 238, 148));
                setfillcolor(WHITE);
                fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
                break;
            case HEAD:
                switch (rand() % 7)
                {
                case 0:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RED);
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
                  break;
                case 1:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(WHITE);
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
                  break;
                case 2:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RGB(100, 149, 237));
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
                  break;
                case 3:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RGB(127, 255, 0));
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
                  break;
                case 4:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RGB(176, 224, 230));
                  fillrectangle(x * 10, y * 10+20, x * 10 + 10, y * 10 + 30);
                  break;
                case 5:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RGB(102, 139, 139));
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 +30);
                  break;
                case 6:
                  setlinecolor(RGB(78, 238, 148));
                  setfillcolor(RGB(46, 139, 87));
                  fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 +30);
                  break;
                default:
                  break;
                }
                break;
            case FOOD:
                setlinecolor(WHITE);
                setfillcolor(RED);
                fillrectangle(x * 10, y * 10 + 20, x * 10 + 10, y * 10 + 30);
            }
      }
    EndBatchDraw(); //结束绘图
}


图片,歌曲要自己插入,图片格式要对,jpeg我试过不行,歌曲要是wav格式(直接修改没用,要借助格式转换器才行,这个搜一下就可以了)。

7.感想
这个小游戏拖了好长时间,又是长时间摸鱼....还是有很多地方还是不足的,至于那个贪吃蛇自己找路吃食物...目前实现不了,bfs不会用呀...
慢慢来吧。




如有不对,欢迎指正。


https://blog.51cto.com/u_15363771/4848990
页: [1]
查看完整版本: 贪吃蛇实现