本文最后更新于7 天前,其中的信息可能已经过时,如有错误请发送评论
前言
有很长一段时间没有发文章了,因为在玩游戏,然后就是做游戏逆向,朋友想搞一个愤怒的小鸟的全通关的破解,然后我废了几天时间帮他做了一个,思路主要是直装(调用so文件,写入全通关存档),然后版本改大,去除更新弹窗,大概花了3,4天,也就是上一篇文章,然后忙完之后又学习了一下C语言
主要是为后续学习逆向打基础,然后学习C语言看的是b站林粒粒的3小时入门C的视频,看完之后又看了黑马程序员的课程,因为我已经有两个语言的学习经历,学习C还是很快的,简单的了解了语法,就一路速通,然后今天已经把结构体学习完毕,因为朋友的教程说是到结构体就够了,所以我也没打算继续看了,然后为了检验学习成果,打算写一个贪吃蛇练练手
我曾经的一个朋友告诉我,当你学习一门语言后想要精进,可以尝试先写个贪吃蛇,当贪吃蛇能够写出来,再去写其他的项目,就更容易得心应手,于是有了这篇文章
代码
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
// 使用宏定义地图宽高
#define map_width 80
#define map_height 25
// 定义墙壁的符号
#define wall '#'
// 定义空地的符号
#define empty ' '
// 定以蛇头的字符
#define Shead '@'
// 定义蛇身的字符
#define Sbody '0'
// 定义食物的字符
#define Sfood '*'
// 使用枚举定义上下左右的整形常量
enum Direction {up,down,left,right};
// 存储地图的二位数组
char GameMap[map_height][map_width];
// 初始化地图
void inItMap() {
for (int i=0;i < map_height;i++) {
for (int j=0;j < map_width;j++) {
if (i == 0 || i == map_height - 1) {
GameMap[i][j] = wall;
}
else if (j == 0 || j == map_width - 1) {
GameMap[i][j] = wall;
}
else {
GameMap[i][j] = empty;
}
}
}
}
// 加载地图
void loadingMap() {
for (int i=0;i<map_height;i++) {
for (int j=0;j<map_width;j++) {
printf("%c",GameMap[i][j]);
}
printf("\n");
}
}
// 定义蛇身的结构体
typedef struct {
int x;
int y;
}Body;
// 定义整条蛇
typedef struct {
Body head;
Body body[100];
int len;
enum Direction dir;
}Snack;
// 定义食物
typedef struct {
int x;
int y;
}Food;
// 初始化蛇
void inItSnack(Snack *snack) {
(*snack).head.x = map_width / 2;
(*snack).head.y = map_height / 2;
(*snack).len = 3;
(*snack).body[0].x = (*snack).head.x;
(*snack).body[0].y = (*snack).head.y + 1;
(*snack).body[1].x = (*snack).head.x;
(*snack).body[1].y = (*snack).head.y + 2;
(*snack).dir = up;
}
// 画出蛇
void drawSnack(Snack *snack) {
GameMap[((*snack).head.y)][((*snack).head.x)] = Shead;
for (int i=0;i < (((*snack).len) - 1);i++) {
GameMap[((*snack).body[i].y)][((*snack).body[i].x)] = Sbody;
}
}
// 移动蛇
void moveSnack(Snack *snack) {
int oldHeadX = (*snack).head.x;
int oldHeadY = (*snack).head.y;
for (int i=((*snack).len-2);i > 0;i--) {
(*snack).body[i].x = (*snack).body[i-1].x;
(*snack).body[i].y = (*snack).body[i-1].y;
}
(*snack).body[0].x = oldHeadX;
(*snack).body[0].y = oldHeadY;
switch ((*snack).dir) {
case up:
(*snack).head.y -= 1;
break;
case down:
(*snack).head.y += 1;
break;
case left:
(*snack).head.x -= 1;
break;
case right:
(*snack).head.x += 1;
break;
}
}
// 控制方向
void control(Snack *snack) {
int res = (_kbhit()) ? (_getch()) : 0;
res = (res == 224) ? (_getch()) : res;
int tempDir;
int current = (*snack).dir;
switch (res) {
case 'w':
case 'W':
case 72:
tempDir = up;
break;
case 's':
case 'S':
case 80:
tempDir = down;
break;
case 'a':
case 'A':
case 75:
tempDir = left;
break;
case 'd':
case 'D':
case 77:
tempDir = right;
break;
default:
tempDir = current;
}
if (!(
(current == up && tempDir == down) ||
(current == down && tempDir == up) ||
(current == left && tempDir == right) ||
(current == right && tempDir == left) ))
{
(*snack).dir = tempDir;
}
}
// 生成食物
Food setFood() {
Food temp;
temp.x = rand() % (map_width - 2) + 1;
temp.y = rand() % (map_height - 2) + 1;
return temp;
}
// 在地图内初始化食物
void inItFood(Food foods[],int len) {
for (int i=0;i<len;i++) {
foods[i] = setFood();
}
}
// 画出食物
void drawfood(Food foods[],int len) {
for (int i=0;i < len;i++) {
GameMap[foods[i].y][foods[i].x] = Sfood;
}
}
// 检查食物被吃
void checkEatFood(Snack *snack,Food foods[],int foods_len) {
for (int i=0;i<foods_len;i++) {
if (((*snack).head.x == foods[i].x) && ((*snack).head.y == foods[i].y))
{
(*snack).len += 1;
foods[i] = setFood();
}
}
}
// 检查蛇头是否撞墙
int checkHitWall(Snack *snack) {
return ((*snack).head.x == 0 ||
(*snack).head.x == map_width - 1) ||
((*snack).head.y == 0 ||
(*snack).head.y == map_height - 1);
}
// 检查蛇头是否撞到自身
int checkHitSelf(Snack* snack) {
for (int i=1;i<((*snack).len - 1);i++) {
if ((((*snack).head.x == (*snack).body[i].x) && ((*snack).head.y == (*snack).body[i].y))) {
return 1;
}
}
return 0;
}
// 把光标移动到左上角
void gotoTopLeft() {
HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = {0,0};
SetConsoleCursorPosition(hout,pos);
}
// 游戏主入口
int main() {
srand(time(NULL));
Snack snack;
inItSnack(&snack);
Food foods[20];
int foods_len = sizeof(foods) / sizeof(Food);
inItFood(foods,foods_len);
while(1) {
inItMap();
control(&snack);
checkEatFood(&snack,foods,foods_len);
moveSnack(&snack);
if (checkHitWall(&snack) || checkHitSelf(&snack)) {
puts("Game Over...");
break;
}
drawfood(foods,foods_len);
drawSnack(&snack);
gotoTopLeft();
loadingMap();
Sleep(100);
}
return 0;
}
因为没有做过游戏,所以思路方面还是问了几下ai,代码方面都是自己写的,所以可能并不是很完美,但是基本上都没什么问题




