当前位置:天才代写 > tutorial > C语言/C++ 教程 > C语言实现贪吃蛇

C语言实现贪吃蛇

2017-11-01 08:00 星期三 所属: C语言/C++ 教程 浏览:672

/*****************************************************************************************************************************
贪吃蛇实现道理:                                                                                                                                                                                *
贪吃蛇游戏在理论上是可以无限的举办下去的(除了撞墙和咬到本身),那么游戏主体就必然是个轮回。                        *
蛇是如何动起来的?在这里就是通过不绝改变蛇的坐标,然后按照蛇的坐标不绝刷新屏幕在视觉上形成蛇的移动结果。*
食物呈此刻随机位置(虽然不能呈此刻障碍物和蛇身上)。                                                                                                        *
蛇能吃到食物其实就是蛇头的坐标与食物的坐标重适时。                                                                                                            *
当蛇咬到本身可能撞到墙的时候游戏竣事(坐标判定)                                                                                                                *
******************************************************************************************************************************/


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


//72,80,75,77是偏向键对应的键值
#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
#define SNAKE 1     //蛇的坐标标识
#define FOOD 2      //食物的坐标标识
#define BAR 3       //墙的坐标标识


//初始化舆图 17*17
char map[17][17] = {0};
//初始化蛇头坐标
unsigned char snake[50] = {77};
//初始化食物坐标
unsigned char food = 68;
//蛇长
char len = 1;


//存储坐标数字与x、y的转换函数
void tran(unsigned char num,unsigned char * x,unsigned char * y);
//打印游戏
void print_game(void);
//获取偏向函数(留意当蛇身长度高出一节时不能转头)
int get_dir(int old_dir);
//移动蛇身函数(游戏大部门内容在个中)
void move_snake(int dir);
//出产食物的函数
unsigned char generate_food(void);
//判定蛇死活的函数(判定了蛇是否撞到界线可能自食)
int isalive(void);


int main(void){
    int dir = UP;   //初始偏向默认向上,UP是我们界说的宏
    //按原理该游戏是可以无限继承下去的,因此是个轮回
    while(1){
        print_game();   //打印游戏
        dir = get_dir(dir);     //获取偏向(我们摁下的偏向)
        move_snake(dir);    //移动蛇身
        if(!isalive()){     //判定蛇的生命状态
            break;
        }
    }


    printf("Game Over!\n");
    return 0;
}
//
void tran(unsigned char num,unsigned char * x,unsigned char * y){
    *x = num >> 4;
    *y = (unsigned char)(num << 4) >> 4;    //留意这里要做个强制范例转换
                                            //按照汇编,假如不做强制转换,y的值与num的值沟通
}


void print_game(void){
    int i,j;
    //按照舆图上每点的环境绘制游戏( i 暗示 x 轴,j 暗示 y 轴),按行打印,j暗示行,i暗示列
    for(j = 0;j < 17;j ++){
        for(i = 0;i < 17;i ++){
            //空缺处所
            if(map[i][j] == 0){
                putchar(' ');
            }
            //蛇身
            else if(map[i][j] == SNAKE){
                putchar('*');
            }
            //围栏
            else if(map[i][j] == BAR){
                putchar('#');
            }
            //食物
            else if(map[i][j] == FOOD){
                putchar('$');
            }
        }
        putchar('\n');
    }
    Sleep(500);     //休眠函数 将历程挂起500ms,包括在window.h(在linux下用 sleep(),#include <unistd.h>)
    system("cls");  //清屏函数 共同下一次 print_game() 起到刷新浸染,包括在stdlib.h中
}
int get_dir(int old_dir){


    int new_dir = old_dir;


    //用kbhit()与getch()组合实现键盘响应
    //kbhit() 查抄当前是否有键盘输入,若有则返回一个非0值,不然返回0
    //getch() 用ch=_getch();会期待你按下任意键之后,把该键字符所对应的ASCII码赋给ch,再执行下面的语句。
    if(_kbhit()){
        _getch();               //第一次输出的偏向键的扩展值,第二次是偏向键的实际值,只有偏向键上下阁下这样
        new_dir = _getch();     //getch()函数要利用两次,原因是因为第一次返回的值指示该键扩展的字符,第二次挪用才返回实际的键代码


        //假如蛇身长度大于1,则不能转头,假如摁转头偏向,则按本来偏向走
        //abs(new_dir - old_dir) == 2 暗示 |LEFT-RIGHT|
        //abs(new_dir - old_dir) == 8 暗示 |UP-DOWN|
        if(len > 1 && (abs(new_dir - old_dir) == 2 || abs(new_dir - old_dir) == 8)){
            new_dir = old_dir;
        }
    }
    return new_dir;
}
void move_snake(int dir){
    int last = snake[0],current;    //last与current用于之后蛇坐标的更新
    int i,j;
    int grow=0;     //判定是否要长身体
    unsigned char x, y,fx,fy;       //蛇坐标与食物坐标
    tran(food, &fx, &fy);   //食物坐标
    tran(snake[0], &x, &y); //蛇头坐标
    switch (dir){           //更新蛇头坐标(坐标原点是左上角)
        case UP:
            y--;
            break;
        case DOWN:
            y++;
            break;
        case LEFT:
            x--;
            break;
        case RIGHT:
            x++;
            break;
    }
    //按位抑或(妙!)
   //http://www.bianceng.cn
    snake[0] = ((x ^ 0) << 4) ^ y;      //将x,y换回一个数
//x与0抑或保存原值
       //将x与y从头合成一个值


    //蛇吃到了食物
    if (snake[0] == food) {
        grow = 1;
        food = generate_food();     //发生新食物
    }


/*******************************************************************************************************************************/
    for (i = 0; i<len; i++) {       //蛇移动的要害,通过将蛇头本来的坐标赋给第二节,本来的第二节赋给第三节,依次下去,完成蛇坐标的更新
        if (i == 0)                //假如只有头,跳过,因为前面已更新蛇头坐标
            continue;
        current = snake[i];       //将当前操纵的蛇节坐标存储到current里
        snake[i] = last;         //完成当前操纵蛇节坐标的更新
        last = current;         //last记录的是上一次操纵蛇节的坐标,这次操纵已经竣事,故把current赋给last
}
/*******************************************************************************************************************************/
   
//假如蛇边长了
    if (grow) {
        snake[len] = last;
        len++;
    }


    for (j = 0; j < 17; j ++){      //将界线与食物加到舆图里去(i,j 对应 x轴和y轴)
        for (i = 0; i < 17; i ++){
            if (i == 0 || i == 16 || j == 0 || j == 16){
                map[i][j] = BAR;
            }
            else if (i == fx&&j == fy){
                map[i][j] = FOOD;
            }
            else{
                map[i][j] = 0;
            }
        }


    for (i = 0; i < len; i++) {     //将蛇加到舆图里去
        tran(snake[i], &x, &y);
        if (snake[i] > 0){
            map[x][y] = SNAKE;
        }
    }
}
}
unsigned char generate_food(void)
{
    unsigned char food_,fx,fy;
    int in_snake=0,i;
    //以当前时间为参数提供种子供rand()函数生成更为随机的数
    srand((unsigned int)time(NULL));
    //轮回发生在界线内且不在蛇身上的食物
    do {
        food_ = rand() % 255;//发生一个0--255的随机数
        tran(food_, &fx, &fy);
        for (i = 0; i < len; i++){
            if (food_ == snake[i]){
            //在不在蛇身上
                in_snake = 1;
            }
        }
    } while (fx == 0 || fx == 16 || fy == 0 || fy == 16 || in_snake);
    return food_;
}
int isalive(void)
{
    int self_eat = 0;
int i;
    unsigned char x, y;
    tran(snake[0], &x, &y);
    for (i = 1; i < len; i++){
        if (snake[0] == snake[i]){
            self_eat = 1;
        }
    }
    //蛇头撞界线可能吃到本身 ,则死掉
    return (x == 0 || x == 16 || y == 0 || y >= 16 || self_eat) ? 0 : 1;
}

 

    关键字:

天才代写-代写联系方式