純C語言寫一個(gè)貪吃蛇,支持devc編譯器
只是貼一下代碼,dev真的很爛,逐條編譯,要是函數(shù)在上頭聲明下面實(shí)現(xiàn)可能通過不了,挺麻煩的。希望不會有人學(xué)習(xí)c語言是靠dev。
學(xué)完了c++才發(fā)現(xiàn)c里面有很多東西跟c++不一樣,例如c++支持引用,c里面函數(shù)的參數(shù)只能是拷貝,new和delete與malloc和free的差別就不說了,我用c++被new和delete折磨過,建議以后能malloc絕不用new,c語言沒有bool類型,用c++多了還以為bool是天經(jīng)地義要有的東西,還有typedef struct snake。c++能直接這么聲明,然后直接snake就行了,但是c語言要typedef struct snake snake;才行。我用的是字符來實(shí)現(xiàn)的,效果不是很好,用的數(shù)據(jù)類型是首尾相接的鏈表,好像還有點(diǎn)小問題,不過這種小東西不值得花太多心思。
#include<stdio.h>
#include<conio.h>
#include<Windows.h>
#include<time.h>
#define WIDTH 9
#define HEIGHT 9
enum element
{
snake,wall,space,food,snakehead,snaketail
};
enum Dir
{
up='w',down='s',left='a',right='d'
};
typedef enum Dir Dir;
typedef int Map[HEIGHT][WIDTH];
struct Snake
{
int x, y;
struct Snake* child;
struct Snake* parent;
};
typedef struct Snake Snake;
void drawMap(const int** map)
{
system("cls");
for (int i = 0;i < HEIGHT;i++)
{
for(int j=0;j<WIDTH;j++)
switch (map[i][j])
{
case snake:printf("S");break;
case wall:printf("W");break;
case space:printf(" ");break;
case food:printf("F");break;
case snakehead:printf("H");break;
case snaketail:printf("T");break;
default:
break;
}
printf("\n");
}
}
char isthrough(const int** map, int x, int y)
{
//if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT)return 0;
if (map[y][x] == space || map[y][x] == food||map[y][x]==snaketail)return 1;
return 0;
}
int** InitMap()
{
int** result= (int**)malloc(sizeof(int*) * HEIGHT);
for (int i = 0;i < HEIGHT;i++)
result[i] = (int*)malloc(sizeof(int) * WIDTH);
for (int i = 0;i < WIDTH;i++)
{
result[0][i] = wall;
result[HEIGHT - 1][i] = wall;
}
for (int i = 1;i < HEIGHT - 1;i++)
{
result[i][0] = wall;
result[i][WIDTH - 1] = wall;
}
for (int i = 1;i < HEIGHT - 1;i++)
for (int j = 1;j < WIDTH - 1;j++)
result[i][j] = space;
return result;
}
void clearMap(int** map)
{
for (int i = 0;i < HEIGHT;i++)
free(map[i]);
free(map);
}
Snake* create()
{
Snake* result= (Snake*)malloc(sizeof(Snake));
result->x = result->y=0;
result->child = result->parent = NULL;
return result;
}
Snake* createN(const int xx,const int yy)
{
Snake* result = (Snake*)malloc(sizeof(Snake));
result->x = xx;
result->y = yy;
result->child = result->parent = NULL;
return result;
}
void insert(Snake* source, Snake* val,char ischild)
{
if (!source->child)
{
source->child = val;
val->parent = source;
val->child = source;
source->parent = val;
return;
}
if (ischild != 0)
{
if (source->child)
{
source->child->parent = val;
val->child = source->child;
}
val->parent = source;
source->child = val;
}
else
{
if (source->parent)
{
source->parent->child = val;
val->parent = source->parent;
}
val->child = source;
source->parent = val;
}
}
void generateFood(int score,int** map)
{
int randNum = WIDTH*HEIGHT-WIDTH * 2 - HEIGHT * 2 + 4 - score;
if (randNum == 0)return;
int foodplace = rand() % randNum;
for (int i = 1;i < HEIGHT - 1;i++)
{
for (int j = 1;j < WIDTH - 1;j++)
{
if (foodplace == 0&&map[i][j]==space)
{
map[i][j] = food;
return;
}
if (map[i][j] == space)foodplace--;
}
}
}
void clearSnake(Snake* head)
{
if(head->parent)
head->parent->child = NULL;
Snake* current = head;
while (current != NULL)
{
Snake* temp = current;
current = current->child;
free(temp);
}
}
char move(int** map, char ch, Snake* head,Snake** tempHead,char* isfood,int* score)
{
switch (ch)
{
case 'w':
if (!isthrough(map, head->x, head->y - 1))return 0;
/*{
if (head->parent != NULL && head->x == head->parent->x && head->y - 1 == head->parent->y)
{
*tempHead = head->parent;
return 1;
}
return 0;
}*/
if (map[head->y - 1][head->x] == food)
{
*tempHead = createN(head->x, head->y - 1);
insert(head, *tempHead, 0);
map[(*tempHead)->y][(*tempHead)->x] = snakehead;
map[(*tempHead)->parent->y][(*tempHead)->parent->x] = snaketail;
*isfood = 0;
(*score)++;
return 1;
}
else if ((*tempHead)->parent != NULL)
{
*tempHead = (*tempHead)->parent;
map[(*tempHead)->y][(*tempHead)->x] = space;
(*tempHead)->x = head->x;
(*tempHead)->y = head->y - 1;
map[head->y][head->x] = snake;
map[(*tempHead)->y][(*tempHead)->x] = snakehead;
map[(*tempHead)->parent->y][(*tempHead)->parent->x] = snaketail;
return 1;
}
map[(*tempHead)->y][(*tempHead)->x] = space;
(*tempHead)->x = head->x;
(*tempHead)->y = head->y-1;
map[(*tempHead)->y][(*tempHead)->x] = snake;
break;
case 'a':
if (!isthrough(map, head->x - 1, head->y))return 0;
/*{
if (head->parent != NULL && head->x - 1 == head->parent->x && head->y== head->parent->y)
{
*tempHead = head->parent;
return 1;
}
return 0;
}*/
if (map[head->y][head->x - 1] == food)
{
*tempHead = createN(head->x - 1, head->y);
insert(head, *tempHead, 0);
map[(*tempHead)->y][(*tempHead)->x] = snakehead;
map[(*tempHead)->parent->y][(*tempHead)->parent->x] = snaketail;
*isfood = 0;
(*score)++;
return 1;
}
else if ((*tempHead)->parent != NULL)
{
*tempHead = (*tempHead)->parent;
map[(*tempHead)->y][(*tempHead)->x] = space;
(*tempHead)->x = head->x - 1;
(*tempHead)->y = head->y;
map[head->y][head->x] = snake;
map[(*tempHead)->y][(*tempHead)->x] = snakehead;
map[(*tempHead)->parent->y][(*tempHead)->parent->x] = snaketail;
return 1;
}
map[(*tempHead)->y][(*tempHead)->x] = space;
(*tempHead)->x = head->x - 1;
(*tempHead)->y = head->y;
map[(*tempHead)->y][(*tempHead)->x] = snake;
break;
case 's':
if (!isthrough(map, head->x, head->y + 1))return 0;
/*{
if (head->parent != NULL && head->x == head->parent->x && head->y + 1 == head->parent->y)
{
*tempHead = head->parent;
return 1;
}
return 0;
}*/
if (map[head->y + 1][head->x] == food)
{
*tempHead = createN(head->x, head->y + 1);
insert(head, *tempHead, 0);
map[(*tempHead)->y][(*tempHead)->x] = snakehead;
map[(*tempHead)->parent->y][(*tempHead)->parent->x] = snaketail;
*isfood = 0;
(*score)++;
return 1;
}
else if ((*tempHead)->parent != NULL)
{
*tempHead = (*tempHead)->parent;
map[(*tempHead)->y][(*tempHead)->x] = space;
(*tempHead)->x = head->x;
(*tempHead)->y = head->y + 1;
map[head->y][head->x] = snake;
map[(*tempHead)->y][(*tempHead)->x] = snakehead;
map[(*tempHead)->parent->y][(*tempHead)->parent->x] = snaketail;
return 1;
}
map[(*tempHead)->y][(*tempHead)->x] = space;
(*tempHead)->x = head->x;
(*tempHead)->y = head->y + 1;
map[(*tempHead)->y][(*tempHead)->x] = snake;
break;
case 'd':
if (!isthrough(map, head->x + 1, head->y))return 0;
/*{
if (head->parent!=NULL&&head->x + 1 == head->parent->x && head->y == head->parent->y)
{
*tempHead = head->parent;
return 1;
}
return 0;
}*/
if (map[head->y][head->x + 1] == food)
{
*tempHead = createN(head->x + 1, head->y);
insert(head, *tempHead, 0);
map[(*tempHead)->y][(*tempHead)->x] = snakehead;
map[(*tempHead)->parent->y][(*tempHead)->parent->x] = snaketail;
*isfood = 0;
(*score)++;
return 1;
}
else if ((*tempHead)->parent != NULL)
{
*tempHead = (*tempHead)->parent;
map[(*tempHead)->y][(*tempHead)->x] = space;
(*tempHead)->x = head->x + 1;
(*tempHead)->y = head->y;
map[head->y][head->x] = snake;
map[(*tempHead)->y][(*tempHead)->x] = snakehead;
map[(*tempHead)->parent->y][(*tempHead)->parent->x] = snaketail;
return 1;
}
map[(*tempHead)->y][(*tempHead)->x] = space;
(*tempHead)->x = head->x + 1;
(*tempHead)->y = head->y;
map[(*tempHead)->y][(*tempHead)->x] = snake;
break;
default:
break;
}
return 1;
}
int main()
{
srand((unsigned int)time(NULL));
struct Snake* head=createN(WIDTH/2,HEIGHT/2);
int** map=InitMap();
Dir turn=right;
InitMap(map);
map[head->y][head->x] = snake;
int score = 1;
char isfood = 0;
char isexit = 0;
char iswin = 0;
while (1)
{
if (!isfood)
{
generateFood(score, map);
isfood = 1;
}
if (score == WIDTH * HEIGHT - WIDTH * 2 - HEIGHT * 2 + 4)
{
iswin = 1;
break;
}
drawMap(map);
Sleep(100);
if (_kbhit())
{
switch (_getch())
{
case 'w':turn = up;break;
case 'a':turn = left;break;
case 's':turn = down;break;
case 'd':turn = right;break;
case 'q':isexit = 1;
default:
break;
}
}
if (isexit)break;
if (!move(map, turn, head, &head, &isfood,&score))
break;
//move(map, turn, head, &head, &isfood,&score);//無敵版
}
clearMap(map);
clearSnake(head);
if (!iswin)
printf("you lose,score:%d\n", score);
else
printf("you win,score:%d\n", score);
_getch();
return 0;
}