用C++实现手动贪吃蛇程序

学习C++有一段时间了,但是一直都没怎么用它来做些事。这两天刚好有时间,就用C++实现了一把贪吃蛇小游戏程序。新手发文,水平有限,望谅解!!话不多说,直接上源码:

-----------common.h头文件程序-------------------------------------

#include<windows.h>
#include<iostream>
using namespace std;

//设置每个坐标位置的值
extern short value[30][60];
//初始化得分
extern int my_scores ;
//蛇头的运动方向
enum direct {  east,west,north,south, };
//移动光标到指定位置
extern void gotoxy(short x, short y);
 

----------------food.h头文件程序---------------------

#pragma once
#include<windows.h>
#include<time.h>
#include"common.h"
#include"point.h"
using namespace std;


class food {
public:
    //产生食物
    void product_food();
    //画出食物
    void draw_food();
private:
    //食物的位置
    point food_position;
};

------------------point.h头文件程序---------------------------

#pragma once

//定义point类
class point {
public:
    //点的两个坐标值
    short x;
    short y;
    //默认构造函数
    point() {}
    point(short m, short n) :x(m), y(n) {}
    //拷贝构造函数
    point(const point& pointer) {
        x = pointer.x;
        y = pointer.y;
    }
    //拷贝赋值运算符
    point& operator=(const point & pointer) {
        x = pointer.x;
        y = pointer.y;
        return *this;
    }
};

 

---------------------printinfo.h头文件程序----------------------------------------

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

class printinfo {
public:
    //打印得分
    void print_score();
    打印出游戏开始时的封面
    void print_cover();
    //打印墙壁,隐藏光标,并将墙壁所处坐标的值全部设为2
    void print_wall();
    //打印出结果-蛇因为撞墙而死
    void print_end_info_wall();
    //打印出结果-蛇因为撞自己而死
    void print_end_info_self();
};

 

------------------snake.h头文件程序----------

#pragma once
#include"point.h"
#include<list>
#include<windows.h>
#include<iostream>
#include"common.h"
using namespace std;

class snake {
private:
    //蛇头
    point snake_head;
    //记录小蛇每次运动之前的最后一节的位置
    point record_tail_point;
    //记录小蛇运动一格后,蛇头将到达的位置点的值,这个值用来判断小蛇是否撞到墙或者自己,或者吃到食物
    int record_new_begin_value;
    //用一个双向链表来装小蛇的全身
    list<point> snake_body;

public:
    //小蛇当前的运动方向
    direct direction;    
    //蛇的长度,用途不大,只有在初始化时设置为3节
    short snake_length;
public:
    //默认构造函数
    snake();
    //画蛇身子
    void draw_snake();
    //蛇动起来
    void snake_move();
    //是否吃到食物
    bool is_eat_food();
    //是否撞到墙
    bool is_collide_wall();
    //是否撞到自己
    bool is_collide_self();
    //蛇变长
    void become_longer();
    //擦除残影
    void remove_shadow();

};

 

----------common.cpp源文件程序------------

#include"common.h"

//设置每个坐标位置的值
short value[30][60] = { 0 };
//初始化得分
int my_scores = 1;

//移动光标到指定位置
void gotoxy(short x, short y) {
    COORD coord = { x,y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
 

--------------food.cpp源文件程序-----------------------------------

#include"food.h"

//产生食物的位置
void food::product_food() {
    do {
        srand(unsigned(time(0)));
        food_position.x = (rand() % 28) * 2 + 2;
        food_position.y = rand() % 28 + 1;
    } while (value[food_position.x][food_position.y] == 1);
}

//将食物在固定坐标上画出来
void food::draw_food() {
    gotoxy(food_position.x, food_position.y);
    value[food_position.x][food_position.y] = 3;
    cout << '*';
}

 

----------------------printinfo.cpp源文件程序----------------------

#include"printinfo.h"
#include<conio.h>

//打印墙壁,隐藏光标,并将墙壁所处坐标的值全部设为2
void printinfo::print_wall() {
    system("cls");
    for (short i = 0; i < 30; i++) {
        gotoxy(0, i);
        cout << '#';
    }
    for (short i = 0; i <30; i++) {
        gotoxy(58, i);
        cout << '#';
    }
    for (short i = 0; i <60; i++) {
        gotoxy(i, 0);
        cout << '#';
        i++;
    }
    for (short i = 0; i < 60; i++) {
        gotoxy(i, 29);
        cout << '#';
        i++;
    }
    for (short i = 0; i < 60; i = i + 2) {
        value[i][0] = 2;
        value[i][29] = 2;
    }
    for (short i = 0; i < 30; i++) {
        value[0][i] = 2;
        value[58][i] = 2;
    }
    //隐藏光标
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO CursorInfo;
    GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标
    CursorInfo.bVisible = false; //隐藏控制台光标
    SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态    
}

//打印得分
void printinfo::print_score() {
    gotoxy(85, 15);
    cout << "您的得分:" << my_scores;
}

//打印出游戏开始时的封面
void printinfo::print_cover() {
    cout << "           " << "欢迎来到贪吃蛇游戏" << endl;
    cout << endl;
    cout << "     " << "a表示向左运动,d表示向右运动" << endl;
    cout << endl;
    cout << "     " << "w表示向上运动,s表示向下运动" << endl;
    cout << endl;
    cout << "             " << "祝您游戏愉快" << endl;
    cout << endl;
    cout << endl;
    cout << "请输入任意键进入游戏" << endl;
    int a = _getch();
}

//打印出结果-蛇因为撞墙而死
void printinfo::print_end_info_wall() {
    system("cls");
    cout << "                   "<<"Game Over" << endl;
    cout << "                "<<"撞墙了!!!!!" << endl;
    char a;
    a=_getch();
    exit(0);
}

//打印出结果-蛇因为撞自己而死
void printinfo::print_end_info_self() {
    system("cls");
    cout << "                   " << "Game Over" << endl;
    cout << "                " << "撞自己了!" << endl;
    char a;
    a = _getch();
    exit(0);
}

---------------------snake.cpp源文件程序-----------------------

#include"snake.h"

//默认构造函数
snake::snake():snake_length(3) {
    snake_head.x = (rand() % 26) * 2 + 6;
    snake_head.y = rand() % 28 + 1;
    for (int i = 0; i < snake_length; i++) {
        snake_body.push_back(point(snake_head.x - 2 * i, snake_head.y));
    }
    record_tail_point = snake_body.back();
}

//画蛇身子
void snake::draw_snake() {
    list<point>::iterator it = snake_body.begin();
    for (; it != snake_body.end(); it++) {
        value[it->x][it->y] = 1;
        gotoxy(it->x, it->y);
        cout << '#';
    }
}

//不管向哪个方向,小蛇都运动一格
void snake::snake_move() {
    record_tail_point = snake_body.back();
    for (auto it = (--(snake_body.end())); it != snake_body.begin();) {
        short& p = it->x;
        short& q = it->y;
        p = (--it)->x;
        it++;
        q = (--it)->y;
    }
    if (direction == east)
        snake_body.begin()->x += 2;
    else if (direction == west)
        snake_body.begin()->x -= 2;
    else if (direction == north)
        snake_body.begin()->y -= 1;
    else
        snake_body.begin()->y += 1;
    record_new_begin_value = value[snake_body.front().x][snake_body.front().y];
}

//是否吃到食物
bool snake::is_eat_food() {
    if (record_new_begin_value== 3)
        return true;
    else
        return false;
}

//蛇变长
void snake::become_longer() {
    snake_body.push_back(record_tail_point);
}

//是否撞到墙
bool snake::is_collide_wall() {
    if (record_new_begin_value== 2)
        return true;
    else
        return false;
}

//是否撞到墙
bool snake::is_collide_self() {
    if (record_new_begin_value == 1)
        return true;
    else
        return false;
}

//擦除残影
void snake::remove_shadow() {
    gotoxy(record_tail_point.x,record_tail_point.y);
    value[record_tail_point.x][record_tail_point.y] = 0;
    cout << ' ';
}

--------------------main.cpp主程序----------------------------------

#include"snake.h"
#include"food.h"
#include"printinfo.h"
#include<conio.h>
#include"common.h"

int main() {
    //实例化一个printinfo类
    printinfo printinfoer;
    //打印游戏封面
    printinfoer.print_cover();
    //打印游戏围墙
    printinfoer.print_wall();
    //实例化一个snake类
    snake snaker;
    //第一次画小蛇
    snaker.draw_snake();
    //实例化一个food类
    food fooder;
    //第一次产生食物
    fooder.product_food();
    //第一次画食物
    fooder.draw_food();
    //打印得分,基础分为1分,没吃1个食物的1分
    printinfoer.print_score();
    while (1) {
        //阻塞状态来等待输入运动方向
        int a = _getch();
        switch (a) {
        case 100://向右    
            //如果自身的运动方向是向左的,那么按d(向右运动)是没有用的,直接跳出本次循环,并进行下次循环
            if (snaker.direction == west) break;
            //将小蛇本身的方向属性改为east
            snaker.direction = east;
            //小蛇运动一格
            snaker.snake_move();
            //画出运动后的小蛇
            snaker.draw_snake();
            //将之前的小蛇最后一节残影删除
            snaker.remove_shadow();
            //判断小蛇运动一格之后是否吃到食物,如果是,进入语句块
            if (snaker.is_eat_food() == 1) {
                //蛇身变长一格
                snaker.become_longer();
                //画出变长后的小蛇
                snaker.draw_snake();
                //重新在内存中产生一个食物
                fooder.product_food();
                //重新画出一个食物
                fooder.draw_food();
                //得分加1
                my_scores++;
                //蛇长度加1
                snaker.snake_length++;
                //打印最新得分
                printinfoer.print_score();
            }
            //判断是否撞到自己,如果是,结束游戏
            if ( snaker.is_collide_self() == 1)
                printinfoer.print_end_info_self();
            //判断是否撞到墙,如果是,结束游戏
            if (snaker.is_collide_wall() == 1 )
                printinfoer.print_end_info_wall();
            break;
        case 97://向左-------(逻辑过程与向右基本相同)
            if (snaker.direction == east) break;
            snaker.direction = west;
            snaker.snake_move();
            snaker.draw_snake();
            snaker.remove_shadow();
            if (snaker.is_eat_food() == 1) {
                snaker.become_longer();
                snaker.draw_snake();
                fooder.product_food();
                fooder.draw_food();
                my_scores++;
                printinfoer.print_score();
            }
            if (snaker.is_collide_self() == 1)
                printinfoer.print_end_info_self();
            if (snaker.is_collide_wall() == 1)
                printinfoer.print_end_info_wall();
            break;
        case 119://向上
            if (snaker.direction==south) break;
            snaker.direction = north;
            snaker.snake_move();
            snaker.draw_snake();
            snaker.remove_shadow();
            if (snaker.is_eat_food() == 1) {
                snaker.become_longer();
                snaker.draw_snake();
                fooder.product_food();
                fooder.draw_food();
                my_scores++;
                printinfoer.print_score();
            }
            if (snaker.is_collide_self() == 1)
                printinfoer.print_end_info_self();
            if (snaker.is_collide_wall() == 1)
                printinfoer.print_end_info_wall();
            break;
        case 115://向下
            if (snaker.direction==north) break;
            snaker.direction = south;
            snaker.snake_move();
            snaker.draw_snake();
            snaker.remove_shadow();
            if (snaker.is_eat_food() == 1) {
                snaker.become_longer();
                snaker.draw_snake();
                fooder.product_food();
                fooder.draw_food();
                my_scores++;
                printinfoer.print_score();
            }
            if (snaker.is_collide_self() == 1)
                printinfoer.print_end_info_self();
            if (snaker.is_collide_wall() == 1)
                printinfoer.print_end_info_wall();
            break;
        default:
            break;
        }   
    }
    return 0;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值