提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
初学C语言,这是我写的第一个C语言的小游戏,给大家奉上,也请各位大佬多多指教。
‘w’,‘a’,‘s’,'d’为方向键,空格为暂停,‘q’,'e’分别为加速减速。
在运行过程中不要改变按全屏,不然输出会乱掉。
代码如下:
#include
#include
#include
#include
typedef struct SNAKE
{
int x;
int y;
struct SNAKE* next;
}snake;
void Pos(int x, int y);
void makesnake(snake** head);
void movesnake(COORD nhead, snake** head);
COORD findtail(snake* head);
void deltail(snake** head);
void printsnake(snake* head);
void cleantail(COORD tail);
void printmap();
BOOL deal(COORD nhead, snake* head);
COORD food();
COORD makefood(snake* head);
void printfood(COORD food);
void release(snake** head);
void release(snake** head)
{
snake* temp, * pre;
temp = *head;
while (temp != NULL) {
pre = temp;
temp = temp->next;
free(pre);
}
}
void printfood(COORD food)
{
Pos(food.X, food.Y);
printf("o");
}
COORD food()
{
COORD sfood;
sfood.X = (rand() % 27 + 1) * 2;
sfood.Y = rand() % 27 + 1;
return sfood;
}
COORD makefood(snake* head)
{
COORD finalfood = food();
snake* temp;
temp = head;
while (temp != NULL)
{
if (finalfood.X == temp->x && finalfood.Y == temp->y)
{
finalfood = food();//如果与蛇身重复则重置食物。
temp = head;//重新在历遍链表。
continue;
}
else
{
temp = temp->next;
}//如果不重复的话,检查下一截蛇身。
}
return finalfood;
}
BOOL deal(COORD nhead, snake* head)
{
snake* temp;
temp = head;
while (temp != NULL)
{
if (nhead.X == temp->x && nhead.Y == temp->y)
{
return 1;
}
else {
temp = temp->next;
}
}
return 0;
}
void printmap()
{
int x, y;
for (x = 0; x < 60; x += 2)
{
Pos(x, 0);
printf("#");
Pos(x, 29);
printf("#");
}
for (y = 0; y < 30; y++)
{
Pos(0, y);
printf(" #");
Pos(59, y);
printf("#");
}
}
void cleantail(COORD tail)
{
Pos(tail.X, tail.Y);
printf(" ");
}
void printsnake(snake* head)
{
snake* temp;
temp = head;
while (temp != NULL)
{
Pos(temp->x, temp->y);
printf("@");
temp = temp->next;
}
}
void deltail(snake** head)
{
snake* pre, * temp, * last = NULL;
temp = (*head);
pre = (*head);
while (temp != NULL)
{
last = pre;
pre = temp;
temp = pre->next;
}
last->next = NULL;
free(pre);
}//找到链表尾部,删除蛇尾。
COORD findtail(snake* head)
{
COORD tail;
snake* temp, * previous = NULL;
temp = head;
while (temp != NULL)
{
previous = temp;
temp = previous->next;
}
tail.X = previous->x;
tail.Y = previous->y;
return tail;
}
void movesnake(COORD nhead, snake** head)
{
snake* newhead, * temp;
newhead = (snake*)malloc(sizeof(snake));
newhead->x = nhead.X;
newhead->y = nhead.Y;
if (*head == NULL)
{
(*head) = newhead;
(*head)->next = NULL;
}
else
{
temp = (*head);
(*head) = newhead;
(*head)->next = temp;
}
}
void makesnake(snake** head)
{
snake* temp, * newbody;
int snakelong = 8;
while (snakelong)
{
newbody = (snake*)malloc(sizeof(snake));
newbody->x = 14 - snakelong;
newbody->y = 3;
if ((*head) != NULL)
{
temp = (*head);
(*head) = newbody;
newbody->next = temp;
}
else
{
(*head) = newbody;
(*head)->next = NULL;
}
snakelong -= 2;
}
}
void Pos(int x, int y)
{
COORD pos;
HANDLE output;
pos.X = x;
pos.Y = y;
output = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output, pos);
}
int main()
{
system("mode con cols=60 lines=31");
Pos(18, 8);
printf("********************");
Pos(18, 9);
printf("|**欢迎来到贪吃蛇**|");
Pos(18, 10);
printf("|***作者:YUXUAN***|");
Pos(18, 11);
printf("|按任意建开始游戏…|");
Pos(18, 12);
printf("********************");
Pos(4, 13);
printf("'w','a','s','d','空格','q','e',分别为上下左右暂停,q为加速,e为减速.\n输入其他字符直接退出游戏。");
_getch();
again:
int snakelong = 4, speed = 400, speedup = 0,ask=1;
snake* head = NULL;
COORD nhead, tail, food;
char dir = 'd', temp = 'd',Q;
makesnake(&head);
food = makefood(head);
system("cls");
printmap();
Pos(0, 30);
printf("蛇长度为%3d,速度为%5.2f格/秒", snakelong, 1000.0 / (speed + speedup*50));
printfood(food);
while (temp == 'w' || temp == 'a' || temp == 's' || temp == 'd' || temp == ' ' || temp == 'q' || temp == 'e')
{
Sleep(speed + (speedup*50));
while (_kbhit())
{
temp = _getch();
if (((dir == 'w' && temp != 'w') && (dir == 'w'&& temp != 's')) && ((dir == 's' && temp != 's') && (dir == 's' && temp != 'w')) && ((dir == 'a' && temp != 'a') && (dir == 'a'&& temp != 'd')) && ((dir == 'd' && temp != 'd') && (dir == 'd' && temp != 'a')) && temp != 'q' && temp != 'e')
{
if (temp == 'w' || temp == 'a' || temp == 's' || temp == 'd' || temp == ' ')
{
break;
}
}//检测到如果得到有用的键入时,就退出。
else
{
if (temp == 'q' || temp == 'e'||temp ==' ')
{
if (temp == 'q')
{
if (((speedup - 1) * 50 + speed) >= 50)
{
speedup--;
}//防止减到零。
temp = dir;
Pos(0, 30);
printf("蛇长度为%3d,速度为%5.2f格/秒", snakelong, 1000.0 / (speed + speedup * 50));
}
if (temp == 'e')
{
speedup++;
temp = dir;
Pos(0, 30);
printf("蛇长度为%3d,速度为%5.2f格/秒", snakelong, 1000.0 / (speed + speedup * 50));
}
}
else
{
continue;
}
}
}
if (temp == ' ')
{
temp = dir;
Pos(1, 1);
printf("暂停!");
_getch();
Pos(1, 1);
printf("# ");
}
else
{
if (dir == 'w' && temp != 's' || dir == 's' && temp != 'w' || dir == 'a' && temp != 'd' || dir == 'd' && temp != 'a') {
dir = temp;
}
}//按键输入。
switch (dir) {
case 'w':
nhead.X = head->x;
nhead.Y = head->y - 1;
break;
case 's':
nhead.X = head->x;
nhead.Y = head->y + 1;
break;
case 'a':
nhead.X = head->x - 2;
nhead.Y = head->y;
break;
case 'd':
nhead.X = head->x + 2;
nhead.Y = head->y;
break;
}
if (nhead.X <= 0 || nhead.Y <= 0 || nhead.X >= 59 || nhead.Y >= 29 || deal(nhead, head))
{
Pos(1, 1);
printf("您失败了!");
Pos(1, 2);
printf("请问是否再玩一遍?(y/n)");
while (ask)
{
Q = _getch();
if ('n' == Q)
{
system("cls");
release(&head);//释放链表。
exit(1);
}
else
{
if ('y' == Q) {
release(&head);
goto again;
}
else
{
ask = 1;
}
}
}
}//判断是否撞到了墙壁。
else
{
movesnake(nhead, &head);//移动蛇,头插法,插入新的蛇头。
tail = findtail(head);//寻找蛇尾。
if (nhead.X == food.X && food.Y == nhead.Y) {
printsnake(head);//输出蛇身。
cleantail(tail);//在原本蛇尾的位置输出空格。
food = makefood(head);
printfood(food);
snakelong++;
if (((speedup) * 50 + speed-1) >= 50)
{
speed--;
Pos(0, 30);
printf("蛇长度为%3d,速度为%5.2f格/秒", snakelong, 1000.0 / (speed + speedup * 50));//蛇速度随蛇长度的变化而改变。
}//防止减到零。
if(snakelong == 784)
{
Pos(20, 15);
printf("你成功了!");
Pos(20, 16);
printf("还想在玩一遍吗?(y/n)");
while (ask)
{
Q = _getch();
if ('n' == Q)
{
system("cls");
release(&head);//释放链表。
exit(1);
}
else
{
if ('y' == Q) {
release(&head);
goto again;
}
else
{
ask = 1;
}
}
}
}
}//吃到了食物不用删除蛇尾,重新生成食物。
else {
deltail(&head);//删除蛇尾。
printsnake(head);//输出蛇身。
cleantail(tail);//在原本蛇尾的位置输出空格。
}//没有吃到食物,删除食物。
}
}
return 0;
}
//17:09 2021/2/12
如果还有需要什么改进的,请大佬们多多指教。