因为编写的打印函数打印方式的原因,贪食蛇会越来越慢,虽然变化十分微小
/*
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 ;
}