純粋な命令行で蛇を食いしん坊にする


詳細
開発環境はlinux+gcc+netbeans
もともとgvimが好きでしたが、c言語をデバッグすることはできませんでした.そこでnetbeansに転戦して、簡単にデバッグすることができて、さわやかです.
 
まず考えを述べなければならない.マルチスレッドであり、1つのスレッドが論理と図面を担当し、1つのスレッドがボタンを傍受する.スレッドが作成したコードを見てみましょう.
 
void * waitForKey(void *para) {
    while (1) {
        input = getch();
    }
}

pthread_t id; //    linux  ,      

 int ret;
    ret = pthread_create(&id, NULL, waitForKey, NULL);//    
    if (ret != 0) {
        exit(1);
    }
 
私はcursesというライブラリも使いました.これはuiを描くために使われているようです.でも/usr/includeには入っていないので、ネット上で降ります
sudo apt-get install libncurses-dev
使用時のフォーマットはこうであるべきです
 
initscr();
do_some_drawing();
refresh();
endwin();
ここで私が使っている関数はmove(x,y)で、カーソルをある行の列に配置します.addStr(s)とaddch(c)もあります.は、カーソルに文字列と文字を書きます.
またgetch()はユーザーボタンを待つ.refresh()もあり、バッファのaddchやaddStrなどの描画操作を画面に出力します.
 
さらにusleep(int)関数も用いたが,ここでのパラメータはint型であり,マイクロ秒数を表し,1秒は1000000マイクロ秒に等しい.ここの間隔は蛇が移動するたびの間隔です.
 
コードは次のとおりです.
#include
#include 
#include 
#include 
#include 

#define MAX_X 70   //   
#define MAX_Y 20  //   
#define CORNER_X 4  //   x  
#define CORNER_Y 2   //   y  

struct point { 
    int x;
    int y;
};
struct point SnakeBody[50]; 
struct point food;

int Length = 4;  //    
int life = 1;   //     
int input = 0;  //       ascii
pthread_t id; //    linux  ,      


void FoodCheck();
void FoodProduce();
void Initializition();
void SnakeHeadMovement();
void DeathCheck();
void Paint();
void * waitForKey(void *);
void drawDot(int x, int y,char s);
void clearDot(int x, int y);
void end();


//   

int main(int argc, char** argv) {

    Initializition();
    while (life) {
        Paint();
        usleep(200000);
        SnakeHeadMovement();
        DeathCheck();
    }
    end();
    return 0;
}

void * waitForKey(void *para) {
    while (1) {
        input = getch();
    }
}

void end() {

    move(1, 0);
    addstr("Press any key to quit!");
    refresh();
    getch();
   endwin();
}


//       

void FoodProduce() {
    int superposition = 0;
    int i;
    srand(time(NULL));
    do {
        food.x = (rand() % ((MAX_X-2) / 2))*2+2;  //2 to MAX_X-2  and is   
        food.y = rand() % (MAX_Y-1)+1;   //1 to MAX_Y-1
        for (i = 0; i < Length; i++) {
            if (food.x == SnakeBody[i].x && food.y == SnakeBody[i].y)
                superposition = 1;
        }
    } while (superposition); /*      */
}

//                 4   

void Initializition() {
    initscr();//curses   

    int i;
    for (i = 3; i <= 6; i++) {//    
        SnakeBody[6 - i].x = 4;
        SnakeBody[6 - i].y = i;
    }
    FoodProduce();
    int ret;
    ret = pthread_create(&id, NULL, waitForKey, NULL);//    
    if (ret != 0) {
        exit(1);
    }

    for ( i = 0; i <= MAX_X; i+=2) {  //   
        drawDot(i, 0,'*');
        drawDot(i, MAX_Y,'*');
    }

    for (i = 0; i <= MAX_Y; i++) {
        drawDot(0, i,'*');
        drawDot(MAX_X, i,'*');
    }

}

//   ,         
void SnakeBodyMovement() {
    int i;
    for (i = Length - 1; i > 0; i--) {
        SnakeBody[i].x = SnakeBody[i - 1].x;
        SnakeBody[i].y = SnakeBody[i - 1].y;
    }

}


void SnakeHeadMovement() {

    clearDot(SnakeBody[Length - 1].x, SnakeBody[Length - 1].y);
    int directionX, directionY; /*          ,               */
    int newX, newY;
    newX = SnakeBody[0].x;
    newY = SnakeBody[0].y;

    directionX = SnakeBody[0].x - SnakeBody[1].x;
    directionY = SnakeBody[0].y - SnakeBody[1].y;
    

   

    if (input == 'w' && directionY<=0) //     
        newY--;
    else if (input == 's' && directionY>=0 )
        newY++;
    else if (input == 'a' && directionX<=0)
        newX -= 2; /*          */
    else if (input == 'd' && directionX>=0)
        newX += 2;
    else {
        newX += directionX;
        newY += directionY;
    }
    FoodCheck(); 
    SnakeBodyMovement();
    SnakeBody[0].x = newX;
    SnakeBody[0].y = newY;

}
//        ,                 

void FoodCheck() {
    if (food.x == SnakeBody[0].x && food.y == SnakeBody[0].y) {
        Length = Length + 1;
        FoodProduce();
    }
}
//      

void DeathCheck() {
    int i;
    if (SnakeBody[0].x <=1 || SnakeBody[0].x >= MAX_X  || SnakeBody[0].y <= 0 || SnakeBody[0].y >=MAX_Y)
        life = 0;
    for (i = 4; i < Length; i++)
        if (SnakeBody[0].x == SnakeBody[i].x && SnakeBody[0].y == SnakeBody[i].y)
            life = 0;
}

//     

void Paint() {
    int i = 0;

    drawDot(SnakeBody[i].x, SnakeBody[i].y,'@');
    for (i=1; i < Length; i++) {
        drawDot(SnakeBody[i].x, SnakeBody[i].y,'*');
    }
    drawDot(food.x, food.y,'$');
    clearDot(0, 0);
    refresh();//    
}

void drawDot(int x, int y,char s) {
    move(y+CORNER_Y, x+CORNER_X);
    addch(s);
}

void clearDot(int x, int y) {
    move(y+CORNER_Y, x+CORNER_X);
    addch(' ');
}

 
コンパイル時のコマンドは以下のgcc main.c -o main -lpthread -lcurses