user-0 提问: 贪吃蛇跑不动了，谁来帮看下，就百多行...

回复:
user: user-1
content: 这是一个控制台的贪吃蛇，仅供参考

user: user-2
content: 看了你写的贪吃蛇游戏，我在Linux下运行没什么大的问题。主要问题如下： 1）是接收输入的地方需要优化一下； 2）蛇会越界，即越过图的边界，你可以做一下校验，尤其是在蛇运动前对其是否到边界做一个预判； 3）蛇吃到果子后，蛇继续运动发现果子还在原地方； 以下是我写的简单贪吃蛇；你可以在这个基础上做的更复杂，比如动态中延长蛇的身体，延长蛇的身体就要考虑蛇在运行中是否会咬到自己。  #include <string.h> #include <time.h>  #define MAP_ROW     20 #define MAP_COL     20  #define SNAKER_BODY_LEN  2  struct pos {     int pos_x;     int pos_y; };  enum game_status {     EATING_FRUIT = 0,     EATEN_FRUIT,     EATEN_SELF };   /*Init the map */ void draw_map(char (*map)[MAP_COL], struct pos *fruit_pos, struct pos *snaker_pos, int snaker_len) {     int i, j, k;     int is_snaker = 0;      for (i = 0; i < MAP_ROW; i++) {         for (j = 0; j < MAP_COL; j++) {             if (fruit_pos->pos_x == i && fruit_pos->pos_y == j) {                 map[i][j] = 'X';             } else {                 is_snaker = 0;                 for (k = 0; k < snaker_len; k++) {                     if (snaker_pos[k].pos_x == i && snaker_pos[k].pos_y == j) {                         if (k == 0)                             map[i][j] = '*';                         else                             map[i][j] = 'o';                         is_snaker = 1;                     }                 }                 if (!is_snaker) {                     map[i][j] = '.';                 }             }         }     } }  /* show the map */ void show_map(char (*map)[MAP_COL], int row, int col) {     int i, j;      for (i = 0; i < row; i++) {         for (j = 0; j < col; j++)             printf("%c ", map[i][j]);         putchar(10);     } }   void add_fruit(struct pos *fruit_pos, struct pos *snaker_pos, int snaker_len) {     int i;     struct pos tmp;      srand(time(NULL));     while (1) {         tmp.pos_x = rand() % MAP_ROW;         tmp.pos_y = rand() % MAP_COL;          for (i = 0; i < snaker_len; i++) {             if (tmp.pos_x == snaker_pos[i].pos_x                     && tmp.pos_y == snaker_pos[i].pos_y)                 continue;         }         memcpy(fruit_pos, &tmp, sizeof(struct pos));         break;     } }  static void change_snaker_body(struct pos *snaker_pos, int snaker_len) {     struct pos tmp;     int i;      tmp = snaker_pos[0];     for (i = 1; i < snaker_len; i++) {         snaker_pos[i] = tmp;         if (i+1 < snaker_len)             tmp = snaker_pos[i+1];     } }  static int check_snaker_status(struct pos *snaker_pos, int snaker_len, struct pos *fruit_pos) {     struct pos tmp;     int i, is_eaten = EATING_FRUIT;      tmp = snaker_pos[0];     if (snaker_len >= 4) { /* snaker maybe bites itself*/         for (i = 3; i< snaker_len; i++) {             if (tmp.pos_x == snaker_pos[i].pos_x                     && tmp.pos_y == snaker_pos[i].pos_y)                 is_eaten = EATEN_SELF;         }      }     if (is_eaten != EATEN_SELF) {         if (fruit_pos->pos_x == tmp.pos_x                 && fruit_pos->pos_y == tmp.pos_y) {             is_eaten = EATEN_FRUIT;             fruit_pos->pos_x = -1;             fruit_pos->pos_y = -1;         }     }      return is_eaten; }  int move_snaker(int dir, char (*map)[MAP_COL], struct pos *fruit_pos, struct pos *snaker_pos, int snaker_len) {     int is_eaten = EATING_FRUIT;      switch (dir) {         case 'w':         case 'W':             if (snaker_pos[0].pos_x > snaker_pos[1].pos_x)                 break;             if (snaker_pos[0].pos_x <= 0)                 break;             change_snaker_body(snaker_pos, snaker_len);             /*                tmp = snaker_pos[0];                for (i = 1; i < snaker_len; i++) {                snaker_pos[i] = tmp;                if (i+1 < snaker_len)                tmp = snaker_pos[i+1];                }                */             snaker_pos[0].pos_x -= 1;             is_eaten = check_snaker_status(snaker_pos, snaker_len, fruit_pos);             /*             if (fruit_pos->pos_x == snaker_pos[0].pos_x                     && fruit_pos->pos_y == snaker_pos[0].pos_y) {                 is_eaten = 1;                 fruit_pos->pos_x = -1;                 fruit_pos->pos_y = -1;             }             */             break;          case 's':         case 'S':             if (snaker_pos[0].pos_x < snaker_pos[1].pos_x)                 break;             if (snaker_pos[0].pos_x >= MAP_ROW - 1)                 break;             change_snaker_body(snaker_pos, snaker_len);             /*             tmp = snaker_pos[0];             for (i = 1; i < snaker_len; i++) {                 snaker_pos[i] = tmp;                 if (i+1 < snaker_len)                     tmp = snaker_pos[i+1];             }             */             snaker_pos[0].pos_x += 1;             is_eaten = check_snaker_status(snaker_pos, snaker_len, fruit_pos);             /*             if (fruit_pos->pos_x == snaker_pos[0].pos_x                     && fruit_pos->pos_y == snaker_pos[0].pos_y) {                 is_eaten = 1;                 fruit_pos->pos_x = -1;                 fruit_pos->pos_y = -1;             }             */             break;          case 'a':         case 'A':             if (snaker_pos[0].pos_y > snaker_pos[1].pos_y)                 break;             if (snaker_pos[0].pos_y <= 0)                 break;             change_snaker_body(snaker_pos, snaker_len);             /*             tmp = snaker_pos[0];             for (i = 1; i < snaker_len; i++) {                 snaker_pos[i] = tmp;                 if (i+1 < snaker_len)                     tmp = snaker_pos[i+1];             }             */             snaker_pos[0].pos_y -= 1;             is_eaten = check_snaker_status(snaker_pos, snaker_len, fruit_pos);             /*             if (fruit_pos->pos_x == snaker_pos[0].pos_x                     && fruit_pos->pos_y == snaker_pos[0].pos_y) {                 is_eaten = EATEN_FRUIT;                 fruit_pos->pos_x = -1;                 fruit_pos->pos_y = -1;             }             */             break;          case 'd':         case 'D':             if (snaker_pos[0].pos_y < snaker_pos[1].pos_y)                 break;             if (snaker_pos[0].pos_y >= MAP_COL-1)                 break;             change_snaker_body(snaker_pos, snaker_len);             /*             tmp = snaker_pos[0];             for (i = 1; i < snaker_len; i++) {                 snaker_pos[i] = tmp;                 if (i+1 < snaker_len)                     tmp = snaker_pos[i+1];             }             */             snaker_pos[0].pos_y += 1;             is_eaten = check_snaker_status(snaker_pos, snaker_len, fruit_pos);             /*             if (fruit_pos->pos_x == snaker_pos[0].pos_x                     && fruit_pos->pos_y == snaker_pos[0].pos_y) {                 is_eaten = 1;                 fruit_pos->pos_x = -1;                 fruit_pos->pos_y = -1;             }             */             break;          default:             break;     }     system("clear");     draw_map(map, fruit_pos, snaker_pos, snaker_len);     show_map(map, MAP_ROW, MAP_COL);      return is_eaten; }    int main(void) {     char map[MAP_ROW][MAP_COL];     struct pos snaker_pos[SNAKER_BODY_LEN] = {{9, 9}, {8, 9}};     struct pos fruit_pos;     int ret = 0;     char dir;      add_fruit(&fruit_pos, snaker_pos, SNAKER_BODY_LEN);     //printf("fruit pos: x = %d, y = %d\n", fruit_pos.pos_x, fruit_pos.pos_y);     draw_map(map, &fruit_pos, snaker_pos, SNAKER_BODY_LEN);     show_map(map, MAP_ROW, MAP_COL);      while (1) {         printf("w(W)->up, s(S)->down, a(A)->left, d(D)->right:\n");         ret = scanf("%c", &dir);         getchar();         while (ret != 1) {             ret = scanf("%c", &dir);             getchar();         }         ret = move_snaker(dir, map, &fruit_pos, snaker_pos, SNAKER_BODY_LEN);         if (ret) {             if (ret == EATEN_SELF) {                 printf("Game over!\n");                 break;             }             system("clear");             add_fruit(&fruit_pos, snaker_pos, SNAKER_BODY_LEN);             draw_map(map, &fruit_pos, snaker_pos, SNAKER_BODY_LEN);             show_map(map, MAP_ROW, MAP_COL);         }     }     return 0; }  一个简单的贪吃蛇游戏，相互学习～

user: user-3
content: 仅供参考：#include <conio.h> #include <windows.h>  void ConPrintAt(int x, int y, char *CharBuffer, int len) {    DWORD count;    COORD coord = {x, y};    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    SetConsoleCursorPosition(hStdOut, coord);    WriteConsole(hStdOut, CharBuffer, len, &count, NULL); } void HideTheCursor() {    CONSOLE_CURSOR_INFO cciCursor;    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if(GetConsoleCursorInfo(hStdOut, &cciCursor))    {       cciCursor.bVisible = FALSE;       SetConsoleCursorInfo(hStdOut, &cciCursor);    } }  void ShowTheCursor() {    CONSOLE_CURSOR_INFO cciCursor;    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if(GetConsoleCursorInfo(hStdOut, &cciCursor))    {       cciCursor.bVisible = TRUE;       SetConsoleCursorInfo(hStdOut, &cciCursor);    } } void GetWH(int *w,int *h) {     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     CONSOLE_SCREEN_BUFFER_INFO csbi;     if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {         *w=csbi.srWindow.Right;         *h=csbi.srWindow.Bottom;     } else {         *w=80;         *h=25;     } } void ClearConsole() {    //Get the handle to the current output buffer...    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    //This is used to reset the carat/cursor to the top left.    COORD coord = {0, 0};    //A return value... indicating how many chars were written    //   not used but we need to capture this since it will be    //   written anyway (passing NULL causes an access violation).    DWORD count;    //This is a structure containing all of the console info    // it is used here to find the size of the console.    CONSOLE_SCREEN_BUFFER_INFO csbi;    //Here we will set the current color    if(GetConsoleScreenBufferInfo(hStdOut, &csbi))    {       //This fills the buffer with a given character (in this case 32=space).       FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);       FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);       //This will set our cursor position for the next print statement.       SetConsoleCursorPosition(hStdOut, coord);    } }  int main() {     unsigned short k;     int x,y,w,h;     char d;      SetConsoleOutputCP(437);     ClearConsole();     GetWH(&w,&h);     x=w/2;y=h/2;     HideTheCursor();     ConPrintAt(x,y,"O",1);     d='o';     while (1) {         Sleep(50);         if (kbhit()) {             k=getch();             if (27==k) break;//按Esc键退出             if (0==k||0xe0==k) k|=getch()<<8;//非字符键             switch (k) {                 case 0x48e0:case 0x04800://上                     d='u';                     if (y>0) {                         ConPrintAt(x,y," ",1);                         y--;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 0x50e0:case 0x05000://下                     d='d';                     if (y<h) {                         ConPrintAt(x,y," ",1);                         y++;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 0x4be0:case 0x04b00://左                     d='l';                     if (x>0) {                         ConPrintAt(x,y," ",1);                         x--;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 0x4de0:case 0x04d00://右                     d='r';                     if (x<w-1) {                         ConPrintAt(x,y," ",1);                         x++;                         ConPrintAt(x,y,"O",1);                     }                 break;             } //          cprintf("%04x pressed.\r\n",k);         } else {             switch (d) {                 case 'u':                     if (y>0) {                         ConPrintAt(x,y," ",1);                         y--;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 'd':                     if (y<h) {                         ConPrintAt(x,y," ",1);                         y++;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 'l':                     if (x>0) {                         ConPrintAt(x,y," ",1);                         x--;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 'r':                     if (x<w-1) {                         ConPrintAt(x,y," ",1);                         x++;                         ConPrintAt(x,y,"O",1);                     }                 break;             }         }     }     ClearConsole();     ShowTheCursor();     return 0; }

user: user-4
content: 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

user: user-5
content: 画蛇添足了....那个LastKey和 switch可以不要的...   直接改s[0]就行了....... 你看着改吧.....估计你还要加好多功能进去，比如吃水果变长，得分数...然后水果一次 刷几个...碰边刷新对面或者死掉..碰自己死掉..另外屏幕闪得有点不舒服....

user: user-5
content: 我复制你的代码试了一下，然后根据自己知道的说些看法---我也是自学的，很多东西不懂： 首先char s[2]; scanf("%1s", s); 无法得到你想要的 s,直接导致   MoveSnake(s, gm, len, x, y, &fcount, &fx, &fy) 中几个判断都无效果，然后无反应----这个我试了，在 MoveSnake中多加了一个 else 之后 ，就能看出来。  所以我改了下 //打印棋谱  	PrintGameMap(gm, len, x, y, fcount, fx, fy); 	char *s; 	while (1) {        printf("输入W:向上，S:向下，A:向左，D:向右\n"); 		char c;         	c = std::cin.get();                 s = new char[2]; 		s[0] = c; 		s[1] = 0; 	//	scanf_s("%s", c); 		 		//printf(s); 		//移动蛇  		MoveSnake(s, gm, len, x, y, &fcount, &fx, &fy); 		delete[]s;  就是只改最后的一点点，可以按键，敲回车后走动了，但是bug还是很多。因为 std::cin.get();是等待按键的，要敲回车才开始工作..所以wwwww 回车 它会向上爬5格然后等待继续。  所以  你应该有一个计时的东东，直接判断时间到了不管你按没按键，或者按错了键，都要走，然后根据俩个时间段之间的最后按键 判断走向。   然后我就 #include<window.h> 加了一个 判断按键的 bool jiancha(char a){ 	if (GetAsyncKeyState(a) & 0x8000) 	{ 	 return true; 	}  else{ 	 return false;  } 改动了	//打印棋谱      PrintGameMap(gm, len, x, y, fcount, fx, fy); 	int LastTime = GetTickCount();         char *s; 	int Lastkey = 1; 	while (1) { 		 	 		if (jiancha('W')){ 			Lastkey = 1; 		} 		if (jiancha('A')){ 			Lastkey = 2; 		} 		if (jiancha('S')){ 			Lastkey = 3; 		} 		if (jiancha('D')){ 			Lastkey = 4; 		} 		if (GetTickCount() - LastTime >= 1000){ 		LastTime = GetTickCount();  		s = new char[2]; 		switch (Lastkey)  		{ 		case 1: 			s[0] = 'w'; 			break; 		case 2: 			s[0] = 'a'; 			break; 		case 3: 			s[0] = 's'; 			break; 		case 4: 			s[0] = 'd'; 			break; 		default: 			break; 		} 		s[1] = 0; 		MoveSnake(s, gm, len, x, y, &fcount, &fx, &fy); 		printf("输入W:向上，S:向下，A:向左，D:向右\n"); 		delete[]s; 		Sleep(20); }  	} 	return 0;  这样以后会动，会有按键反应，但是还有很多问题，1 靠边就没了，2吃掉水果，蛇离开，水果会刷原地。3：吃掉水果仅仅是吃掉水果....没啥意义。