#include <stdio.h>
//#include <easyx.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <time.h>
//#include <graphics.h>
// 游戏设置
#define WIDTH 30
#define HEIGHT 20
#define SPEED 150
// 方向枚举
typedef enum { STOP = 0, LEFT, RIGHT, UP, DOWN } Direction;
// 蛇的结构体
typedef struct
{
int x, y;
} Segment;
// 游戏结构
typedef struct
{
bool gameOver;//结束
Direction dir;
Segment* snake;
int snakeLength;//蛇身长度
int foodX, foodY;//食物坐标
int score;//得分
} Game0;
//游戏登录界面结构
typedef struct Game
{
char num[20]; // 帐号
char name[100]; // 昵称
char password[50]; // 密码
char categoryNum[20]; // 分类号
int sorce; // 出版单位
struct Game* next; // 链表指针
} Game;
Game* head = NULL; // 链表头指针
const char* FILE_NAME = "games.dat"; // 数据文件名
// 释放资源
void cleanupGame(Game0* game)
{
free(game->snake);
}
// 释放所有内存
static void freeAllGames()
{
Game* p = head;
while (p != NULL)
{
Game* temp = p;
p = p->next;
free(temp);
}
head = NULL;
}
static void loadFile()
{
FILE* fp = fopen(FILE_NAME, "rb");
if (fp == NULL)
{
printf("未找到数据文件,将创建新文件。\n");
return;
}
freeAllGames();// 释放原有链表
// 读取文件数据
Game* newGame;
while ((newGame = (Game*)malloc(sizeof(Game))) != NULL)
{
if (fread(newGame, sizeof(Game), 1, fp) == 1)
{
newGame->next = NULL;
if (head == NULL)
{
head = newGame;
}
else
{
Game* p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = newGame;
}
}
else
{
free(newGame);
break;
}
}
fclose(fp);
printf("已从文件加载%d条游戏记录...\n", head ? 1 : 0); // 简化计数
}
// 保存数据到文件
static void saveFile()
{
FILE* fp = fopen(FILE_NAME, "wb");
if (fp == NULL)
{
printf("无法创建文件!\n");
return;
}
Game* p = head;
while (p != NULL)
{
fwrite(p, sizeof(Game), 1, fp);
p = p->next;
}
fclose(fp);
}
static Game* createNewGame()
{
Game* newGame = (Game*)malloc(sizeof(Game));
if (newGame == NULL)
{
printf("内存分配失败!\n");
exit(1);
}
newGame->next = NULL;
return newGame;
}
static void menu()
{
system("cls"); // 清屏
printf("***** 贪吃蛇 *****\n");
printf("1. 注册\n");
printf("2. 排行榜\n");
printf("3. 开始游戏\n");
printf("4. 登录\n");
printf("5. 修改玩家信息\n");
printf("6. 账号注销\n");
printf("7. 退出游戏\n");
printf("****************************\n");
}
static void input()
{
system("cls");
printf("===== 注册 =====\n");
Game* newaccount = createNewGame();
printf("请输入帐号: ");
fgets(newaccount->num, 20, stdin);
newaccount->num[strcspn(newaccount->num, "\n")] = 0; // 去除换行符
printf("请输入游戏昵称: ");
fgets(newaccount->name, 100, stdin);
newaccount->name[strcspn(newaccount->name, "\n")] = 0;
printf("请输入密码: ");
fgets(newaccount->password, 50, stdin);
newaccount->password[strcspn(newaccount->password, "\n")] = 0;
getchar(); // 吸收换行符
// 添加到链表尾部
if (head == NULL)
{
head = newaccount;
}
else
{
Game* p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = newaccount;
}
saveFile(); // 保存到文件
printf("注册成功!\n");
}
//登录
void logon()
{
system("cls");
printf("===== 玩家登录 =====\n");
if (head == NULL)
{
printf("暂无玩家信息!\n");
return;
}
char num[100];
char password[100];
printf("请输入玩家账号: ");
fgets(num, 100, stdin);
num[strcspn(num, "\n")] = 0; // 去除换行符
printf("请输入玩家密码: ");
fgets(password, 100, stdin);
password[strcspn(password, "\n")] = 0; // 去除换行符
Game* p = head;
while (p != NULL)
{
if (strcmp(p->num, num) == 0)
if(strcmp(p->password, password)==0)
{
printf("欢迎进入游戏:%s\n", p->name);
// 保存到文件
saveFile();
printf("登录成功!\n");
return;
}
p = p->next;
}
printf("账号或密码错误!\n");
}
// 修改玩家信息
void modify()
{
system("cls");
printf("===== 玩家信息修改 =====\n");
if (head == NULL)
{
printf("暂无玩家信息!\n");
return;
}
char name[100];
printf("请输入要修改的玩家账号: ");
fgets(name, 100, stdin);
name[strcspn(name, "\n")] = 0; // 去除换行符
Game* p = head;
while (p != NULL)
{
if (strcmp(p->name, name) == 0)
{
printf("找到玩家:%s\n", p->name);
printf("请输入新的帐号(%s): ", p->num);
fgets(p->num, 20, stdin);
p->num[strcspn(p->num, "\n")] = 0;
printf("请输入新的昵称(%s): ", p->name);
fgets(p->name, 100, stdin);
p->name[strcspn(p->name, "\n")] = 0;
printf("请输入新的密码(%s): ", p->password);
fgets(p->password, 50, stdin);
p->password[strcspn(p->password, "\n")] = 0;
getchar(); // 吸收换行符
saveFile(); // 保存到文件
printf("玩家信息修改成功!\n");
return;
}
p = p->next;
}
printf("未找到昵称为\"%s\"的玩家\n", name);
}
//注销账号
void deleteinform()
{
system("cls");
printf("===== 注销账号 =====\n");
if (head == NULL)
{
printf("暂无玩家信息!\n");
return;
}
char num[100];
printf("请输入要删除的玩家账号: ");
fgets(num, 100, stdin);
num[strcspn(num, "\n")] = 0; // 去除换行符
Game* p = head;
Game* prev = NULL;
while (p != NULL)
{
if (strcmp(p->num, num) == 0)
{
// 找到要删除的节点
if (prev == NULL)
{
head = p->next;// 删除头节点
}
else
{
prev->next = p->next;// 删除中间或尾节点
}
printf("已删除玩家:%s的账号\n", p->name);
free(p); // 释放内存
saveFile(); // 保存到文件
return;
}
prev = p;
p = p->next;
}
printf("未找到账号为\"%s\"的玩家!\n", num);
}
//排行榜
void charts()
{
int i=0;
system("cls");
printf("===== 排行榜 =====\n");
if (head == NULL)
{
printf("暂无玩家信息!\n");
return;
}
printf("%-15s %-30s %-20s %-15s\n","排名", "帐号", "玩家名", "玩家得分");
printf("------------------------------------------------\n");
Game* p = head;
while (p != NULL)
{
i++;
printf("%-15d %-30s %-20s %-15s\n",i, p->num, p->name, p->password);
p = p->next;
}
}
// 初始化游戏
void initGame(Game0* game)
{
game->gameOver = false;
game->dir = STOP;
game->score = 0;
game->snakeLength = 3;
// 分配蛇身内存
game->snake = (Segment*)malloc(sizeof(Segment) * (WIDTH * HEIGHT));
if (!game->snake)
{
printf("内存分配失败!\n");
exit(1);
}
// 初始化蛇身位置
for (int i = 0; i < game->snakeLength; i++)
{
game->snake[i].x = WIDTH / 2 - i;
game->snake[i].y = HEIGHT / 2;
}
srand(time(0));// 生成食物
game->foodX = rand() % (WIDTH - 2) + 1;
game->foodY = rand() % (HEIGHT - 2) + 1;
}
// 生成食物
void generateFood(Game0* game)
{
bool valid;
do
{
valid = true;
game->foodX = rand() % (WIDTH - 2) + 1;
game->foodY = rand() % (HEIGHT - 2) + 1;
// 确保食物不在蛇身上
for (int i = 0; i < game->snakeLength; i++)
{
if (game->snake[i].x == game->foodX && game->snake[i].y == game->foodY)
{
valid = false;
break;
}
}
} while (!valid);
}
// 输入处理
void processInput(Game0* game)
{
if (_kbhit())
{
switch (_getch())
{
case 'a': if (game->dir != RIGHT) game->dir = LEFT; break;
case 'd': if (game->dir != LEFT) game->dir = RIGHT; break;
case 'w': if (game->dir != DOWN) game->dir = UP; break;
case 's': if (game->dir != UP) game->dir = DOWN; break;
case 'x': game->gameOver = true; break;
}
}
}
// 检查碰撞
void checkCollision(Game0* game)
{
// 撞墙检测
if (game->snake[0].x <= 0 || game->snake[0].x >= WIDTH - 1 ||game->snake[0].y <= 0 || game->snake[0].y >= HEIGHT - 1)
{
game->gameOver = true;
}
// 自撞检测
for (int i = 1; i < game->snakeLength; i++)
{
if (game->snake[0].x == game->snake[i].x && game->snake[0].y == game->snake[i].y)
{
game->gameOver = true;
}
}
}
// 更新游戏状态
void updateGame(Game0* game)
{
if (game->dir == STOP) return;
// 保存尾部位置
int tailX = game->snake[game->snakeLength - 1].x;
int tailY = game->snake[game->snakeLength - 1].y;
// 移动蛇身(从尾部到头部)
for (int i = game->snakeLength - 1; i > 0; i--)
{
game->snake[i] = game->snake[i - 1];
}
//方向
switch (game->dir)
{
case LEFT: game->snake[0].x--; break;
case RIGHT: game->snake[0].x++; break;
case UP: game->snake[0].y--; break;
case DOWN: game->snake[0].y++; break;
}
// 检查是否吃到食物
if (game->snake[0].x == game->foodX && game->snake[0].y == game->foodY)
{
game->score += 10;
// 增加蛇身长度
game->snakeLength++;
game->snake[game->snakeLength - 1].x = tailX;
game->snake[game->snakeLength - 1].y = tailY;
generateFood(game);
}
// 检查碰撞
checkCollision(game);
}
//游戏
void drawGame(Game0* game)
{
system("cls");
// 上边界
for (int i = 0; i < WIDTH; i++)
printf("#");
printf("\n");
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
{
// 绘制左右边界
if (x == 0 || x == WIDTH - 1)
{
printf("#");
}
// 绘制蛇头
else if (x == game->snake[0].x && y == game->snake[0].y)
{
printf("O");
}
// 绘制蛇身
else
{
bool isBody = false;
for (int i = 1; i < game->snakeLength; i++)
{
if (x == game->snake[i].x && y == game->snake[i].y)
{
printf("o");
isBody = true;
break;
}
}
// 绘制食物
if (!isBody)
{
if (x == game->foodX && y == game->foodY)
printf("F");
else
printf(" ");
}
}
}
printf("\n");
}
// 下边界
for (int i = 0; i < WIDTH; i++)
printf("#");
printf("\n");
// 显示分数
printf("分数: %d\n", game->score);
printf("按 'x' 退出游戏\n");
}
int main()
{
//initgraph(1000, 1000);//500x500的图形窗口
//cleardevice();
//settextstyle(20,0,"宋体");
/*outtextxy(500, 500, L"登录:");
int ch = _getch();
if(ch==119)//w
cleardevice();
while (1)
{
setlinecolor(WHITE);
setfillcolor(WHITE);
rectangle(0, 0, 200, 200);
}
*/
//system("cls");
loadFile(); // 程序启动时加载数据
char n;//选项
char b;
while (1)
{
menu();
printf("请输入功能序号: ");
scanf("%c", &n);
getchar();
if(0<=(n-'0')&&(n-'0')<10)
switch (n-'0')
{
case 1: input(); break;
case 2: charts(); break;
case 3: game:
char cmd[50];
printf("mode con cols=%d lines=%d", WIDTH, HEIGHT + 5);
system(cmd);
Game0 game;
initGame(&game);
while (!game.gameOver)
{
drawGame(&game);
processInput(&game);
updateGame(&game);
Sleep(SPEED);
}
printf("\n游戏结束! 最终分数: %d\n", game.score);
cleanupGame(&game);
system("pause");
break;
case 4: logon();
printf("是否进入游戏\n是'y' 否'n'\n");
scanf("%c",&b);
if(b=='y')
goto game;
else if(b=='n')
break;
case 5: modify(); break;
case 6: deleteinform(); break;
case 7:
freeAllGames();
printf("感谢使用!\n");
return 0;
default:
printf("该功能不存在,请重新选择!\n");
}
else
printf("输入错误,请重新选择!\n");
printf("\n按任意键继续...");
getch();
}
return 0;
}
将得分数据score存入结构体sorce中