作者:淡淡很淡淡真淡 | 来源:互联网 | 2023-09-25 18:54
学了编程后难免会有些手痒,于是饥渴难耐的我瞄上了小学的经典记忆——贪吃蛇。
下面我就游戏的设计来逐步讲解我打造C语言版贪吃蛇的过程。这是一个系列的文章,共三篇,第一篇讲游戏的主体设计,第二篇就设计的细节及具体实现给出讲解,第三篇给出简易游戏AI的设计。
游戏中用到了Windows的库,只保证能在Windows环境下运行。
先看最终效果:
游戏地图大小为40*30,这里为了测试缩小地图到10*10大小。
可以看到游戏里有启动提示,模式选择,作弊模式,排行榜的功能模块。
下面应用自顶向下,逐步求精的设计思想来完成这条蛇。
游戏主体设计
1. 框架分析
主函数是游戏的流程,包含:
- 开始游戏
用于游戏开始的提示,只显示一次。 - 选择模式
进行难度的选择。 - 进行游戏
游戏过程的主体。 - 游戏结束
用于游戏结束的提示,每次游戏结束都显示。 - 重新开始
返回第二步。
模板如下:
int main() {startGame();while(1) {selectMode();playGame();gameOver();restart();}return 0;
}
游戏的目标就是依次实现以上函数。
2. 要素分析
贪吃蛇里需要有基础的游戏功能及排行榜模块,据此分析贪吃蛇游戏需要的要素如下:
- 地图
地图控制蛇可移动的范围,地图只要在蛇移动一步局部刷新即可。地图在开始游戏时只打印一次。 - 蛇
蛇需要储存节点的坐标以及蛇长以及蛇的速度,以一个结构体实现。 - 食物
食物在蛇吃掉后需要立即在新位置产生,需要包含食物当前坐标以及是否存在的信息,以一个结构体实现。 - 玩家
用于记录玩家信息,每次结束游戏后进行排名,需要包含玩家姓名,游戏日期,以及分数,以一个结构体实现。
可以这么定义以上要素:
struct Snake {int x[MAP_LENGTH * MAP_HIGHT];int y[MAP_LENGTH * MAP_HIGHT];int length;int speed;
};struct Food {int x;int y;int exist;
};struct Player {char name[20];char date[20];int score;
};
其中蛇的x[n], y[n] 表示蛇节点的坐标,定义最大蛇长为地图长*宽,x[0], y[0] 表示蛇头的横纵坐标。
3. 实现框架中的函数
- startGame();
游戏开始的提示,简单的printf()即可。
加入排行版时可在其中加入inputName()函数,用于获取当前玩家姓名。 - selectMode();
根据玩家输入选择蛇的速度用以调整难度。printf() 加switch 即可。
下文代码中snake.speed 是刷新时间的间隔。 - playGame();
游戏过程的主要程序,首先初始化游戏地图,然后当蛇不死时依次打印蛇,食物,蛇长(即分数),然后蛇移动,判断是否吃食物,再根据需要产生食物。 - gameOver();
游戏结束提示,可在此时打印排行榜。 - restart();
获取特定输入,重新开始游戏。
实现如下:
void startGame() {printf("贪吃蛇游戏\n\n");printf("方向键或WASD控制\n");printf("长按加速\n");printf("按空格键暂停\n\n");printf("按任意键开始游戏\n");getch();inputName();
}
void selectMode() {system("cls");printf("请选择游戏模式:\n");printf("1. easy\n");printf("2. normal\n");printf("3. hard\n");printf("4. very hard\n");printf("5. crazy\n");printf("6. go die\n");char input = getch();switch (input) {case '1':snake.speed = 600;strcpy(mode, "easy");break;case '2':snake.speed = 300;strcpy(mode, "normal");break;case '3':snake.speed = 100;strcpy(mode, "hard");break;case '4':snake.speed = 50;strcpy(mode, "very hard");break;case '5':snake.speed = 20;strcpy(mode, "crazy");break;case '6':snake.speed = 10;strcpy(mode, "go die");break;default:snake.speed = 300;strcpy(mode, "normal");break;}return;
}
void playGame() {initGame();while (!snakeDie()) {printSnake();printFood();printLength();locateCursor(0, MAP_HIGHT + 3);snakeMove();eatFood();productFood();}
}
void gameOver() {system("cls"); printf("\n\n\n\n Game over\n\n\n\n");printf("你的蛇长:printf("按空格键重玩\n\n");rank();
}
void restart() {char ch = 0;while(ch != ' ') {ch = getch();}
}
4. 具体函数的实现
为了让大家对贪吃蛇框架有个具体的了解,这里贴出头文件,具体实现下期见。
#include
#include
#include
#include
#include #define MAP_LENGTH 40
#define MAP_HIGHT 30
#define BLANK_CELL ' '
#define WALL_CELL '*'
#define INIT_SNAKE_LENGTH 3
#define SNAKE_HEAD 2
#define SNAKE_BODY 3
#define SNAKE_FOOD 1
#define UP (input == 'W' || input == 'w' || input == 72)
#define DOWN (input == 'S' || input == 's' || input == 80)
#define LEFT (input == 'A' || input == 'a' || input == 75)
#define RIGHT (input == 'D' || input == 'd' || input == 77)
#define PAUSE (input == ' ')
#define CHEAT (input == 'C' || input == 'c')void initSnake();
void initFood();
void printMap();
void printMode();
void initGame();void printSnake();
void printFood();
void printLength();void productFood();
void eatFood();int inputValid(char input);
void snakeControlMove(char input);
void snakeAutoMove();
void snakeMove();
int snakeDie();void startGame();
void selectMode();
void playGame();
void gamePause();
void gameOver();
void restart();void locateCursor(int x, int y);
void switchCursorVisible();void inputName();
void getTime();
void initRank();
void ranking(FILE * fp, struct Player player[]);
void printRank(FILE * fp, struct Player player[]);
void rank();void switchCheatMode();
void snakeSmartMove();struct Snake {int x[MAP_LENGTH * MAP_HIGHT + 1];int y[MAP_LENGTH * MAP_HIGHT + 1];int length;int speed;
};struct Food {int x;int y;int exist;
};struct Player {char name[20];char date[20];int score;
};struct Snake snake;
struct Food food;
struct Player currentPlayer;
char mode[20];
int cheat;