贪吃蛇小游戏-笔记篇2

1、更改不合理走位

      在上一篇的末尾,完成了贪吃蛇小游戏中四方走位,但是,同样当小蛇在向上或者向右走的时候,此时在摁与之想反的反方向,就会立刻响应键盘的操作,这是不对的(当然也可以把这个当作特色,并不进行更改),在小蛇活动的时候,摁上与之相反的按键,要让小蛇不响应这个按键,那么此时引用abs()函数。

abs()‌是一个求绝对值的函数。‌在不同的编程语言中,abs()函数用于计算一个数的绝对值,即去掉该数的符号,无论是正数还是负数,都会返回其正值。

更改完成之后的小蛇走位的代码:

#include <stdlib.h>
#include <ncurses.h>
#include <pthread.h>

#define UP    1//定义成绝对值的形式,上下一对,左右一对
#define DOWN  -1
#define LEFT  2
#define RIGHT -2

struct Snake{
    int hang;
    int lie;
    struct Snake *next;
};

struct Snake *head = NULL;
struct Snake *tail = NULL;
int key;
int dir;

void initNcurse(){
    initscr();
    keypad(stdscr,1);
    noecho();//不要把无关的功能键的信息显示在界面上,避免地图出现乱码情况
}

int hasSnakeNode(int i,int j){ 
     struct Snake *p; 
     p = head;

    while(p != NULL){
        if(p->hang == i && p->lie == j){ 
            return 1;
        }   
        p = p->next;
         
    }   
    return 0;
}


void gamePic(){
 int hang;
    int lie;

    move(0,0);
    for(hang=0;hang<20;hang++){
        if(hang == 0){
            for(lie=0;lie<20;lie++){
                printw("--");
        }
            printw("\n");
    }

        if(hang >=0 && hang<=19)
        {
            for(lie=0;lie<=20;lie++){
                if(lie == 0 || lie == 20){
                    printw("|");
                }else if(hasSnakeNode(hang,lie)){
                    printw("[]");
                }
                else{
                    printw("  ");
                }
            }

            printw("\n");
        }
        if (hang == 19){
            for(lie=0;lie<20;lie++){
                printw("--");
            }
            printw("\n");
            printw("By ljs,key = %d\n",key);
        }
    }
}
void addNode(){
    struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));

    new->next = NULL;


    switch(dir){
        case UP:
            new->hang = tail->hang-1;
            new->lie = tail->lie;
            break;
        case DOWN:
            new->hang = tail->hang+1;
            new->lie = tail->lie;
            break;
        case LEFT:
            new->hang = tail->hang;
            new->lie = tail->lie-1;
            break;
        case RIGHT:
            new->hang = tail->hang;
            new->lie = tail->lie+1;
            break;
    }

    tail->next = new;
    tail = new;
}

void initSnake(){

    struct Snake *p;

    dir = RIGHT;

    while(head != NULL){
        p =head;
        head = head->next;
        free(p);
    }
head = (struct Snake *)malloc(sizeof(struct Snake));
    head->hang = 2;
    head->lie = 1;
    head->next = NULL;

    tail = head;

    addNode();
    addNode();
}
void deleNode(){
    struct Snake *p;
    p=head;
    head = head->next;

    free(p);
}
void moveSnake(){

    addNode();
    deleNode();

    if(tail->hang == 0||tail->lie == 0||tail->hang == 20 || tail->lie == 20){
        initSnake();

    }
}

void* refreshJieMian(){
    while(1){
        moveSnake();
        gamePic();
        refresh();
        usleep(100000);
    }
}

void turn(int direction){//来判断行走方向与键盘输入方法是否相反
    if(abs(dir) != abs(direction)){//让用户输入的方向键与现在正在走的方向的绝对值不相等,不相等时才能转向
        dir = direction;
}
}

void* changeDir(){
    while(1){
        key = getch();
        switch(key){
            case KEY_DOWN:
                turn(DOWN);//调用转弯函数
                break;
            case KEY_UP:
                turn(UP);
                break;
            case KEY_LEFT:
                turn(LEFT);
                break;
            case KEY_RIGHT:
                turn(RIGHT);
                break;
        }
    }
}

int main()
{
    pthread_t t1;
    pthread_t t2;

    initNcurse();
    initSnake();

    gamePic();

    pthread_create(&t1,NULL,refreshJieMian,NULL);
    pthread_create(&t2,NULL,changeDir,NULL);
    while(1);
    getch();
    endwin();

    return 0;


2、贪吃蛇的食物

关心的是,

1、食物的位置与符号

2、位置同样可以使用贪吃蛇的节点结构体

3、符号用“##”表示

#include <stdlib.h>
#include <ncurses.h>
#include <pthread.h>

#define UP    1
#define DOWN  -1
#define LEFT  2
#define RIGHT -2

struct Snake{
    int hang;
    int lie;
    struct Snake *next;
};

struct Snake *head = NULL;
struct Snake *tail = NULL;
int key;
int dir;

struct Snake food;

void initFood(){//初始化食物
    static int x = 4;
    static int y = 5;//定义静态变量,不改变

    food.hang = x;
    food.lie = y;

    x+=2;
    y+=2;

    noecho();
}

void initNcurse(){
    initscr();
    keypad(stdscr,1);
    noecho();
}

int hasSnakeNode(int i,int j){ 
struct Snake *p;
     p = head;

    while(p != NULL){
        if(p->hang == i && p->lie == j){
            return 1;
        }
        p = p->next;

    }
    return 0;
}


int hasFood(int i,int j){//当蛇的尾巴结点等于食物结点的行列值时。返回1,否则返回0
        if(food.hang == i && food.lie == j){
            return 1;
        }

    return 0;
}




void gamePic(){
    int hang;
    int lie;

    move(0,0);
    for(hang=0;hang<20;hang++){
        if(hang == 0){
            for(lie=0;lie<20;lie++){
                printw("--");
        }
            printw("\n");
    }

        if(hang >=0 && hang<=19)
        {
            for(lie=0;lie<=20;lie++){
                if(lie == 0 || lie == 20){
                    printw("|");
                }else if(hasSnakeNode(hang,lie)){
                    printw("[]");

                }else if(hasFood(hang,lie)){
                    printw("##");
                }
                else{
                    printw("  ");
                }
            }

            printw("\n");
        }
        if (hang == 19){
            for(lie=0;lie<20;lie++){
                printw("--");
            }
            printw("\n");
            printw("By ljs,key = %d\n",key);
        }
    }
}

void addNode(){
    struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));

    new->next = NULL;


    switch(dir){
        case UP:
            new->hang = tail->hang-1;
            new->lie = tail->lie;
            break;
        case DOWN:
            new->hang = tail->hang+1;
            new->lie = tail->lie;
            break;
        case LEFT:
            new->hang = tail->hang;
            new->lie = tail->lie-1;
            break;
        case RIGHT:
            new->hang = tail->hang;
            new->lie = tail->lie+1;
            break;
    }

    tail->next = new;
    tail = new;
}

void initSnake(){

    struct Snake *p;

    dir = RIGHT;

    while(head != NULL){
        p =head;
        head = head->next;
        free(p);
    }
    initFood();
    head = (struct Snake *)malloc(sizeof(struct Snake));//开辟空间
    head->hang = 2;
    head->lie = 1;
    head->next = NULL;

    tail = head;

    addNode();
    addNode();
}
void deleNode(){
struct Snake *p;
    p=head;
    head = head->next;

    free(p);
}
void moveSnake(){

    addNode();
    if(hasFood(tail->hang,tail->lie)){//返回值是1时,重新初始化食物,否则删除节点
        initFood();
    }else{
        deleNode();
    }

    if(tail->hang == 0||tail->lie == 0||tail->hang == 20 || tail->lie == 20){
        initSnake();

    }
}

void* refreshJieMian(){
    while(1){
        moveSnake();
        gamePic();
        refresh();
        usleep(100000);
    }
}

void turn(int direction){
    if(abs(dir) != abs(direction)){
        dir = direction;
    }
}

void* changeDir(){
    while(1){
        key = getch();
        switch(key){
            case KEY_DOWN:
                turn(DOWN);
                break;
            case KEY_UP:
                turn(UP);
                break;
            case KEY_LEFT:
                turn(LEFT);
                break;
            case KEY_RIGHT:
                turn(RIGHT);
                break;
        }
    }
}

int main()
{
    pthread_t t1;
    pthread_t t2;

    initNcurse();
    initSnake();

    gamePic();

    pthread_create(&t1,NULL,refreshJieMian,NULL);
    pthread_create(&t2,NULL,changeDir,NULL);

    while(1);
    getch();
    endwin();

    return 0;
}

3、贪吃蛇的食物2

贪吃蛇的食物随机在框里出现

若食物的坐标时(x,y)

则要求0<=x<=19

0<=y<=19

引用rand()函数,生成随机数的函数

思路,对rand()%20取余运算

代码修改如下:

void initFood(){
    int x = rand()%20;//对随机数除以20取余,这个取余的范围就时0-19
    int y = rand()%20;

    food.hang = x;
    food.lie = y;

    noecho();
}

4、优化代码并且贪吃蛇碰到自己死亡

问题一,蛇没到最顶端就死掉了

原因是tail.hang=0

修改代码如下:

void moveSnake(){
    
    addNode();
    if(hasFood(tail->hang,tail->lie)){
        initFood();
    }else{
        deleNode();
    }   

    if(tail->hang < 0||tail->lie == 0||tail->hang == 20 || tail->lie == 20){
        initSnake();
    
    }   
}

问题二,蛇撞不死自己

代码实现如下:

#include <stdlib.h>
#include <ncurses.h>
#include <pthread.h>

#define UP    1
#define DOWN  -1
#define LEFT  2
#define RIGHT -2

struct Snake{
    int hang;
    int lie;
    struct Snake *next;
};

struct Snake *head = NULL;
struct Snake *tail = NULL;
int key;
int dir;

struct Snake food;

void initFood(){
    int x = rand()%20;
    int y = rand()%20;

    food.hang = x;
    food.lie = y;

    noecho();
}

void initNcurse(){
    initscr();
    keypad(stdscr,1);
    noecho();
}

int hasSnakeNode(int i,int j){
     struct Snake *p;
     p = head;
     while(p != NULL){
        if(p->hang == i && p->lie == j){
            return 1;
        }
        p = p->next;

    }
    return 0;
}


int hasFood(int i,int j){
        if(food.hang == i && food.lie == j){
            return 1;
        }

    return 0;
}




void gamePic(){
    int hang;
    int lie;

    move(0,0);
    for(hang=0;hang<20;hang++){
        if(hang == 0){
            for(lie=0;lie<20;lie++){
                printw("--");
        }
            printw("\n");
    }

        if(hang >=0 && hang<=19)
        {
            for(lie=0;lie<=20;lie++){
                if(lie == 0 || lie == 20){
                    printw("|");
                }else if(hasSnakeNode(hang,lie)){
                    printw("[]");

                }else if(hasFood(hang,lie)){
                    printw("##");
                }
                else{
                    printw("  ");
                }
            }

            printw("\n");
        }
        if (hang == 19){
            for(lie=0;lie<20;lie++){
                printw("--");
            }
            printw("\n");
            printw("By ljs,key = %d,food.hang = %d,food.lie = %d\n",key,food.hang,food.lie);
        }
    }
}

void addNode(){
    struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));

    new->next = NULL;


    switch(dir){
        case UP:
            new->hang = tail->hang-1;
            new->lie = tail->lie;
            break;
        case DOWN:
            new->hang = tail->hang+1;
            new->lie = tail->lie;
            break;
        case LEFT:
            new->hang = tail->hang;
            new->lie = tail->lie-1;
            break;
        case RIGHT:
            new->hang = tail->hang;
            new->lie = tail->lie+1;
            break;
    }

    tail->next = new;
    tail = new;
}

void initSnake(){

    struct Snake *p;

    dir = RIGHT;

    while(head != NULL){
        p =head;
        head = head->next;
        free(p);
    }
    initFood();
    head = (struct Snake *)malloc(sizeof(struct Snake));
    head->hang = 2;
    head->lie = 1;
    head->next = NULL;

    tail = head;

    addNode();
    addNode();
}
void deleNode(){
    struct Snake *p;
    p=head;
    head = head->next;
    free(p);
}

int ifSnakeDie(){

    struct Snake *p;
    p = head;

    if(tail->hang < 0||tail->lie == 0||tail->hang == 20 || tail->lie == 20){//蛇碰到边界返回1,然后重新初始化,就是死亡了
        return 1;
    }

    while(p->next != NULL){//当p的下一个不为空时,执行while循环
        if(p->hang == tail->hang && p->lie == tail ->lie){//判断头结点的行列与尾巴结点的行列是否相等,如果相等证明贪吃蛇的头尾巴和身子相撞了,返回1,蛇死亡
            return 1;
        }
        p = p->next;
    }
    return 0;


}

void moveSnake(){

    addNode();
    if(hasFood(tail->hang,tail->lie)){
        initFood();
    }else{
        deleNode();
    }

    if(ifSnakeDie()){//判断函数的返回值是不是1,是否执行初始化蛇函数,也就是蛇是否死亡函数
        initSnake();

    }
}

void* refreshJieMian(){
    while(1){
        moveSnake();
        gamePic();
        refresh();
        usleep(100000);
    }
}

void turn(int direction){
    if(abs(dir) != abs(direction)){
        dir = direction;
    }
}

void* changeDir(){
    while(1){
        key = getch();
        switch(key){
            case KEY_DOWN:
                turn(DOWN);
                break;
            case KEY_UP:
                turn(UP);
                break;
            case KEY_LEFT:
                turn(LEFT);
                break;
            case KEY_RIGHT:
                turn(RIGHT);
                break;
        }
    }
}

int main()
{
    pthread_t t1;
    pthread_t t2;

    initNcurse();
    initSnake();
    gamePic();

    pthread_create(&t1,NULL,refreshJieMian,NULL);
    pthread_create(&t2,NULL,changeDir,NULL);

    while(1);
    getch();
    endwin();

    return 0;
}

执行代码:

页面

退回

 页面

按ctrl+C

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值