双向链表基本实现简单贪吃蛇

前两个星期仔细学习了一下链表,然后发现双向链表用来写贪吃蛇还不错。(差点被CPP充满“健壮性”的链表教学劝退了)

具体实现起来还是有一点困难,看了一些博客,不过它们有些写的还不是很好(比如,不记录链表的tail项,每次都从head遍历至尾,这不就是CPP上“较慢的实现”吗 = =)。

我这个现在也有问题,比如在20来分之后,有时候就会吃到笑脸之后会卡顿一两秒 。。。还是too young。

 

游戏运行大概如下图:(感觉好丢人啊 = =)

 《双向链表基本实现简单贪吃蛇》

有些东西是现拿的,比如隐藏光标:

 1 // 隐藏光标
 2 void gotoxy(int x, int y) {
 3     HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
 4     COORD pos;
 5     pos.X = x;
 6     pos.Y = y;
 7     SetConsoleCursorPosition(handle, pos);
 8 }
 9 void HideCursor() {
10     CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
11     SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
12 }

我还不知道句柄是什么呢,= =。

 

讲不清,看代码吧。

 

Snake.h 头文件

  1 #ifndef _SNAKE_H_
  2 #define _SNAKE_H_
  3 
  4 const int COL = 15;
  5 const int ROW = 15;
  6 
  7 typedef struct SnakeNode {
  8     int x;
  9     int y;
 10     struct SnakeNode *pre;
 11     struct SnakeNode *next;
 12 }Node, *pNode;
 13 typedef struct Food {
 14     int x;
 15     int y;
 16 }Food, *pFood;
 17 
 18 //一些全局变量 
 19 int score = 0;
 20 int difficulty = 4;
 21 pNode pTail = NULL;
 22 
 23 // 隐藏光标
 24 void gotoxy(int x, int y) {
 25     HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
 26     COORD pos;
 27     pos.X = x;
 28     pos.Y = y;
 29     SetConsoleCursorPosition(handle, pos);
 30 }
 31 void HideCursor() {
 32     CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
 33     SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
 34 }
 35 
 36 pNode InitSnake(void) {
 37     pNode pHead = (pNode)malloc(sizeof(Node));
 38     pHead->x = ROW / 2;
 39     pHead->y = COL / 2;
 40     pHead->next = pHead->pre = NULL;
 41     pTail = pHead;
 42     pTail->pre = pTail->next = NULL;
 43     return pHead;
 44 }
 45 
 46 Food CreateFood(void) {
 47     Food food;
 48     srand((unsigned)time(NULL));
 49     food.x = rand() % ROW;
 50     food.y = rand() % COL;
 51     return food;
 52 }
 53 
 54 void AdjustDifficulty(int score) {
 55     if (score == 5)
 56         difficulty = 3;
 57     else if (score == 10)
 58         difficulty = 2;
 59     else if (score == 20)
 60         difficulty = 1;
 61 }
 62 
 63 bool SnakeDeath(pNode pHead) {
 64     for (pNode pt = pHead->next; pt != NULL; pt = pt->next) {
 65         if (pt->x == pHead->x&&pt->y == pHead->y)
 66             return true;
 67     }
 68     return false;
 69 }
 70 
 71 bool FoodInSnake(pNode pHead,pFood pFood) {
 72     for (pNode pt = pHead; pt != NULL; pt = pt->next) {
 73         if (pFood->x == pt->x&&pFood->y == pt->y)
 74             return true;
 75     }
 76     return false;
 77 }
 78 
 79 bool Move(pNode pHead, char key) {
 80     bool game_over = false;
 81     pNode pt = pTail;
 82     while (pt != pHead) { // 每个节点依次向前完成蛇的移动 
 83         pt->x = pt->pre->x;
 84         pt->y = pt->pre->y;
 85         pt = pt->pre;
 86     }
 87     switch (key) {
 88     case'd': {
 89         pHead->x += 1;
 90         if (pHead->x >= ROW)
 91             pHead->x -= ROW;
 92         break;
 93     }
 94     case'a': {
 95         pHead->x -= 1;
 96         if (pHead->x < 0)
 97             pHead->x += ROW;
 98         break;
 99     }
100     case's': {
101         pHead->y += 1;
102         if (pHead->y >= COL)
103             pHead->y -= COL;
104         break;
105     }
106     case'w': {
107         pHead->y -= 1;
108         if (pHead->y < 0)
109             pHead->y += COL;
110         break;
111     }
112     }
113     if (SnakeDeath(pHead))
114         game_over = true;
115     return game_over;
116 }
117 
118 char CheckKey(char direct) {
119     char key;
120     if (kbhit()) { // kbhit函数检查是否有键盘端的输入 
121         key = getch();
122         if (direct != 'd'&& key == 'a')
123             direct = key;
124         else if (direct != 'a'&&key == 'd')
125             direct = key;
126         else if (direct != 'w'&&key == 's')
127             direct = key;
128         else if (direct != 's'&&key == 'w')
129             direct = key;
130         else if (key == 27) // 27是esc的ascII码
131             direct = key;
132     }
133     return direct;
134 }
135 
136 pNode EatFood(pNode pHead, pFood pFood) {
137     pNode p_add = NULL, pt = NULL;
138     if (pFood->x == pHead->x&&pFood->y == pHead->y) {
139         p_add = (pNode)malloc(sizeof(Node));
140         score++;
141         pTail->next = p_add;
142         p_add->pre = pTail;
143         p_add->next = NULL;
144         pTail = p_add;
145         // 检查食物是否出现在蛇身的位置上
146         do { 
147             *pFood = CreateFood(); 
148         }while (FoodInSnake(pHead, pFood));
149     }
150     return pHead;
151 }
152 
153 void Show(pNode pHead, Food food) {
154     int row = 0, col = 0, flag = 0;
155     pNode pt = NULL;
156     printf("---方向控制:上:w 下:s 左:a 右:d(Esc退出)---\n");
157     printf("----------------------------------------\n");
158     printf("当前分数为:  %d   \n",score);
159     printf("当前等级为:  %d   \n---", 5-difficulty);
160     for (row = 0; row < ROW; row++)
161         printf("");
162     putchar('\n');
163     for (col = 0; col < COL; col++) {
164         printf(" |");
165         for (row = 0; row < ROW; row++) {
166             pt = pHead;
167             flag = 0;
168             //打印出蛇  
169             while (pt != NULL) {
170                 if (row == pt->x && col == pt->y) {
171                     if (pt == pHead)
172                         printf("");
173                     else
174                         printf("");
175                     flag = 1;
176                     break;
177                 }
178                 pt = pt->next;
179             }
180             //打印出食物或两个空格  
181             if (!flag) {
182                 if (row == food.x && col == food.y) {
183                     printf(":)");
184                     continue;
185                 }
186                 printf("  ");
187             }
188         }
189         printf("|\n");
190     }
191     printf("  ");
192     for (row = 0; row < ROW; row++)
193         printf("");
194     putchar('\n');
195 }
196 
197 void ExitGame(pNode *ppHead)
198 {
199     pNode p_delete = NULL, p_save = NULL;
200     while (*ppHead != NULL) {
201         p_save = (*ppHead)->next;
202         if (p_save != NULL)
203             p_save->pre = NULL;
204         p_delete = *ppHead;
205         free(p_delete);
206         p_delete = NULL;
207         *ppHead = p_save;
208     }
209 }
210 #endif

Snake.c 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <time.h>
 4 #include <conio.h>
 5 #include <Windows.h>
 6 #include <stdbool.h>
 7 #include "rSnake.h"
 8 
 9 int main(void)
10 {
11     bool game_over = false;
12     char direct = 'a', input;
13     Food food = CreateFood();
14     pNode head = InitSnake();
15     HideCursor();
16     do{
17         head = EatFood(head, &food);
18         input = CheckKey(direct);
19         if (27 == input){
20             game_over = true;
21             break;
22         }
23         else
24             direct = input;
25         game_over = Move(head, direct);
26         system("cls");
27         Show(head, food);
28         AdjustDifficulty(score);
29         Sleep(difficulty*50); 
30     } while (game_over == false);
31 
32     if (game_over){
33         printf("游戏结束!\n");
34         ExitGame(&head);
35         if (head==NULL)
36             printf("内存释放成功!\n");
37         else
38             printf("内存释放失败!\n");
39     }
40     getch();
41     return 0;
42 }

 

    原文作者:codinRay
    原文地址: https://www.cnblogs.com/ray-coding-in-rays/p/6283834.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞