#include
#include
#include
#include
#include
#define Row_len 60 //界面宽度(列数)
#define Line_len 20 //界面长度(行数)
struct snake //定义一个单向链表代表蛇{
int x; //蛇的横坐标 int y; //蛇的纵坐标 struct snake *next;
}SNAKE;
void PrintMenu(void); //输出菜单void StartGame(int map[][Row_len], struct snake *snake);
void Instruct(void);
void Print(int map[][Row_len], struct snake *snake_head, int X, int Y); //输出游戏界面struct snake *Eat(struct snake *snake_head, int X, int Y);
struct snake *Snake_Move(struct snake *snake_head, int direction);
int Read_Key(int *direction);
int IsBump(struct snake *snake_head);
void DeleteMemory(struct snake *snake_head);
int main()
{
int choice, ret, i, j;
int map[Line_len][Row_len]; //定义一个二维整形数组表示地图(游戏界面) SNAKE *snake; struct snake *snake_head = NULL, *snake_1 = NULL;
snake_head = (struct snake *)malloc(sizeof(struct snake));
srand(time(NULL));
if(snake_head == NULL)
{
system("cls");
printf("\n\n\n\n\n\n\n\t\t\t\t程序遇到了一个故障,很可能是没有足够的空间!\n");
system("pause");
exit(0);
}
snake_head->x = 2; //贪吃蛇的蛇头初始坐标为(1, 1),初始蛇的长度为1 snake_head->y = 1;
snake_1 = (struct snake *)malloc(sizeof(struct snake));
if(snake_1 == NULL)
{
system("cls");
printf("\n\n\n\n\n\n\n\t\t\t\t程序遇到了一个故障,很可能是没有足够的空间!\n");
system("pause");
exit(0);
}
snake_1->x = 1;
snake_1->y = 1;
snake_head->next = snake_1;
for(i = 0; i < Line_len; i++)
{
for(j = 0; j < Row_len; j++)
{
map[i][j] = 32;
}
}
do{
system("cls");
PrintMenu();
printf("请输入你想操作的菜单序号:");
ret = scanf("%d", &choice);
while(ret != 1)
{
while(getchar() != '\n');
printf("请输入有效的序号:");
ret = scanf("%d", &choice);
}
switch(choice)
{
case 1:
StartGame(map, snake_head);
break;
case 2:
Instruct();
break;
case 3:
exit(0);
default:
printf("没有这个选项,请重新输入!\n");
}
}while(1);
}
void PrintMenu(void)
{
system("cls");
printf("\t\t\t贪吃蛇游戏菜单\n\n\n");
printf("\t\t\t1.开始游戏\n\n\n");
printf("\t\t\t2.关于游戏\n\n\n");
printf("\t\t\t3.退出游戏\n\n\n");
return;
}
/*函数功能:在屏幕上显示关于游戏的一些信息*/
void Instruct(void)
{
char str[500] = "贪吃蛇是一款经典的游戏\n这款游戏非常适合大一学完C语言之后编写\n所以作者在大一学完C语言后用纯C语言编写出这个游戏作为期末大作业\n基本上是自己编写的,在网上参考了一些的函数的用法\n无版权,欢迎各位参考和改进\n希望能给各位玩家带来良好的游戏体验\n";
char *pstr = str;
system("cls");
for( ; *pstr != '\0'; pstr++)
{
Sleep(40);
putchar(*pstr);
}
system("pause");
printf("\n\n\t\t\t贪吃蛇游戏指南\n");
printf("1.按\"↑\"\"↓\"\"←\"\"→\"四个键可改变贪吃蛇的移动方向\n");
printf("2.你可以通过吃食物来得分\n");
printf("3.吃的食物越多,贪吃蛇就越长,移动速度也就越快\n");
printf("4.存在以下情形之一,游戏结束:\n");
printf("*蛇头撞墙\n");
printf("*蛇头撞到蛇身\n");
printf("作者:*** 2017.12.27\n");
system("pause");
return;
}
个人认为以下是代码的精华部分,花费了我较多的时间和精力//游戏开始void StartGame(int map[][Row_len], struct snake *snake_head)
{
int direction = 4; //贪吃蛇的移动方向:1,2,3,4分别表示上下左右。移动方向初始化为4。 int IsContinue = 1;//代表游戏是否继续:0, 1分别表示结束,继续游戏。 int snake_len = 1; //代表贪吃蛇的长度,初始化为1 int x, y; //代表食物的坐标 int score = 0; //记录玩家所得分数 int PauseTime;
while(IsContinue)
{
PauseTime = 40 + 1000 / snake_len;
Sleep(PauseTime); //蛇的移动速度与贪吃蛇蛇的长度成反相关关系 x = rand() % (Row_len - 2) + 1 ; //产生一个1 ~ Row_len之间的随机数, 代表食物的横坐标 y = rand() % (Line_len - 2) + 1 ; //产生一个1 ~ Line_len之间的随机数, 代表食物的纵坐标 snake_head = Snake_Move(snake_head, direction); //贪吃蛇的移动 direction = Read_Key(&direction); //读取用户从键盘输入的方向 IsContinue = IsBump(snake_head); //判断是否撞墙或者撞到自己 if(snake_head->x == x && snake_head->y == y) //如果蛇吃到了食物 {
snake_head = Eat(snake_head, x, y);
score++;
snake_len++;
}
Print(map, snake_head, x, y);
DeleteMemory(snake_head);
}
printf("游戏结束\n你的得分为%d\n", score);
system("pause");
}
/*函数功能:将贪吃蛇吃到的食物坐标作为参数传入。新建一个节点作为链表的表头,并将所有节点数据前进一个节点,返回添加节点后的链表的头指针*/
struct snake *Eat(struct snake *snake_head, int X, int Y)
{
struct snake *head = NULL;
head = (struct snake *)malloc(sizeof(struct snake));
if(head == NULL) //若申请动态内存失败,退出程序 {
system("cls");
printf("\n\n\n\n\n\n\n\t\t\t\t程序遇到了一个故障,很可能是没有足够的空间!\n");
system("pause");
exit(0);
}
head->x = X;//将食物的坐标赋值给新建节点p; head->y = Y;
head->next = snake_head;
return head;
}
//贪吃蛇蛇的移动,返回移动后的头链表struct snake *Snake_Move(struct snake *snake_head, int direction)
{
int x_location[100], i = 0;
int y_location[100];
struct snake *pr = snake_head, *pt = snake_head;
if(direction == 1) //头节点的移动 {
snake_head->y--;
}
else if(direction == 2)
{
snake_head->y++;
}
else if(direction == 3)
{
snake_head->x--;
}
else
{
snake_head->x++;
}
while(pr->next != NULL) //若未到表尾,则移动新建节点添加到表尾 {
x_location[i] = pr->x; //用一维数组x_location记录蛇的横坐标 y_location[i] = pr->y; //用一维数组y_location记录蛇的纵坐标 pr = pr->next;
i++;
}
i = 0;
*-* while(pt->next != NULL) //若未到表尾,则移动新建节点添加到表尾 {
pt->x = x_location[i];
pt->y = y_location[i];
pt = pt->next;
}
return snake_head;
}
/*函数功能:改变贪吃蛇的移动方向。若用户输入了除上下左右键的其他键,则返回原来的移动方向*/
int Read_Key(int *direction)
{
int key;
key = getch();
if(key == 72)
{
*direction = 1;
}
else if(key == 80)
{
*direction = 2;
}
else if(key == 75)
{
*direction = 3;
}
else if(key == 77)
{
*direction = 4;
}
else
{
}
return *direction;
}
int IsBump(struct snake *snake_head)
{
struct snake *pr = snake_head;
if(pr->x < 1 || pr->x > Line_len - 2 || pr->y < 1 || pr->y > Row_len - 2) //若蛇头撞到了墙 {
return 0;
}
else
{
while(pr->next != NULL) //若未到表尾, 则移动pr直到pr指向表尾 {
pr = pr->next;
if(snake_head->x == pr->x && snake_head->y == pr->y) //若蛇头撞到蛇身 {
return 0;
}
}
}
return 1;
}
void DeleteMemory(struct snake *snake_head)
{
struct snake *p = snake_head, *pr = NULL;
while(p != NULL)
{
pr = p;
p = p->next;
free(pr);
}
}
//输出游戏界面void Print(int map[][Row_len], struct snake *snake_head, int X, int Y)
{
struct snake *pr = snake_head;
int i, j;
system("cls"); //清屏 for(i = 0; i < Line_len; i++)
{
for(j = 0; j < Row_len; j++)
{
map[i][j] = 32;
}
}
for(j = 0, i = 0; i < Line_len; i++) //边框 {
map[i][j] = 35;
}
for(i = 0, j = 1; j < Row_len; j++)
{
map[i][j] = 35;
}
for(j = Row_len - 1, i = 1; i < Line_len; i++)
{
map[i][j] = 35;
}
for(i = Line_len - 1, j = 1; j < Row_len - 1; j++)
{
map[i][j] = 35;
}
map[X][Y] = 111; //食物 while(pr->next != NULL) //若未到表尾,则移动pr直到pr指向表尾 {
map[pr->x][pr->y] = 42;
pr = pr->next;
}
for(i = 0; i < Line_len; i++)
{
for(j = 0; j < Row_len; j++)
{
printf("%c", map[i][j]);
}
printf("\n");
}
}
贪吃蛇试用版.exe - 0 error(s), 0 warning(s)