鱼C论坛

 找回密码
 立即注册
查看: 5785|回复: 82

[技术交流] 贪吃蛇:C++

[复制链接]
发表于 2020-8-21 16:33:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 livcui 于 2020-8-22 21:22 编辑

Snake.gif
使用 EasyX 库制作的贪吃蛇,下面是源代码:    (没hide权限,骗不了回复)

另外,EasyX 仅支持 VC ,这是下载地址 https://easyx.cn/downloads/

如果不想安装 EasyX,可下载打包好的 EXE 文件 Snake.zip (43.95 KB, 下载次数: 48)



源文件:
// Code.cpp
#include "Snake.h"
#include <cstdio>
#include <string>
#include <sstream>
#include <time.h>
#include <conio.h>

Snake::Snake(): hwnd(initgraph(480 + 153, 480))// 设置窗口大小 (730, 480)
                                , speed(50), level_ () {

        setbkcolor(WHITE);                // 窗口颜色为白 White

        // 初始化蛇
        snake.num = 3;                                // 初始化时为三节
        snake.snakeXY[0].x = 20;        // 间隔10像素
        snake.snakeXY[0].y = 0;
        snake.snakeXY[1].x = 10;
        snake.snakeXY[1].y = 0;
        snake.snakeXY[2].x = 0;
        snake.snakeXY[2].y = 0;
        snake.postion = right;                // 初始化方向为右

        // 初始化食物
        food.foodXY.x = rand() % 65 * 10;        // 随机生成坐标
        food.foodXY.y = rand() % 48 * 10;
        food.flag = 1;                // 食物存在
        // 检测食物和蛇坐标是否重复
        for (int i = 0; i < snake.num; i++) {
                // 如果坐标重复,重新生成
                if (food.foodXY.x == snake.snakeXY[i].x and food.foodXY.y == snake.snakeXY[i].y) {
                        food.foodXY.x = rand() % 65 * 10;
                        food.foodXY.y = rand() % 48 * 10;
                }
        }
}
Snake::~Snake() {}

// 按键处理
void Snake::keyDown() {

        char userKey;
        userKey = _getch();

        switch (userKey) {

                // 上下左右
        case right:
                if (snake.postion != down) snake.postion = up;
                break;
        case left:
                if (snake.postion != right) snake.postion = left;
                break;
        case down:
                if (snake.postion != left) snake.postion = right;
                break;
        case up:
                if (snake.postion != up) snake.postion = down;
                break;

                // 调整速度(数字键 1, 2, 3, 4, ... , 10)
        case 49:
                speed = 10;
                break;
        case 50:
                speed = 20;
                break;
        case 51:
                speed = 30;
                break;
        case 52:
                speed = 40;
                break;
        case 53:
                speed = 50;
                break;
        case 54:
                speed = 60;
                break;
        case 55:
                speed = 70;
                break;
        case 56:
                speed = 80;
                break;
        case 57:
                speed = 90;
                break;
        case 48:
                speed = 100;
                break;
        default:
                break;

        }

}
// 画蛇
void Snake::drawSnake() {

        for (int i = 0; i < snake.num; i++) {

                setlinecolor(BLACK);        //矩形边框颜色为黑Black
                setfillcolor(BLUE);                //矩形内部颜色为蓝blue
                fillrectangle(snake.snakeXY[i].x, snake.snakeXY[i].y, snake.snakeXY[i].x + 10, snake.snakeXY[i].y + 10);
        }
}
// 移动蛇
void Snake::moveSnake() {

        // 除蛇第一节以外的移动坐标处理
        for (int i = snake.num - 1; i > 0; i--) {

                snake.snakeXY[i].x = snake.snakeXY[i - 1].x;
                snake.snakeXY[i].y = snake.snakeXY[i - 1].y;
        }
        // 第一节坐标处理
        switch (snake.postion) {

        case right:
                snake.snakeXY[0].x += 10;
                break;
        case left:
                snake.snakeXY[0].x -= 10;
                break;
        case down:
                snake.snakeXY[0].y += 10;
                break;
        case up:
                snake.snakeXY[0].y -= 10;
                break;
        default:
                break;
        }
}
// 移动蛇 - 穿墙
void Snake::moveSnake_2() {

        // 除蛇第一节以外的移动坐标处理
        for (int i = snake.num - 1; i > 0; i--) {

                snake.snakeXY[i].x = snake.snakeXY[i - 1].x;
                snake.snakeXY[i].y = snake.snakeXY[i - 1].y;
        }
        // 第一节坐标处理, 穿墙
        switch (snake.postion) {

        case right:
                snake.snakeXY[0].x += 10;
                break;
        case left:
                snake.snakeXY[0].x -= 10;
                break;
        case down:
                snake.snakeXY[0].y += 10;
                break;
        case up:
                snake.snakeXY[0].y -= 10;
                break;
        default:
                break;
        }

        if (snake.snakeXY[0].x > 470) snake.snakeXY[0].x = 0;
        if (snake.snakeXY[0].x < 0) snake.snakeXY[0].x = 470;
        if (snake.snakeXY[0].y > 470) snake.snakeXY[0].y = 0;
        if (snake.snakeXY[0].y < 0) snake.snakeXY[0].y = 470;
}
// 初始化食物
void Snake::initFood() {

        srand(time(NULL));
        food.foodXY.x = rand() % 48 * 10;        // 随机生成坐标
        food.foodXY.y = rand() % 48 * 10;
        food.flag = 1;

        // 检测食物和蛇坐标是否重复
        for (int i = 0; i < snake.num; i++) {
                // 如果坐标重复,重新生成
                if (food.foodXY.x == snake.snakeXY[i].x and food.foodXY.y == snake.snakeXY[i].y) {
                        food.foodXY.x = rand() % 48 * 10;        // 随机生成坐标
                        food.foodXY.y = rand() % 48 * 10;
                }
        }
}
// 画食物
void Snake::drawFood() {

        fillrectangle(food.foodXY.x, food.foodXY.y, food.foodXY.x + 10, food.foodXY.y + 10);
        setlinecolor(BLACK);        //矩形边框颜色为黑Black
        setfillcolor(BLUE);                //矩形内部颜色为蓝blue

}
// 吃食物
void Snake::eatFood() {

        if (snake.snakeXY[0].x == food.foodXY.x and snake.snakeXY[0].y == food.foodXY.y) {

                // 蛇吃掉后长度 +1
                snake.num++;
                food.eatGrade += 1;
                food.flag = 0;

                // 蛇吃掉后重新画食物
                void drawFood();
        }
}
// 判断蛇撞墙而死
void Snake::snakeWallDie() {

        if (snake.snakeXY[0].x > 470 or
                snake.snakeXY[0].x < 0 or
                snake.snakeXY[0].y > 470 or
                snake.snakeXY[0].y < 0 ) {
                outtextxy(200, 200, "你撞墙了!");
                snake.flag = 1;                // 蛇死亡
        }
}
// 判断蛇自杀而死
void Snake::snakeBodyDie() {

        for (int i = 1; i < snake.num; i++) {

                if (snake.snakeXY[0].x == snake.snakeXY[i].x and snake.snakeXY[0].y == snake.snakeXY[i].y) {
                        outtextxy(200, 200, "你自杀了!");

                        snake.flag = 1;                // 蛇死亡
                }
        }
}
// 显示分数
void Snake::showGrade() {

        //char arr[10];
        //sprintf(arr, "%d", food.eatGrade);
        std::ostringstream ss;
        ss << food.eatGrade;
        std::string str = ss.str();
        setbkmode(BLUE);
        settextcolor(BLACK);
        outtextxy(500, 25, "分数");
        outtextxy(550, 25, str.c_str());
}

// 运行
void Snake::run() {

        setbkcolor(BLACK);                // 窗口颜色为黑 BLACK
        settextcolor(WHITE);        // 文字颜色
        outtextxy(50, 50, "选择模式");
        outtextxy(60, 80, "( 1    经典");
        outtextxy(60, 100, "( 2    围墙");
        
        switch (_getch()) {

        case '1':
                level_ = 0;
                break;
        case '2':
                level_ = 1;
                break;
        default:
                level_ = 0;
        }
        setbkcolor(WHITE);                // 窗口颜色为白 WHITE

loop:
        while (true) {
        
                while (_kbhit()) {

                        keyDown();                // 如果有键盘输入, 检测输入
                }
                cleardevice();        // 刷新
                switch (level_){        // 不同模式
                case 0:
                        snakeBodyDie();
                        moveSnake_2();                                // 移动蛇 - 穿墙
                        setlinecolor(BLACK);                // 画线颜色为黑 Black
                        setlinestyle(PS_DASH, 2);        // 设置线 (虚线, 宽 2)
                        line(480, 480, 480, 0);                // 画线
                        // 线条恢复默认
                        setlinestyle(PS_SOLID, 1);        // 设置线 (实线, 宽 1)
                        outtextxy(500, 60, "游戏模式 : ");
                        outtextxy(590, 60, "经典");
                        break;
                case 1:
                        snakeWallDie();
                        snakeBodyDie();
                        moveSnake();                                // 移动蛇 - 围墙
                        setlinecolor(BLACK);                // 画线颜色为黑 Black
                        setlinestyle(PS_SOLID, 5);        // 设置线 (实线, 宽 5)
                        line(480, 480, 480, 0);                // 画线
                        line(1, 1, 1, 480);
                        line(479, 479, 1, 479);
                        line(1, 1, 480, 1);
                        // 线条恢复默认
                        setlinestyle(PS_SOLID, 1);        // 设置线 (实线, 宽 1)
                        outtextxy(500, 60, "游戏模式 : ");
                        outtextxy(590, 60, "围墙");
                        break;
                default:
                        snakeBodyDie();
                        moveSnake_2();        // 移动蛇 - 穿墙
                        setlinecolor(BLACK);                // 画线颜色为黑 Black
                        setlinestyle(PS_DASH, 2);        // 设置线 (虚线, 宽 2)
                        line(480, 480, 480, 0);                // 画线
                        // 线条恢复默认
                        setlinestyle(PS_SOLID, 1);        // 设置线 (实线, 宽 1)
                        break;
                }
                drawSnake();        // 画蛇
                if (snake.flag == 1) {                // 如果蛇死了...

                        if (MessageBox(NULL, "再玩一局?", "GameOver", MB_YESNO) != IDYES) return;
                        else {
                                snake.flag = 0;
                                snake.num = 3;
                                snake.snakeXY[0].x = 20;
                                snake.snakeXY[0].y = 0;
                                snake.snakeXY[1].x = 10;
                                snake.snakeXY[1].y = 0;
                                snake.snakeXY[2].x = 0;
                                snake.snakeXY[2].y = 0;
                                snake.postion = right;
                                food.eatGrade = 0;
                                goto loop; 
                                
                        }
                }
                if (food.flag != 1) initFood();                // 初始化食物
                if (food.flag == 1) drawFood();                // 画食物
                eatFood();                // 吃食物
                showGrade();                // 显示分数

                outtextxy(530, 450, "作者: livcui");

                Sleep(speed);                // 间隔时间50ms
        }

        char ch = getchar();        // 退出
}
// Main.cpp
#include "Snake.h"
#include <Windows.h>
#include <graphics.h>
#include <conio.h>

int main() {

        Snake snake;
        snake.run();

        return 0;
}

头文件:
// Snake.h
#ifndef SNAKE_H_
#define SNAKE_H_
#include <graphics.h>
#include <conio.h>

class Snake {

private:

        HWND hwnd;
        int speed;
        int level_;

        // 坐标 XY
        struct pointXY {
                int x;
                int y;
        };
        // 蛇属性
        struct snakeProperty {
                int num;                                //蛇的节数
                pointXY snakeXY[100];   //节数最多100节
                char postion;                        //方向
                int flag;                                //蛇是否死亡
        } snake;
        // 枚举方向
        enum movPostion {

                right = 72, left = 75, down = 77, up = 80        //对应上下左右键的键码值
                //right = 'd', left = 'a', down = 's', up = 'w'        //对应dasw键的键码值
        };

        //食物的属性
        struct foodProperty {

                pointXY foodXY;                // 食物坐标
                int eatGrade;                // 吃掉食物所得分数
                int flag;                    // 食物是否存在

        }food;

        void keyDown();                // 按键处理
        void drawSnake();        // 画蛇
        void moveSnake();        // 移动蛇
        void moveSnake_2();        // 移动蛇 - 穿墙
        void drawFood();        // 画食物
        void eatFood();                // 吃食物
        void snakeDie();        // 判断蛇死亡
        void snakeWallDie();// 判断蛇撞墙死亡
        void snakeBodyDie();// 判断蛇自杀而死
        void showGrade();        // 显示分数
        void initFood();        // 初始化食物

public:
        Snake();
        ~Snake();
        void run();

};

#endif

评分

参与人数 3荣誉 +3 鱼币 +1 收起 理由
鱼的七秒记忆 + 1 感谢楼主无私奉献!
xiao-wugui + 1 + 1 鱼C有你更精彩^_^
昨非 + 1 我没白嫖鱼币,真心支持,感谢

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-8-21 16:33:59 | 显示全部楼层
本帖最后由 livcui 于 2020-8-21 16:35 编辑

自占沙发
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-21 16:40:07 | 显示全部楼层
1.png
2.png
3.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-21 16:41:27 | 显示全部楼层

回帖奖励 +3 鱼币

用exe试的呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-21 16:49:58 | 显示全部楼层
不错哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-21 17:02:20 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-8-21 17:39:25 | 显示全部楼层
厉害了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-21 17:48:25 | 显示全部楼层

回帖奖励 +3 鱼币

谢谢大佬!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-8-21 17:58:41 | 显示全部楼层
本帖最后由 livcui 于 2020-8-21 22:30 编辑


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-21 19:59:21 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-21 20:29:37 | 显示全部楼层
牛啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-8-21 20:35:37 | 显示全部楼层

回帖奖励 +3 鱼币

厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-8-21 21:04:56 | 显示全部楼层

回帖奖励 +3 鱼币

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-21 21:14:08 | 显示全部楼层
大佬
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-8-21 21:25:36 | 显示全部楼层
66666
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-21 23:06:36 | 显示全部楼层

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-8-22 18:29:58 | 显示全部楼层
厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-8-22 18:30:30 | 显示全部楼层

回帖奖励 +3 鱼币

玩玩
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-8-22 18:31:02 | 显示全部楼层
6666
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2020-8-22 19:43:35 | 显示全部楼层

回帖奖励 +3 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-13 03:22

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表