C语言版贪吃蛇控制台Linux游戏NCurse

项目的目的

熟练掌握C语言,并非要精通Ncurse

Ncurse的输入输出

#include <curses.h>

int main(){
    initscr();//ncurse界面的初始化
    printw("hello world\n");//这是ncurse模式下的printf
    getch();//等待用户输入,如果没有这句话,程序就退出了,看不到运行的结果,也就是看不到上面那句话
    endwin();//程序退出,调用该函数来回复shell终端的显示,如果没有这句话,shell终端字乱码,坏掉。
    return 0;
}

编译指令

vi cursedemo.c
gcc cursedemo.c -lcurses
./a.out

要改名的话

gcc cursedemo.c -lcurses -o cursedemo
./cursedemo

Ncurse上下左右键获取

#include <curses.h>

int main(){
    int key;//因为用char表示的话是1字节8位最大值是128,小于curses.h中定义的方向值
    initscr();
    keypad(stdscr,1);//想要获取方向键必须写的函数
    while(1){
        key = getch();
        switch(key){
            case KEY_DOWN:
                printw("DOWN\n");
                break;
            case KEY_UP:
                printw("UP\n");
                break;
            case KEY_LEFT:
                printw("LEFT\n");
                break;
            case KEY_RIGHT:
                printw("RIGHT\n");
                break;
        }
    }
    endwin();
    return 0;
}

地图规划

大小20x20或40x40

地图竖直方向上的边界“|”

地图水平方向上的边界“–”

贪吃蛇的身子“[]”

贪吃蛇的食物“##”

地图实现

第1和最后一行画“–”,其它行首列和最后一列画“|”,其余画空格

//初始化ncurse
//画地图
#include <curses.h>

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

void gamePic(){
    int hang;
    int lie;
    
    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{
                    printw("  ");
                }
            }
            printw("\n");
        }
        
        if(hang == 19){
            for(lie=0;lie<20;lie++){
                printw("--");
            }
            printw("\n");
            printw("By Aaron\n");
        }
    }
}

int main()
{
    initNcurse();
    gamePic();
    
    getch();
    endwin();
    return 0;
}

画蛇的身子

用链表作蛇身,当蛇身的坐标与地图上的坐标相等,画蛇身

//定义蛇身
//初始化蛇身
//添加蛇身
//画蛇身
#include <curses.h>
#include <stdlib.h>

typedef struct Snake{
    int row;
    int column;
    struct Snake *next;
}Snake;

Snake *head;
Snake *tail;

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

int hasSnakeNode(int row,int column){
    Snake *p = head;
    while(p != NULL){
        if(p->row == row && p->column == column){
            return 1;
        }
        p = p->next;
    }
    return 0;
}

void gamePic(){
    int row;
    int column;
    
    for(row=0;row<20;row++){
        if(row == 0 || row == 19){
            for(column=0;column<20;column++){
                printw("--");
            }
            printw("\n");
        }
        
        if(row>0 && row<19){
            for(column=0;column<=20;column++){
                if(column==0 || column==20){
                    printw("|");
                }else if(hasSnakeNode(row,column)){
                    printw("[]");
                }else{
                    printw("  ");
                }
            }
            printw("\n");
        }
    }
}

void addNode(){
    Snake *newNode = (Snake *)malloc(sizeof(Snake));
    newNode->row = tail->row;
    newNode->column = tail->column + 1;
    newNode->next = NULL;
    
    tail->next = newNode;
    tail = newNode;
}

void initSnake(){
    head = (Snake *)malloc(sizeof(Snake));
    head->row = 2;
    head->column = 2;
    head->next = NULL;
    
    tail = head;
    addNode();
    addNode();
    addNode();
}

int main()
{
    initNcurse();
    initSnake();
    
    gamePic();
    
    getch();
    endwin();
    return 0;
}

让蛇向右移动

蛇向右移就是在蛇的尾部添加一个节点并删除头部节点

//判断按键如果向右
//蛇向右移动
注意在画图的方法中添加move(0,0);
#include <curses.h>
#include <stdlib.h>

typedef struct Snake{
    int row;
    int column;
    struct Snake *next;
}Snake;

Snake *head;
Snake *tail;

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

int hasSnakeNode(int row,int column){
    Snake *p = head;
    while(p != NULL){
        if(p->row == row && p->column == column){
            return 1;
        }
        p = p->next;
    }
    return 0;
}

void gamePic(){
    int row;
    int column;
    
    move(0,0);
    
    for(row=0;row<20;row++){
        if(row == 0 || row == 19){
            for(column=0;column<20;column++){
                printw("--");
            }
            printw("\n");
        }
        
        if(row>0 && row<19){
            for(column=0;column<=20;column++){
                if(column==0 || column==20){
                    printw("|");
                }else if(hasSnakeNode(row,column)){
                    printw("[]");
                }else{
                    printw("  ");
                }
            }
            printw("\n");
        }
    }
}

void addNode(){
    Snake *newNode = (Snake *)malloc(sizeof(Snake));
    newNode->row = tail->row;
    newNode->column = tail->column + 1;
    newNode->next = NULL;
    
    tail->next = newNode;
    tail = newNode;
}

void initSnake(){
    head = (Snake *)malloc(sizeof(Snake));
    head->row = 2;
    head->column = 2;
    head->next = NULL;
    
    tail = head;
    addNode();
    addNode();
    addNode();
}

void deleteNode(){
    Snake *p;
    p = head;
    head = head->next;
    free(p);
}

void moveSnake(){
    addNode();
    deleteNode();
}

int main()
{
    int control;
    initNcurse();
    initSnake();
    
    gamePic();
    
    while(1){
        control = getch();
        if(control == KEY_RIGHT){
            moveSnake();
            gamePic();
        }
    }
    
    getch();
    endwin();
    return 0;
}

蛇向右移动撞墙

如果蛇的坐标到了墙的地方就初始化蛇

#include <curses.h>
#include <stdlib.h>

typedef struct Snake{
    int row;
    int column;
    struct Snake *next;
}Snake;

Snake *head = NULL;
Snake *tail = NULL;

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

int hasSnakeNode(int row,int column){
    Snake *p = head;
    while(p != NULL){
        if(p->row == row && p->column == column){
            return 1;
        }
        p = p->next;
    }
    return 0;
}

void gamePic(){
    int row;
    int column;
    
    move(0,0);
    
    for(row=0;row<20;row++){
        if(row == 0 || row == 19){
            for(column=0;column<20;column++){
                printw("--");
            }
            printw("\n");
        }
        
        if(row>0 && row<19){
            for(column=0;column<=20;column++){
                if(column==0 || column==20){
                    printw("|");
                }else if(hasSnakeNode(row,column)){
                    printw("[]");
                }else{
                    printw("  ");
                }
            }
            printw("\n");
        }
    }
}

void addNode(){
    Snake *newNode = (Snake *)malloc(sizeof(Snake));
    newNode->row = tail->row;
    newNode->column = tail->column + 1;
    newNode->next = NULL;
    
    tail->next = newNode;
    tail = newNode;
}

void initSnake(){
    Snake *p = NULL;
    while(head != NULL){
        p = head;
        head = head->next;
        free(p);
    }
    
    head = (Snake *)malloc(sizeof(Snake));
    head->row = 2;
    head->column = 2;
    head->next = NULL;
    
    tail = head;
    addNode();
    addNode();
    addNode();
}

void deleteNode(){
    Snake *node = head;
    head = head->next;
    free(node);
}

void moveRight(){
    addNode();
    deleteNode();
    if(tail->row == 0 || tail->row == 20 || tail->column == 0 || tail->column == 20){
        initSnake();
    }
}
int main()
{
    initNcurse();
    initSnake();
    gamePic();
    int control;
    while(1){
        control = getch();
        if(control == KEY_RIGHT){
            moveRight();
            gamePic();
        }
    }
    
    getch();
    endwin();
    return 0;
}

向右自动移动

去掉按键判断,将向右移动放在死循环中每隔一段时间刷新一次

#include <curses.h>
#include <stdlib.h>

typedef struct Snake{
    int row;
    int column;
    struct Snake *next;
}Snake;

Snake *head = NULL;
Snake *tail = NULL;

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

int hasSnakeNode(int row,int column){
    Snake *p = head;
    while(p != NULL){
        if(p->row == row && p->column == column){
            return 1;
        }
        p = p->next;
    }
    return 0;
}

void gamePic(){
    int row;
    int column;
    
    move(0,0);
    
    for(row=0;row<20;row++){
        if(row == 0 || row == 19){
            for(column=0;column<20;column++){
                printw("--");
            }
            printw("\n");
        }
        
        if(row>0 && row<19){
            for(column=0;column<=20;column++){
                if(column==0 || column==20){
                    printw("|");
                }else if(hasSnakeNode(row,column)){
                    printw("[]");
                }else{
                    printw("  ");
                }
            }
            printw("\n");
        }
    }
}

void addNode(){
    Snake *newNode = (Snake *)malloc(sizeof(Snake));
    newNode->row = tail->row;
    newNode->column = tail->column + 1;
    newNode->next = NULL;
    
    tail->next = newNode;
    tail = newNode;
}

void initSnake(){
    Snake *p = NULL;
    while(head != NULL){
        p = head;
        head = head->next;
        free(p);
    }
    
    head = (Snake *)malloc(sizeof(Snake));
    head->row = 2;
    head->column = 2;
    head->next = NULL;
    
    tail = head;
    addNode();
    addNode();
    addNode();
}

void deleteNode(){
    Snake *node = head;
    head = head->next;
    free(node);
}

void moveRight(){
    addNode();
    deleteNode();
    if(tail->row == 0 || tail->row == 20 || tail->column == 0 || tail->column == 20){
        initSnake();
    }
}
int main()
{
    initNcurse();
    initSnake();
    gamePic();
    int control;
    while(1){
        moveRight();
        gamePic();
        refresh();
        usleep(100000);
    }
    
    getch();
    endwin();
    return 0;
}

开启一条新线程运行2个while(1)

#include <stdio.h>
#include <pthread.h>

void* func1(){
    while(1){
        printf("this is func1\n");
        sleep(1);
    }
}

void* func2(){
    while(1){
        printf("this is func2\n");
        sleep(1);
    }
}

int main()
{
    pthread_t th1;
    // start a new thread th1 to run func1
    pthread_create(&th1,NULL,func1,NULL);
    func2();
    return 0;
}

保存代码

gcc threadDemo -lpthread

./a.out

使用线程实现蛇向4个方向移动

初步实现开启2个新线程

一个线程不停移动蛇,一个线程不断接收方向按键变化

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

typedef struct Snake{
    int row;
    int column;
    struct Snake *next;
}Snake;

Snake *head = NULL;
Snake *tail = NULL;

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

int hasSnakeNode(int row,int column){
    Snake *p = head;
    while(p != NULL){
        if(p->row == row && p->column == column){
            return 1;
        }
        p = p->next;
    }
    return 0;
}

void gamePic(){
    int row;
    int column;
    
    move(0,0);
    
    for(row=0;row<20;row++){
        if(row == 0 || row == 19){
            for(column=0;column<20;column++){
                printw("--");
            }
            printw("\n");
        }
        
        if(row>0 && row<19){
            for(column=0;column<=20;column++){
                if(column==0 || column==20){
                    printw("|");
                }else if(hasSnakeNode(row,column)){
                    printw("[]");
                }else{
                    printw("  ");
                }
            }
            printw("\n");
        }
    }
}

void addNode(){
    Snake *newNode = (Snake *)malloc(sizeof(Snake));
    newNode->row = tail->row;
    newNode->column = tail->column + 1;
    newNode->next = NULL;
    
    tail->next = newNode;
    tail = newNode;
}

void initSnake(){
    Snake *p = NULL;
    while(head != NULL){
        p = head;
        head = head->next;
        free(p);
    }
    
    head = (Snake *)malloc(sizeof(Snake));
    head->row = 2;
    head->column = 2;
    head->next = NULL;
    
    tail = head;
    addNode();
    addNode();
    addNode();
}

void deleteNode(){
    Snake *node = head;
    head = head->next;
    free(node);
}

void moveRight(){
    addNode();
    deleteNode();
    if(tail->row == 0 || tail->row == 20 || tail->column == 0 || tail->column == 20){
        initSnake();
    }
}

void refreshPic(){
    while(1){
        moveRight();
        gamePic();
        refresh();
        usleep(100000);
    }
}

void changeDir(){
    int key;
    while(1){
        key = getch();
        switch(key){
            case KEY_DOWN:
                printw("DOWN\n");
                break;
            case KEY_UP:
                printw("UP\n");
                break;
            case KEY_LEFT:
                printw("LEFT\n");
                break;
            case KEY_RIGHT:
                printw("RIGHT\n");
                break;
        }
    }
}

int main()
{
    initNcurse();
    initSnake();
    gamePic();
    
    pthread_t th1;
    pthread_t th2;
    pthread_create(&th1,NULL,refreshPic,NULL);
    pthread_create(&th2,NULL,changeDir,NULL);
    
    while(1);
    getch();
    endwin();
    return 0;
}

gcc moveFourDirection.c -lcurses -lpthread

./a.out

初步实现蛇向4个方向移动

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

# define UP 1
# define DOWN 2
# define LEFT 3
# define RIGHT 4

typedef struct Snake{
    int row;
    int column;
    struct Snake *next;
}Snake;

Snake *head = NULL;
Snake *tail = NULL;

int direction;

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

int hasSnakeNode(int row,int column){
    Snake *p = head;
    while(p != NULL){
        if(p->row == row && p->column == column){
            return 1;
        }
        p = p->next;
    }
    return 0;
}

void gamePic(){
    int row;
    int column;
    
    move(0,0);
    
    for(row=0;row<20;row++){
        if(row == 0 || row == 19){
            for(column=0;column<20;column++){
                printw("--");
            }
            printw("\n");
        }
        
        if(row>0 && row<19){
            for(column=0;column<=20;column++){
                if(column==0 || column==20){
                    printw("|");
                }else if(hasSnakeNode(row,column)){
                    printw("[]");
                }else{
                    printw("  ");
                }
            }
            printw("\n");
        }
    }
}

void addNode(){
    Snake *newNode = (Snake *)malloc(sizeof(Snake));
    newNode->next = NULL;
    
    switch(direction){
        case UP:
            newNode->row = tail->row - 1;
            newNode->column = tail->column;
            break;
        case DOWN:
            newNode->row = tail->row + 1;
            newNode->column = tail->column;
            break;
        case LEFT:
            newNode->row = tail->row;
            newNode->column = tail->column - 1;
            break;
        case RIGHT:
            newNode->row = tail->row;
            newNode->column = tail->column + 1;
            break;
    }
    
    tail->next = newNode;
    tail = newNode;
}

void initSnake(){
    Snake *p = NULL;
    
    direction = RIGHT;
    
    while(head != NULL){
        p = head;
        head = head->next;
        free(p);
    }
    
    head = (Snake *)malloc(sizeof(Snake));
    head->row = 2;
    head->column = 2;
    head->next = NULL;
    
    tail = head;
    addNode();
    addNode();
    addNode();
}

void deleteNode(){
    Snake *node = head;
    head = head->next;
    free(node);
}

void moveRight(){
    addNode();
    deleteNode();
    if(tail->row == 0 || tail->row == 20 || tail->column == 0 || tail->column == 20){
        initSnake();
    }
}

void refreshPic(){
    while(1){
        moveRight();
        gamePic();
        refresh();
        usleep(100000);
    }
}

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

int main()
{
    initNcurse();
    initSnake();
    gamePic();
    
    pthread_t th1;
    pthread_t th2;
    pthread_create(&th1,NULL,refreshPic,NULL);
    pthread_create(&th2,NULL,changeDir,NULL);
    
    while(1);
    getch();
    endwin();
    return 0;
}

用绝对值方式解决不合理走位

蛇能转向的根本是尾部朝不同方向添加新节点,头部删除节点

要让蛇方向改变的同时朝相应的方向自动移动,实时接收方向变化的指令->写在死循环里,自动移动->不断移动->写在死循环里,同时执行->开启2个线程

//实时改变方向
//按不同方向改变添加节点的坐标
//刷新画面让蛇不停移动
//开启2个线程分别执行变方向和刷新画面
#include <curses.h>
#include <stdlib.h>
#include <pthread.h>

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

typedef struct Snake{
    int row;
    int column;
    struct Snake *next;
}Snake;

Snake *head = NULL;
Snake *tail = NULL;

int direction;

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

int hasSnakeNode(int row,int column){
    Snake *p = head;
    while(p != NULL){
        if(p->row == row && p->column == column){
            return 1;
        }
        p = p->next;
    }
    return 0;
}

void gamePic(){
    int row;
    int column;
    
    move(0,0);
    
    for(row=0;row<20;row++){
        if(row == 0 || row == 19){
            for(column=0;column<20;column++){
                printw("--");
            }
            printw("\n");
        }
        
        if(row>0 && row<19){
            for(column=0;column<=20;column++){
                if(column==0 || column==20){
                    printw("|");
                }else if(hasSnakeNode(row,column)){
                    printw("[]");
                }else{
                    printw("  ");
                }
            }
            printw("\n");
        }
    }
}

void addNode(){
    Snake *newNode = (Snake *)malloc(sizeof(Snake));
    newNode->next = NULL;
    
    switch(direction){
        case UP:
            newNode->row = tail->row - 1;
            newNode->column = tail->column;
            break;
        case DOWN:
            newNode->row = tail->row + 1;
            newNode->column = tail->column;
            break;
        case LEFT:
            newNode->row = tail->row;
            newNode->column = tail->column - 1;
            break;
        case RIGHT:
            newNode->row = tail->row;
            newNode->column = tail->column + 1;
            break;
    }
    
    tail->next = newNode;
    tail = newNode;
}

void initSnake(){
    Snake *p = NULL;
    
    direction = RIGHT;
    
    while(head != NULL){
        p = head;
        head = head->next;
        free(p);
    }
    
    head = (Snake *)malloc(sizeof(Snake));
    head->row = 2;
    head->column = 2;
    head->next = NULL;
    
    tail = head;
    addNode();
    addNode();
    addNode();
}

void deleteNode(){
    Snake *node = head;
    head = head->next;
    free(node);
}

void moveRight(){
    addNode();
    deleteNode();
    if(tail->row == 0 || tail->row == 20 || tail->column == 0 || tail->column == 20){
        initSnake();
    }
}

void refreshPic(){
    while(1){
        moveRight();
        gamePic();
        refresh();
        usleep(100000);
    }
}

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

void changeDir(){
    int key;
    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()
{
    initNcurse();
    initSnake();
    gamePic();
    
    pthread_t th1;
    pthread_t th2;
    pthread_create(&th1,NULL,refreshPic,NULL);
    pthread_create(&th2,NULL,changeDir,NULL);
    
    while(1);
    getch();
    endwin();
    return 0;
}

做贪吃蛇的食物

初步实现

//随机定义食物位置
//画食物
//蛇移动吃食物就随机产生下一个
#include <curses.h>
#include <stdlib.h>
#include <pthread.h>

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

typedef struct Snake{
    int row;
    int column;
    struct Snake *next;
}Snake;

Snake *head = NULL;
Snake *tail = NULL;

int direction;

Snake food;
void initFood(){
    static int x = 4;
    static int y = 5;
    food.row = x;
    food.column = y;
    x+=2;
    y+=2;
}

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

int hasSnakeNode(int row,int column){
    Snake *p = head;
    while(p != NULL){
        if(p->row == row && p->column == column){
            return 1;
        }
        p = p->next;
    }
    return 0;
}

int hasFood(int row,int column){
    if(food.row == row && food.column == column){
        return 1;
    }
    return 0;
}

void gamePic(){
    int row;
    int column;
    
    move(0,0);
    
    for(row=0;row<20;row++){
        if(row == 0 || row == 19){
            for(column=0;column<20;column++){
                printw("--");
            }
            printw("\n");
        }
        
        if(row>0 && row<19){
            for(column=0;column<=20;column++){
                if(column==0 || column==20){
                    printw("|");
                }else if(hasSnakeNode(row,column)){
                    printw("[]");
                }else if(hasFood(row,column)){
                    printw("##");
                }else{
                    printw("  ");
                }
            }
            printw("\n");
        }
    }
}

void addNode(){
    Snake *newNode = (Snake *)malloc(sizeof(Snake));
    newNode->next = NULL;
    
    switch(direction){
        case UP:
            newNode->row = tail->row - 1;
            newNode->column = tail->column;
            break;
        case DOWN:
            newNode->row = tail->row + 1;
            newNode->column = tail->column;
            break;
        case LEFT:
            newNode->row = tail->row;
            newNode->column = tail->column - 1;
            break;
        case RIGHT:
            newNode->row = tail->row;
            newNode->column = tail->column + 1;
            break;
    }
    
    tail->next = newNode;
    tail = newNode;
}

void initSnake(){
    Snake *p = NULL;
    
    direction = RIGHT;
    
    while(head != NULL){
        p = head;
        head = head->next;
        free(p);
    }
    
    initFood();
    head = (Snake *)malloc(sizeof(Snake));
    head->row = 2;
    head->column = 2;
    head->next = NULL;
    
    tail = head;
    addNode();
    addNode();
    addNode();
}

void deleteNode(){
    Snake *node = head;
    head = head->next;
    free(node);
}

void moveRight(){
    addNode();
    
    if(hasFood(tail->row,tail->column){
        initFood();
    }else{
        deleteNode(); 
    }
    
    if(tail->row == 0 || tail->row == 20 || tail->column == 0 || tail->column == 20){
        initSnake();
    }
}

void refreshPic(){
    while(1){
        moveRight();
        gamePic();
        refresh();
        usleep(100000);
    }
}

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

void changeDir(){
    int key;
    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()
{
    initNcurse();
    initSnake();
    gamePic();
    
    pthread_t th1;
    pthread_t th2;
    pthread_create(&th1,NULL,refreshPic,NULL);
    pthread_create(&th2,NULL,changeDir,NULL);
    
    while(1);
    getch();
    endwin();
    return 0;
}

吃掉食物让食物随机产生

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

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

typedef struct Snake{
    int row;
    int column;
    struct Snake *next;
}Snake;

Snake *head = NULL;
Snake *tail = NULL;

int direction;

Snake food;
void initFood(){
    int x = rand()%20;
    int y = rand()%20;
    food.row = x;
    food.column = y;
}

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

int hasSnakeNode(int row,int column){
    Snake *p = head;
    while(p != NULL){
        if(p->row == row && p->column == column){
            return 1;
        }
        p = p->next;
    }
    return 0;
}

int hasFood(int row,int column){
    if(food.row == row && food.column == column){
        return 1;
    }
    return 0;
}

void gamePic(){
    int row;
    int column;
    
    move(0,0);
    
    for(row=0;row<20;row++){
        if(row == 0 || row == 19){
            for(column=0;column<20;column++){
                printw("--");
            }
            printw("\n");
        }
        
        if(row>0 && row<19){
            for(column=0;column<=20;column++){
                if(column==0 || column==20){
                    printw("|");
                }else if(hasSnakeNode(row,column)){
                    printw("[]");
                }else if(hasFood(row,column)){
                    printw("##");
                }else{
                    printw("  ");
                }
            }
            printw("\n");
        }
    }
}

void addNode(){
    Snake *newNode = (Snake *)malloc(sizeof(Snake));
    newNode->next = NULL;
    
    switch(direction){
        case UP:
            newNode->row = tail->row - 1;
            newNode->column = tail->column;
            break;
        case DOWN:
            newNode->row = tail->row + 1;
            newNode->column = tail->column;
            break;
        case LEFT:
            newNode->row = tail->row;
            newNode->column = tail->column - 1;
            break;
        case RIGHT:
            newNode->row = tail->row;
            newNode->column = tail->column + 1;
            break;
    }
    
    tail->next = newNode;
    tail = newNode;
}

void initSnake(){
    Snake *p = NULL;
    
    direction = RIGHT;
    
    while(head != NULL){
        p = head;
        head = head->next;
        free(p);
    }
    
    initFood();
    head = (Snake *)malloc(sizeof(Snake));
    head->row = 2;
    head->column = 2;
    head->next = NULL;
    
    tail = head;
    addNode();
    addNode();
    addNode();
}

void deleteNode(){
    Snake *node = head;
    head = head->next;
    free(node);
}

void moveRight(){
    addNode();
    
    if(hasFood(tail->row,tail->column){
        initFood();
    }else{
        deleteNode(); 
    }
    
    if(tail->row == 0 || tail->row == 20 || tail->column == 0 || tail->column == 20){
        initSnake();
    }
}

void refreshPic(){
    while(1){
        moveRight();
        gamePic();
        refresh();
        usleep(100000);
    }
}

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

void changeDir(){
    int key;
    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()
{
    initNcurse();
    initSnake();
    gamePic();
    
    pthread_t th1;
    pthread_t th2;
    pthread_create(&th1,NULL,refreshPic,NULL);
    pthread_create(&th2,NULL,changeDir,NULL);
    
    while(1);
    getch();
    endwin();
    return 0;
}

修复贪吃蛇往上不到墙就死和咬不死自己的问题

//如果蛇撞到墙或咬到自己就初始化蛇身
#include <curses.h>
#include <stdlib.h>
#include <pthread.h>

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

typedef struct Snake{
    int row;
    int column;
    struct Snake *next;
}Snake;

Snake *head = NULL;
Snake *tail = NULL;

int direction;

Snake food;
void initFood(){
    int x = rand()%20;
    int y = rand()%20;
    food.row = x;
    food.column = y;
}

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

int hasSnakeNode(int row,int column){
    Snake *p = head;
    while(p != NULL){
        if(p->row == row && p->column == column){
            return 1;
        }
        p = p->next;
    }
    return 0;
}

int hasFood(int row,int column){
    if(food.row == row && food.column == column){
        return 1;
    }
    return 0;
}

void gamePic(){
    int row;
    int column;
    
    move(0,0);
    
    for(row=0;row<20;row++){
        if(row == 0 || row == 19){
            for(column=0;column<20;column++){
                printw("--");
            }
            printw("\n");
        }
        
        if(row>0 && row<19){
            for(column=0;column<=20;column++){
                if(column==0 || column==20){
                    printw("|");
                }else if(hasSnakeNode(row,column)){
                    printw("[]");
                }else if(hasFood(row,column)){
                    printw("##");
                }else{
                    printw("  ");
                }
            }
            printw("\n");
        }
    }
}

void addNode(){
    Snake *newNode = (Snake *)malloc(sizeof(Snake));
    newNode->next = NULL;
    
    switch(direction){
        case UP:
            newNode->row = tail->row - 1;
            newNode->column = tail->column;
            break;
        case DOWN:
            newNode->row = tail->row + 1;
            newNode->column = tail->column;
            break;
        case LEFT:
            newNode->row = tail->row;
            newNode->column = tail->column - 1;
            break;
        case RIGHT:
            newNode->row = tail->row;
            newNode->column = tail->column + 1;
            break;
    }
    
    tail->next = newNode;
    tail = newNode;
}

void initSnake(){
    Snake *p = NULL;
    
    direction = RIGHT;
    
    while(head != NULL){
        p = head;
        head = head->next;
        free(p);
    }
    
    initFood();
    head = (Snake *)malloc(sizeof(Snake));
    head->row = 2;
    head->column = 2;
    head->next = NULL;
    
    tail = head;
    addNode();
    addNode();
    addNode();
}

void deleteNode(){
    Snake *node = head;
    head = head->next;
    free(node);
}

int ifSnakeDie(){
    Snake *node = head;
    if(tail->row < 0 || tail->row == 20 || tail->column == 0 || tail->column == 20){
        return 1;
    }
    while(node->next != NULL){
        if(node->row == tail->row && node->column == tail->column){
            return 1;
        }
        node = node->next;
    }
}

void moveRight(){
    addNode();
    
    if(hasFood(tail->row,tail->column){
        initFood();
    }else{
        deleteNode(); 
    }
    
    if(ifSnakeDie()){
        initSnake();
    }
}

void refreshPic(){
    while(1){
        moveRight();
        gamePic();
        refresh();
        usleep(100000);
    }
}

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

void changeDir(){
    int key;
    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()
{
    initNcurse();
    initSnake();
    gamePic();
    
    pthread_t th1;
    pthread_t th2;
    pthread_create(&th1,NULL,refreshPic,NULL);
    pthread_create(&th2,NULL,changeDir,NULL);
    
    while(1);
    getch();
    endwin();
    return 0;
}

完整贪吃蛇思路

简洁版:

//初始化nurse
//画地图
//初始化画蛇身
//开启2个线程分别实时变向和根据方向自动移动
//初始化随机位置食物
//蛇吃食物就产生下一个随机食物并且变长
//蛇撞墙或咬到自己就重新开始

详细版:

//初始化ncurse
//画地图
//定义蛇身
//初始化蛇身
//添加蛇身
//画蛇身
//判断按键如果向右
//蛇向右移动
注意在画图的方法中添加move(0,0);
如果蛇的坐标到了墙的地方就初始化蛇
去掉按键判断,将向右移动放在死循环中每隔一段时间刷新一次
//实时改变方向
//按不同方向改变添加节点的坐标
//刷新画面让蛇不停移动
//开启2个线程分别执行变方向和刷新画面
//随机定义食物位置
//画食物
//蛇移动吃食物就随机产生下一个
//如果蛇撞到墙或咬到自己就初始化蛇身
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值