如何用C++实现控制台贪吃蛇程序

头文件及全局变量声明:

#include <iostream>
#include <Windows.h>
#include <ctime>
#include <conio.h>
#include <String>
using namespace std;

int death = 0;
int scores = 0;

首先枚举方向:(上下左右):

enum Direction {
        Up,
        Down,
        Left,
        Right
};

然后定义蛇身体(一个小方块)的结构体:

struct block {
        int X;
        int Y;
};

调用windows的API,实现控制台输出位置重定向:

void ToPosition(int x,int y){
        COORD pos;
        pos.X = x;
        pos.Y = y;
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleCursorPosition(hOut,pos);
}
调用windows的API,检测键盘输入:
void GetInput(int obj){    //等待键盘输入obj,否则一直等待
        while(1) {
                if(kbhit()) {
                        char ch = getch();
                        if(ch == obj)
                                return;
                }
        }
}
定义蛇类,构造函数中初始化位置并打印。数据成员包括蛇身(结构体数组),食物,当前方向,上次方向,刷新时间以及分数,方法包括刷新位置,打印蛇身,清空打印,食物初始化,刷新食物:
class snake {
public:
        snake(){
                score = 0;
                length = 3;
                s[0].X = 15;
                s[0].Y = 10;
                s[1].X = 14;
                s[1].Y = 10;
                s[2].X = 13;
                s[2].Y = 10;
                ToPosition(s[0].X,s[0].Y);
                cout<<"@";
                for(int i = 1; i < length; i++) {
                        ToPosition(s[i].X,s[i].Y);
                        cout<<"*";
                }
                lastDirection = Direction(3);
                direction = Direction(3);
                FoodInit();
        }
        void print(){
                flash();
                Clear();
                Food();
                ToPosition(food.X,food.Y);
                cout<<"#";
                for(int i = length - 1; i > 0; i--) {
                        s[i] = s[i-1];
                }
                if(direction == Up) {
                        s[0].X = s[0].X;
                        s[0].Y = s[0].Y - 1;
                }
                if(direction == Down) {
                        s[0].X = s[0].X;
                        s[0].Y = s[0].Y + 1;
                }
                if(direction == Left) {
                        s[0].X = s[0].X - 1;
                        s[0].Y = s[0].Y;
                }
                if(direction == Right) {
                        s[0].X = s[0].X + 1;
                        s[0].Y = s[0].Y;
                }
                ToPosition(s[0].X,s[0].Y);
                cout<<"@";
                for(int i = 1; i < length; i++) {
                        ToPosition(s[i].X,s[i].Y);
                        cout<<"*";
                }
                for(int i = 1; i < length; i++) {
                        if(s[0].X == s[i].X && s[0].Y == s[i].Y)
                                death=1;
                }
                if(s[0].X == 0 || s[0].X == 30 || s[0].Y == 1 || s[0].Y == 20)
                        death =1;
                ToPosition(34,2);
                cout<<"Score: "<<score;
        }
        void flash(){
                char input = ' ';
                int start = clock();
                while(clock() - start < 200) {
                        if(kbhit()) {
                                input = getch();
                        }
                }
                switch(input) {
                case 'a':  if(direction!= Right) direction = Left; break;
                case 'w':  if(direction!= Down) direction = Up; break;
                case 'd':  if(direction!= Left) direction = Right; break;
                case 's':  if(direction!= Up) direction = Down; break;
                case ' ':  direction = lastDirection; break;
                }
                lastDirection = direction;
        }
        void Clear(){
                for(int i = 1; i < 30; i++)
                        for(int j = 2; j < 20; j++) {
                                ToPosition(i,j);
                                cout<<" ";
                        }
        }
        void FoodInit(){
                srand((unsigned)time(NULL));
                food.X = rand()%28 + 2;
                food.Y = rand()%18 + 2;
        }
        void Food(){
                if(s[0].X == food.X && s[0].Y == food.Y) {
                        int flag = 1;
                        while(flag) {
                                srand((unsigned)time(NULL));
                                food.X = rand()%29 + 1;
                                food.Y = rand()%18 + 2;
                                for(int i = 0; i < length; i++) {
                                        if(food.X == s[i].X && food.Y == s[i].Y) {
                                                srand((unsigned)time(NULL));
                                                food.X = rand()%29 + 1;
                                                food.Y = rand()%18 + 2;
                                                break;
                                        }else{
                                                flag = 0;
                                        }
                                }
                                score++;
                                scores++;
                                s[length] = s[length-1];
                                length++;
                        }
                }
        }

private:
        int length;
        Direction direction;
        Direction lastDirection;
        int flashtime;
        block s[100];
        block food;
        int score;
};
定义游戏类,构造函数中打印游戏界面,开始游戏。方法包括:开始游戏,运行游戏(死亡检测),结束游戏,打印游戏界面:
class Game {
public:
        Game(){
                for(int i = 0; i < 25; i++) {
                        ToPosition(0,i);
                        cout<<"                                              ";
                }
                death = 0;
                scores = 0;
                PrintFrame();
                GameStart();
        }
        void GameStart(){
                GetInput(32);
                ToPosition(34,12);
                cout<<"                                             ";
                GameRun();
        }
        void GameRun(){
                ToPosition(34,2);
                snake sk;
                while(!death) {
                        sk.print();
                }
                GameOver();
        }
        void GameOver(){
                for(int i = 0; i < 25; i++) {
                        ToPosition(0,i);
                        cout<<"                                              ";
                }
                ToPosition(0,0);
                cout<<"GAME OVER!"<<endl;
                cout<<"Score: "<<scores<<endl;
        }
        ~Game(){


        }
        void PrintFrame(){
                int Line = 30;
                int Long = 20;
                ToPosition(Long/2+3,0);
                cout<<"SNAKE";
                for(int i = 0; i < Line; i++) {
                        ToPosition(i,1);
                        cout<<"*";
                        ToPosition(i,Long);
                        cout<<"*";
                }
                for(int i = 1; i < Long + 1; i++) {
                        ToPosition(0,i);
                        cout<<"$";
                        ToPosition(Line,i);
                        cout<<"$";
                }
                ToPosition(34,7);
                cout<<"Up:    "<<"w";
                ToPosition(34,8);
                cout<<"Left:  "<<"a";
                ToPosition(34,9);
                cout<<"Down:  "<<"s";
                ToPosition(34,10);
                cout<<"Right: "<<"d";
                ToPosition(34,12);
                cout<<"Please press the space key to start the game.";
        }
private:


};

主函数完成游戏启停逻辑:

int main(){
        while(1) {
                Game game;
                cout<<"Please press the Y key to reload the game."<<endl;
                GetInput(121);
        }
        return 0;
}

完整版代码附后,转载请注明出处。

点击查看完整版代码

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值