EGE图形库实现贪吃蛇

在学习过程中作为练习做的一个小游戏,还有许多做得不好的地方,欢迎各位帮我指出来,共同进步!

部分思路在代码的注释中有体现。

这是代码部分:

#include <graphics.h>
#include <stdio.h>

#define Interval 20
#define Width 30 
#define Height 30 //可以只定义Width,即一个正方形
#define Wall -1
#define Empty 0
#define Body 1
#define Head 2
#define Food 3

typedef struct Snake
{
    int row;
    int col;
}Snake;


int grid[600/Interval][600/Interval] = {0}; //记录蛇状态的二维数组
int speed = Interval;
int len = 3; //记录蛇的长度,默认是3(包括蛇头)
int dir = 3; //移动方向,默认向左
Snake snake[Width*Height]; //记录蛇的结构体数组
bool food_exsit = false; // 标记食物是否存在
Snake snake_food = {0}; //生成食物的坐标
enum Dir{
    UP,RIGHT,DOWN,LEFT
};
int score = 0;
int vect[4][2] = {{0,-1},{1,0},{0,1},{-1,0}}; //方向向量,分别表示上、右、下、左
bool game_over = false;  //游戏是否结束标志,false表示没有结束
int sleep_time = 0;
PIMAGE img;

void draw_Wall();
void init_game();
void init_snake();
void draw_snake();
void prod_food();
void move(int dir);
void begin_game();
void KeyEnevnt();
void eat_food();
void judge_border();
void inc_len(int dir);
void judge_gameover(int choice);
void draw_end();
void draw_welcome();
int choose();
void continue_game();
void init_grid();

int main()
{
    initgraph(Interval*Width,Interval*Height);
    // initgraph(800,800);
    draw_welcome();
    int ret = choose();
    switch (int a = 0)
    {
        case 0:begin_game();  break; 
        case 1: continue_game(); break;
    }
    begin_game();
    getch();
    return 0;
}
void draw_welcome()
{
    img = newimage(0,0);
    getimage(img,"E:\\photo\\picture-9.jpg");
    putimage(0,0,img);
    char str[2][20] = {{"begin game"},{"continue game"}}; //继续游戏暂时没有实现
    setfillcolor(GREEN);
    setfontbkcolor(WHITE);
    setfont(20,0,"楷体");
    for(int i = 0;i < 2;i++)
    {
        ege_fillrect(Height/2*Interval-80,Width/2*Interval+ 120*i,200,100);
        outtextxy(Height/2*Interval-20,Width/2*Interval+ 120*i+40,str[i]);
    }
}
int choose()
{
    mouse_msg msg;
    int ret = -1;
    bool flag = true;
    draw_welcome();
    for(;is_run() && flag;delay_fps(60))
    {
        if(mousemsg())
        {
            msg = getmouse();
            if(msg.is_left() && msg.is_down())
            {
                for(int i = 0;i < 2;i++)
                {
                    if(msg.x >= Height/2*Interval-80 && msg.x <= Height/2*Interval-80+200 && msg.y >= Width/2*Interval+ 120*i && msg.y <= Width/2*Interval+ 120*i+100)
                    {
                        ret = i;
                        flag = false;
                        break;
                    }
                }
            }
        }
    }  
    return ret;
}
void continue_game()
{
    //用一个.txt文件记录上一次的数组值,再重新为当前数组赋值,有时间再做
    ;
}
void begin_game()
{
    init_game();
    for(;is_run();delay_fps(60))
    {
        cleardevice();
        draw_snake();
        
        if(food_exsit == false) //false表示食物被吃
        {
            inc_len(dir);
            prod_food();
        }
        move(dir);
        judge_gameover(0);
        if(game_over)
            draw_end();
        eat_food();
        KeyEnevnt();     
        Sleep(100);
    }
}
void inc_len(int dir) //蛇的长度增加(在蛇移动的方向)
{                     
    int x = vect[dir][0]; int y = vect[dir][1];
    snake[len].row = snake[len-1].row+y; 
    snake[len].col = snake[len-1].col + x;
    len++;
    grid[snake[len-1].row][snake[len-1].col] = Body;
}
void judge_border()  //判断蛇是否超出边界
{
    bool flag = true;
    if(snake[0].row < 1)
        snake[0].row = Height - 2;//为什么要减2:让蛇头从倒数第二个格子出来
    if(snake[0].row > Height-2)  //这里的row,col表示蛇的数组坐标
        snake[0].row = 1;
    if(snake[0].col < 1)
        snake[0].col = Width-2;
    if(snake[0].col > Width-2)       
        snake[0].col = 1;
    judge_gameover(0);
    grid[snake[0].row][snake[0].col] = Head;
}
void eat_food()
{
    if(snake[0].row == snake_food.row && snake[0].col == snake_food.col)
    {
        score += 10;
        food_exsit = false;
    }
}
void KeyEnevnt()
{
    key_msg msg;
    while(kbhit()) //在一个循环内进行按键的判断,比起用if判断按键的情况要好一些
    {
        msg = getkey();
        int key = msg.key;
        switch (key)
        {
            case 'w': case 'W':
            if(dir != DOWN)
                dir = UP; break;
            case 'd': case 'D': 
            if(dir != LEFT)
                dir = RIGHT; break;
            case 's': case 'S': 
            if(dir != UP)
                dir = DOWN; break;
            case 'a': case 'A': 
            if(dir != RIGHT)
                dir = LEFT; break;
        }
    }
}
void init_game()
{
    //设置墙
    for(int i = 0;i < Width;i++)
    {
        grid[i][0] = Wall;
        grid[0][i] = Wall;
        grid[i][Height-1] = Wall;
        grid[Width-1][i] = Wall;
    }
    game_over = false;
    food_exsit = false;
    ege_enable_aa(true);
    setbkcolor(EGERGB(116,206,222));
    setcolor(GREEN);
    init_snake();
    prod_food();
    len = 3;
    init_grid();
    score = 0;
}
void draw_Wall()
{
    setfillcolor(YELLOW);
    setcolor(BLACK);
    for(int i = 0;i < Width;i++)
    {
        ege_fillrect(0,Interval*i,Interval,Interval*(i+1));
        ege_fillrect(Interval*i,0,Interval*(i+1),Interval);
        ege_fillrect(Interval*i,(Height-1)*Interval,Interval*(i+1),(Height)*Interval);
        ege_fillrect((Width-1)*Interval,Interval*i,Width*Interval,Interval*(i+1));
        line(i*Interval,0,i*Interval,(Width)*Interval);
        line(0,i*Interval,(Width)*Interval,i*Interval);
    }
}
//初始化蛇
void init_snake()
{
    len = 3;
    grid[Height/2][Width/2] = Head; //Height表示行,Width表示列
    grid[Height/2][Width/2+1]= Body;
    grid[Height/2+1][Width/2+1] = Body;  
    snake[0].row =  Height/2; snake[0].col = Width/2;
    snake[1].row = Height/2; snake[1].col = Width/2+1;
    snake[2].row = Height/2+1; snake[2].col = Width/2+1;
}
//以表示格子的数组grid为基准绘图
void draw_snake()
{
    draw_Wall();
    setfillcolor(GREEN);
    for(int row = 0;row < Height;row++)
    {
        for(int col=0;col < Width;col++)
        {
            if(grid[row][col] == Head)
            {
                // ege_rectangle(col*Interval,row*Interval,Interval,Interval);
                ege_fillellipse(col*Interval,row*Interval,Interval,Interval); //注意坐标和row、col的关糄1�7
            }
            if(grid[row][col] == Body)
            {
                setcolor(BLUE);
                ege_rectangle(col*Interval,row*Interval,Interval,Interval);
                circle(col*Interval+10,row*Interval+10,10);
            }
        }
    }
    if(food_exsit)
    {
        setfillcolor(RED);
        ege_fillellipse(snake_food.col*Interval,snake_food.row*Interval,Interval,Interval);
    }
}
//随机生成食物
void prod_food()
{
    randomize();
    int row,col;
    do{
        col = random(Width);
        row = random(Height);
    }while(grid[row][col] != Empty);   //避免食物生成在墙上或者蛇上
    snake_food.row = row;
    snake_food.col = col;
    food_exsit = true;
}
//控制蛇的移动
void move(int dir)
{                          
    int x = vect[dir][0]; 
    int y = vect[dir][1];
    grid[snake[len-1].row][snake[len-1].col] = Empty; //最后一节标记为空
    for(int i = len-1;i > 0;i--)                      //从蛇尾开始,每个表示蛇体的结构体向前移动,蛇头再以表示dir的方向上增加
    {                                                 //宏观上看,蛇头就开始移动
        snake[i] = snake[i-1];
    }
    snake[0].row += y; snake[0].col += x; 
    // grid[snake[0].row][snake[0].col] = Head;
    for(int i = 1;i < len-1;i++)
    {
        grid[snake[i].row][snake[i].col] = Body;
    }
    // grid[snake[0].row][snake[0].col] = Head;
    judge_border();
}
void judge_gameover(int choice) //choice表示选择游戏模式
{
    if(choice == 0) //可以穿墙
    {
        if(grid[snake[0].row][snake[0].col] == Body) //蛇头和蛇身重合
            game_over = true;
    }
    //不可以穿墙的,就是增加一个边界的判断条件
    ;
}
void draw_end() //游戏结束时的界面
{
    cleardevice();
    setbkcolor(EGERGB(116,206,222));
    char str[3][30] = {{"game voer"},{"Press esc to exit"}};
    sprintf(str[2],"score:%d",score);
    setfont(40,0,"楷体");
    for(int i = 0;i < 3;i++)
    {
        outtextxy(Height/2*Interval-70,Width/2*Interval+50*i,str[i]);
    }
    key_msg msg;
    bool flag = true;
    while(flag){
        while(kbmsg){
            msg = getkey();
            if(msg.key == key_esc && msg.msg == key_msg_down)
                flag = false;
        }
    }
    printf("Exit succseefully\n");
    // game_over = false;
    init_game();
    begin_game();
}
void init_grid(){ //初始化记录蛇状态的格子
    for(int i = 0;i < Width;i++){
        for(int j = 0;j < Height;j++){
            grid[i][j] = 0;
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值