贪吃蛇和智能AI算法

#include<stdio.h>
#include<graphics.h>   //该头文件是用于引用easyx
#include<conio.h>
#include<time.h>   //该头文件里包含函数引用目的是生成一个随机数种子 进行蛇颜色的一个随机变换
#include<mmsystem.h>   // 该函数是为了将音频mp3格式进行一个库的调用
#pragma comment (lib,"winmm.lib")  //导入了这个库才能支持对Windows的音频编程


// ********************************* //

struct 
{
    POINT xy[100];//定义坐标
    char position;//定义方向
    int num;//定义长度 
}snake;   // 这里初始化蛇

struct 
{
    POINT fdxy;//坐标
    int flag;//标志
    int grade;//分数

}food;  //初始化食物


enum position {up,down,left,right};//枚举类型方向

// ****************************************//

void initsnake() //该函数是用于初始前三节蛇的属性
{
    snake.xy[0].x = 0;
    snake.xy[0].y = 0;
    snake.xy[1].x = 10;
    snake.xy[1].x = 0;
    snake.xy[2].x = 20;
    snake.xy[2].x = 0;
    snake.position = right;
    snake.num = 3;
};

void drawSnake()//该函数用于定义出蛇的样貌
{
    for (int i = 0; i < snake.num; i++)
    {
        setfillcolor(RGB(rand() % 255, rand() % 255, rand() % 255));//使蛇身各节颜色产生随机变化
        fillrectangle(snake.xy[i].x, snake.xy[i].y, snake.xy[i].x + 10, snake.xy[i].y + 10);
    }

}


void moveSnake()//该函数用于操作蛇的移动
{
    for (int i = snake.num-1; i>0 ; i--)
    {
        snake.xy[i].x = snake.xy[i-1].x;
        snake.xy[i].y = snake.xy[i-1].y;
    }   //
    switch (snake.position)
    {
    case up:   snake.xy[0].y -= 10;  break;
    case down:   snake.xy[0].y += 10;  break;
    case left:   snake.xy[0].x -= 10;   break;
    case right:  snake.xy[0].x += 10;   break;
    }
}

void Snakemoveinperson() //蛇的移动模式
{

    
        if (snake.xy[0].x > food.fdxy.x)
        {
            snake.position = left;
        }
        else if (snake.xy[0].x < food.fdxy.x)
        {
            snake.position = right;
        }
        else if (snake.xy[0].y > food.fdxy.y)
        {
            snake.position = up;
        }
        else if (snake.xy[0].y < food.fdxy.y)
        {
            snake.position = down;
        }


}


void keyDown()//使蛇通过键盘按键来操作蛇的方向
{
    char userkey = _getch(); //通过getch  函数对于键盘进行一个数的输入和获取
    switch (userkey) // 这里是用于对蛇方向的一个选择 避免蛇的同一方向进行的一个移动
    {
    

    case 'W':
    case 'w':
    case 72 :
        if (snake.position != down)
            snake.position = up;
        break;
    case 's':
    case 'S':
    case 80:
        if (snake.position != up)
            snake.position = down;
        break;
    case 'a':
    case 'A':
    case 75:
        if (snake.position != right)
            snake.position = left;
        break;
    case 'd':
    case 'D':
    case 77:
        if (snake.position != left)
            snake.position = right;
        break;
    }
}

HWND hwnd = NULL;//这里是定义一个句柄窗口 用于对于弹窗的出现


int  SnakeDie()//通过判断蛇的位置坐标判断蛇是否超过界限死亡
{
    if (snake.xy[0].x > 800 || snake.xy[0].x < 0 || snake.xy[0].y>610 || snake.xy[0].y < 0)
    {
        MessageBox(hwnd , "撞墙了,游戏结束","gameover",MB_OK);//ok 按钮是用来终止消息的
        return 1; // 如果蛇 死了 就返回值为1 
    }
    return 0; //如果蛇没有触碰的话 就返回一个值 为0 ,进行一个失败的返回 从而不得判定蛇的死亡

}

void initFood()//初始化食物 由于食物的出现会是在一个整数 并且是10的一个 相应的倍数 所以 利于rand 函数进行食物的随机出现
{
    food.fdxy.x = rand() % 80 * 10;
    food.fdxy.y = rand() % 60 * 10;//使食物随机产生在地图上
    food.flag = 1; // 1代表存在 
    

    //避免食物重合在蛇的身体上了 
    for (int i = 0; i < snake.num; i++)
    {
        if (food.fdxy.x == snake.xy[i].x && food.fdxy.y == snake.xy[i].y)
//这里是蛇的坐标和食物的坐标 进行一个判断
        {
            food.fdxy.x = rand() % 80 *10 ;
            food.fdxy.y = rand() % 60 *10 ;
        }

    }
}


void drawFood()//画食物
{
    setlinecolor(BLACK); //这里是食物的边框颜色
    setfillcolor(RGB(240, 255, 255)); // 这里是食物的一个填充色
    fillrectangle(food.fdxy.x, food.fdxy.y, food.fdxy.x + 10, food.fdxy.y + 10);// 这里是初始化食物

}

//这里是吃食物的操纵
void eatFood()
{
    if (snake.xy[0].x == food.fdxy.x && snake.xy[0].y == food.fdxy.y)
    {
        snake.num++;
        food.flag = 0; //吃完食物后 利用flag 的值判定进行一个食物的重新生成
        food.grade += 10;//吃一个食物增加 10分  
    }

}


void showGrade()
{
 // 格式化打印  

    char grade[20]; //这里是屏幕上显示出来的分数
    sprintf_s(grade, "分数是 :%d", food.grade);//格式化打印输出函数的调用
    
    settextcolor(BLACK); // 这里是sprintf函数的格式化打印颜色
    settextstyle(20, 0,"楷体");   //0为自适应
    outtextxy(600, 50, grade); //在指定位置显示一个字符串
    

}


int highscore;
void File_in()
{
    FILE* fp;
    fp = fopen("save.txt", "w+");       //以读写的方式建立一个名为save.txt的文件
    fprintf(fp, "%d", food.grade);           //把分数写进文件中
    fclose(fp);                         //关闭文件
}

/**
 * 在文件中读取最高分
 **/
void File_out()
{
    FILE* fp;
    fp = fopen("save.txt", "a+");       //打开文件save.txt
    fscanf_s(fp, "%d", &food.grade);    //把文件中的最高分读出来
    highscore = food.grade;
    fclose(fp);                         //关闭文件
}


void gotoxy(int x, int y) //这使画出蛇的图形
{
    COORD c;//这里是定义在屏幕上打印的位置
    c.X = x;
    c.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c); //改变颜色
}

int color(int c)  //这里是蛇的颜色
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);        //更改文字颜色
    return 0;
}


int main()
{

        gotoxy(35, 1);
        color(15);
        printf("/^\\/^\\");      //蛇眼睛

        gotoxy(34, 2);
        printf("|__|  O|");      //蛇眼睛

        gotoxy(33, 2);
        color(15);
        printf("_");

        gotoxy(25, 3);
        color(15);
        printf("\\/");          //蛇信

        gotoxy(31, 3);
        color(15);
        printf("/");

        gotoxy(37, 3);
        color(15);
        printf(" \\_/");         //蛇眼睛

        gotoxy(41, 3);
        color(15);
        printf(" \\");

        gotoxy(26, 4);
        color(15);
        printf("\\____");       //舌头

        gotoxy(32, 4);
        printf("_________/");

        gotoxy(31, 4);
        color(15);
        printf("|");

        gotoxy(43, 4);
        color(15);
        printf("\\");

        gotoxy(32, 5);
        color(15);
        printf("\\_______");    //蛇嘴

        gotoxy(44, 5);
        color(15);
        printf("\\");

        gotoxy(39, 6);
        printf("|     |                  \\");  //下面都是画蛇身

        gotoxy(38, 7);
        printf("/      /                   \\");

        gotoxy(37, 8);
        printf("/      /                    \\ \\");

        gotoxy(35, 9);
        printf("/      /                       \\ \\");

        gotoxy(34, 10);
        printf("/     /                          \\  \\");

        gotoxy(33, 11);
        printf("/     /             _----_         \\   \\");

        gotoxy(32, 12);
        printf("/     /           _-~      ~-_         |  |");

        gotoxy(31, 13);
        printf("(      (        _-~    _--_    ~-_     _/  |");

        gotoxy(32, 14);
        printf("\\     ~-____-~    _-~    ~-_    ~-_-~    /");

        gotoxy(33, 15);
        printf("~-_           _-~          ~-_       _-~");

        gotoxy(35, 16);
        printf("~--______-~                ~-___-~");
    


    char oo=_getch();

    system("cls");
    printf("\n \n \n \n \t **************************************************");

    printf("\n\n\n\t 本游戏背景音乐———古典吉他版本D大调卡农 ");

    printf("\n\n\n\t输入p进入玩家WASD方向键模式  输入o进入自动寻路(AI)模式");
    printf("");
    printf("\n\t***************************************************");

    char m = _getch();

    switch (m)
    {

    case 'o':
    {


        srand((unsigned int)time(NULL));  //定义随机种子函数 使得rand 函数成立
        initgraph(800, 600); // 初始化窗口的大小 
        setbkcolor(RGB(255, 255, 255));  //设置背景颜色
        cleardevice(); //清除屏幕 使得屏幕变色!

        mciSendString("open 5.21.mp3", 0, 0, 0);  //打开背景音乐
        mciSendString("play 5.21.mp3", 0, 0, 0); //关闭背景音乐


        initsnake(); //初始化蛇
        drawSnake(); //画蛇
        while (1) //无限循环
        {
            cleardevice();//这里是清除屏幕操纵
            drawSnake(); //画蛇
            Snakemoveinperson();//蛇的移动
            moveSnake();//蛇的移动

            if (food.flag == 0)// 判别食物的出现
            {
                initFood();  // 初始化食物
            }

            drawFood();
            eatFood();
            showGrade();

            Sleep(70); //这里调用函数来使得蛇的移动快慢

        }


        char op = _getch();//防止退出 使一直维持在这个页面!
        closegraph();
        return 0;

    }

    // 这个为无敌自动寻路状态!


    case 'p':
    {

        srand((unsigned int)time(NULL));
        initgraph(800, 600);
        setbkcolor(RGB(255, 255, 255));  //设置背景颜色
        cleardevice(); //清除屏幕 使得屏幕变色!

        mciSendString("open 5.21.mp3", 0, 0, 0);
        mciSendString("play 5.21.mp3", 0, 0, 0);


        initsnake();
        drawSnake();
        File_out();
        food.grade = 0;
        while (1)
        {
            cleardevice();//这里是清除屏幕操纵

            moveSnake();
            drawSnake();
            
            if (food.flag == 0)
            {
                initFood();
            }
            
            if (_kbhit())
            {
                keyDown();
            }

            if (SnakeDie())
            {
                break;
            }
            drawFood();
            eatFood();
            showGrade();
            Sleep(70);

        }

    
        if (highscore < food.grade)
        {
            File_in();
        }
        char op = _getch();//防止退出 使一直维持在这个页面!
        closegraph();
        return 0;

    }

    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值