C语言——贪食蛇代码

因为编写的打印函数打印方式的原因,贪食蛇会越来越慢,虽然变化十分微小


/*
Name:      Snake Game
Date:      2014/06/16
By:        peterliang461
Remarks:   This is a simple snake, just can be run, no other function such
           as, it moves faster while it eats food
*/

#include <stdio.h>
#include <stdlib.h> //Including malloc() and free()
//For sleep(), includex <unistd.h> in linux and <windows.h> in windows
//#include <unistd.h>
#include <windows.h>
//Including <conio.h> to use kbhit, and this function is just for windows
#include <conio.h>

//The game is played in Wall*Wall area, length from 0 to 19,
//-1 and Wall is wall
#define Wall 20

_Bool life = 1;     //The flag of Gameover

//The structure saves snake's position, it is a line list
typedef struct SnakeBody{
    int x;    //x for column
    int y;    //y for row
    struct SnakeBody *next;
}Body;

//To initialize snake's body, food's position and direction
Body *Initialize(int *food, char *direction);

//To show the picture
void Show(Body *headpointer, int *food);

void gotoxy(int x, int y);

//To check if it is contrary between two
int CheckDir(char direction, char getdir);

//To change the snake's body line list
Body *Move(Body *headpointer, char direction, Body *tempdata);

//Weather eat food or not
int IsEatFood(Body *headpointer, int *food);

//Increasing body's length
void IncreaseBody(Body *headpointer, Body tempdata);

//To make a new food and put it
void PutTheFood(Body *headpointer, int *food);

//If it hit itself
int IsHitBody(Body *headpointer);

//If it hit wall
int IsHitWall(Body *headpointer);

int main(void){
    int score = 0;   //The score you get
    int food[2] = {0, 0};   //The food's position
    // 'a', 's', 'd' and 'w' means left, down, right and up
    char direction = 'd';
    char getdir = 'd';   //the key we get from keyboard
    Body *head_of_body = NULL;   //The line list for snake body
    //A Body structure is used between Move() and IncreaseBody()
    Body tempdata;

    //To initialize snake's body, food's position and direction
    head_of_body = (Body *)Initialize(food, &direction);
    while (1){      //A big iteration
        Show(head_of_body, food);   //To show the picture
	//sleep(1) for linux to stop 1 second
	//sleep(1);
	//Sleep(250) for windows to stop 1 second
	Sleep(250);
	if (kbhit()){   //If key is hit, do it
	    getdir = getch();  //getch() does not print what we put
	    fflush(stdin);   //Killed the others
	    //To check if it is contrary between two
	    if (CheckDir(direction, getdir)){
	        //To update the direction of snake
	        direction = getdir;
	    }
	}
	//To change the snake's body line list
	head_of_body = (Body *)Move(head_of_body, direction, &tempdata);
	if (IsEatFood(head_of_body, food)){   //Weather eat food or not
	    //Increasing body's length and score
            IncreaseBody(head_of_body, tempdata);
	    score += 1;
	    PutTheFood(head_of_body, food); //To make a new food and put it
	}
	if (IsHitBody(head_of_body) ||
	    IsHitWall(head_of_body)){ //If it hit itself or wall
	    life = 0;    //To change the flag
	}
	//To check the flag, if it is gameover, iteration breaks
	if (0 == life){
	    break;
	}
    }
    printf("GameOver\nThe score is %d\n", score);

    return 0;
}

//To initialize snake's body, food's position and direction
Body *Initialize(int *food, char *direction){
    int index;
    Body *headpointer, *temp;

    //To set the snake's body with 3 length
    headpointer = (Body *)malloc(sizeof(Body));
    headpointer->x = 2, headpointer->y = 0;
    temp = headpointer;
    for (index = 1; index > -1; index--){
         temp->next = (Body *)malloc(sizeof(Body));
	 temp = temp->next;
	 temp->x = index, temp->y = 0;
    }
    temp->next = NULL;
    //To set food's position
    PutTheFood(headpointer, food);
    //To set the direction
    *direction = 'd';       //Going right when it starts

    return headpointer;
}

//To show the picture
void Show(Body *headpointer, int *food){
    int index_x, index_y;
    int tempone;
    int flag = 0;   //The flag shows that this point has body
    Body *temp;

    //The game is played in a Wall*Wall area
    //Printing
    //"clear" for linux
    //system("clear");
    //gotyxy() for windows
    gotoxy(0, 0);  //If we use CLS, it will flash
    //Printing the wall
    for (index_x = -1; index_x <= 20; index_x++){
        putchar('/');
    }
    putchar('\n');
    for (index_y = 0; index_y < Wall; index_y++){
        printf("/");  //Printint the wall
        for (index_x = 0; index_x < Wall; index_x++){
	    temp = headpointer;
	    while (temp != NULL){ //To check all body's line list
	        if (temp->x == index_x && temp->y == index_y){
		    flag = 1;
		    break;
		}
		temp = temp->next; //Going to next pointer
	    }
	    if(flag){
	        putchar('#');
	    }
	    else {
	        //To print if it is the food's position
	        if (food[0] == index_x && food[1] == index_y){
	            putchar('*');
	        }
		else {
		    putchar(' ');
		}
	    }
	    flag = 0; //Changing flag to 0, prepare for the next iteration
	}
	printf("/\n");  //Printing the wall and going to next line
    }
    //Printing the wall
    for (index_x = -1; index_x <= 20; index_x++){
        putchar('/');
    }

    return;
}

//To check if it is contrary between two
int CheckDir(char direction, char getdir){
    int flag = 1;

    //To confirm that getdir is not other keys such as '\n'
    if (getdir != 'a' && getdir != 'd' && getdir != 'w' && getdir != 's'){
        return 0;
    }
    //If it is contrary, the function return 0, otherwise it return 1
    switch (direction){
        case 'a':
	    flag = (getdir == 'd' ? 0 : 1);
	    break;
	case 'd':
	    flag = (getdir == 'a' ? 0 : 1);
	    break;
	case 'w':
	    flag = (getdir == 's' ? 0 : 1);
	case 's':
	    flag = (getdir == 'w' ? 0 : 1);
	    break;
    }

    return flag;
}

//To change the snake's body line list
Body *Move(Body *headpointer, char direction, Body *tempdata){
    //Cteated a new head pointer to add at the first of line list,
    //and cut the last one of the line list
    Body *newhead;
    Body *temp, *pre;

    newhead = (Body *)malloc(sizeof (Body));
    //x for column, y for row
    switch (direction){
        case 'a': //Going left, column minux one
	    newhead->x = headpointer->x - 1;
	    newhead->y = headpointer->y;
	    break;
	case 'd': //Goint right, column plus one
	    newhead->x = headpointer->x + 1;
	    newhead->y = headpointer->y;
	    break;
	case 'w':  //Going up, row minux one
	    newhead->x = headpointer->x;
	    newhead->y = headpointer->y - 1;
	    break;
	case 's': //Going down, row plus one
	    newhead->x = headpointer->x;
	    newhead->y = headpointer->y + 1;
	    break;
    }
    newhead->next = headpointer;  //To add the new head to the line list
    //Cut the last one of the line list
    temp = headpointer;
    pre = NULL;
    while (temp->next != NULL){ //Found the last one
        pre = temp;
        temp = temp->next;
    }
    pre->next = NULL;
    //To save the data which is used in IncreaseBody()
    tempdata->x = temp->x;
    tempdata->y = temp->y;
    tempdata->next = NULL;
    free(temp);

    return newhead;
}

int IsEatFood(Body *headpointer, int *food){
    int flag = 0; //The flag shows eating food

    //In this case, headpointer is the position where the snake's head is
    //in the next picture, because we do Move() before IsEatFood(),
    //headpointer is the new one
    if (food[0] == headpointer->x &&
        food[1] == headpointer->y){
        flag = 1;
    }

    return flag;
}

//Increasing body's length
void IncreaseBody(Body *headpointer, Body tempdata){
    //We do Move() before to add a new head and cut the tail, to increase
    //its body, we only need to keep the tail
    int temp_x, temp_y;
    Body *temp, *tail;

    tail = (Body *)malloc(sizeof (Body));
    //Found the last
    temp = headpointer;
    while (temp->next != NULL){
        temp = temp->next;
    }
    //To set the data
    tail->x = tempdata.x;
    tail->y = tempdata.y;
    temp->next = tail;
    tail->next = NULL;

    return;
}

//To make a new food and put it
void PutTheFood(Body *headpointer, int *food){
    int temp_x, temp_y;
    int flag = 1;  //The flag shows correct
    Body *temp;

    while (1){
        temp_x = rand() % 20;
	temp_y = rand() % 20;
	//To check all point in the list
	temp = headpointer;
	while (temp != NULL){
	    //If it is not the same one, do the next iteration
	    if (temp->x == temp_x && temp->y == temp_y){
		flag = 0;
	        break;
	    }
	    temp = temp->next;
	}
	if (flag){
	    food[0] = temp_x;
	    food[1] = temp_y;
	    break;  //It jumps out from while(1)
	}
	flag = 1;  //Changing flag to 1, prepare for the next iteration
    }

    return ;
}

//If it hit itself
int IsHitBody(Body *headpointer){
    Body *temp;
    int flag = 0; //0, it does not hit, 1, it hits

    //We compare the headpointer and the other pointers after it
    temp = headpointer->next;
    while (temp != NULL){
	if (temp->x == headpointer->x && temp->y == headpointer->y){
	    flag = 1;
	    break;
	}
	else {
	    temp = temp->next;
	}
    }

    return flag;
}

//If it hit wall
int IsHitWall(Body *headpointer){
    int temp_x, temp_y;
    int flag = 0; //0, it does not hit, 1, it hits

    if (headpointer->x == -1 || headpointer->x == Wall ||
        headpointer->y == -1 || headpointer->y == Wall){
        flag = 1;
    }

    return flag;
}

void gotoxy(int x, int y){
    COORD pos = {x, y};
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hOut, pos);

    return ;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值