读万卷书,行万里路——木子成
/*********************************************** map数组:二维矩阵值-1为游戏墙 map数组:二维矩阵值1为蛇头 map数组:二维矩阵值2为蛇身 map数组:二维矩阵值3为食物 程序同一运行多次游戏时会暂停3秒 吃到一个食物,蛇移动速度加快,最快速度有阈值 方向键英文小写输入有效 屏幕最大化体验最佳 上:w、下:s、左:a、右:d 暂停:q、退出游戏 *************************************************/main.c
#include<windows.h> void pr_map(); //打印墙 void pr_startG(); //打印游戏开始界面 void deal_key(); //处理按键响应 void init_map(); //初始化游戏数据 void wait_start(); char Pause = 0; //游戏暂停开关 char GameStart = 0; //撞墙标识 void main() { init_game(); //初始化游戏数据 while (1) if (!GameStart) //游戏未开始界面 { pr_start(); //打印游戏开始界面 wait_start(); } else //游戏开始界面 { deal_key(); //响应按键 if (!Pause) { pr_game(); //打印游戏界面 update_snake();//更新地图 } } }init.c
#include<time.h> #include<stdlib.h> #define up 'w' #define down 's' #define left 'a' #define right 'd' #define M 24 #define snake_size 3 int map[M][M]; extern char dir_key; extern char down_key; extern int speed; extern int score; void update_food(); typedef struct Snakes { int x; int y; struct Snakes* next; }snake; snake* head; //初始化地图 void init_game() { snake* p = (snake*)malloc(sizeof(snake)); head = (snake*)malloc(sizeof(snake)); p = head; srand((int)time(NULL)); //女娲在此播下随机种子 //蛇头位置 int i, j; int x = rand() % (M / 2) + 3; int y = rand() % (M / 2) + 3; //循环进行游戏初始化 for (i = 0; i < M; i++) for (j = 0; j < M; j++) map[i][j] = 0; speed = 200; score = 0; //食物总在蛇头右下方 update_food(); //随机贪食蛇位置、方向 if (x < y) //蛇身横向 { for (i = 0; i < snake_size; i++) if (i == 0) { map[x][y] = 1; head->x = x; head->y = y; } else { map[x - i][y] = 2; snake* q = (snake*)malloc(sizeof(snake)); p->next = q; q->x = x - i; q->y = y; p = q; p->next = NULL; } dir_key = right; //初始化蛇移动方向 } else //蛇身纵向 { for (i = 0; i < snake_size; i++) if (i == 0) { map[x][y] = 1; head->x = x; head->y = y; } else { map[x][y - i] = 2; snake* q = (snake*)malloc(sizeof(snake)); p->next = q; q->x = x; q->y = y - i; p = q; p->next = NULL; } dir_key = down; } //标记游戏墙,数组外围一圈 for (i = 0; i < M; i++) for (j = 0; j < M; j++) if (i == 0 || i == M - 1 || j == 0 || j == M - 1) map[i][j] = -1; }function.c
#include<stdlib.h> #include<conio.h> #include<windows.h> #define up 'w' #define down 's' #define left 'a' #define right 'd' #define stop 'q' #define out 'p' #define M 24 //游戏地图尺寸 void pr_map(); void init_game(); typedef struct Snakes { int x; int y; struct Snakes* next; }snake; extern int map[M][M]; extern snake* head; extern char GameStart; extern char Pause; char key[4] = { up, down, left, right }; //方便处理蛇移动是否反向,反向不响应,并且游戏正常 char dir_key; char down_key; int score = 0; //游戏得分 int speed = 200; //蛇移动速度 //移动光标 void gotoxy(int x, int y) { COORD pos; HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); pos.X = x; pos.Y = y; SetConsoleCursorPosition(hOutput, pos); // 隐藏光标 CONSOLE_CURSOR_INFO cursor; cursor.bVisible = FALSE; cursor.dwSize = sizeof(cursor); SetConsoleCursorInfo(hOutput, &cursor); } //添加食物 void update_food() { int x, y; while (1) { x = 1 + rand() % (M - 2); y = 1 + rand() % (M - 2); if (map[x][y] == 0) { map[x][y] = 3; break; } } } //头部前进 void go_key() { snake* new_head = (snake*)malloc(sizeof(snake)); //分配存储空间 map[head->x][head->y] = 2; //头部变身体 switch (dir_key) { case up: new_head->x = head->x; new_head->y = head->y - 1; break; case down: new_head->x = head->x; new_head->y = head->y + 1; break; case left: new_head->x = head->x - 1; new_head->y = head->y; break; case right: new_head->x = head->x + 1; new_head->y = head->y; break; } if (map[new_head->x][new_head->y] == 3) //吃掉食物 { update_food(); score += 10; speed = (speed < 100) ? speed + 0 : speed - 50; //加快速度 } new_head->next = head; head = new_head; map[head->x][head->y] = 1; //标记头部 Sleep(speed); } //消除尾巴 void cat_tail() { snake* tail = (snake*)malloc(sizeof(snake)); tail = head; while (tail->next->next != NULL) //下一节的下一节身体存在 tail = tail->next; map[tail->next->x][tail->next->y] = 0; //消除尾巴(头部加一方式前进) free(tail->next); //释放内存 tail->next = NULL; //尾部结构指向空,方便寻找 } //更新蛇的位置 void update_snake() { switch (dir_key) { case up: if (map[head->x][head->y - 1] == 0 || map[head->x][head->y - 1] == 3) { if (map[head->x][head->y - 1] == 0) //1----如果没有吃到食物将消除尾巴 cat_tail(); //1、2顺序勿换,head更新,cat_tail()易失效 go_key(); //2----头部前进 } else if (map[head->x][head->y - 1] == -1 || map[head->x][head->y - 1] == 2) { GameStart = 0; break; } break; case down: if (map[head->x][head->y + 1] == 0 || map[head->x][head->y + 1] == 3) { if (map[head->x][head->y + 1] == 0) cat_tail(); go_key(); } else if (map[head->x][head->y + 1] == -1 || map[head->x][head->y + 1] == 2) { GameStart = 0; break; } break; case left: if (map[head->x - 1][head->y] == 0 || map[head->x - 1][head->y] == 3) { if (map[head->x - 1][head->y] == 0) cat_tail(); go_key(); } else if (map[head->x - 1][head->y] == -1 || map[head->x - 1][head->y] == 2) { GameStart = 0; break; } break; case right: if (map[head->x + 1][head->y] == 0 || map[head->x + 1][head->y] == 3) { if (map[head->x + 1][head->y] == 0) cat_tail(); go_key(); } else if (map[head->x + 1][head->y] == -1 || map[head->x + 1][head->y] == 2) { GameStart = 0; break; } break; } } //处理按键 void deal_key() { if (_kbhit()) { switch (down_key = _getch()) { case up: if (dir_key == key[1]) //反向移动指令不生效 break; dir_key = down_key; //无论此指令是否意味着撞墙,交由update_snake()函数处理 break; case down: if (dir_key == key[0]) break; dir_key = down_key; break; case left: if (dir_key == key[3]) break; dir_key = down_key; break; case right: if (dir_key == key[2]) break; dir_key = down_key; break; case out: exit(0); } if (down_key == stop) { if (Pause == 0) Pause = 1; else Pause = 0; } } } //等待用户按任意键开始游戏 void wait_start() { while (1) //等待用户按任意键开始游戏 if (_kbhit()) { GameStart = 1; //游戏开始开关打开 break; } pr_map(); //打印地图 init_game(); //同一运行程序,游戏多次进行时初始化游戏数据 }print.c
#include<stdio.h> #include<conio.h> #include<stdlib.h> #include<windows.h> #define M 24 extern map[M][M]; extern GameStart; extern score; void gotoxy(int x, int y); //打印得分 void pr_score() { if(score / 100000000 >= 1) //多判断结构意在保证得分显示居中显示框 { gotoxy(45 + 21, 4); printf("%d", score); } else if (score/1000000>=1) { gotoxy(45 + 22, 4); printf("%d", score); } else if (score / 10000 >= 1) { gotoxy(45 + 23, 4); printf("%d", score); } else if (score / 100 >= 1) { gotoxy(45 + 23, 4); printf("%d", score); } else { gotoxy(45 + 24, 4); printf("\033[40;36m%d\033[0m", score); } system("color 0E"); //这里其实是一个bug,但是无意间发现此法可让蛇身、食物、得分显示闪烁 } //打印地图 void pr_map() { system("cls"); //清除此时屏幕上显示的游戏提示 system("color 0E"); //设置屏幕颜色 for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) { if (map[i][j] == -1) { gotoxy(i * 2 + 45, j + 5); printf("■"); } } gotoxy(45 + 16, 4); printf("■"); gotoxy(45 + 32, 4); printf("■"); gotoxy(45 + 16, 3); printf("■■■■■■■■■"); } //打印游戏界面 void pr_game() { for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) { if (map[i][j] == 0) { gotoxy(i * 2 + 45, j + 5); printf(" "); } else if (map[i][j] == 1) { gotoxy(i * 2 + 45, j + 5); printf("\033[40;33m●\033[0m"); } else if (map[i][j] == 2) { gotoxy(i * 2 + 45, j + 5); printf("○"); } else if (map[i][j] == 3) { gotoxy(i * 2 + 45, j + 5); printf("\033[40;31m⊙\033[0m"); } } pr_score(); } //打印游戏未开始界面 void pr_start() { pr_map(); if(score!=0) pr_score(); gotoxy(61, 11); printf("▁▁▁▁▁▁▁▁"); gotoxy(61, 12); printf("▏请切换最大屏 ▏"); gotoxy(61, 13); printf("▔▔▔▔▔▔▔▔"); gotoxy(57, 14); printf("▁▁▁▁▁▁▁▁▁▁▁▁"); gotoxy(57, 15); printf("▏请切换英文小写输入法 ▏"); gotoxy(57, 16); printf("▔▔▔▔▔▔▔▔▔▔▔▔"); gotoxy(53, 17); printf("▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁"); gotoxy(53, 18); printf("▏上: w ▏下: s ▏左: a ▏右: d ▏"); gotoxy(53, 19); printf("▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔"); gotoxy(53, 20); printf("▏暂停:q▏ ▏退出:p▏"); gotoxy(53, 21); printf("▔▔▔▔ ▔▔▔▔"); gotoxy(58, 25); printf("▁▁▁▁▁▁▁▁▁▁▁"); gotoxy(58, 26); printf("▏请按任意键开始游戏 ▏"); gotoxy(58, 27); printf("▔▔▔▔▔▔▔▔▔▔▔"); Sleep(3000); //防止蛇撞墙后,用户按任意键立马继续游戏 }
