C语言300行代码实现贪吃蛇

完整代码:

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include <time.h>

#define ARRAY_SIZE 20                        // 区域大小
int AreaArray[ARRAY_SIZE][ARRAY_SIZE];        // 数组

#define        WALL            0                // 墙壁
#define        VALID            1                // 可走区域
#define        SELF            2                // 蛇身
#define        NEWP            3                // 果实
#define        HEAD            4                // 蛇头

const char *Shape[] = {
    "■",        // 墙壁图案
    "  ",        // 可走区域图案ww
    "◎",        // 蛇身图案
    "⊙"    ,        // 果实图案
    "●"            // 蛇头图案
};
// 记录分数
int score = 0;
int high_score = 0;
// 蛇的所有坐标
int xy[(ARRAY_SIZE - 2)*(ARRAY_SIZE - 2) + 1][2] = {0};
// 方向状态
enum {
    LEFT,
    TOP,
    RIGHT,
    BOTTOM
} Direction;

// 保存最高记录
void GameSaveHighScore()
{
    FILE *fp = fopen("high_score.txt", "w");
    if (fp == NULL)
    {
        printf("open file error.\n");
        return;
    }
    fprintf(fp, "%d", high_score);
    fclose(fp);
}

// 载入最高记录
void GameLoadHighScore()
{
    FILE *fp = fopen("high_score.txt", "r");
    if (fp == NULL)
    {
        printf("open file error.\n");
        return;
    }
    fscanf(fp, "%d", &high_score);
    fclose(fp);
}

// 生成特定区域内随机数
int GetRand(int start, int end)
{
    static unsigned long count;
    srand((unsigned int)time(0)+ count--);
    return rand() % (end - start + 1) + start;
}

// 刷新果实坐标
void GameUpdateNewp()
{
    static int x, y;
    int i, j, z;
    // 计算蛇长度
    for (i = 0; xy[i][0] || xy[i][1]; i++);
    // 添加上新吃的果实
    i++;
    // 生成随机数
    i = GetRand(0, (ARRAY_SIZE - 2)*(ARRAY_SIZE - 2) - i - 1);
    // 计算新果实坐标
    for (j = 1;i && j < ARRAY_SIZE - 1; j++)
    {
        for (z = 1;i && z < ARRAY_SIZE - 1; z++)
        {
            if (AreaArray[j][z] == VALID)
                i--;
            if (!i) break;
        }
        if (!i) break;
    }
    // 加入新果实
    AreaArray[j][z] = NEWP;
    // 去掉之前的果实
    if (x || y)
        AreaArray[y][x] = VALID;
    //
    x = z;
    y = j;
}

// 根据用户操作更新游戏, 返回新状态
int GameUpdate()
{
    int x = 0, y = 0, i;
    // 根据方向检测碰撞
    switch (Direction)
    {
        case LEFT:
            x--;
            break;
        case TOP:
            y--;
            break;
        case RIGHT:
            x++;
            break;
        case BOTTOM:
            y++;
            break;
    }
    // 计算蛇长度
    for (i = 0; xy[i][0] || xy[i][1]; i++);
    // 判断下一个位置是否与蛇头碰撞
    switch (AreaArray[xy[0][1] + y][xy[0][0] + x])
    {
        case SELF:
        case WALL:
            return 0;        // 撞自己或者撞墙了
        case NEWP:
            score++;
            i++;            // 吃到果实, 长度加1
            xy[i][0] = 0;    // 加结束标志
            xy[i][1] = 0;    // 加结束标志
            GameUpdateNewp();// 刷新果实坐标
        case VALID:
            i--;
            // 移动蛇
            while (i>0)
            {
                xy[i][0] = xy[i-1][0];
                xy[i][1] = xy[i-1][1];
                i--;
            }
            // 蛇头坐标
            xy[0][0] += x;
            xy[0][1] += y;
            break;
    }
    return 1;
}

// 刷新显示
void GameFresh()
{
    int i, j;
    // 去掉显示数组上蛇身旧状态的痕迹
    for (i = 1; i < ARRAY_SIZE - 1; i++)
        for (j = 1; j < ARRAY_SIZE - 1; j++)
            if(AreaArray[i][j]== SELF || AreaArray[i][j] == HEAD)
                AreaArray[i][j] = VALID;
    // 把蛇的坐标更新到显示数组
        // 蛇头
    AreaArray[xy[0][1]][xy[0][0]] = HEAD;
        // 蛇身
    for (i = 1; xy[i][0] || xy[i][1]; i++)
        AreaArray[xy[i][1]][xy[i][0]] = SELF;
    // 清屏
    system("cls");
    // 显示
    for (i = 0; i < ARRAY_SIZE; i++)
    {
        for (j = 0; j < ARRAY_SIZE; j++)
                printf("%s", Shape[AreaArray[i][j]]);
        printf("\n");
    }
    printf("current score: %d\n", score);
    printf("high score: %d\n", high_score);
}

// 游戏初始化
void GameInit()
{
    int i, j;
    // 初始化显示数组整个区域
    for (i = 0; i < ARRAY_SIZE; i++)
        for (j = 0; j < ARRAY_SIZE; j++)
            if (i && j && (i != ARRAY_SIZE - 1) && (j != ARRAY_SIZE - 1))
                AreaArray[i][j] = VALID;    // 可行走区域
            else
                AreaArray[i][j] = WALL;        // 墙壁
                                            // 随机生成蛇头坐标
    xy[0][0] = GetRand(2, ARRAY_SIZE - 3);
    xy[0][1] = GetRand(2, ARRAY_SIZE - 3);
    // 根据蛇头坐标生成蛇身坐标
    if (GetRand(0, 1))
    {
        if (xy[0][0] > ARRAY_SIZE / 2)
        {
            i = xy[0][0] + 1;
            Direction = LEFT;
        }
        else
        {
            i = xy[0][0] - 1;
            Direction = RIGHT;
        }
        j = xy[0][1];
    }
    else
    {
        i = xy[0][0];
        if (xy[0][1] > ARRAY_SIZE / 2)
        {
            j = xy[0][1] + 1;
            Direction = TOP;
        }
        else
        {
            j = xy[0][1] - 1;
            Direction = BOTTOM;
        }
    }
    xy[1][0] = i;
    xy[1][1] = j;
    // 蛇身结束标志
    xy[2][0] = 0;
    xy[2][1] = 0;
    // 更新
    GameUpdate();
    GameUpdateNewp();
    GameFresh();
}

void GameStart()
{
    int state = 1;
    int time = 100;
    system("cls");
    printf("================= Game rule ==============\n");
    printf("\tContinue key : \tany\n");
    printf("\tQuit key : \tQ\n");
    printf("\tUp key : \tW\n");
    printf("\tDown key : \tS\n");
    printf("\tLeft key : \tA\n");
    printf("\tRight key : \tD\n");
    printf("==========================================\n");
    score = 0;
    GameLoadHighScore();
    getch();
    GameInit();
    while (state)
    {
        // 检测有输入
        if(kbhit())
            switch (getch())
            {
                case 'q':
                case 'Q':
                    state = 0;        // 结束游戏
                    break;
                case 'w':
                case 'W':
                    if(Direction != BOTTOM)
                        Direction = TOP;
                    break;
                case 's':
                case 'S':
                    if (Direction != TOP)
                        Direction = BOTTOM;
                    break;
                case 'a':
                case 'A':
                    if (Direction != RIGHT)
                        Direction = LEFT;
                    break;
                case 'd':
                case 'D':
                    if (Direction != LEFT)
                        Direction = RIGHT;
                    break;
                default:;
            }
        state = GameUpdate();        // 更新
        GameFresh();                // 刷新显示
        Sleep(time);
    }
    printf("######### Game over #########\n");
    // 最高记录
    if (score > high_score) high_score = score;
    GameSaveHighScore();
    getch();
}

int main()
{
    while(1) GameStart();
    return 0;
}

 

运行截图:

  • 13
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值