大一贪吃蛇

效果图
效果图

  • 此代码使用了背景音乐,需提前调试编译器
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#include<conio.h>
#include<Mmsystem.h>

#pragma comment(lib, "winmm.lib")

#define SIDE 24//正方形区域边长
#define LEN 50//通关游戏长度

#define MY_CENTER_BORDER_COLOR 0xf0
#define MY_CENTER_CENTTER_COLOR 0x80
#define MY_SCORE_CENTER 0xa1
#define MY_SCORE_COLOR   0xf9
#define MY_INFORMATION_COLOR    0x8f

#include <windows.h>

#define MY_GAME_BACK_COLOR 0x30
HANDLE handle;
int SPEED = 400;//移动一格的时间 ,毫秒
clock_t time1, time2;
int SCORE = 0;
// #define MY_GAME_BACK_COLOR 0xdf

void printStart(int x, int y);

char printEnd(int x, int y);

void dispDrawscore();

void cube(int x, int y);

void gotoxy(int x, int y);

void cubefood(int x, int y);

void clear(int x, int y);

void boards(int x);

void dispDrawScore(int score);

void headmove(int *x, int *y, char s);

void linemove(int *x, int *y, int z);

void food(int *x, int *y, time_t t);

void startGame();

void initHandle();

void setTitle(char title[40]);

void setPosition(int x, int y);

void setColor(int color);

void setCursorVisible(int flag);

void setWindowSize(int w, int h);

void dispDrawGameBackground();

void dispDrawInformation();

void sPeed();

void dispDrawRect(int x, int y, int width, int height, int borderColor, int centerColor);

void hang(int x, int y, int width);

void lie(int x, int y, int height);

void dispDrawintroduce(int x);


int main() {
    initHandle();
    setWindowSize(100, 30);
    setCursorVisible(0);
    setTitle("贪吃蛇 v2.0 pro plus");
    srand((unsigned) time(NULL));
    time1 = clock();
    int x = 5,y = 5;
    printStart(x, y);
    again:PlaySound(TEXT(".\\海绵宝宝.wav"), NULL, SND_FILENAME | SND_ASYNC);
    dispDrawGameBackground();
    dispDrawRect(12, 2, 26, 26, MY_CENTER_BORDER_COLOR, MY_CENTER_CENTTER_COLOR);
    dispDrawRect(39, 2, 10, 26, MY_CENTER_BORDER_COLOR, MY_CENTER_CENTTER_COLOR);
    dispDrawRect(1, 2, 10, 14, MY_CENTER_BORDER_COLOR, MY_CENTER_CENTTER_COLOR);
    dispDrawRect(1, 17, 10, 11, MY_CENTER_BORDER_COLOR, MY_CENTER_CENTTER_COLOR);
    dispDrawInformation();
    dispDrawintroduce(1);
    dispDrawScore(SCORE);
    sPeed();
    startGame();
    char s = printEnd(x, y);
    if (s == '1') {
        system("cls");
        goto again;
    }
    return 0;
}


void printStart(int x, int y) {

    while (1) {
//1、设置时间间隔
        time2 = clock();
        if (time2 - time1 > 400) {
//2、输出游戏logo

            {
                int color = rand() % 0x10;
                if (color == 0x00) {
                    color = 0x01;
                } else if (color == 0x07) {
                    color = 0x0d;
                } else if (color == 0x08) {
                    color = 0x09;//颜色转换
                }
                //绘制图案
                setColor(color);
                setPosition(x, y);//设置光标位置
                float n, m, a;
                for (m = 1.5f; m > -1.5f; m -= 0.1f) {
                    for (n = -1.5f; n < 1.5f; n += 0.05f) {
                        a = n * n + m * m - 1;
                        putchar(a * a * a - n * n * m * m * m <= 0.0f ? '*' : ' ');
                    }
                    putchar('\n');//打印心形

                }
                setPosition(x + 8, y + 10);
                printf("我爱贪吃蛇!");
                setPosition(x + 8, y + 11);
                printf("我爱贪吃蛇!");
                setPosition(x + 8, y + 12);
                printf("我爱贪吃蛇!");
                setPosition(x + 5, y + 17);
                printf("请摁下回车键开始游戏!");
            }
            time1 = time2;
        }
        if (kbhit()) {
            system("cls");
            //if(kbhit())
            break;//进入游戏
        }

    }
}

//system("pause");
//system("cls");
//char s;
//if((s=getchar())=="1")
char printEnd(int x, int y) {
    char s = 0;
    while (1) {
//1、设置时间间隔
        time2 = clock();
        if (time2 - time1 > 400) {
//2、输出游戏logo
            int color = rand() % 0x10;
            if (color == 0x00) {
                color = 0x01;
            } else if (color == 0x07) {
                color = 0x0d;
            } else if (color == 0x08) {
                color = 0x09;//颜色转换
            }
            //绘制图案
            setColor(color);
            setPosition(x + 2, y);//设置光标
            printf("■■■■■■        ■■■       ■■            ■■  ■■■■■■■");
            setPosition(x + 1, y + 1);
            printf("■■               ■■   ■■     ■■■        ■■■  ■■");
            setPosition(x, y + 2);
            printf("■■               ■■       ■■   ■■■■    ■■■■  ■■");
            setPosition(x, y + 3);
            printf("■■               ■■       ■■   ■■■■■■■■■■  ■■");
            setPosition(x, y + 4);
            printf("■■       ■■■  ■■       ■■   ■■  ■■■■  ■■  ■■■■■■■");
            setPosition(x, y + 5);
            printf("■■         ■■  ■■■■■■■■  ■■    ■■    ■■  ■■");
            setPosition(x + 1, y + 6);
            printf("■■       ■■  ■■       ■■   ■■            ■■  ■■");
            setPosition(x + 2, y + 7);
            printf("■■■■■■   ■■       ■■   ■■            ■■  ■■■■■■■");
            setPosition(x + 1, y + 10);
            printf("■■■■■■     ■■        ■■      ■■■■■■■    ■■■■■■");
            setPosition(x, y + 11);
            printf("■■        ■■   ■■        ■■      ■■              ■■      ■■");
            setPosition(x, y + 12);
            printf("■■        ■■   ■■        ■■      ■■              ■■      ■■");
            setPosition(x, y + 13);
            printf("■■        ■■   ■■        ■■      ■■              ■■    ■■■");
            setPosition(x, y + 14);
            printf("■■        ■■   ■■■    ■■■      ■■■■■■■    ■■■■■■");
            setPosition(x, y + 15);
            printf("■■        ■■     ■■    ■■        ■■              ■■  ■■");
            setPosition(x, y + 16);
            printf("■■        ■■       ■■■■          ■■              ■■    ■■");
            setPosition(x + 1, y + 17);
            printf("■■■■■■           ■■            ■■■■■■■    ■■      ■■");
            setPosition(x + 6, y + 18);
            printf("不服气?按1再来一次!");
            time1 = time2;
        }
        fflush(stdin);
        //s = 0;
        if (kbhit())//kbhit()非阻塞函数
        {
            s = getch();
            if (s == '1')//getch()阻塞函数//夏昕睿这个王八蛋,空格写的双引号" "??!!让我改了1个小时才发现!!!!
            {
                system("cls");
                //if(kbhit())
                break;//进入游戏
            } else
                exit(0);
            // fflush(stdin);
        }
    }
    //s=getch();
    return s;
}

void dispDrawscore() {
    setColor(0X8f);
    setPosition(5, 9);
    printf("%d", SCORE);
}

// int flag = 0;

void gotoxy(int x, int y) {
    COORD coord = {2 * x + 26, y + 3};  //坐标句柄 //GetStdHandle(STD_OUTPUT_HANDLE)实例化句柄
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}//这个句柄可以把数转换为坐标

void setcolor(int fore, int ground) {
    // HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(handle, fore % 16 | ground % 16 * 16);
    //只有这样做才能分开控制前景色和背景色,但这样做之后不完全遵守十进制颜色对照表了,背景色遵循前景色对照方式
} //设置颜色

void cube(int x, int y) {
    gotoxy(x, y);
    printf("■");
}//打出除了食物外其他的

void cubefood(int x, int y) {
    gotoxy(x, y);
    printf("●");
}//打印食物
void clear(int x, int y) {
    gotoxy(x, y);
    printf("  ");
}//清除

void boards(int x) {

    int i;
    cube(-1, -1);
    for (i = 0; i <= x; i++) {
        cube(-1, i);
        cube(i, -1);
        cube(x, i);
        cube(i, x);
    }
}//打印边框
void dispDrawScore(int score) {
    //1.绘制矩形
    //dispDrawRect(1,2,10,14,MY_CENTER_BORDER_COLOR,MY_SCORE_CENTER_COLOR);

    //2.写 "分数"
    setColor(MY_SCORE_COLOR);
    setPosition(5, 2);
    printf("分数");
}

void headmove(int *x, int *y, char s) {
    if (s == 'w')y[0]--;
    if (s == 's')y[0]++;
    if (s == 'a')x[0]--;
    if (s == 'd')x[0]++;
}//蛇头的转向和前进

void linemove(int *x, int *y, int z)//z=len蛇长
{
    int i;
    for (i = z - 1; i > 0; i--)
        x[i] = x[i - 1], y[i] = y[i - 1];//不断把前面的地址向后传递(实际上xy数组并非指针,而是蛇身节点的位置),即向前运动后上一状态情况的蛇的第1234个节点所在的坐标位置变为了当前状态第2345个节点(第五个被clear()清除,第一个节点通过headmove()前进,cube()打印)从而实现了蛇的移动
}//蛇的移动
void food(int *x, int *y, time_t t) {
    // setcolor(6,8);
    srand(t);                // rand()和srand()要一起使用,其中srand()用来初始化随机数种子,rand()用来产生随机数。
    time_t t1 = clock();
    srand(t1);
    int Rand = rand() % 16;
    if (Rand != 8 && Rand != 10)
        setcolor(Rand, 8);
    *x = rand() % SIDE, *y = rand() % SIDE;//%SIDE保证了食物一定生成在方框区域内
    cubefood(*x, *y);
    setcolor(10, 8);
}//食物的颜色设置及打印

void startGame() {
    // initHandle();
    // setCursorVisible(0);
    setcolor(9, 1);                    
    boards(SIDE);
    setcolor(10, 8);
    int x[100] = {}, y[100] = {};
    *x = 11, *y = 11;
    int a = *x, b = *y, e = 1, p = 1, i, len = 4, r = 0, pp = 3;//len蛇长//e=1有食物反之则无//a,b是食物地址//r是输赢的判断
    SCORE = 0;
    for (int i = 0; i < len; i++) {
        cube(*x + i, *y);                        //初始蛇头
    }
    while (a == *x && b == *y)                    //可以保证第一个食物不与蛇头重合
    {                                    //?????????????????
        food(&a, &b, clock());
    }                                    //生成第一个食物
    gotoxy(SIDE, SIDE);                    //光标回到方框角落
    char dua0 = getch(), dua = 0;
    while (!r) {
        dispDrawscore();
        Sleep(SPEED);               //速度
        if (!e) {
            p = 1;
            while (p) {
                food(&a, &b, clock());            //生成一个食物
                for (i = 0; i < len; i++)              //判断食物是否在蛇身体上
                    if (a == x[i] && b == y[i])
                        p = 2;                    //p = 2让其打印一个新的food
                p--;
            }
        }                                    //生成食物
        if (kbhit()) {
            dua0 = getch();        //??????????//检查当前是否有键盘输入,若有则返回一个非0值,否则返回0。
            if (dua0 != 'a' && dua0 != 'w' && dua0 != 's' && dua0 != 'd')  //此循环实现了空格键暂停
            {
                while (1) {
                    dua0 = getch();
                    if (dua0 == 'a' || dua0 == 'w' || dua0 == 's' || dua0 == 'd')
                        break;
                }
            }
            // Sleep(20000);
        }
        if (dua + dua0 != 'a' + 'd' && dua + dua0 != 'w' + 's')//如果扭头方向和当前方向相反,方向不变
            dua = dua0;                   //方向不相反,蛇扭头
        if (e) {//有食物就删蛇尾,没食物(因为迟到了食物)就不删,从而实现了吃食物加蛇长len
            setcolor(10, 8);
            clear(x[len - 1], y[len - 1]);    //删除蛇尾
            linemove(x, y, len);
        } else                //else不加也可以,反正意思就是每次循环都要把e置1,因为食物一直存在(除了被刚吃掉的半个循环内e=0,这会让food()函数重新打印一个新的食物)
            e = 1;          //保证了食物在下一次被吃掉之前只打印一给个
        headmove(x, y, dua);              //扭头&&蛇头的不断前进
        if (x[0] == -1 || y[0] == -1 || x[0] == SIDE || y[0] == SIDE) {
            r = 1;
            // break;//加上后撞墙头消失
        }                                //判断蛇是否碰壁
        for (i = 1; i < len; i++) {
            if (x[0] == x[i] && y[0] == y[i])
                r = 1;
        }                                //判断蛇是否撞上自己
        time_t t1 = clock();
        srand(t1);
        int Rand = rand() % 16;   //使蛇身变幻颜色
        if (Rand != 8)           //使蛇身不与背景颜色重合
            setcolor(Rand, 8);
        // printf("%d",Rand);
        cube(x[0], y[0]);                //打印蛇头
        // gotoxy(SIDE,SIDE);//光标
        if (x[0] == a && y[0] == b) {
            len++;                      //吃上食物蛇长+1
            e = 0;
            linemove(x, y, len);
            SPEED -= 10;
            SCORE += 10;
        }                                
        if (len == LEN)
            r = 2;
        if (pp > 0) {
            clear(11 + pp, 11);
            pp--;
        }
    }
    setcolor(3, 8);//设置游戏结束的文本颜色
    SPEED = 400;
// gotoxy(20,5);
    if (r == 1)printf("\n      GAME OVER!!!\n");
    if (r == 2)printf("\n       YOU WIN!!!\n ");
    setcolor(0, 0);
    system("cls");
// system("pause");
// fflush(stdin);						//清空输入流
// printf("      不服输?\n按“1”再来一局!!!");

}

//1.初始化句柄
void initHandle() {
    handle = GetStdHandle(STD_OUTPUT_HANDLE);
}

//2.设置标题
void setTitle(char title[40]) {
    SetConsoleTitleA(title);
}

//3.设置位置
void setPosition(int x, int y) {
    COORD coord = {x * 2, y};
    SetConsoleCursorPosition(handle, coord);
}

//4.设置颜色
void setColor(int color) {
    SetConsoleTextAttribute(handle, color);
}

//5.设置光标是否可见
void setCursorVisible(int flag) {
    CONSOLE_CURSOR_INFO info;
    info.bVisible = flag;
    info.dwSize = 100;
    SetConsoleCursorInfo(handle, &info);
}

//6.设置窗口大小
void setWindowSize(int w, int h) {
    COORD coord = {w, h};
    SetConsoleScreenBufferSize(handle, coord);
    SMALL_RECT rect = {0, 0, w - 1, h - 1};
    SetConsoleWindowInfo(handle, 1, &rect);
}

//绘制整个窗体背景色  30行 100列
void dispDrawGameBackground() {
    //设置背景色
    setColor(MY_GAME_BACK_COLOR);

    for (int i = 0; i < 30; i++) {
        //输出前调整光标位置
        setPosition(0, i);
        printf("%100s", "");
    }
}

//绘制信息提示区域
void dispDrawInformation() {
    //dispDrawRect(39,2,10,26,MY_CENTER_BORDER_COLOR,0xf9);
    setColor(MY_SCORE_COLOR);
    setPosition(43, 2);
    printf("说明");
    setColor(MY_INFORMATION_COLOR);
    setPosition(42, 4);
    printf("游戏说明");
    setColor(MY_INFORMATION_COLOR);
    setPosition(42, 6);
    printf("【游戏】");
    setColor(MY_INFORMATION_COLOR);
    setPosition(41, 7);
    printf("W w:向上移动");
    setColor(MY_INFORMATION_COLOR);
    setPosition(41, 8);
    printf("S s:向下移动");
    setColor(MY_INFORMATION_COLOR);
    setPosition(41, 9);
    printf("A a:向左移动");
    setColor(MY_INFORMATION_COLOR);
    setPosition(41, 10);
    printf("D d:向右移动");
    setColor(MY_INFORMATION_COLOR);
    setPosition(41, 11);
    printf("Q q:退出游戏");
    setColor(MY_INFORMATION_COLOR);
    setPosition(42, 13);
    printf("【控制】");
    setColor(MY_INFORMATION_COLOR);
    setPosition(41, 14);
    printf("空格:开始游戏");
    setColor(MY_INFORMATION_COLOR);
    setPosition(41, 15);
    printf("↑:增加难度");
    setColor(MY_INFORMATION_COLOR);
    setPosition(41, 17);
    printf("↓:降低难度");
    setColor(MY_INFORMATION_COLOR);
    setPosition(41, 18);
    printf("空格键:暂停");
}


void sPeed() {
    int DEGREE;
    while (1) {
        int s = getch();
        if (s == 72)
            SPEED -= 50;
        else if (s == 80)
            SPEED += 50;
        else if (s == ' ')   //getch无法通过判断'\n'的方式结束输入,
            return;
        switch (SPEED) {
            case 400:
                DEGREE = 1;
                break;
            case 350:
                DEGREE = 2;
                break;
            case 300:
                DEGREE = 3;
                break;
            case 250:
                DEGREE = 4;
                break;
            case 200:
                DEGREE = 5;
                break;
            case 150:
                DEGREE = 6;
                break;
            case 100:
                DEGREE = 7;
                break;
            case 50:
                DEGREE = 8;
                break;
            case 0:
                DEGREE = 9;
                break;
        }
        dispDrawintroduce(DEGREE);
    }
}


void dispDrawRect(int x, int y, int width, int height, int borderColor, int centerColor) {

    setColor(borderColor);
    setPosition(x, y);
    for (int i = 0; i < width; i++) {
        printf("%2s", "");
    }
    setPosition(x, y + height - 1);
    for (int i = 0; i < width; i++) {
        printf("%2s", "");
    }
    for (int i = 0; i < height; i++) {
        setPosition(x, y + i);
        printf("%2s", "");
    }
    for (int i = 0; i < height; i++) {
        setPosition(x + width - 1, y + i);
        printf("%2s", "");
    }
    setColor(centerColor);
    for (int i = 0; i < height - 2; i++) {
        setPosition(x + 1, y + 1 + i);
        for (int j = 0; j < width - 2; j++) {
            printf("%2s", "");
        }
    }

}


void hang(int x, int y, int width) {
    setPosition(x, y);
    for (int i = 0; i < width; i++) {
        printf("%2s", "");
    }
}

void lie(int x, int y, int height) {
    for (int i = 0; i < height; i++) {
        setPosition(x, y + i);
        printf("%2s", "");
    }
}


void dispDrawintroduce(int x) {

    setColor(MY_CENTER_CENTTER_COLOR);
    for (int i = 0; i < 9; i++) {
        setPosition(2, 18 + i);
        for (int j = 0; j < 8; j++) {
            printf("%2s", "");
        }
    }
    setColor(MY_SCORE_COLOR);
    setPosition(5, 17);
    printf("等级");
    setColor(MY_CENTER_BORDER_COLOR);
    if (x == 0) {
        hang(4, 19, 4);
        hang(4, 25, 4);
        lie(4, 19, 7);
        lie(7, 19, 7);
    } else if (x == 1) {
        lie(6, 19, 7);
    } else if (x == 2) {
        hang(4, 19, 4);
        hang(4, 22, 4);
        hang(4, 25, 4);
        lie(4, 22, 3);
        lie(7, 19, 3);
    } else if (x == 3) {
        hang(4, 19, 4);
        hang(4, 22, 4);
        hang(4, 25, 4);
        lie(7, 19, 7);
    } else if (x == 4) {
        hang(4, 22, 5);
        lie(4, 19, 3);
        lie(7, 19, 7);
    } else if (x == 5) {
        hang(4, 19, 4);
        hang(4, 22, 4);
        hang(4, 25, 4);
        lie(4, 19, 3);
        lie(7, 22, 3);
    } else if (x == 6) {
        hang(4, 19, 4);
        hang(4, 22, 4);
        hang(4, 25, 4);
        lie(4, 19, 7);
        lie(7, 22, 3);
    } else if (x == 7) {
        hang(4, 19, 4);
        lie(7, 19, 7);
    } else if (x == 8) {
        hang(4, 19, 4);
        hang(4, 22, 4);
        hang(4, 25, 4);
        lie(4, 19, 7);
        lie(7, 19, 7);
    } else if (x == 9) {
        hang(4, 19, 4);
        hang(4, 22, 4);
        hang(4, 25, 4);
        lie(4, 19, 3);
        lie(7, 19, 7);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值