贪吃蛇C++

这是贪吃蛇的效果图。一边看《新三国》,一边写的结果。第一次写C++的,用类实现,还挺好玩的。

设计总共分为3个类:地图,蛇,食物

先上传全部代码:头文件

#include <stdio.h>  
#include <stdlib.h>  
#include <string>  
#include <iterator>  
#include <algorithm>  
#include <iostream>  
#include <vector>  
#include <deque>  
#include <list>  
#include <set> 
#include<Windows.h>  
#include<conio.h> 

using namespace std;

typedef unsigned char  uchar;

struct Point{
    int x;
    int y;
};

enum SnakeState{
    Eat = 0,
    NotEat = 1,
    HitWall = -1,
    Common = 10
}snakeState;

enum SnakeDir{
    Up = 72,
    Down = 80,
    Left = 75,
    Right = 77
};

class CSnake;
class CFood;

class CMap{
public:
    CMap(int t, int l, int w, int h);
    ~CMap();

    void mapUpdate(CSnake& s,CFood& f);
    bool mapShow();

private:
    int top;
    int left;
    int width;
    int height;
    
    uchar **mat;
    uchar dir;
    uchar lastDir;

    CSnake *snake;
    CFood *food;
};

class CSnake{
    
public:
    CSnake(int t, int l, int w, int h);
    ~CSnake();

    friend class CMap;

    int newHeadPoint(uchar dir, Point foodpoint);

private:
    int top;
    int left;
    int width;
    int height;

    vector<Point*> snakeBody;
    Point headPoint;
};

class CFood{
public:
    CFood(int t, int l, int w, int h);
    ~CFood();

    friend class CMap;

    Point newFoodPoint();
private:
    int top;
    int left;
    int width;
    int height;

    Point foodPoint;
};

cpp文件:

#include <stdio.h>  
#include <stdlib.h>  
#include <string>  
#include <iterator>  
#include <algorithm>  
#include <iostream>  
#include <vector>  
#include <deque>  
#include <list>  
#include <set> 
#include<Windows.h>  
#include<conio.h> 
#include "main.h"

using namespace std;

void delay(int n)
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int k = 100 + 100;
        }
    }
}

CMap::CMap(int t, int l, int w, int h)
{
    top = t;
    left = l;
    width = w;
    height = h;

    dir = Down;
    lastDir = Down;

    //内存分配
    mat = new uchar*[height];
    for (int i = 0; i < height; i++)
    {
        mat[i] = new uchar[width];
    }

    //初始化路径矩阵边界
    for (int i = 0; i < height; i++)
    {
        mat[i][0] = '#';
        for (int j = 1; j < width - 1; j++)
        {
            if (i == 0 || i == height - 1)
            {
                mat[i][j] = '#';
            }
            else
            {
                mat[i][j] = ' ';
            }
        }
        mat[i][width - 1] = '#';
    }

    snake = new CSnake(0, 0, 50, 25);
    food = new CFood(0, 0, 50, 25);
}
CMap::~CMap()
{
    for (int i = 0; i < height; i++)
    {
        delete mat[i];
    }
    delete mat;
}
void CMap::mapUpdate(CSnake& s, CFood& f)
{
    mat[f.foodPoint.y][f.foodPoint.x] = 'O';

    for (int i = 0; i < s.snakeBody.size(); i++)
    {
        if (i == 0)
        {
            mat[s.snakeBody[i]->y][s.snakeBody[i]->x] = '@';
        }
        else
        {
            mat[s.snakeBody[i]->y][s.snakeBody[i]->x] = '*';
        }
    }
}
bool CMap::mapShow()
{
    //设置顶点坐标,使得绘制一直在起点
    COORD coord;
    coord.X = top;
    coord.Y = left;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);

    for (int i = 1; i < height - 1; i++)
    {
        memset(mat[i] + 1, ' ', width - 2);
    }

    //更新食物坐标和蛇坐标
    mapUpdate(*snake, *food);

    while (kbhit())
    {
        dir = getch();
        if (lastDir + dir == 152)//利用ascii码特性,防止蛇走反方向
        {
            dir = lastDir;
        }
    }
    //更新蛇坐标
    int res = snake->newHeadPoint(dir,food->foodPoint);
    lastDir = dir;

    if (res == Eat)
    {
        //产生新的食物坐标
        food->newFoodPoint();
    }
    
    //绘制所有,包括地图,蛇,食物
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            cout << mat[i][j];
        }
        cout << endl;
    }
    if (res == HitWall)
    {
        return true;
    }
    return false;
}

CSnake::CSnake(int t, int l, int w, int h)
{
    top = t;
    left = l;
    width = w;
    height = h;

    //随机起始坐标
    srand(5);
    headPoint.x = rand() % (width - 2) + 1;
    headPoint.y = rand() % (height - 2) + 1;
    Point *tmp = new Point(); tmp->x = headPoint.x; tmp->y = headPoint.y;
    snakeBody.push_back(tmp);
}
CSnake::~CSnake()
{
    for (int i = 0; i < snakeBody.size(); i++)
    {
        delete snakeBody[i];
    }
}

int CSnake::newHeadPoint(uchar dir, Point foodpoint)
{
    switch (dir)
    {
        //
    case Up:headPoint.y--; break;
        //
    case Down:headPoint.y++; break;
        //
    case Left:headPoint.x--; break;
        //
    case Right:headPoint.x++; break;

    default:
        break;
    }
    if ((headPoint.x == 0) || (headPoint.x == width - 1) || (headPoint.y == 0) || (headPoint.y == height - 1))
    {
        return HitWall;
    }

    //吃到食物
    if ((headPoint.x == foodpoint.x) && (headPoint.y == foodpoint.y))
    {
        Point *tmp = new Point(); tmp->x = foodpoint.x; tmp->y = foodpoint.y;
        snakeBody.insert(snakeBody.begin(), tmp);
        headPoint.x = foodpoint.x; headPoint.y = foodpoint.y;
        return Eat;
    }
    else//没吃到食物
    {
        for (int i = snakeBody.size() - 1; i > 0; i--)
        {
            snakeBody[i]->x = snakeBody[i - 1]->x;
            snakeBody[i]->y = snakeBody[i - 1]->y;
        }
        snakeBody[0]->x = headPoint.x; snakeBody[0]->y = headPoint.y;
        return NotEat;
    }
    return Common;
    
}

CFood::CFood(int t, int l, int w, int h)
{
    top = t;
    left = l;
    width = w;
    height = h;

    srand(8);
    newFoodPoint();
}
CFood::~CFood()
{
}
Point CFood::newFoodPoint()
{
    foodPoint.x = rand() % (width - 2) + 1;
    foodPoint.y = rand() % (height - 2) + 1;

    return foodPoint;
}

int main(int argc, char *argv[])
{
    CMap map(0, 0, 50, 25);
    while (1)
    {
        bool res= map.mapShow();
        delay(8000);
        if (res)
        {
            cout << "GAME OVER!" << endl;
            break;
        }
    }
    return 0;
}

首先看食物类:

class CFood{
public:
    CFood(int t, int l, int w, int h);
    ~CFood();

    friend class CMap;

    Point newFoodPoint();
private:
    int top;
    int left;
    int width;
    int height;

    Point foodPoint;
};

CFood::CFood(int t, int l, int w, int h)
{
    top = t;
    left = l;
    width = w;
    height = h;

    srand(8);
    newFoodPoint();
}
CFood::~CFood()
{
}
Point CFood::newFoodPoint()
{
    foodPoint.x = rand() % (width - 2) + 1;
    foodPoint.y = rand() % (height - 2) + 1;

    return foodPoint;
}

newFoodPoint函数用于产生随机的食物坐标点,当吃掉食物时调用这个函数。这个类比较简单。

class CSnake{
    
public:
    CSnake(int t, int l, int w, int h);
    ~CSnake();

    friend class CMap;

    int newHeadPoint(uchar dir, Point foodpoint);

private:
    int top;
    int left;
    int width;
    int height;

    vector<Point*> snakeBody;
    Point headPoint;
};
CSnake::CSnake(int t, int l, int w, int h)
{
    top = t;
    left = l;
    width = w;
    height = h;

    //随机起始坐标
    srand(5);
    headPoint.x = rand() % (width - 2) + 1;
    headPoint.y = rand() % (height - 2) + 1;
    Point *tmp = new Point(); tmp->x = headPoint.x; tmp->y = headPoint.y;
    snakeBody.push_back(tmp);
}
CSnake::~CSnake()
{
    for (int i = 0; i < snakeBody.size(); i++)
    {
        delete snakeBody[i];
    }
}

int CSnake::newHeadPoint(uchar dir, Point foodpoint)
{
    switch (dir)
    {
        //
    case Up:headPoint.y--; break;
        //
    case Down:headPoint.y++; break;
        //
    case Left:headPoint.x--; break;
        //
    case Right:headPoint.x++; break;

    default:
        break;
    }
    if ((headPoint.x == 0) || (headPoint.x == width - 1) || (headPoint.y == 0) || (headPoint.y == height - 1))
    {
        return HitWall;
    }

    //吃到食物
    if ((headPoint.x == foodpoint.x) && (headPoint.y == foodpoint.y))
    {
        Point *tmp = new Point(); tmp->x = foodpoint.x; tmp->y = foodpoint.y;
        snakeBody.insert(snakeBody.begin(), tmp);
        headPoint.x = foodpoint.x; headPoint.y = foodpoint.y;
        return Eat;
    }
    else//没吃到食物
    {
        for (int i = snakeBody.size() - 1; i > 0; i--)
        {
            snakeBody[i]->x = snakeBody[i - 1]->x;
            snakeBody[i]->y = snakeBody[i - 1]->y;
        }
        snakeBody[0]->x = headPoint.x; snakeBody[0]->y = headPoint.y;
        return NotEat;
    }
    return Common;
    
}

这个是蛇的类,主要实现一个newHeadPoint的函数用于规划蛇身体snakeBody的位置坐标。还有一个headPoint的点结构体。

输入参数是一个方向参数dir和食物坐标参数。方向来控制蛇身的移动,食物坐标来检测是否吃到食物。

通过不断移动蛇身体的坐标,最后把headPoint点赋给第一个点来实现蛇身体的移动。

class CMap{
public:
    CMap(int t, int l, int w, int h);
    ~CMap();

    void mapUpdate(CSnake& s,CFood& f);
    bool mapShow();

private:
    int top;
    int left;
    int width;
    int height;
    
    uchar **mat;
    uchar dir;
    uchar lastDir;

    CSnake *snake;
    CFood *food;
};

CMap::CMap(int t, int l, int w, int h)
{
    top = t;
    left = l;
    width = w;
    height = h;

    dir = Down;
    lastDir = Down;

    //内存分配
    mat = new uchar*[height];
    for (int i = 0; i < height; i++)
    {
        mat[i] = new uchar[width];
    }

    //初始化路径矩阵边界
    for (int i = 0; i < height; i++)
    {
        mat[i][0] = '#';
        for (int j = 1; j < width - 1; j++)
        {
            if (i == 0 || i == height - 1)
            {
                mat[i][j] = '#';
            }
            else
            {
                mat[i][j] = ' ';
            }
        }
        mat[i][width - 1] = '#';
    }

    snake = new CSnake(0, 0, 50, 25);
    food = new CFood(0, 0, 50, 25);
}
CMap::~CMap()
{
    for (int i = 0; i < height; i++)
    {
        delete mat[i];
    }
    delete mat;
}
void CMap::mapUpdate(CSnake& s, CFood& f)
{
    mat[f.foodPoint.y][f.foodPoint.x] = 'O';

    for (int i = 0; i < s.snakeBody.size(); i++)
    {
        if (i == 0)
        {
            mat[s.snakeBody[i]->y][s.snakeBody[i]->x] = '@';
        }
        else
        {
            mat[s.snakeBody[i]->y][s.snakeBody[i]->x] = '*';
        }
    }
}
bool CMap::mapShow()
{
    //设置顶点坐标,使得绘制一直在起点
    COORD coord;
    coord.X = top;
    coord.Y = left;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);

    for (int i = 1; i < height - 1; i++)
    {
        memset(mat[i] + 1, ' ', width - 2);
    }

    //更新食物坐标和蛇坐标
    mapUpdate(*snake, *food);

    while (kbhit())
    {
        dir = getch();
        if (lastDir + dir == 152)//利用ascii码特性,防止蛇走反方向
        {
            dir = lastDir;
        }
    }
    //更新蛇坐标
    int res = snake->newHeadPoint(dir,food->foodPoint);
    lastDir = dir;

    if (res == Eat)
    {
        //产生新的食物坐标
        food->newFoodPoint();
    }
    
    //绘制所有,包括地图,蛇,食物
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            cout << mat[i][j];
        }
        cout << endl;
    }
    if (res == HitWall)
    {
        return true;
    }
    return false;
}

地图类。类的初始化会把mat数组给初始化了。边界为#,蛇身为*,食物为O

mapUpdate函数用于更新mat数组。mapShow为界面显示地图。这个都比较简单。

流程为:

清空mat矩阵中部——更新数组——按键检测——蛇移动——绘制所有

原文地址:https://www.cnblogs.com/wyc199288/p/6365932.html