C++贪吃蛇实现

本文档展示了C++实现贪吃蛇游戏的完整代码,包括`Snake`、`Food`和`_Wall`类的定义及游戏逻辑。游戏通过不断更新屏幕内容形成动画效果,用户通过键盘输入控制蛇移动,遇到墙壁或自身会游戏结束。
摘要由CSDN通过智能技术生成

#define _CRT_SECURT_NO_WARNINGS
#include<iostream>
using namespace std;
#include"wall.h"
#include"snake.h"
#include"food.h"
#include<time.h>
#include<conio.h>
#include<Windows.h>

//本人做贪吃蛇项目后 总结 贪吃蛇游戏中其实并不是蛇在动 而是像动画片一样 计算机在不断的输出着数组中的内容有变化就输出形成了动画


int main()
{
    //
    srand((unsigned int)time(NULL));
    //是否死亡表示

    bool isdead=false;  //检测是否死亡

    char preKey = NULL;
    _Wall wall;  //构造
    wall.initWall();   //设置墙
    Food  _food(wall);     //构造
    Snake snake(wall,_food);  //构造
    snake.initSnake();   //设置蛇
    _food.setfood();    //设置食物
    
    wall.drawWall(snake.getScore());      //画

    //接收用户输入
    
    while (!isdead)
    {
        char key = _getch();

        if ( preKey==NULL&& key == snake.LEFT)   //防止第一次按左结束
        {
            continue;
        }
        do
        {
            if (key == snake.DOWN || key == snake.LEFT || key == snake.RIGHT || key == snake.UP)  //屏蔽出了wsad外的其他按键
            {
                //判断本次按键是否与上次冲突
                if (
                    (key == snake.LEFT && preKey == snake.RIGHT) ||
                    (key == snake.UP && preKey == snake.DOWN) ||
                    (key == snake.RIGHT && preKey == snake.LEFT) ||             //防止反方向按键结束游戏
                    (key == snake.DOWN && preKey == snake.UP) 
                    )
                {
                    key = preKey;                    
                }
                else 
                {
                    preKey = key;
                }
                

                if (snake.move(key) == true)
                {
                    system("cls");             //清屏
                    wall.drawWall(snake.getScore());
                    int _time = snake.getSleepTime();
                    Sleep(_time);         //windows系统中有Sleep函数(注意大写),void Sleep(DWORD dwMilliseconds);提供挂起的毫秒数,并且需包含windows.h
                }
                else
                {
                    isdead = true;
                    break;
                }

            }
            else
            {
                key = preKey;   //强制将错误按键变为上次方向
            }
        } while (!_kbhit());//当没有键盘输入返回0
        
    }
    
    system("pause");
    return EXIT_SUCCESS;
}

 

#pragma once
#include<iostream>
#include"wall.h"
#include"food.h"
using namespace std;


class Snake
{
public:
    Snake(_Wall& tempWall, Food& food);
    enum { UP = 'w', DOWN = 's', LEFT = 'a', RIGHT = 'd' };
    

    struct Point
    {
        //数据域
        int x;
        int y;
        //指针域

        Point* next;
    };

    //设置蛇
    void initSnake();

    //销毁节点
    void destroyPiont();

    //添加节点
    void addPiont(int x, int y);

    //头节点
    Point* phead;
    //删除节点方法
    void deletPoint();
    //移动蛇操作 
    //返回值代表是否成功
    bool move(char key);
    Food & _food;
    _Wall & wall;
    bool isRool;  //判断是否循环

    //设定难度
    //获取刷屏时间
    int getSleepTime();
    //获取蛇的身段
    int countList();
    //计算得分
    int  getScore();
    

    
};

 

#include "snake.h"
//默认构造初始化头节点
 //使用了初始化列表 _Wall& wall;wall(tempwall) 构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式
Snake::Snake(_Wall& tempWall, Food& food):wall (tempWall), _food(food)
{
    phead = NULL;
    isRool = false;
}

void Snake::initSnake()
{
    destroyPiont();
    addPiont(5,3);
    addPiont(5,4);
    addPiont(5,5);
}

//销毁节点
void Snake::destroyPiont()
{
    Point* pCur = phead;
    while (phead!=NULL)
    {
        pCur = phead->next;
        delete phead;
        phead = pCur;
    }
}

void Snake::addPiont(int x, int y)
{
    //创建新节点
    Point* newPoint = new Point;
    newPoint->x = x;
    newPoint->y = y;
    newPoint->next = NULL;

    //如果原来头不为空改为身子

    if (phead != NULL)
    {

        wall.setWall(phead->x, phead->y, '=');        //头变为身子画=号
         
    }

    newPoint->next = phead;

    phead = newPoint;
    wall.setWall(phead->x, phead->y, '@');     //画头@


}
//删除节点
void Snake::deletPoint()
{
    //两个节点以上  才去做删除操作
    if (phead == NULL || phead->next == NULL)
    {
        return;
    }
    Point* pCur = phead->next;
    Point* pPre = phead;

    while (pCur->next!=NULL)
    {
         pPre = pPre->next;
         pCur = pCur->next;
    }
    //delete it

    wall.setWall(pCur->x, pCur->y, ' ');

    delete pCur;
    pCur = NULL;
    pPre->next = NULL;


}

bool Snake::move(char key)
{
    int x = phead->x;
    int y = phead->y;
    
    switch (key)
    {
    case UP:
        x--;
        break;
    case DOWN:
        x++;
        break;
    case LEFT:
        y--;
        break;
    case RIGHT:
        y++;
        break;
    
    default:
        break;
    }
    //如果碰到是尾巴不应该死亡
    Point* pCur = phead->next;
    Point* pPre = phead;

    while (pCur->next != NULL)
    {
        pPre = pPre->next;
        pCur = pCur->next;
    }

    if (pCur->x == x && pCur->y == y)
    {
        //说明碰到尾巴
        isRool = true;
    }
    else
    {
        //让吃到自己和墙壁后显示更合理
        if (wall.getWall(x, y) == '*'  )        
        {
            addPiont(x, y);
            deletPoint();
            system("cls");
            wall.drawWall(getScore());
            cout << "GAME OVER!!!" << endl;
            return false;
        }
        if (wall.getWall(x, y) == '=')
        {
            addPiont(x, y);
            system("cls");
            wall.drawWall(getScore());
            cout << "GAME OVER!!!" << endl;
            return false;
        }
    }    

    if (wall.getWall(x, y) == '#')
    {
        addPiont(x, y);
        //重新设置食物
        _food.setfood();

    }
    else
    {
        
        addPiont(x, y);
        deletPoint();
        if (isRool == true)
        {
            wall.setWall(x, y, '@');
        }
    }
    return true;             //这个位置我第一次写时候没有return true 导致我输入什么都没反应 所以记得添加
}
//获取刷屏时间
int Snake::getSleepTime()
{
    int sleeptime = 0;
    int size = countList();
    if (size < 5)
    {
        sleeptime = 300;
    }
    else if (size >= 5 && size <= 8)
    {
        sleeptime = 200;
    }
    else
    {
        sleeptime = 100;
    }
    
    return sleeptime;
}
//获取长度
int Snake::countList()
{
    int size = 0;
    Point* curPiont = phead;
    while (curPiont != NULL)
    {
        size++;

        curPiont = curPiont->next;

    }
    return size;
}

int Snake::getScore()
{
    int size = countList();
    int piont = (size - 3) * 10;
    return piont;
}

 

 

#pragma once
#include<iostream>
#include "wall.h"
using namespace std;

class Food
{
public:
    Food(_Wall& tempWall);

    int foodx;
    int foody;
    
    //设置食物
    void setfood();
    _Wall& wall;

};
#pragma once
#include "food.h"

Food::Food(_Wall& tempWall) :wall(tempWall)
{

}

void Food::setfood()
{
    while (1)
    {

        foodx = rand() % (_Wall::ROW - 2) + 1;
        foody = rand() % (_Wall::COL - 2) + 1;
        //随机食物不能碰到蛇身
        if (wall.getWall(foodx, foody) == ' ')
        {
            wall.setWall(foodx, foody, '#');
            break;
        }
    }
}
 

#ifndef _WALL_HEAD
#define _WALL_HEAD

#include<iostream>

using namespace std;

class _Wall
{
public:
    
    
    enum { ROW = 26, COL = 26 };
    //设置墙
    void initWall();
    //画墙
    void drawWall(int score);
    //根据索引设置二维数组的内容
    void setWall(int a,int b,char c);
    //获取二维数组中的值
    char getWall(int a, int b);

    
private:

    char gameArray[ROW][COL];

};

#endif // !_WALL_HEAD
 

 

#include "wall.h"
#pragma once
//设置墙
void _Wall::initWall()
{
    for (int i = 0; i < ROW; ++i)
    {
        for (int j = 0; j < COL; ++j)
        {
            if (i == 0 || j == 0 || i == (ROW - 1) || j == (COL - 1))
            {
                gameArray[i][j] = '*';
            }
            else
            {
                gameArray[i][j] = ' ';
            }
        }
    }

}
//画墙
void _Wall::drawWall(int score)
{
    for (int i = 0; i < ROW; ++i)
    {
        for (int j = 0; j < COL; ++j)
        {
            cout << gameArray[i][j]<<" " ;
        }
        if (i == 10)
        {
            cout << "create by zhy";
        }
        if (i == 11)
        {
            cout << "a : left";
        }
        if (i == 12)
        {
            cout << "d : right";
        }
        if (i == 13)
        {
            cout << "w : up";
        }

        if (i == 14)
        {
            cout << "s : down";
        }
        if (i == 15)
        {
            cout << score<<"分";
        }

        cout << endl;
    }
}
//根据索引设置二维数组的内容
void _Wall::setWall(int a, int b, char c)
{
    gameArray[a][b] = c;
}

char _Wall::getWall(int a, int b)
{
    return gameArray[a][b];
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值