C贪吃蛇

C语言贪吃蛇

1、思路

  1. 贪吃蛇需要游戏的方框,那么方框怎么在控制台上画出来呢?
    其实控制台也是有坐标的,将光标移动到特定的位置就可以在特定的位置输出了,利用函数SetConsoleCursorPosition将光标设定到我们想要的地方就可以画出方框了。其实蛇与食物都是这样画出来的。
  2. 怎样移动蛇呢?
    假设用int a[10]表示蛇的位置a[0] 为蛇的尾巴,a[9]为舌头,移动的时候只需要把a[1]—a[9] 复制给a[0]—-a[8],然后a[9]的值在移动方向上左响应的调整,例如蛇向右边移动,则y轴坐标不变,x轴坐标增加一个格子
  3. 和按动方向键转变蛇的移动方向呢?
    其实这和2一样,两者都要一个标志,标志蛇移动的方向。当按动方向键时改变这个标志,然后移动的时候舌头就可以做相应的改变。

2、函数分析

/*光标移到指定位置*/
void gotoXY(HANDLE hOut, int x, int y);
/*设置文本的颜色*/
void setTextColor(int i);
/*游戏环境设置*/
void setFrame();
/*画方框*/
void drawFrame();
/*显示信息*/
void showInformation();
/*打印食物*/
void printFood();
/*判断撞墙*/
int collsionWall();
/*判断穿墙*/
void throughWall();
/*打印蛇*/
void printSnake();
/*光标移到指定位置*/
void initSnake();
/*吃食物*/
void eatFood();
/*移动蛇的坐标*/
void moveSnake();
//蛇头接触蛇身蛇死亡返回 1
int isDied();
/*游戏结束*/
int gameover();

主函数:

int main()
{
    srand(time(NULL));
    do{
        setFrame();
        drawFrame();
        showInformation();
        initSnake();
        printFood();

        while (1){
            g_acc = 0;
            showInformation();
            if (_kbhit()){
                if (keyPush()){
                    break;
                }
            }

            moveSnake();
            eatFood();
            printSnake();
            if (isDied()){
                break;
            }
            if (g_acc == 0){
                Sleep(g_snake.speed);
            }
            else{
                Sleep(100);
            }
        }
    } while (gameover());
    return 0;
}

3、代码

#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
#include <math.h>

#define LEFT 4
#define TOP 3
#define WIDTH 20
#define HEIGTH 20
#define LENGTH ((WIDTH * HEIGTH ))

#define TOUP 72
#define TODOWN 80
#define TOLEFT 75
#define TORIGHT 77
//食物的样子
const char* FOODSTYLE[] = { "※","㊣","つ","ヒ","む","ら","☆","★","□","@","\
&","#","∵","∴","∷","あ","ほ","Ю","\
¥","€","¢","£","①","③","④","Β","ǖ","ㄈ","氼","ひ","щ","╋","╳"};
const int FOODLENGTH = sizeof(FOODSTYLE)/sizeof(char*);
//蛇的样子
const char* SNAKESTYLE[] = { "○", "●", "◎", "⊙" };
const int SNAKEBODYCOUNT = sizeof(SNAKESTYLE) / sizeof(char*);

//蛇的结构
typedef struct {
    int x[LENGTH];//x轴
    int y[LENGTH];//y轴
    int direction;//方向
    int length;//蛇的长度
    int count;//已经吃的食物的个数
    int level;//游戏等级
    int score;//游戏得分
    int speed;//游戏速度
}Snake;

typedef struct {
    int x, y;
}Pos;

HANDLE g_hOut;
Snake g_snake = {
    
    {0},{0},TORIGHT,3,0,1,0,500 };
Pos g_food = {0,0};
Pos g_snake_tail = { 0, 0 };
int g_acc = 0;
/*光标移到指定位置*/
void gotoXY(HANDLE hOut, int x, int y);
/*设置文本的颜色*/
void setTextColor(int i);
/*游戏环境设置*/
void setFrame();
/*画方框*/
void drawFrame();
/*显示信息*/
void showInformation();
/*打印食物*/
void printFood();
/*判断撞墙*/
int collsionWall();
/*判断穿墙*/
void throughWall();
/*打印蛇*/
void printSnake();
/*光标移到指定位置*/
void initSnake();
/*吃食物*/
void eatFood();
/*移动蛇的坐标*/
void moveSnake();
//蛇头接触蛇身蛇死亡返回 1
int isDied();
/*游戏结束*/
int gameover();

void gotoXY(HANDLE hOut, int x, int y)
{
    COORD pos = { x, y };
    SetConsoleCursorPosition(hOut, pos);
}

void setTextColor(int i)
{
    //HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);
    if (i == 0){
        SetConsoleTextAttribute(g_hOut, BACKGROUND_GREEN | FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
    }
    else if (i == 1){
        SetConsoleTextAttribute(g_hOut, BACKGROUND_GREEN | FOREGROUND_INTENSITY | FOREGROUND_RED );
    }
}

void setFrame(){
    system("cls");
    system("color 2E");  
    g_hOut = GetStdHandle(STD_OUTPUT_HANDLE); //定义显示器句柄变量

    COORD frame_size = { LEFT + 2 * WIDTH + WIDTH, TOP + HEIGTH + TOP };
    SetConsoleScreenBufferSize(g_hOut, frame_size);
    CONSOLE_CURSOR_INFO CursorInfo;
    GetConsoleCursorInfo(g_hOut, &CursorInfo);//获取控制台光标信息  
    CursorInfo.bVisible = false; //隐藏控制台光标  
    SetConsoleCursorInfo(g_hOut, &CursorInfo);//设置控制台光标状态 

    SetConsoleTitleA("贪吃蛇");
    gotoXY(g_hOut, (LEFT * 2 + WIDTH * 2)/2 - 4, TOP - 2);
    printf("贪吃蛇游戏");
    //CloseHandle(g_hOut);
}

void drawFrame(){
    //setTextColor();
    //g_hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    gotoXY(g_hOut, LEFT, TOP);
    printf("╔");
    gotoXY(g_hOut, LEFT, TOP + HEIGTH);
    printf("╚");
    gotoXY(g_hOut, LEFT + 2 * WIDTH, TOP);
    printf("╗");
    gotoXY(g_hOut, LEFT + 2 * WIDTH, TOP + HEIGTH);
    printf("╝");
    for (int i = 2; i < 2*WIDTH; i += 2){
        gotoXY(g_hOut, LEFT + i, TOP);
        printf("═");
    }
    for (int i = 2; i < 2 * WIDTH; i += 2){
        gotoXY(g_hOut, LEFT + i, TOP + HEIGTH);
        printf("═");
    }
    for (int i = 1; i < HEIGTH; i += 1){
        gotoXY(g_hOut, LEFT, TOP+i);
        printf("║");
    }
    for (int i = 1; i < HEIGTH; i += 1){
        gotoXY(g_hOut, LEFT + 2 * WIDTH, TOP + i);
        printf("║");
    }
}

void showInformation(){
    int inter = 10;
    gotoXY(g_hOut, LEFT + 2 * WIDTH + inter, TOP + 1);
    printf("游戏得分:%d", g_snake.score);

    gotoXY(g_hOut, LEFT + 2 * WIDTH + inter, TOP + 3);
    printf("游戏等级:%d", g_snake.level);

    gotoXY(g_hOut, LEFT + 2 * WIDTH + inter, TOP + 5);
    printf("食物个数:%d", g_snake.count);

    gotoXY(g_hOut, LEFT + 2 * WIDTH + inter, TOP + 7);
    printf("游戏速度:%d", g_snake.speed);

    gotoXY(g_hOut, LEFT + 2 * WIDTH + inter, TOP + 9);
    printf("Esc 退出游戏");

    gotoXY(g_hOut, LEFT + 2 * WIDTH + inter, TOP + 11);
    printf("长按方向键:加速");

    gotoXY(g_hOut, LEFT + 2 * WIDTH + inter, TOP + 13);
    printf("按s键停止,按任意键开始");
}

void printFood(){
    while (1){
        g_food.x = 2 * (rand() % (WIDTH - 1) + 1) + LEFT;
        g_food.y = (rand() % (HEIGTH - 1) + 1) + TOP;
        int i = 0;
        for (; i < g_snake.length; ++i){
            if (g_food.x == g_snake.x[i] &&
                g_food.y == g_snake.y[i]){
                break;
            }
        }
        if (i == g_snake.length){
            break;
        }
    }
    gotoXY(g_hOut, g_food.x, g_food.y);
    printf(FOODSTYLE[rand() % FOODLENGTH]);
    //printf("☆");
}

int collsionWall(){
    if (g_snake.y[g_snake.length - 1] <= TOP
        || g_snake.y[g_snake.length - 1] >= TOP + HEIGTH
        || g_snake.x[g_snake.length - 1] <= LEFT
        || g_snake.x[g_snake.length - 1] >= LEFT + 2 * WIDTH){
        return 1;
    }
    return 0;
}

void throughWall(){
    if (g_snake.direction == TOUP &&
        g_snake.y[g_snake.length - 1] == TOP){
        g_snake.y[g_snake.length - 1] = TOP + HEIGTH - 1;
    }
    if (g_snake.direction == TODOWN &&
        g_snake.y[g_snake.length - 1] == TOP + HEIGTH){
        g_snake.y[g_snake.length - 1] = TOP + 1;
    }
    if (g_snake.direction == TOLEFT &&
        g_snake.x[g_snake.length - 1] == LEFT){
        g_snake.x[g_snake.length - 1] = LEFT + 2*WIDTH - 2;
    }
    if (g_snake.direction == TORIGHT &&
        g_snake.x[g_snake.length - 1] == LEFT + 2 * WIDTH){
        g_snake.x[g_snake.length - 1] = LEFT + 2;
    }
    /*g_snake_tail.x = g_snake.x[0];
    g_snake_tail.y = g_snake.y[0];*/
}

void eatFood(){
    if ((g_snake.x[g_snake.length - 1] == g_food.x) &&
        (g_snake.y[g_snake.length - 1] == g_food.y)){//吃到食物了
        //蛇的长度增加1,并移动蛇的坐标
        memmove_s((void*)&g_snake.x[1], g_snake.length * sizeof(int), (void*)g_snake.x, g_snake.length*sizeof(int));
        memmove_s((void*)&g_snake.y[1], g_snake.length * sizeof(int), (void*)g_snake.y, g_snake.length*sizeof(int));

        ++g_snake.count;
        ++g_snake.length;
        ++g_snake.score;
        g_snake.score = 1.4*g_snake.score;
        g_snake.level = g_snake.count/5+1;
        if (g_snake.speed > 100){
            g_snake.speed -= 10;
        }
        g_snake.x[0] = g_snake_tail.x;
        g_snake.y[0] = g_snake_tail.y;
        printFood();
    }
}

void initSnake(){
    g_snake.x[0] = g_snake_tail.x = LEFT + 2;
    g_snake.y[0] = g_snake_tail.y = TOP + (HEIGTH >> 1);

    for (int i = 1; i < g_snake.length; ++i){
        g_snake.x[i] = g_snake.x[i - 1] + 2;
        g_snake.y[i] = g_snake.y[i - 1];
    }
}

void printSnake(){
    //setTextColor();
    int i = 0;
    gotoXY(g_hOut, g_snake.x[i], g_snake.y[i]);
    printf(SNAKESTYLE[rand() % SNAKEBODYCOUNT]);
    //putwchar(rand() % SNAKEBODYCOUNT);

    for (++i; i < g_snake.length - 1; ++i){
        gotoXY(g_hOut, g_snake.x[i], g_snake.y[i]);
        //printf("◎");
        printf(SNAKESTYLE[rand() % SNAKEBODYCOUNT]);
    }
    setTextColor(1);
    gotoXY(g_hOut, g_snake.x[i], g_snake.y[i]);
    printf("¤");
    setTextColor(0);
}

void moveSnake(){
    gotoXY(g_hOut, g_snake.x[0], g_snake.y[0]);
    printf("  ");
    g_snake_tail.x = g_snake.x[0];
    g_snake_tail.y = g_snake.y[0];

    memmove_s((void*)g_snake.x, (g_snake.length-1)*sizeof(int), (void*)&g_snake.x[1], (g_snake.length - 1)*sizeof(int));
    memmove_s((void*)g_snake.y, (g_snake.length-1)*sizeof(int), (void*)&g_snake.y[1], (g_snake.length - 1)*sizeof(int));
    switch (g_snake.direction){
    case TOUP:
        g_snake.y[g_snake.length - 1] -= 1;
        break;
    case TODOWN:
        g_snake.y[g_snake.length - 1] += 1;
        break;
    case TOLEFT:
        g_snake.x[g_snake.length - 1] -= 2;
        break;
    case TORIGHT:
        g_snake.x[g_snake.length - 1] += 2;
        break;
    default:
        break;
    }
    //throughWall();
}

int isDied(){
    for (int i = g_snake.length - 2; i >= 0; --i){
        if ((g_snake.x[i] == g_snake.x[g_snake.length - 1])
            && (g_snake.y[i] == g_snake.y[g_snake.length - 1])){
            return 1;
        }
    }
    return collsionWall();  
}

int keyPush(){  
    char ch = _getch();
    if (ch == 0x1B){
        //fflush(stdin);
        return 1;
    }
    if (ch == 's'){
        //system("pause");
        _getch();
    }
    if (ch == -32){
        ch = _getch();
        if ((ch == TOUP || ch == TODOWN || ch == TOLEFT || ch == TORIGHT)){
            if (ch == TOUP && g_snake.direction == TODOWN){
                return 0;
            }
            else if (ch == TODOWN && g_snake.direction == TOUP){
                return 0;
            }
            else if (ch == TOLEFT && g_snake.direction == TORIGHT){
                return 0;
            }
            else if (ch == TORIGHT && g_snake.direction == TOLEFT){
                return 0;
            }
            g_snake.direction = ch;
            Sleep(20);
            g_acc = 1;
        }

    }

    //fflush(stdin);
    return 0;
}

int gameover(){
    char ch = 0;
    system("cls");
    gotoXY(g_hOut, (LEFT * 2 + WIDTH * 2) / 2 - 4, TOP + HEIGTH / 2);
    printf("GAME OVER");
    Sleep(500);
    system("cls");
    gotoXY(g_hOut, (LEFT * 2 + WIDTH * 2) / 2 - 4, TOP + HEIGTH / 2);
    printf("try again?(y/n):");
    scanf_s("%c", &ch);
    fflush(stdin);
    if (ch == 'y' || ch == 'Y'){
        //HANDLE g_hOut;
        g_snake = { { 0 }, { 0 }, TORIGHT, 3, 0, 1, 0, 500 };
        g_food = { 0, 0 };
        g_snake_tail = { 0, 0 };
        g_acc = 0;
        return 1;
    }
    return 0;
    //exit(1);
}
int main()
{
    srand(time(NULL));
    do{
        setFrame();
        drawFrame();
        showInformation();
        initSnake();
        printFood();

        while (1){
            g_acc = 0;
            showInformation();
            if (_kbhit()){
                if (keyPush()){
                    break;
                }
            }

            moveSnake();
            eatFood();
            printSnake();
            if (isDied()){
                break;
            }
            if (g_acc == 0){
                Sleep(g_snake.speed);
            }
            else{
                Sleep(100);
            }
        }
    } while (gameover());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiaolixi199311/article/details/79180362