简易游戏----贪吃蛇

设计思路:

  1. 界面设置:采用system()函数来调整界面的大小,背景颜色
  2. 绘制地图:采用库函数获取坐标(下面具体介绍)
  3. 蛇的设计:采用链式结构实现蛇
  4. 食物设计:rand()随机产生食物坐标
  5. 蛇的移动:蛇移动实现采用链表相关操作,下面具体介绍
  6. 方向控制:采用GetAsyncKeyState()函数,通过键盘操作蛇移动的方向
  7. 蛇移动速度:采用Sleep()函数控制蛇移动速度

具体功能:

  1. 增加自身速度:分数每增加5分,进行加速
  2. 人为加速:按shift键进行加速
  3. 人为减速:按Ctrl键进行减速
  4. 暂停:游戏中按空格键可暂停,在按一次可继续游戏
  5. 退出:游戏过程中按Esc键可退出游戏

几个函数:

1.system
(这里只说明游戏中所用到的命令,详细请点击链接http://blog.csdn.net/s200820212/article/details/32695369

功 能: 发出一个DOS命令
用 法: int system(char *command);
system函数已经被收录在标准c库中,可以直接调用
程序例:

 #include <stdlib.h>   
 #include <stdio.h>   
 int main(void)   
 {
  printf("About to spawn command.com and run a DOS command\n");   system("dir");   
  return 0;   
  }

system(“pause”)
用冻结屏幕,便于观察程序的执行结果;
system(“CLS”)
实现清屏操作。
system调用color函数可以改变控制台的前景色和背景,具体参数在下面说明。
例,用 system(“color 0A”); 其中color后面的0是背景色代号,A是前景色代号。各颜色代码如下:

0=黑色      
1=蓝色      
2=绿色      
3=湖蓝色   
4=红色   
5=紫色
6=黄色
7=白色
8=灰色
9=淡蓝色
A=淡绿色
B=淡浅绿色
C=淡红色
D=淡紫色
E=淡黄色
F=亮白色

2.SetConsoleCursorPosition

这里写图片描述

解释:设置控制台光标坐标,参数就是设备句柄,坐标,那么把标准输出的句柄传给函数,就可以把光标定位在对应的位置了(左上角位置是0,0然后向左 向下延伸)

CROOD:

typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD, *PCOORD;

很明显这个结构可以用来记录坐标
HANDLE:

一个句柄,用来接收GetHandle()返回的句柄

3.GetStdHandle

函数声明如下 :

  HANDLE GetStdHandle(
  DWORD nStdHandle
  );

  GetStdHandle()返回标准的输入、输出或错误的设备的句柄,也就是获得输入、输出/错误的屏幕缓冲区的句柄。
  其参数nStdHandle的值为下面几种类型的一种:

   值  含义
  STD_INPUT_HANDLE 标准输入的句柄
  STD_OUTPUT_HANDLE 标准输出的句柄
  STD_ERROR_HANDLE 标准错误的句柄

4.GetAsyncKeyState()
具体点击下面链接
http://blog.csdn.net/fengfengfengmy/article/details/5570330

游戏代码:

Snake.h

#ifndef __SNAKE_H__
#define __SNAKE_H__

#define FOOD "■"
#define INIT_X  24//蛇的初始位置
#define INIT_Y   4

#define STARTSPEED  500//开始速度
#define SPEDGRADE   5//加速分数  
#define  STARTLENTH  5//开始蛇的长度


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




//蛇走的方向
enum DIRECTION
{
    UP = 1,//上
    DOWN,//下
    LEFT,//左
    RIGHT,//右

};


//蛇的状态

enum Status
{
    OK,//活的
    KILL_BY_WALL,//撞墙
    KILL_BY_SELF,//自己咬死
};

//蛇身节点
typedef struct Node
{
    int x;
    int y;
    struct Node* next;
}SnakeNode;



//蛇本身
typedef struct snake
{
    SnakeNode* _pSnake;//蛇头指针
    SnakeNode* _food;//蛇的食物
    enum DIRECTION _Dir;//行走方向
    enum Status _Status;//当前状态
    int _SleepTime;//每走一步停留的时间
    int _Length;//蛇的长度
}Snake;





void StartMenu();//开始界面
void DrawMap();//地图
void SetPos(int x, int y);//设置光标
void InitSnake(Snake* ps);//初始化蛇结构体
void InitFood(Snake*  ps);//初始化食物
int IsFood(SnakeNode* ps, SnakeNode* NewSnake);//判断是否有食物
void SnakeMove(Snake* ps);//蛇的移动
void EatFood(Snake* ps, SnakeNode* NewSnake);//吃食物
void NoFood(Snake* ps, SnakeNode* NewSnake);//没食物
void SnakeRun(Snake* ps);//方向选择
int KillBySelf(Snake* ps);//判断是否撞到自己身上
int KillByWALL(Snake* ps);//判断是否撞墙

#endif   //__SNAKE_H__

Snake.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"snake.h"


//设置光标位置
void SetPos(int x, int y)
{
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);


    COORD pos = { 0 };
    pos.X = x;
    pos.Y = y;

    SetConsoleCursorPosition(handle, pos);
}



//开始界面
void StartMenu()
{

    system("COLOR f3");//设置背景颜色
    system("mode con cols=120 lines=35");//设置显示框大小

    SetPos(33, 10);
    printf("******************************");
    SetPos(33, 12);
    printf("*   欢迎来到贪吃蛇游戏!     *");
    SetPos(33, 14);
    printf("******************************");

    SetPos(33, 18);
    system("pause");
    system("cls");


    SetPos(33, 10);
    printf("************************************");
    SetPos(33, 12);
    printf("*  选项:1->开始游戏    0->退出    *");
    SetPos(33, 14);
    printf("*  操作:↑ ↓ ← →控制方向       *");
    SetPos(33, 16);
    printf("*   按空格暂停/继续,ESC退出       *");
    SetPos(33, 18);
    printf("*   按shift加速,Ctrl减速          *");
    SetPos(33, 20);
    printf("************************************");

    SetPos(33, 22);
    system("pause");
    system("cls");



}



//地图
void DrawMap()
{
    int i;
    //上面边框
    for (i = 0; i < 70; i += 2)
    {
        SetPos(i, 0);
        printf(FOOD);
    }


    //下面边框
    for (i = 0; i < 70; i += 2)
    {
        SetPos(i, 30);
        printf(FOOD);
    }

    //左边边框
    for (i = 0; i < 30; i++)
    {
        SetPos(0, i);
        printf(FOOD);
    }

    //右边边框
    for (i = 0; i <= 30; i++)
    {
        SetPos(70, i);
        printf(FOOD);
    }
    printf("\n");

    SetPos(76, 5);
    printf("   计分:");
    SetPos(85, 5);
    printf("%d ", 0);//每次吃完食物更新分数
}



//初始化蛇结构体
void InitSnake(Snake* ps)
{
    SnakeNode* cur = NULL;
    int i = 0;

    cur = (SnakeNode*)malloc(sizeof(SnakeNode));
    memset(cur, 0, sizeof(SnakeNode));

    cur->x = INIT_X;
    cur->y = INIT_Y;

    for (i = 1; i <= 4; i++)
    {
        ps->_pSnake = malloc(sizeof(SnakeNode));
        ps->_pSnake->next = cur;
        ps->_pSnake->x = INIT_X + i * 2;
        ps->_pSnake->y = INIT_Y;
        cur = ps->_pSnake;
    }

    while (cur != NULL)
    {
        SetPos(cur->x, cur->y);
        printf(FOOD);
        cur = cur->next;
    }


    ps->_Status = OK;
    ps->_SleepTime = STARTSPEED;
    ps->_Dir = RIGHT;
    ps->_Length = STARTLENTH;
}

//初始化食物
void InitFood(Snake*  ps)
{
    SnakeNode* food = NULL;
    food = (SnakeNode*)malloc(sizeof(SnakeNode));

flag:
    memset(food, 0, sizeof(SnakeNode));
    do
    {
        food->x = rand() % 70 + 2;
    } while (food->x % 2 != 0);

    food->y = rand() % 29 + 1;

    SnakeNode* cur = ps->_pSnake;

    while (cur != NULL)
    {
        if (cur->x == food->x&&cur->y == food->y)
        {
            goto flag;
        }

        cur = cur->next;
    }

    ps->_food = food;
    SetPos(food->x, food->y);
    printf(FOOD);

}




//蛇的移动
int IsFood(SnakeNode* food, SnakeNode* NewSnake)
{
    if (food->x == NewSnake->x && food->y == NewSnake->y)
        return 1;

    return 0;
}

//吃食物
void EatFood(Snake* ps, SnakeNode* NewSnake)
{


    int sum = SPEDGRADE;//加速分数,每增加5加速
    //头插
    SnakeNode* cur = ps->_pSnake;
    NewSnake->next = cur;
    cur = NewSnake;

    ps->_pSnake = NewSnake;

    while (cur != NULL)
    {
        SetPos(cur->x, cur->y);

        printf(FOOD);
        cur = cur->next;
    }


    ++ps->_Length;

        int grade = ps->_Length-STARTLENTH;//分数
        SetPos(85, 5);
        printf("%d ", grade);//每次吃完食物更新分数


    if (grade == sum)
    {
        //分数每增加5分,加速
        ps->_SleepTime -= 100;
        sum += SPEDGRADE;

    }

    InitFood(ps);
}

//没食物
void NoFood(Snake* ps, SnakeNode* NewSnake)
{


    //先头插,后尾删
    SnakeNode* cur = ps->_pSnake;
    NewSnake->next = cur;
    ps->_pSnake = NewSnake;

    cur = NewSnake;

    while (cur->next->next != NULL)
    {
        SetPos(cur->x, cur->y);

        printf(FOOD);
        cur = cur->next;
    }

    SetPos(cur->next->x, cur->next->y);
    printf("  ");
    free(cur->next);
    cur->next = NULL;



}


//蛇移动
void SnakeMove(Snake* ps)
{
    Sleep(ps->_SleepTime);

    SnakeNode* NewSnake = (SnakeNode*)malloc(sizeof(SnakeNode));
    memset(NewSnake, 0, sizeof(SnakeNode));

    NewSnake->x = ps->_pSnake->x;
    NewSnake->y = ps->_pSnake->y;


    switch (ps->_Dir)
    {
    case UP:
        NewSnake->y--;
        break;
    case DOWN:
        NewSnake->y++;
        break;
    case LEFT:
        NewSnake->x -= 2;
        break;
    case RIGHT:
        NewSnake->x += 2;
        break;
    default:
        break;
    }
    int ret = IsFood(ps->_food, NewSnake);

    if (ret == 1)
    {
        //有食物
        EatFood(ps, NewSnake);
    }
    else
    {
        NoFood(ps, NewSnake);
    }


}


//控制方向
void SnakeRun(Snake* ps)
{

    do
    {
        if (GetAsyncKeyState(VK_LEFT) && ps->_Dir != LEFT)
        {
            ps->_Dir = LEFT;
        }
        else if (GetAsyncKeyState(VK_RIGHT) && ps->_Dir != RIGHT)
        {
            ps->_Dir = RIGHT;
        }
        else if (GetAsyncKeyState(VK_UP) && ps->_Dir != UP)
        {
            ps->_Dir = UP;
        }
        else if (GetAsyncKeyState(VK_DOWN) && ps->_Dir != DOWN)
        {
            ps->_Dir = DOWN;
        }
        else if (GetAsyncKeyState(VK_ESCAPE))//esc键正常退出
        {
            exit(0);
        }
        else if (GetAsyncKeyState(VK_SPACE))//空格暂停或继续
        {
            while (1)
            {
                Sleep(300);
                if (GetAsyncKeyState(VK_SPACE)) //按空格键继续
                {
                    break;
                }

            }
        }
        else if (GetAsyncKeyState(VK_CONTROL))//Ctrl键减速
        {
            ps->_SleepTime += 100;
        }
        else if (GetAsyncKeyState(VK_SHIFT))//shift键加速
        {
            ps->_SleepTime -= 100;
        }

        SnakeMove(ps);

        if (KillBySelf(ps) == 1)
        {
            ps->_Status = KILL_BY_SELF;
        }

        if (KillByWALL(ps) == 2)
        {
            ps->_Status = KILL_BY_WALL;
        }
    } while (ps->_Status == OK);




}

//判断是否撞到自己身上
int KillBySelf(Snake* ps)
{
    SnakeNode* cur = ps->_pSnake->next;

    while (cur != NULL)
    {
        if (ps->_pSnake->x == cur->x&&ps->_pSnake->y == cur->y)
        {
            return 1;
        }
        cur = cur->next;
    }
    return 0;
}

//判断是否撞墙
int KillByWALL(Snake* ps)
{
    SnakeNode* cur = ps->_pSnake;

    if (cur->x == 0 || cur->x == 70 || cur->y == 0 || cur->y == 30)
        return 2;

    return 0;
}

test.c

#include<stdio.h>

#include"snake.h"


void play()
{
    Snake snake = { 0 };
    DrawMap();//地图
    InitSnake(&snake);//初始化蛇
    InitFood(&snake);//初始化食物
    while (snake._Status == OK)
    {

        SnakeMove(&snake);
        SnakeRun(&snake);
    }
    int grade = snake._Length - STARTLENTH;//获取游戏结束后的分数

    if (snake._Status == KILL_BY_SELF)
    {

            SetPos(34, 10);
            printf("Game Over\n");
            SetPos(34, 12);
            printf("本次得分为:%d\n",grade);
            SetPos(34, 14);
            system("pause");
    }

    if (snake._Status == KILL_BY_WALL)
    {

        SetPos(34, 10);
        printf("Game Over\n");

        SetPos(34, 12);
        printf("本次得分为:%d\n", grade);

        SetPos(34, 14);
        system("pause");
    }
}

void game()
{


    while (1)
    {
        StartMenu();
        int input = 0;
        SetPos(77, 5);
        printf("请选择:");
        scanf("%d", &input);
        system("cls");
        if (1 == input)
        {
            play();
        }
        else if (0 == input)
        {
            exit(0);
        }

    }
}


int main()
{
    game();
    return 0;
}

效果展示:

开始界面:

这里写图片描述

撞墙而死,游戏结束:

这里写图片描述

撞到自己,游戏结束:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/zhangye3017/article/details/79036249