C语言实现:影院票务管理系统(铠甲怪兽管理系统)(详细解析+效果展示)C语言实现:影院票务管理系统(铠甲怪兽管理系统)(详细解析+效果展示)
目录
效果展示
影院票务管理系统(铠甲怪兽管理系统)
项目背景
这个项目是一个用 C 编写的台程序,原本是要求写一个影院票务管理系统,但是主播魔改了一下,改成了铠甲打怪项目:
概念对照表
| 光影铠甲概念 | 影院票务概念 | 说明 |
|---|---|---|
铠甲 (movie) |
电影 | 每个铠甲就是一部电影,有名称、类型、属性、授权价格(票价)、状态 |
怪兽 (monster) |
座位 | 封印状态表示座位是否被占用 |
场景 (MonsterScene) |
影厅 | 不同场景对应不同影厅 |
用户 (user) |
观众/管理员 | 普通用户是观众,管理员是影院管理者 |
授权/购票 (order) |
购票记录 | 用户购买铠甲授权 → 购票记录 |
出战 (battle) |
入场观影 | 铠甲出战怪兽 → 观众入场观影 |
座位矩阵 (showSeatMatrix) |
座位布局 | 可视化显示座位状态 |
属性克制 (attr) |
电影类型/座位策略 | 不同铠甲属性可克制怪兽 → 可类比座位策略或优惠策略 |
密码/登录 (login) |
用户验证 | 登录验证身份 |
注册 (reg) |
会员注册 | 新用户注册 |
数据持久化 (save/load) |
数据库 | 保存用户/电影/座位/订单信息 |
系统功能分析
用户功能
-
注册与登录
- 注册成为预备铠甲勇士(会员)
- 登录后可访问系统功能
-
浏览与搜索铠甲(电影)
- 查看所有铠甲信息
- 按名称、类型、属性搜索
-
授权/购票
- 选择铠甲(电影)
- 选择授权时长(电影时长)
- 选择座位(怪兽)和场次(影厅)
-
查看订单
- 可召唤铠甲(闲置铠甲/未出战)
- 所有授权记录显示
-
退票与密码修改
- 退未出战订单
- 修改用户登录密码
-
铠甲出战(观影)
- 铠甲属性克制怪兽(座位)
- 战斗胜利 → 封印怪兽(占座成功)
- 战斗失败 → 铠甲破损(座位被占/失败)
管理员功能
-
铠甲管理(电影管理)
- 浏览、添加、删除、修改铠甲
-
场景座位矩阵管理(影厅管理)
- 设置矩阵行列数
- 查看场景座位布局
- 修改怪兽封印状态(座位占用情况)
-
系统管理
- 查看所有用户
- 修改管理员密码
- 初始化怪兽列表(座位数据重置)
源码展示
entity.h
c
#ifndef ENTITY_H
#define ENTITY_H
#include <time.h>
typedef enum {
ARMOR_IDLE,
ARMOR_IN_BATTLE,
ARMOR_REPAIRING,
ARMOR_DAMAGED
} ArmorStatus;
typedef enum {
ATTR_FIRE,
ATTR_WATER,
ATTR_THUNDER,
ATTR_EARTH,
ATTR_WIND
} MonsterAttr;
typedef enum {
SCENE_KAI1_CITY,
SCENE_KAI1_MOUNTAIN,
SCENE_KAI1_OCEAN,
SCENE_KAI1_ANCIENT,
SCENE_KAI2_HOPE_CITY,
SCENE_KAI2_ARES,
SCENE_KAI2_OTHER
} MonsterScene;
typedef struct user {
int id;
char name[50];
char password[50];
int isAdmin;
struct user* next;
} user;
typedef struct movie {
int id;
char title[50];
float price;
char type[50];
ArmorStatus status;
MonsterAttr attr;
struct movie* next;
} movie;
typedef struct monster {
int id;
char name[50];
int level;
MonsterAttr attr;
int danger;
int isDefeated;
MonsterScene scene;
struct monster* next;
} monster;
typedef struct battleTask {
int id;
int userId;
int armorId;
int monsterId;
int status;
float matchScore;
struct battleTask* next;
} battleTask;
typedef struct {
int row;
int col;
} SceneMatrixConfig;
typedef struct order {
int id;
int userId;
int movieId;
char movieName[50];
int quantity;
float totalPrice;
int monsterId;
int battleResult;
MonsterScene scene;
time_t timestamp;
struct order* next;
} order;
#endif
dal.h
c
#ifndef DAL_H
#define DAL_H
#include "entity.h"
extern SceneMatrixConfig sceneMatrixConfig[7];
extern user* adminUser;
extern user* head;
extern user* currentUser;
extern movie* movieList;
extern monster* monsterList;
extern battleTask* battleTaskList;
extern order* orderList;
void save_to_file();
void load_from_file();
void addUser(user* newUser);
user* findUserById(int id);
user* findUserByName(const char* name);
void addMovie();
movie* findMovieById(int id);
void deleteMovie();
monster* findMonsterById(int id);
void addMonster();
void addOrder(order* newOrder);
order* findOrderById(int id);
#endif
bll.h
c
#ifndef BLL_H
#define BLL_H
#include "entity.h"
#include "dal.h"
void login();
void reg();
void changePassword();
void browseMovies();
void searchMovie();
void updateMovie();
void buyTicket();
void myOrders();
void refundTicket();
void view_all_armor();
void updateMonsterStatus();
void initMonsterList();
void browseMonster();
void searchMonsterByScene();
void battleMonster();
void showMonsterDynamicMatrix(monster* monsterListArr[], int monsterCount, MonsterScene targetScene);
void adminSetSceneMatrix();
void inputPassword(char* password, int maxLen);
const char* attrToString(MonsterAttr attr);
const char* sceneToString(MonsterScene scene);
void showSeatMatrix(MonsterScene scene);
void clearScreen();
#endif
ui.h
c
#ifndef UI_H
#define UI_H
#include "entity.h"
#include "bll.h"
void usermenu();
void adminmenu();
void formatTimestamp(time_t timestamp, char* outBuf, int bufSize);
#endif
dal.c
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "entity.h"
#include "dal.h"
#include"ui.h"
#include "bll.h"
SceneMatrixConfig sceneMatrixConfig[7] = {
{4,4}, {4,4}, {4,4}, {4,4},
{4,4}, {4,4}, {4,4}
};
user* adminUser = NULL;
user* head = NULL;
movie* movieList = NULL;
user* currentUser = NULL;
order* orderList = NULL;
monster* monsterList = NULL;
void save_to_file() {
FILE* fp = fopen("wj.txt", "w");
if (!fp) {
printf("文件打开失败\n");
return;
}
user* p = head;
while (p) {
fprintf(fp, "USER %d %s %s %d\n", p->id, p->name, p->password, p->isAdmin);
p = p->next;
}
movie* m = movieList;
while (m) {
fprintf(fp, "ARMOR %d %s %.2f %s %d %d\n",
m->id, m->title, m->price, m->type, m->attr, m->status);
m = m->next;
}
order* o = orderList;
while (o) {
fprintf(fp, "ORDER %d %d %d \"%s\" %d %.2f %d %d %ld\n",
o->id, o->userId, o->movieId, o->movieName,
o->quantity, o->totalPrice, o->monsterId,
o->battleResult, o->timestamp);
o = o->next;
}
monster* ms = monsterList;
while (ms) {
fprintf(fp, "MONSTER %d %s %d %d %d %d %d\n",
ms->id, ms->name, ms->level, ms->attr, ms->danger, ms->isDefeated, ms->scene);
ms = ms->next;
}
fclose(fp);
printf("数据保存成功(用户+铠甲+订单+怪兽)!\n");
}
void load_from_file() {
user* p1 = head; while (p1) { user* next = p1->next; free(p1); p1 = next; } head = NULL;
movie* p2 = movieList; while (p2) { movie* next = p2->next; free(p2); p2 = next; } movieList = NULL;
order* p3 = orderList; while (p3) { order* next = p3->next; free(p3); p3 = next; } orderList = NULL;
monster* p4 = monsterList; while (p4) { monster* next = p4->next; free(p4); p4 = next; } monsterList = NULL;
FILE* fp = fopen("wj.txt", "r");
if (!fp) { initMonsterList(); return; }
char type[20]; int id, isAdmin, userId, movieId, quantity, armorAttr, armorStatus, monsterId, battleResult;
int monsterLevel, monsterAttrVal, monsterDanger, isDefeated, scene;
char name[50], password[50], title[50], movieName[100], armorType[50], monsterName[50];
float price, totalPrice; long timestamp;
char line[256];
while (fscanf(fp, "%19s", type) != EOF) {
fgets(line, sizeof(line), fp);
if (strcmp(type, "USER") == 0) {
if (sscanf(line, "%d %49s %49s %d", &id, name, password, &isAdmin) == 4) {
user* u = (user*)malloc(sizeof(user));
u->id = id; strcpy(u->name, name); strcpy(u->password, password); u->isAdmin = isAdmin;
u->next = head; head = u;
}
}
else if (strcmp(type, "ARMOR") == 0) {
if (sscanf(line, "%d %49s %f %49s %d %d", &id, title, &price, armorType, &armorAttr, &armorStatus) == 6) {
movie* m = (movie*)malloc(sizeof(movie));
m->id = id; strcpy(m->title, title); strcpy(m->type, armorType); m->price = price;
m->attr = (MonsterAttr)armorAttr; m->status = (ArmorStatus)armorStatus;
m->next = movieList; movieList = m;
}
}
else if (strcmp(type, "ORDER") == 0) {
order* o = (order*)malloc(sizeof(order));
if (sscanf(line, "%d %d %d \"%49[^\"]\" %d %f %d %d %ld",
&id, &userId, &movieId, o->movieName, &quantity, &totalPrice, &monsterId, &battleResult, ×tamp) == 9) {
o->id = id; o->userId = userId; o->movieId = movieId;
o->quantity = quantity; o->totalPrice = totalPrice; o->monsterId = monsterId;
o->battleResult = battleResult; o->timestamp = (time_t)timestamp;
o->next = orderList; orderList = o;
}
else free(o);
}
else if (strcmp(type, "MONSTER") == 0) {
if (sscanf(line, "%d %49s %d %d %d %d %d", &id, monsterName, &monsterLevel, &monsterAttrVal, &monsterDanger, &isDefeated, &scene) == 7) {
monster* m = (monster*)malloc(sizeof(monster));
m->id = id; strcpy(m->name, monsterName); m->level = monsterLevel; m->attr = (MonsterAttr)monsterAttrVal;
m->danger = monsterDanger; m->isDefeated = isDefeated; m->scene = (MonsterScene)scene;
m->next = monsterList; monsterList = m;
}
}
}
fclose(fp);
if (!monsterList) initMonsterList();
printf("铠甲数据加载成功(用户/铠甲/订单/怪兽)\n");
}
const char* attrToString(MonsterAttr attr) {
switch (attr) {
case ATTR_EARTH: return "土属性";
case ATTR_WIND: return "风属性";
case ATTR_WATER: return "水属性";
case ATTR_FIRE: return "火属性";
case ATTR_THUNDER:return "雷属性";
default: return "未知属性";
}
}
const char* sceneToString(MonsterScene scene) {
switch (scene) {
case SCENE_KAI1_CITY: return "铠一-城市市区";
case SCENE_KAI1_MOUNTAIN: return "铠一-郊外山林";
case SCENE_KAI1_OCEAN: return "铠一-沿海区域";
case SCENE_KAI1_ANCIENT: return "铠一-远古遗迹";
case SCENE_KAI2_HOPE_CITY:return "铠二-希望市";
case SCENE_KAI2_ARES: return "铠二-阿瑞斯星球";
case SCENE_KAI2_OTHER: return "铠二-其他区域";
default: return "未知场景";
}
}
void initMonsterList() {
monster* temp = monsterList;
while (temp != NULL) {
monster* next = temp->next;
free(temp);
temp = next;
}
monsterList = NULL;
const struct {
int id;
const char* name;
int level;
MonsterAttr attr;
int danger;
int isDefeated;
MonsterScene scene;
} monsterData[] = {
{101, "恶参兽", 1, ATTR_EARTH, 2, 0, SCENE_KAI1_CITY},
{102, "刺木兽", 1, ATTR_EARTH, 2, 0, SCENE_KAI1_CITY},
{103, "蚱蜢兽", 1, ATTR_WIND, 3, 0, SCENE_KAI1_CITY},
{104, "魔马兽", 2, ATTR_WIND, 4, 0, SCENE_KAI1_CITY},
{105, "岩石兽", 2, ATTR_EARTH, 4, 0, SCENE_KAI1_CITY},
{106, "鳄鱼兽", 3, ATTR_WATER, 5, 0, SCENE_KAI1_CITY},
{107, "魔牛兽", 3, ATTR_EARTH, 5, 0, SCENE_KAI1_CITY},
{108, "蚂蚁兽", 2, ATTR_EARTH, 4, 0, SCENE_KAI1_CITY},
{109, "杏木兽", 3, ATTR_EARTH, 5, 0, SCENE_KAI1_CITY},
{110, "百合兽", 3, ATTR_EARTH, 5, 0, SCENE_KAI1_CITY},
{111, "脓液兽", 4, ATTR_EARTH, 6, 0, SCENE_KAI1_CITY},
{112, "恶狼兽", 5, ATTR_WIND, 7, 0, SCENE_KAI1_CITY},
{121, "苍蝇兽", 4, ATTR_WIND, 6, 0, SCENE_KAI1_MOUNTAIN},
{122, "蜘蛛兽", 4, ATTR_EARTH, 6, 0, SCENE_KAI1_MOUNTAIN},
{123, "恶蚊兽", 4, ATTR_WIND, 6, 0, SCENE_KAI1_MOUNTAIN},
{124, "蝎子兽", 5, ATTR_EARTH, 7, 0, SCENE_KAI1_MOUNTAIN},
{125, "蝴蝶兽", 5, ATTR_WIND, 7, 0, SCENE_KAI1_MOUNTAIN},
{126, "螳螂兽", 5, ATTR_WIND, 7, 0, SCENE_KAI1_MOUNTAIN},
{127, "蜈蚣兽", 6, ATTR_EARTH, 8, 0, SCENE_KAI1_MOUNTAIN},
{128, "天牛兽", 6, ATTR_WIND, 8, 0, SCENE_KAI1_MOUNTAIN},
{129, "地鼠兽", 5, ATTR_EARTH, 7, 0, SCENE_KAI1_MOUNTAIN},
{130, "魔蝉兽", 6, ATTR_WIND, 8, 0, SCENE_KAI1_MOUNTAIN},
{131, "刀疤兽", 4, ATTR_EARTH, 6, 0, SCENE_KAI1_MOUNTAIN},
{132, "毒蛾兽", 4, ATTR_WIND, 6, 0, SCENE_KAI1_MOUNTAIN},
{141, "贝壳兽", 5, ATTR_WATER, 7, 0, SCENE_KAI1_OCEAN},
{142, "乌贼兽", 6, ATTR_WATER, 8, 0, SCENE_KAI1_OCEAN},
{143, "螃蟹兽", 7, ATTR_WATER, 9, 0, SCENE_KAI1_OCEAN},
{144, "龙虾兽", 7, ATTR_WATER, 9, 0, SCENE_KAI1_OCEAN},
{145, "章鱼兽", 7, ATTR_WATER, 9, 0, SCENE_KAI1_OCEAN},
{146, "鲨鱼兽", 8, ATTR_WATER, 9, 0, SCENE_KAI1_OCEAN},
{147, "水母兽", 7, ATTR_WATER, 9, 0, SCENE_KAI1_OCEAN},
{148, "海星兽", 6, ATTR_WATER, 8, 0, SCENE_KAI1_OCEAN},
{149, "水草兽", 5, ATTR_WATER, 7, 0, SCENE_KAI1_OCEAN},
{150, "飞蛾兽", 6, ATTR_WIND, 8, 0, SCENE_KAI1_OCEAN},
{151, "海马兽", 6, ATTR_WATER, 8, 0, SCENE_KAI1_OCEAN},
{152, "海螺兽", 6, ATTR_WATER, 8, 0, SCENE_KAI1_OCEAN},
{161, "穷奇", 8, ATTR_EARTH, 9, 0, SCENE_KAI1_ANCIENT},
{162, "饕餮", 8, ATTR_FIRE, 9, 0, SCENE_KAI1_ANCIENT},
{163, "混沌", 8, ATTR_WIND, 9, 0, SCENE_KAI1_ANCIENT},
{164, "梼杌", 8, ATTR_THUNDER,9, 0, SCENE_KAI1_ANCIENT},
{165, "恶火护法", 7, ATTR_FIRE, 9, 0, SCENE_KAI1_ANCIENT},
{166, "恶水护法", 7, ATTR_WATER, 9, 0, SCENE_KAI1_ANCIENT},
{167, "恶金护法", 7, ATTR_THUNDER,9, 0, SCENE_KAI1_ANCIENT},
{168, "恶木护法", 7, ATTR_WIND, 9, 0, SCENE_KAI1_ANCIENT},
{169, "恶土护法", 7, ATTR_EARTH, 9, 0, SCENE_KAI1_ANCIENT},
{170, "黑魔兽", 9, ATTR_THUNDER,10,0, SCENE_KAI1_ANCIENT},
{171, "魔一", 8, ATTR_EARTH, 9, 0, SCENE_KAI1_ANCIENT},
{172, "魔二", 8, ATTR_FIRE, 9, 0, SCENE_KAI1_ANCIENT},
{201, "巴约比", 5, ATTR_WIND, 6, 0, SCENE_KAI2_HOPE_CITY},
{202, "巴萨帝", 5, ATTR_FIRE, 6, 0, SCENE_KAI2_HOPE_CITY},
{203, "库彼修", 5, ATTR_EARTH, 6, 0, SCENE_KAI2_HOPE_CITY},
{204, "沙古拉", 6, ATTR_EARTH, 7, 0, SCENE_KAI2_HOPE_CITY},
{205, "沙鲁克", 6, ATTR_EARTH, 7, 0, SCENE_KAI2_HOPE_CITY},
{206, "沙尔曼", 6, ATTR_EARTH, 7, 0, SCENE_KAI2_HOPE_CITY},
{207, "巴克特", 6, ATTR_WATER, 7, 0, SCENE_KAI2_HOPE_CITY},
{208, "巴库鲁", 6, ATTR_WIND, 7, 0, SCENE_KAI2_HOPE_CITY},
{209, "库克", 7, ATTR_FIRE, 8, 0, SCENE_KAI2_HOPE_CITY},
{210, "巴尔格姆", 7, ATTR_THUNDER,8, 0, SCENE_KAI2_HOPE_CITY},
{211, "巴纳雷斯", 7, ATTR_WIND, 8, 0, SCENE_KAI2_HOPE_CITY},
{212, "库拉", 8, ATTR_WATER, 9, 0, SCENE_KAI2_HOPE_CITY},
{221, "路法", 10,ATTR_THUNDER,10,0, SCENE_KAI2_ARES},
{222, "安迷修", 9, ATTR_FIRE, 9, 0, SCENE_KAI2_ARES},
{223, "乔奢费", 9, ATTR_WIND, 9, 0, SCENE_KAI2_ARES},
{224, "库忿斯", 9, ATTR_EARTH, 9, 0, SCENE_KAI2_ARES},
{225, "沙宾", 8, ATTR_EARTH, 8, 0, SCENE_KAI2_ARES},
{226, "吉拉", 7, ATTR_THUNDER,8, 0, SCENE_KAI2_ARES},
{227, "库列斯克", 7, ATTR_FIRE, 8, 0, SCENE_KAI2_ARES},
{228, "巴尔格姆", 7, ATTR_WIND, 8, 0, SCENE_KAI2_ARES},
{229, "巴纳雷斯", 7, ATTR_WATER, 8, 0, SCENE_KAI2_ARES},
{230, "库克", 7, ATTR_EARTH, 8, 0, SCENE_KAI2_ARES},
{231, "沙鲁克", 6, ATTR_FIRE, 7, 0, SCENE_KAI2_ARES},
{232, "巴库鲁", 6, ATTR_WIND, 7, 0, SCENE_KAI2_ARES},
{241, "灰冥分队杂兵",4, ATTR_FIRE, 5, 0, SCENE_KAI2_OTHER},
{242, "赤冥分队杂兵",4, ATTR_EARTH, 5, 0, SCENE_KAI2_OTHER},
{243, "蓝冥分队杂兵",4, ATTR_WIND, 5, 0, SCENE_KAI2_OTHER},
{244, "紫冥分队杂兵",4, ATTR_WATER, 5, 0, SCENE_KAI2_OTHER},
{245, "沙古拉", 6, ATTR_EARTH, 7, 0, SCENE_KAI2_OTHER},
{246, "巴克特", 6, ATTR_WATER, 7, 0, SCENE_KAI2_OTHER},
{247, "巴萨帝", 6, ATTR_FIRE, 7, 0, SCENE_KAI2_OTHER},
{248, "巴约比", 6, ATTR_WIND, 7, 0, SCENE_KAI2_OTHER},
{249, "库彼修", 7, ATTR_EARTH, 8, 0, SCENE_KAI2_OTHER},
{250, "库拉", 8, ATTR_WATER, 9, 0, SCENE_KAI2_OTHER},
{251, "安迷修", 9, ATTR_FIRE, 9, 0, SCENE_KAI2_OTHER},
{252, "修罗铠甲(受控)",10,ATTR_THUNDER,10,0,SCENE_KAI2_OTHER}
};
int monsterCount = sizeof(monsterData) / sizeof(monsterData[0]);
monster* tail = NULL;
for (int i = 0; i < monsterCount; i++) {
monster* newMonster = (monster*)malloc(sizeof(monster));
if (!newMonster) {
printf("内存分配失败!\n");
return;
}
newMonster->id = monsterData[i].id;
strcpy(newMonster->name, monsterData[i].name);
newMonster->level = monsterData[i].level;
newMonster->attr = monsterData[i].attr;
newMonster->danger = monsterData[i].danger;
newMonster->isDefeated = monsterData[i].isDefeated;
newMonster->scene = monsterData[i].scene;
newMonster->next = NULL;
if (!monsterList) {
monsterList = newMonster;
tail = newMonster;
}
else {
tail->next = newMonster;
tail = newMonster;
}
}
printf(" 怪兽列表初始化完成!共加载 %d 只原版怪兽\n", monsterCount);
}
bll.c
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "entity.h"
#include "dal.h"
#include"ui.h"
#include "bll.h"
void addMovie() {
clearScreen();
movie* newmovie = (movie*)malloc(sizeof(movie));
if (newmovie == NULL)
{
printf("分配内存失败\n");
getchar(); getchar();
clearScreen();
return;
}
int maxid = 0;
movie* p = movieList;
while (p != NULL)
{
if (p->id > maxid) maxid = p->id;
p = p->next;
}
newmovie->id = maxid + 1;
printf("添加铠甲,请输入新铠甲的名字:");
char name[50] = { 0 };
scanf("%s", name);
movie* checkMovie = movieList;
int nameExists = 0;
while (checkMovie != NULL) {
if (strcmp(checkMovie->title, name) == 0) {
nameExists = 1;
break;
}
checkMovie = checkMovie->next;
}
if (nameExists) {
printf("\n错误:名称为「%s」的铠甲已存在,无法重复添加!\n", name);
free(newmovie);
newmovie = NULL;
getchar(); getchar();
clearScreen();
return;
}
strcpy(newmovie->title, name);
printf("添加铠甲,请输入新铠甲的授权能量值:");
float money;
scanf("%f", &money);
newmovie->price = money;
printf("请输入铠甲类型(全能型/爆发型/速度型/防御型):");
scanf("%s", newmovie->type);
printf("请输入铠甲属性(1=火属性 2=水属性 3=雷属性 4=土属性 5=风属性):");
int attr;
scanf("%d", &attr);
if (attr < 1 || attr > 5) {
printf("\n❌ 错误:属性值必须是1-5!添加失败\n");
free(newmovie);
newmovie = NULL;
getchar(); getchar();
clearScreen();
return;
}
newmovie->attr = (MonsterAttr)(attr - 1);
newmovie->status = ARMOR_IDLE;
newmovie->next = movieList;
movieList = newmovie;
printf("\n 铠甲「%s」添加成功!ID:%d\n", name, newmovie->id);
save_to_file();
printf("按任意键继续。。。。。\n");
getchar(); getchar();
clearScreen();
}
void myOrders() {
clearScreen();
if (currentUser == NULL) {
printf("请先登录铠甲召唤系统后再查看授权记录!\n");
getchar(); getchar();
clearScreen();
return;
}
char orderTime[64];
order* userOrder = orderList;
int availableArmorCount = 0;
printf("\n======= 可召唤的闲置铠甲(当前可用)=======\n");
while (userOrder != NULL) {
if (userOrder->userId == currentUser->id) {
movie* armor = movieList;
while (armor != NULL) {
if (armor->id == userOrder->movieId && armor->status == ARMOR_IDLE) {
availableArmorCount++;
formatTimestamp(userOrder->timestamp, orderTime, sizeof(orderTime));
printf("订单ID: %d | 铠甲: %s | 类型: %s | 属性: %s | 时长: %d小时 | 总价: %.2f | 创建时间: %s\n",
userOrder->id, armor->title, armor->type, attrToString(armor->attr),
userOrder->quantity, userOrder->totalPrice, orderTime);
break;
}
armor = armor->next;
}
}
userOrder = userOrder->next;
}
if (availableArmorCount == 0) {
printf("暂无可召唤的闲置铠甲!\n");
}
printf("\n======= 所有铠甲授权记录(含不可用)=======\n");
userOrder = orderList;
int totalOrderCount = 0;
while (userOrder != NULL) {
if (userOrder->userId == currentUser->id) {
totalOrderCount++;
formatTimestamp(userOrder->timestamp, orderTime, sizeof(orderTime));
printf("订单ID: %d | 铠甲: %s | 场次: %s | 时长: %d小时 | 总价: %.2f | 战斗记录: %s | 创建时间: %s\n",
userOrder->id, userOrder->movieName, sceneToString(userOrder->scene),
userOrder->quantity, userOrder->totalPrice,
userOrder->battleResult == -1 ? "未出战" :
(userOrder->battleResult == 1 ? "胜利" : "失败"), orderTime);
}
userOrder = userOrder->next;
}
if (totalOrderCount == 0) {
printf("你暂无任何铠甲授权记录!\n");
}
printf("\n按任意键返回菜单...\n");
getchar(); getchar();
clearScreen();
}
void buyTicket() {
clearScreen();
if (currentUser == NULL) {
printf("请先登录系统!\n");
getchar(); getchar();
clearScreen();
return;
}
browseMovies();
int armorId, hourNum, sceneChoice;
printf("请输入要授权的铠甲ID:");
scanf("%d", &armorId);
movie* selectedArmor = movieList;
while (selectedArmor != NULL) {
if (selectedArmor->id == armorId) break;
selectedArmor = selectedArmor->next;
}
if (!selectedArmor) {
printf("未找到该铠甲!\n");
getchar(); getchar();
clearScreen();
return;
}
if (selectedArmor->status == ARMOR_IN_BATTLE || selectedArmor->status == ARMOR_DAMAGED) {
printf("该铠甲不可授权(战斗中/破损)!\n");
getchar(); getchar();
clearScreen();
return;
}
printf("请选择授权时长(小时):");
scanf("%d", &hourNum);
if (hourNum <= 0) {
printf("授权时长必须大于0!\n");
getchar(); getchar();
clearScreen();
return;
}
printf("请选择出战场次(1-7):\n");
printf("1: 铠一-城市市区 2: 铠一-郊外山林 3: 铠一-沿海区域\n");
printf("4: 铠一-远古遗迹 5: 铠二-希望市 6: 铠二-阿瑞斯星球 7: 铠二-其他区域\n");
scanf("%d", &sceneChoice);
if (sceneChoice < 1 || sceneChoice > 7) {
printf("场次选择错误!\n");
getchar(); getchar();
clearScreen();
return;
}
MonsterScene selectedScene = (MonsterScene)(sceneChoice - 1);
order* checkOrder = orderList;
int hasPurchased = 0;
while (checkOrder != NULL) {
if (checkOrder->userId == currentUser->id &&
checkOrder->movieId == selectedArmor->id &&
checkOrder->scene == selectedScene &&
checkOrder->battleResult == -1) {
hasPurchased = 1;
break;
}
checkOrder = checkOrder->next;
}
if (hasPurchased) {
printf("\n你已购买过【%s】在【%s】场次的未出战授权,无法重复购买!\n",
selectedArmor->title, sceneToString(selectedScene));
getchar(); getchar();
clearScreen();
return;
}
int row = sceneMatrixConfig[selectedScene].row;
int col = sceneMatrixConfig[selectedScene].col;
monster*** seatMatrix = (monster***)malloc(row * sizeof(monster**));
if (!seatMatrix) {
printf("内存分配失败!\n");
getchar(); getchar();
clearScreen();
return;
}
for (int i = 0; i < row; i++) {
seatMatrix[i] = (monster**)malloc(col * sizeof(monster*));
if (!seatMatrix[i]) {
printf("内存分配失败!\n");
for (int j = 0; j < i; j++) free(seatMatrix[j]);
free(seatMatrix);
getchar(); getchar();
clearScreen();
return;
}
for (int j = 0; j < col; j++) {
seatMatrix[i][j] = NULL;
}
}
monster* seat = monsterList;
int r = 0, c = 0;
while (seat != NULL && r < row) {
if (seat->scene == selectedScene) {
seatMatrix[r][c] = seat;
c++;
if (c >= col) {
c = 0;
r++;
}
}
seat = seat->next;
}
printf("\n===== %s 座位矩阵(%d×%d)=====\n", sceneToString(selectedScene), row, col);
printf(" ");
for (int c = 0; c < col; c++) {
printf(" 列%d ", c + 1);
}
printf("\n");
for (int r = 0; r < row; r++) {
printf("行%d ", r + 1);
for (int c = 0; c < col; c++) {
if (seatMatrix[r][c] == NULL) {
printf(" [ 空 ] ");
}
else {
char seatChar = seatMatrix[r][c]->isDefeated ? 'X' : 'O';
printf(" [%c]%2d ", seatChar, seatMatrix[r][c]->id);
}
}
printf("\n");
}
printf("说明:O=可选择 | X=已占用 | 数字=怪兽ID | 空=无怪兽\n");
int targetRow, targetCol;
monster* selectedSeat = NULL;
while (1) {
printf("\n请输入要选择的座位坐标(格式:行号 列号,空格分隔):");
scanf("%d %d", &targetRow, &targetCol);
if (targetRow < 1 || targetRow > row || targetCol < 1 || targetCol > col) {
printf(" 坐标错误!行号范围1-%d,列号范围1-%d,请重新输入!\n", row, col);
continue;
}
int rIdx = targetRow - 1;
int cIdx = targetCol - 1;
if (seatMatrix[rIdx][cIdx] == NULL) {
printf(" 该位置无怪兽!请选择有数字的位置!\n");
continue;
}
if (seatMatrix[rIdx][cIdx]->isDefeated == 1) {
printf(" 该座位已被占用!请选择标有O的位置!\n");
continue;
}
selectedSeat = seatMatrix[rIdx][cIdx];
printf("选择成功!座位:行%d列%d | 怪兽ID:%d | 名称:%s\n",
targetRow, targetCol, selectedSeat->id, selectedSeat->name);
break;
}
for (int i = 0; i < row; i++) {
free(seatMatrix[i]);
}
free(seatMatrix);
seatMatrix = NULL;
selectedSeat->isDefeated = 1;
order* newOrder = (order*)malloc(sizeof(order));
if (!newOrder) {
printf("内存分配失败!\n");
getchar(); getchar();
clearScreen();
return;
}
int maxOrderId = 0;
order* o = orderList;
while (o != NULL) {
if (o->id > maxOrderId) maxOrderId = o->id;
o = o->next;
}
newOrder->id = maxOrderId + 1;
newOrder->userId = currentUser->id;
newOrder->movieId = selectedArmor->id;
strcpy(newOrder->movieName, selectedArmor->title);
newOrder->quantity = hourNum;
newOrder->totalPrice = selectedArmor->price * hourNum;
newOrder->monsterId = selectedSeat->id;
newOrder->battleResult = -1;
newOrder->scene = selectedScene;
newOrder->timestamp = time(NULL);
newOrder->next = orderList;
orderList = newOrder;
save_to_file();
char createTime[64];
formatTimestamp(newOrder->timestamp, createTime, sizeof(createTime));
printf("\n==================== 授权成功 ====================\n");
printf("├─ 订单ID: %d\n", newOrder->id);
printf("├─ 铠甲: %s\n", newOrder->movieName);
printf("├─ 场次: %s\n", sceneToString(newOrder->scene));
printf("├─ 授权时长: %d小时\n", newOrder->quantity);
printf("├─ 总价: %.2f 元\n", newOrder->totalPrice);
printf("├─ 选择座位: 行%d列%d(怪兽ID:%d)\n", targetRow, targetCol, selectedSeat->id);
printf("└─ 创建时间: %s\n", createTime);
printf("==================================================\n");
printf("\n按任意键返回菜单...\n");
getchar(); getchar();
clearScreen();
}
void deleteMovie() {
clearScreen();
int id;
printf("请输入要销毁的铠甲id\n");
scanf("%d", &id);
movie* cur = movieList;
movie* pre = NULL;
while (cur != NULL)
{
if (cur->id == id)
{
if (pre == NULL)
{
movieList = movieList->next;
}
else
{
pre->next = cur->next;
}
save_to_file();
printf("铠甲销毁成功,按任意键继续。。。。。\n");
getchar(); getchar();
clearScreen();
return;
}
pre = cur;
cur = cur->next;
}
printf("未找到id为%d的铠甲\n", id);
printf("按任意键继续\n");
getchar(); getchar();
clearScreen();
}
void updateMovie() {
clearScreen();
printf("===== 可修复的铠甲列表 =====\n");
movie* p = movieList;
int hasRepairable = 0;
printf("铠甲ID\t名称\t\t当前状态\n");
while (p != NULL) {
if (p->status != ARMOR_IDLE) {
hasRepairable = 1;
printf("%d\t%s\t\t%s\n",
p->id,
p->title,
p->status == ARMOR_IN_BATTLE ? "战斗中" :
(p->status == ARMOR_REPAIRING ? "维修中" : "破损"));
}
p = p->next;
}
if (!hasRepairable) {
printf("暂无需要修复的铠甲(所有铠甲均为闲置状态)\n");
printf("按任意键继续...\n");
getchar(); getchar();
clearScreen();
return;
}
int id;
printf("\n请输入要调校的铠甲ID: ");
scanf("%d", &id);
p = movieList;
while (p != NULL)
{
if (p->id == id)
{
bool hasOrder = false;
order* o = orderList;
while (o != NULL) {
if (o->movieId == p->id) {
hasOrder = true;
break;
}
o = o->next;
}
if (hasOrder) {
clearScreen();
printf("=============================================\n");
printf(" 操作失败\n");
printf(" 该铠甲已被召唤授权,无法修改状态!\n");
printf("=============================================\n");
printf("按任意键返回...\n");
getchar(); getchar();
clearScreen();
return;
}
printf("当前铠甲名: %s\n", p->title);
printf("当前铠甲状态: %s\n",
p->status == ARMOR_IDLE ? "闲置" :
(p->status == ARMOR_IN_BATTLE ? "战斗中" :
(p->status == ARMOR_REPAIRING ? "维修中" : "破损")));
printf("请输入新铠甲状态(1=闲置 2=战斗中 3=维修中 4=破损): ");
int status;
scanf("%d", &status);
p->status = (ArmorStatus)(status - 1);
printf("铠甲状态调校成功!\n");
save_to_file();
printf("按任意键继续...");
getchar(); getchar();
clearScreen();
return;
}
p = p->next;
}
printf("未找到ID为%d的铠甲\n", id);
printf("按任意键继续...\n");
getchar(); getchar();
clearScreen();
}
void addMonster() {
clearScreen();
monster* newMonster = (monster*)malloc(sizeof(monster));
if (newMonster == NULL) {
printf("内存分配失败!无法新增怪兽\n");
getchar(); getchar();
clearScreen();
return;
}
int maxId = 0;
monster* p = monsterList;
while (p != NULL) {
if (p->id > maxId) maxId = p->id;
p = p->next;
}
newMonster->id = maxId + 1;
printf("\n===== 新增怪兽(新增座位)=====\n");
printf("请输入怪兽名称:");
scanf("%s", newMonster->name);
printf("请输入怪兽等级:");
scanf("%d", &newMonster->level);
printf("请输入怪兽属性(1=火 2=水 3=雷 4=土 5=风):");
int attr;
scanf("%d", &attr);
newMonster->attr = (MonsterAttr)(attr - 1);
printf("请输入怪兽危险等级(1-10):");
scanf("%d", &newMonster->danger);
printf("请输入怪兽封印状态(0=未封印 1=已封印):");
scanf("%d", &newMonster->isDefeated);
printf("请选择怪兽出没地点(场次):\n");
printf("1: 铠一-城市市区\n2: 铠一-郊外山林\n3: 铠一-沿海区域\n");
printf("4: 铠一-远古遗迹\n5: 铠二-希望市\n6: 铠二-阿瑞斯星球\n7: 铠二-其他区域\n");
int scene;
scanf("%d", &scene);
newMonster->scene = (MonsterScene)(scene - 1);
newMonster->next = NULL;
if (monsterList == NULL) {
monsterList = newMonster;
}
else {
p = monsterList;
while (p->next != NULL) p = p->next;
p->next = newMonster;
}
printf("怪兽新增成功!ID:%d\n", newMonster->id);
save_to_file();
printf("按任意键返回...\n");
getchar(); getchar();
clearScreen();
}
void updateMonsterStatus() {
clearScreen();
printf("\n===== 修改怪兽封印状态(修改座位)=====\n");
printf("请输入要修改的怪兽ID:");
int id;
scanf("%d", &id);
monster* p = monsterList;
while (p != NULL) {
if (p->id == id) {
printf("当前怪兽:%s | 封印状态:%s\n",
p->name, p->isDefeated ? "已封印" : "未封印");
printf("请输入新的封印状态(0=未封印 1=已封印):");
scanf("%d", &p->isDefeated);
printf("怪兽封印状态修改成功!\n");
save_to_file();
getchar(); getchar();
clearScreen();
return;
}
p = p->next;
}
printf("未找到ID为%d的怪兽!\n", id);
getchar(); getchar();
clearScreen();
}
void battleMonster() {
clearScreen();
if (currentUser == NULL) {
printf("请先登录铠甲召唤系统!\n");
getchar(); getchar();
clearScreen();
return;
}
order* userOrder = orderList;
int hasArmor = 0;
while (userOrder != NULL) {
if (userOrder->userId == currentUser->id) {
hasArmor = 1;
break;
}
userOrder = userOrder->next;
}
if (hasArmor == 0) {
printf("你还没有授权任何铠甲!请先去召唤授权(购票)\n");
getchar(); getchar();
clearScreen();
return;
}
printf("\n===== 选择讨伐场次(怪兽出没场景)=====\n");
printf("1: 铠一-城市市区\n2: 铠一-郊外山林\n3: 铠一-沿海区域\n");
printf("4: 铠一-远古遗迹\n5: 铠二-希望市\n6: 铠二-阿瑞斯星球\n7: 铠二-其他区域\n");
printf("请选择要讨伐的场次:");
int sceneChoice;
scanf("%d", &sceneChoice);
MonsterScene targetScene;
switch (sceneChoice) {
case 1: targetScene = SCENE_KAI1_CITY; break;
case 2: targetScene = SCENE_KAI1_MOUNTAIN; break;
case 3: targetScene = SCENE_KAI1_OCEAN; break;
case 4: targetScene = SCENE_KAI1_ANCIENT; break;
case 5: targetScene = SCENE_KAI2_HOPE_CITY; break;
case 6: targetScene = SCENE_KAI2_ARES; break;
case 7: targetScene = SCENE_KAI2_OTHER; break;
default:
clearScreen();
printf("输入错误!\n");
getchar(); getchar();
clearScreen();
return;
}
clearScreen();
monster* tempMonster = monsterList;
int hasUndefeated = 0;
int monsterCount = 0;
int monsterIds[100];
monster* monsterListArr[100];
printf("\n===== %s 场次可讨伐的怪兽(未封印)=====\n", sceneToString(targetScene));
while (tempMonster != NULL) {
if (tempMonster->isDefeated == 0 && tempMonster->scene == targetScene) {
hasUndefeated = 1;
monsterCount++;
monsterIds[monsterCount - 1] = tempMonster->id;
monsterListArr[monsterCount - 1] = tempMonster;
}
tempMonster = tempMonster->next;
}
if (hasUndefeated) {
showMonsterDynamicMatrix(monsterListArr, monsterCount, targetScene);
}
if (hasUndefeated == 0) {
printf("该场次暂无未封印的怪兽!\n");
getchar(); getchar();
clearScreen();
return;
}
int monsterChoice;
printf("请选择要讨伐的怪兽序号(1-%d):", monsterCount);
scanf("%d", &monsterChoice);
if (monsterChoice < 1 || monsterChoice > monsterCount) {
clearScreen();
printf("输入错误!\n");
getchar(); getchar();
clearScreen();
return;
}
monster* targetMonster = monsterListArr[monsterChoice - 1];
clearScreen();
printf("\n===== 选择出战铠甲 =====\n");
userOrder = orderList;
int armorCount = 0;
movie* armorList[100];
while (userOrder != NULL) {
if (userOrder->userId == currentUser->id) {
movie* p = movieList;
while (p != NULL) {
if (p->id == userOrder->movieId && p->status == ARMOR_IDLE) {
armorCount++;
armorList[armorCount - 1] = p;
printf("%d. 铠甲名称:%s | 属性:%s | 授权时长:%d小时\n",
armorCount,
p->title,
attrToString(p->attr),
userOrder->quantity);
break;
}
p = p->next;
}
}
userOrder = userOrder->next;
}
if (armorCount == 0) {
printf("你暂无闲置铠甲可出战(已出战/维修中/破损)\n");
getchar(); getchar();
clearScreen();
return;
}
int armorChoice;
printf("请选择出战的铠甲序号(1-%d):", armorCount);
scanf("%d", &armorChoice);
if (armorChoice < 1 || armorChoice > armorCount) {
clearScreen();
printf("输入错误!\n");
getchar(); getchar();
clearScreen();
return;
}
movie* battleArmor = armorList[armorChoice - 1];
clearScreen();
printf("\n===== 铠甲出战!缉捕怪兽 =====\n");
printf("场次:%s | %s VS %s 战斗开始!\n",
sceneToString(targetScene), battleArmor->title, targetMonster->name);
int battleResult = 0;
if (
(battleArmor->attr == ATTR_FIRE && targetMonster->attr == ATTR_WIND) ||
(battleArmor->attr == ATTR_WIND && targetMonster->attr == ATTR_EARTH) ||
(battleArmor->attr == ATTR_EARTH && targetMonster->attr == ATTR_WATER) ||
(battleArmor->attr == ATTR_WATER && targetMonster->attr == ATTR_THUNDER) ||
(battleArmor->attr == ATTR_THUNDER && targetMonster->attr == ATTR_FIRE)
) {
battleResult = 1;
printf("【属性克制】%s对%s造成致命伤害!\n", battleArmor->title, targetMonster->name);
}
else if (battleArmor->attr == targetMonster->attr) {
if (battleArmor->price >= targetMonster->danger * 2) {
battleResult = 1;
printf("【同属性对决】%s凭借高授权等级战胜%s!\n", battleArmor->title, targetMonster->name);
}
else {
battleResult = 0;
printf("【同属性对决】%s授权等级不足,被%s击败!\n", battleArmor->title, targetMonster->name);
}
}
else {
battleResult = 0;
printf("【属性被克制】%s不敌%s,战斗失败!\n", battleArmor->title, targetMonster->name);
}
if (battleResult == 1) {
targetMonster->isDefeated = 1;
battleArmor->status = ARMOR_IDLE;
printf("战斗胜利!%s已被封印!\n", targetMonster->name);
}
else {
battleArmor->status = ARMOR_DAMAGED;
printf("战斗失败!%s破损,需要维修!\n", battleArmor->title);
}
userOrder = orderList;
while (userOrder != NULL) {
if (userOrder->userId == currentUser->id && userOrder->movieId == battleArmor->id) {
userOrder->monsterId = targetMonster->id;
userOrder->battleResult = battleResult;
break;
}
userOrder = userOrder->next;
}
save_to_file();
printf("\n战斗结束!按任意键返回菜单...\n");
getchar(); getchar();
clearScreen();
}
void showMonsterDynamicMatrix(monster* monsterListArr[], int monsterCount, MonsterScene targetScene) {
int matrixCol = sceneMatrixConfig[targetScene].col;
printf("\n========== %s 可讨伐怪兽图鉴(%d×%d矩阵版)==========\n",
sceneToString(targetScene),
sceneMatrixConfig[targetScene].row,
matrixCol);
for (int i = 0; i < monsterCount; i++) {
monster* m = monsterListArr[i];
if (i + 1 < 10) {
printf("[%d] %-12s | %-8s | 危险等级:%d",
i + 1, m->name, attrToString(m->attr), m->danger);
}
else {
printf("[%d] %-11s | %-8s | 危险等级:%d",
i + 1, m->name, attrToString(m->attr), m->danger);
}
if ((i + 1) % matrixCol == 0) {
printf("\n------------------------------------------------------------\n");
}
else if (i != monsterCount - 1) {
printf(" | ");
}
}
if (monsterCount % matrixCol != 0) {
printf("\n");
}
printf("===========================================================\n");
}
void adminSetSceneMatrix() {
clearScreen();
if (currentUser == NULL || currentUser->isAdmin != 0) {
printf("无管理员权限!仅系统管理员可修改矩阵尺寸!\n");
getchar(); getchar();
clearScreen();
return;
}
printf("======= 铠甲勇士系统-管理员面板【怪兽矩阵配置】=======\n");
printf("1. 设置场景怪兽矩阵尺寸\n");
printf("2. 查看所有场景矩阵配置\n");
printf("请选择操作:");
int op;
scanf("%d", &op);
if (op == 1) {
printf("\n======= 选择要配置的场景 =======\n");
printf("1: 铠一-城市市区\n2: 铠一-郊外山林\n3: 铠一-沿海区域\n");
printf("4: 铠一-远古遗迹\n5: 铠二-希望市\n6: 铠二-阿瑞斯星球\n7: 铠二-其他区域\n");
printf("请选择场景:");
int sceneChoice;
scanf("%d", &sceneChoice);
if (sceneChoice < 1 || sceneChoice > 7) {
printf(" 场景选择错误!请选择1-7之间的场景!\n");
getchar(); getchar();
clearScreen();
return;
}
MonsterScene targetScene = (MonsterScene)(sceneChoice - 1);
printf("请输入该场景怪兽矩阵行数(2-4):");
int row;
scanf("%d", &row);
printf("请输入该场景怪兽矩阵列数(2-4):");
int col;
scanf("%d", &col);
if (row < 2 || row > 4 || col < 2 || col > 4) {
printf(" 行数/列数必须在2-4之间!\n");
getchar(); getchar();
clearScreen();
return;
}
sceneMatrixConfig[targetScene].row = row;
sceneMatrixConfig[targetScene].col = col;
printf("场景「%s」矩阵尺寸已设置为 %d×%d!\n",
sceneToString(targetScene), row, col);
getchar(); getchar();
clearScreen();
}
else if (op == 2) {
printf("\n======= 所有场景矩阵配置 =======\n");
const char* sceneNames[] = {
"铠一-城市市区", "铠一-郊外山林", "铠一-沿海区域",
"铠一-远古遗迹", "铠二-希望市", "铠二-阿瑞斯星球", "铠二-其他区域"
};
for (int i = 0; i < 7; i++) {
printf("%d. %-15s → %d×%d矩阵\n",
i + 1, sceneNames[i],
sceneMatrixConfig[i].row, sceneMatrixConfig[i].col);
}
printf("\n按任意键返回...");
getchar(); getchar();
clearScreen();
}
else {
printf(" 输入错误!\n");
getchar(); getchar();
clearScreen();
}
}
void refundTicket() {
clearScreen();
if (currentUser == NULL) {
printf("请先登录系统!\n");
getchar(); getchar();
clearScreen();
return;
}
order* userOrders[100];
int orderCount = 0;
order* o = orderList;
char orderCreateTime[64];
while (o != NULL) {
if (o->userId == currentUser->id && o->battleResult == -1) {
userOrders[orderCount++] = o;
}
o = o->next;
}
if (orderCount == 0) {
printf("\n暂无可退订单(仅未出战的授权订单可退)!\n");
getchar(); getchar();
clearScreen();
return;
}
printf("===== 可退授权订单列表 =====\n");
for (int i = 0; i < orderCount; i++) {
order* cur = userOrders[i];
formatTimestamp(cur->timestamp, orderCreateTime, sizeof(orderCreateTime));
printf("[%d] 订单ID: %d | 铠甲: %s | 场次: %s | 金额: %.2f | 创建时间: %s\n",
i + 1, cur->id, cur->movieName, sceneToString(cur->scene), cur->totalPrice, orderCreateTime);
}
int index;
printf("\n请输入要退票的订单序号(1-%d):", orderCount);
scanf("%d", &index);
if (index < 1 || index > orderCount) {
printf("输入无效!\n");
getchar(); getchar();
clearScreen();
return;
}
order* targetOrder = userOrders[index - 1];
o = orderList;
order* pre = NULL;
int found = 0;
while (o != NULL) {
if (o == targetOrder) {
found = 1;
break;
}
pre = o;
o = o->next;
}
if (!found) return;
movie* armor = movieList;
while (armor != NULL) {
if (armor->id == targetOrder->movieId) {
armor->status = ARMOR_IDLE;
break;
}
armor = armor->next;
}
monster* seat = monsterList;
while (seat != NULL) {
if (seat->id == targetOrder->monsterId && seat->scene == targetOrder->scene) {
seat->isDefeated = 0;
break;
}
seat = seat->next;
}
if (pre == NULL) {
orderList = o->next;
}
else {
pre->next = o->next;
}
time_t now = time(NULL);
char buf[64];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&now));
formatTimestamp(targetOrder->timestamp, orderCreateTime, sizeof(orderCreateTime));
printf("\n 退票成功!退票时间:%s | 原订单创建时间:%s\n", buf, orderCreateTime);
showSeatMatrix(targetOrder->scene);
free(o);
o = NULL;
save_to_file();
printf("\n按任意键返回菜单...\n");
getchar(); getchar();
clearScreen();
}
void changePassword() {
clearScreen();
if (currentUser == NULL) {
printf("请先登录铠甲召唤系统后再修改密码!\n");
getchar(); getchar();
clearScreen();
return;
}
char oldPwd[50] = { 0 };
char newPwd[50] = { 0 };
char confirmPwd[50] = { 0 };
printf("===== 铠甲召唤密码修改 =====\n");
printf("当前召唤人:%s\n", currentUser->name);
printf("请输入原召唤密码:");
inputPassword(oldPwd, sizeof(oldPwd) - 1);
if (strcmp(currentUser->password, oldPwd) != 0) {
printf("\n❌ 原密码错误!密码修改失败\n");
getchar(); getchar();
clearScreen();
return;
}
printf("\n请输入新召唤密码(6-20位):");
inputPassword(newPwd, sizeof(newPwd) - 1);
if (strlen(newPwd) < 6 || strlen(newPwd) > 20) {
printf("\n 新密码长度必须在6-20位之间!\n");
getchar(); getchar();
clearScreen();
return;
}
printf("\n请再次输入新召唤密码:");
inputPassword(confirmPwd, sizeof(confirmPwd) - 1);
if (strcmp(newPwd, confirmPwd) != 0) {
printf("\n 两次输入的新密码不一致!\n");
getchar(); getchar();
clearScreen();
return;
}
if (strcmp(newPwd, oldPwd) == 0) {
printf("\n 新密码不能与原密码相同!\n");
getchar(); getchar();
clearScreen();
return;
}
strcpy_s(currentUser->password, sizeof(currentUser->password), newPwd);
save_to_file();
printf("\n 密码修改成功!下次登录请使用新密码\n");
printf("\n按任意键返回菜单...\n");
getchar(); getchar();
clearScreen();
}
ui.c
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include "entity.h"
#include "dal.h"
#include "bll.h"
#include"ui.h"
static void browseMonsterByScene(MonsterScene targetScene) {
clearScreen();
monster* p = monsterList;
if (p == NULL) {
printf("该场景暂无怪兽!\n");
printf("按任意键继续...\n");
getchar(); getchar();
clearScreen();
return;
}
printf("===== %s 场景怪兽列表 =====\n", sceneToString(targetScene));
printf("怪兽ID\t怪兽名称\t等级\t属性\t危险等级\t封印状态\n");
printf("------------------------------------------------------------\n");
int found = 0;
while (p != NULL) {
if (p->scene == targetScene) {
found = 1;
printf("%d\t%s\t%d\t%s\t%d\t%s\n",
p->id, p->name, p->level,
attrToString(p->attr), p->danger,
p->isDefeated ? "已封印(X)" : "未封印(O)");
}
p = p->next;
}
if (!found) printf("该场景暂无怪兽!\n");
printf("\n按任意键返回矩阵页面...\n");
getchar(); getchar();
clearScreen();
}
void adminmenu() {
int choice;
do {
clearScreen();
printf("\n====================================\n");
printf(" 光影铠甲 - 管理员控制面板\n");
printf("====================================\n");
printf("【座位状态说明】\n");
printf(" O: 怪兽未封印 → 空座(可选择)\n");
printf(" X: 怪兽已封印 → 已占座(有人坐)\n");
printf(" 空: 无怪兽 → 怪兽逃跑(位置空缺)\n");
printf("------------------------------------\n");
printf("1. 铠甲管理(新增/删除/修改/浏览)\n");
printf("2. 场景座位总控(怪兽/矩阵管理)\n");
printf("3. 系统管理(用户/数据/密码)\n");
printf("0. 退出登录(铠甲解体)\n");
printf("------------------------------------\n");
printf("请选择操作: ");
while (getchar() != '\n');
scanf("%d", &choice);
switch (choice) {
case 1: {
clearScreen();
int armorChoice;
do {
clearScreen();
printf("\n===== 铠甲管理面板 =====\n");
printf("1. 浏览所有铠甲\n");
printf("2. 新增铠甲\n");
printf("3. 删除铠甲\n");
printf("4. 修改铠甲信息\n");
printf("0. 返回上一级\n");
printf("------------------------\n");
printf("请选择操作: ");
while (getchar() != '\n');
scanf("%d", &armorChoice);
switch (armorChoice) {
case 1: browseMovies(); break;
case 2: addMovie(); break;
case 3: deleteMovie(); break;
case 4: updateMovie(); break;
case 0: clearScreen(); break;
default:
clearScreen();
printf("输入错误!请选择0-4的数字!\n");
getchar(); getchar();
clearScreen();
break;
}
} while (armorChoice != 0);
break;
}
case 2: {
clearScreen();
int sceneChoice;
printf("\n===== 选择操作场景 =====\n");
printf("1: 铠一-城市市区\n2: 铠一-郊外山林\n3: 铠一-沿海区域\n");
printf("4: 铠一-远古遗迹\n5: 铠二-希望市\n6: 铠二-阿瑞斯星球\n7: 铠二-其他区域\n");
printf("------------------------\n");
printf("请选择场景(1-7): ");
while (getchar() != '\n');
scanf("%d", &sceneChoice);
if (sceneChoice < 1 || sceneChoice > 7) {
clearScreen();
printf("场景选择错误!请选择1-7的数字!\n");
getchar(); getchar();
clearScreen();
break;
}
MonsterScene targetScene = (MonsterScene)(sceneChoice - 1);
int seatOp;
do {
clearScreen();
printf("\n===== 当前场景:%s 座位矩阵 =====\n", sceneToString(targetScene));
showSeatMatrix(targetScene);
printf("\n【操作提示】O=空座 | X=已占座 | 数字=怪兽ID | 空=无怪兽\n");
printf("------------------------------------\n");
printf("===== 该场景座位操作 =====\n");
printf("1. 查看本场景所有怪兽\n");
printf("2. 按坐标修改怪兽封印状态\n");
printf("0. 返回上一级\n");
printf("------------------------\n");
printf("请选择操作: ");
while (getchar() != '\n');
scanf("%d", &seatOp);
switch (seatOp) {
case 1:
browseMonsterByScene(targetScene);
break;
case 2: {
clearScreen();
printf("\n===== %s - 按坐标修改怪兽封印状态 =====\n", sceneToString(targetScene));
showSeatMatrix(targetScene);
int targetRow, targetCol;
printf("\n请输入要修改的怪兽坐标(格式:行号 列号):");
scanf("%d %d", &targetRow, &targetCol);
int row = sceneMatrixConfig[targetScene].row;
int col = sceneMatrixConfig[targetScene].col;
if (targetRow < 1 || targetRow > row || targetCol < 1 || targetCol > col) {
clearScreen();
printf("坐标错误!行号范围1-%d,列号范围1-%d!\n", row, col);
getchar(); getchar();
clearScreen();
break;
}
int rIdx = targetRow - 1;
int cIdx = targetCol - 1;
monster*** seatMatrix = (monster***)malloc(row * sizeof(monster**));
if (!seatMatrix) {
printf("内存分配失败!\n");
getchar(); getchar();
clearScreen();
break;
}
for (int i = 0; i < row; i++) {
seatMatrix[i] = (monster**)malloc(col * sizeof(monster*));
memset(seatMatrix[i], NULL, col * sizeof(monster*));
}
monster* seat = monsterList;
int r = 0, c = 0;
while (seat != NULL && r < row) {
if (seat->scene == targetScene) {
seatMatrix[r][c] = seat;
c++;
if (c >= col) { c = 0; r++; }
}
seat = seat->next;
}
if (seatMatrix[rIdx][cIdx] == NULL) {
clearScreen();
printf("该坐标无怪兽(怪兽逃跑)!无法修改状态!\n");
for (int i = 0; i < row; i++) free(seatMatrix[i]);
free(seatMatrix);
getchar(); getchar();
clearScreen();
break;
}
monster* targetMonster = seatMatrix[rIdx][cIdx];
printf("\n当前选中:行%d列%d | 怪兽ID:%d | 名称:%s\n",
targetRow, targetCol, targetMonster->id, targetMonster->name);
printf("当前状态:%s(%c)\n",
targetMonster->isDefeated ? "已封印(已占座)" : "未封印(空座)",
targetMonster->isDefeated ? 'X' : 'O');
int statusChoice;
printf("请选择新状态(0=未封印/O 1=已封印/X):");
scanf("%d", &statusChoice);
if (statusChoice != 0 && statusChoice != 1) {
clearScreen();
printf("状态选择错误!只能输入0或1!\n");
for (int i = 0; i < row; i++) free(seatMatrix[i]);
free(seatMatrix);
getchar(); getchar();
clearScreen();
break;
}
targetMonster->isDefeated = statusChoice;
save_to_file();
clearScreen();
printf("\n修改成功!\n");
printf("怪兽ID:%d | 新状态:%s(%c)\n",
targetMonster->id,
targetMonster->isDefeated ? "已封印(已占座)" : "未封印(空座)",
targetMonster->isDefeated ? 'X' : 'O');
for (int i = 0; i < row; i++) free(seatMatrix[i]);
free(seatMatrix);
printf("\n按任意键返回矩阵页面...\n");
getchar(); getchar();
clearScreen();
break;
}
case 4:
adminSetSceneMatrix();
break;
case 0:
clearScreen();
break;
default:
clearScreen();
printf("输入错误!请选择0-4的数字!\n");
getchar(); getchar();
clearScreen();
break;
}
} while (seatOp != 0);
break;
}
case 3: {
clearScreen();
int sysChoice;
do {
clearScreen();
printf("\n===== 系统管理面板 =====\n");
printf("1. 查看所有召唤人\n");
printf("2. 修改管理员密码\n");
printf("3. 初始化怪兽列表\n");
printf("0. 返回上一级\n");
printf("------------------------\n");
printf("请选择操作: ");
while (getchar() != '\n');
scanf("%d", &sysChoice);
switch (sysChoice) {
case 1: view_all_armor(); break;
case 2: changePassword(); break;
case 3:
clearScreen();
initMonsterList();
printf("\n按任意键继续...\n");
getchar(); getchar();
clearScreen();
break;
case 0: clearScreen(); break;
default:
clearScreen();
printf("输入错误!请选择0-4的数字!\n");
getchar(); getchar();
clearScreen();
break;
}
} while (sysChoice != 0);
break;
}
case 0:
clearScreen();
printf("管理员已退出登录!\n");
printf("按任意键返回主界面...\n");
getchar(); getchar();
clearScreen();
break;
default:
clearScreen();
printf("输入错误!请选择0-3的数字选项!\n");
getchar(); getchar();
clearScreen();
break;
}
} while (choice != 0);
}
void usermenu() {
int choice;
do {
clearScreen();
printf("╔════════════════════╗\n");
printf("║ 用户菜单 ║\n");
printf("╠════════════════════╣\n");
printf("║ 1. 浏览铠甲信息 ║\n");
printf("║ (浏览电影) ║\n");
printf("║ 2. 搜索铠甲 ║\n");
printf("║ (搜索电影) ║\n");
printf("║ 3. 召唤授权 ║\n");
printf("║ (购票) ║\n");
printf("║ 4. 可召唤的铠甲 ║\n");
printf("║ (我的订单) ║\n");
printf("║ 5. 铠甲出战打怪 ║\n");
printf("║ (选场次观影) ║\n");
printf("║ 6. 退票 ║\n");
printf("║ 7. 修改召唤密码 ║\n");
printf("║ 0. 铠甲解体 ║\n");
printf("║ (退出登录) ║\n");
printf("╚════════════════════╝\n");
printf("请选择: ");
while (getchar() != '\n');
scanf("%d", &choice);
switch (choice) {
case 1: clearScreen(); browseMovies(); break;
case 2: clearScreen(); searchMovie(); break;
case 3: clearScreen(); buyTicket(); break;
case 4: clearScreen(); myOrders(); break;
case 5: clearScreen(); battleMonster(); break;
case 6: clearScreen(); refundTicket(); break;
case 7: clearScreen(); changePassword(); break;
case 0: clearScreen(); printf("正在退出登录...\n"); break;
default:
clearScreen();
printf("输入错误!请选择0-7之间的数字\n");
printf("按回车键继续...");
getchar(); getchar();
}
} while (choice != 0);
}
void browseMovies() {
clearScreen();
movie* p = movieList;
if (p == NULL)
{
printf("暂无铠甲\n");
printf("按任意键继续。。。。\n");
getchar(); getchar();
clearScreen();
return;
}
printf("铠甲ID\t铠甲名称\t授权价格\t铠甲类型\t铠甲属性\t铠甲状态\n");
while (p != NULL)
{
printf("%d\t%s\t%.2f\t%s\t%s\t%s\n",
p->id,
p->title,
p->price,
p->type,
p->attr == ATTR_FIRE ? "火属性" :
(p->attr == ATTR_WATER ? "水属性" :
(p->attr == ATTR_THUNDER ? "雷属性" :
(p->attr == ATTR_EARTH ? "土属性" : "风属性"))),
p->status == ARMOR_IDLE ? "闲置" :
(p->status == ARMOR_IN_BATTLE ? "战斗中" :
(p->status == ARMOR_REPAIRING ? "维修中" : "破损")));
p = p->next;
}
printf("按任意键继续。。。。。\n");
getchar(); getchar();
clearScreen();
}
void browseMonster() {
clearScreen();
monster* p = monsterList;
if (p == NULL)
{
printf("暂无怪兽\n");
printf("按任意键继续。。。。\n");
getchar(); getchar();
clearScreen();
return;
}
printf("怪兽ID\t怪兽名称\t等级\t属性\t危险等级\t封印状态\t出没地点\n");
while (p != NULL)
{
printf("%d\t%s\t%d\t%s\t%d\t%s\t%s\n",
p->id,
p->name,
p->level,
p->attr == ATTR_FIRE ? "火属性" :
(p->attr == ATTR_WATER ? "水属性" :
(p->attr == ATTR_THUNDER ? "雷属性" :
(p->attr == ATTR_EARTH ? "土属性" : "风属性"))),
p->danger,
p->isDefeated ? "已封印" : "未封印",
sceneToString(p->scene));
p = p->next;
}
printf("按任意键继续。。。。。\n");
getchar(); getchar();
clearScreen();
}
bool isSubsequenceIgnoreCase(const char* str, const char* sub) {
if (*sub == '\0') return true;
while (*str != '\0') {
char c1 = (*str >= 'A' && *str <= 'Z') ? (*str + 32) : *str;
char c2 = (*sub >= 'A' && *sub <= 'Z') ? (*sub + 32) : *sub;
if (c1 == c2) {
sub++;
if (*sub == '\0') return true;
}
str++;
}
return false;
}
void searchMovie()
{
clearScreen();
int searchType;
char keyword[50] = { 0 };
printf("===== 铠甲搜索 =====\n");
printf("1. 按铠甲名称搜索(子序列模糊匹配)\n");
printf("2. 按铠甲类型搜索(子序列模糊匹配)\n");
printf("3. 按铠甲属性搜索(火/水/雷等,精确匹配)\n");
printf("请选择搜索方式:");
while (getchar() != '\n');
scanf("%d", &searchType);
while (getchar() != '\n');
printf("请输入搜索关键词:");
fgets(keyword, sizeof(keyword), stdin);
keyword[strcspn(keyword, "\n")] = '\0';
if (strlen(keyword) == 0) {
printf("\n 搜索关键词不能为空!\n");
getchar();
clearScreen();
return;
}
movie* p = movieList;
int found = 0;
printf("\n===== 铠甲搜索结果 =====\n");
printf("铠甲ID\t名称\t\t授权价格\t类型\t\t属性\t\t状态\n");
printf("----------------------------------------------------------------------\n");
while (p != NULL)
{
int match = 0;
switch (searchType)
{
case 1:
match = isSubsequenceIgnoreCase(p->title, keyword);
break;
case 2:
match = isSubsequenceIgnoreCase(p->type, keyword);
break;
case 3:
if (strcmp(keyword, "火") == 0 || strcmp(keyword, "火属性") == 0)
match = (p->attr == ATTR_FIRE);
else if (strcmp(keyword, "水") == 0 || strcmp(keyword, "水属性") == 0)
match = (p->attr == ATTR_WATER);
else if (strcmp(keyword, "雷") == 0 || strcmp(keyword, "雷属性") == 0)
match = (p->attr == ATTR_THUNDER);
else if (strcmp(keyword, "土") == 0 || strcmp(keyword, "土属性") == 0)
match = (p->attr == ATTR_EARTH);
else if (strcmp(keyword, "风") == 0 || strcmp(keyword, "风属性") == 0)
match = (p->attr == ATTR_WIND);
break;
default:
printf(" 搜索方式错误!请选择1-3\n");
getchar();
clearScreen();
return;
}
if (match)
{
found = 1;
printf("%-6d%-12s%-12.2f%-12s%-12s%-12s\n",
p->id,
p->title,
p->price,
p->type,
attrToString(p->attr),
p->status == ARMOR_IDLE ? "闲置" :
(p->status == ARMOR_IN_BATTLE ? "战斗中" :
(p->status == ARMOR_REPAIRING ? "维修中" : "破损")));
}
p = p->next;
}
if (found == 0)
{
printf("\n 未找到符合「%s」条件的铠甲\n", keyword);
}
printf("\n按任意键继续。。。。。\n");
getchar();
clearScreen();
}
void view_all_armor() {
clearScreen();
user* p = head;
if (p == NULL)
{
printf("暂无召唤人\n");
printf("按任意键继续。。。。\n");
getchar(); getchar();
clearScreen();
return;
}
printf("召唤人ID\t召唤人名称\t身份\n");
while (p != NULL)
{
printf("%d\t%s\t%s\n",
p->id,
p->name,
p->isAdmin == 1 ? "管理员" : "普通用户");
p = p->next;
}
printf("按任意键继续。。。。。\n");
getchar(); getchar();
clearScreen();
}
void searchMonsterByScene() {
int s;
printf("\n===== 选择出没地点(电影场次)=====\n");
printf("1: 铠一-城市市区\n2: 铠一-郊外山林\n3: 铠一-沿海区域\n");
printf("4: 铠一-远古遗迹\n5: 铠二-希望市\n6: 铠二-阿瑞斯星球\n7: 铠二-其他区域\n");
printf("请选择:");
scanf("%d", &s);
MonsterScene target;
switch (s) {
case 1: target = SCENE_KAI1_CITY; break;
case 2: target = SCENE_KAI1_MOUNTAIN; break;
case 3: target = SCENE_KAI1_OCEAN; break;
case 4: target = SCENE_KAI1_ANCIENT; break;
case 5: target = SCENE_KAI2_HOPE_CITY; break;
case 6: target = SCENE_KAI2_ARES; break;
case 7: target = SCENE_KAI2_OTHER; break;
default: printf("输入错误!\n"); getchar(); getchar(); return;
}
printf("\n===== 地点「%s」的怪兽 =====\n", sceneToString(target));
printf("ID\t名称\t\t等级\t属性\t\t是否封印\n");
printf("------------------------------------------------------------\n");
monster* p = monsterList;
int found = 0;
while (p) {
if (p->scene == target) {
found = 1;
printf("%d\t%-15s\t%d\t%s\t%s\n",
p->id,
p->name,
p->level,
attrToString(p->attr),
p->isDefeated ? "已封印" : "可封印");
}
p = p->next;
}
if (!found) printf("该地点暂无怪兽\n");
printf("按回车返回...\n");
getchar(); getchar();
}
void login() {
clearScreen();
char name[50];
char password[50];
int trycount = 0;
const int maxtry = 5;
user* p;
while (trycount < maxtry) {
printf("\n=====召唤者身份验证=====\n");
printf("请输入召唤人姓名: ");
scanf("%s", name);
p = head;
while (p != NULL) {
if (strcmp(p->name, name) == 0) {
break;
}
p = p->next;
}
if (p == NULL) {
trycount++;
printf("「无法合体!」还剩余%d次验证机会\n", maxtry - trycount);
continue;
}
printf("=====请输入召唤密码=====\n");
inputPassword(password, 15);
printf("\n");
if (strcmp(p->password, password) == 0) {
printf("\n「铠甲合体!」\n");
printf("铠甲合体!!!!,召唤人: %s\n", p->name);
currentUser = p;
clearScreen();
if (p->isAdmin == 0)
{
adminmenu();
}
else
{
usermenu();
}
return;
}
else {
trycount++;
printf("「密码错误,合体失败!」还剩余%d次机会\n", maxtry - trycount);
}
}
printf("\n「您不是铠甲召唤人!」登录失败!\n");
getchar(); getchar();
clearScreen();
}
void reg()
{
clearScreen();
int admin;
printf("\n====================================\n");
printf(" 预备铠甲勇士认证\n");
printf("====================================\n");
printf("「没有做不到的事,只有不想做的事。」\n\n");
printf("请选择你的铠甲类型:\n");
printf("0. 天赐铠甲(管理员)\n");
printf("1. 人造铠甲(普通用户)\n");
printf("请输入你的选择: ");
scanf("%d", &admin);
char name[50];
char password[50];
printf("\n===== 召唤者注册 =====\n");
printf("召唤人姓名: ");
scanf("%s", name);
user* p;
p = head;
while (p != NULL)
{
if (strcmp(p->name, name) == 0)
{
printf("「此代号已被其他铠甲勇士使用!」\n");
getchar(); getchar();
clearScreen();
return;
}
p = p->next;
}
user* newuser = (user*)malloc(sizeof(user));
if (newuser == NULL)
{
printf("「能量不足,召唤失败!」\n");
getchar(); getchar();
clearScreen();
return;
}
if (admin == 0)
{
newuser->isAdmin = 0;
printf("天赐铠甲选择了你!\n");
}
else
{
newuser->isAdmin = 1;
printf("人造铠甲,等待你的召唤!\n");
}
int count = 0;
p = head;
while (p != NULL)
{
count++;
p = p->next;
}
newuser->id = count + 1;
printf("\n请设置你的召唤密码: \n");
inputPassword(password, 15);
printf("\n");
strcpy(newuser->name, name);
strcpy(newuser->password, password);
newuser->next = head;
head = newuser;
printf("\n====================================\n");
printf("「铠甲合体!」\n");
printf("恭喜你,%s,成为第%d位铠甲勇士!\n", name, newuser->id);
printf("「从现在开始你就是铠甲召唤人。」\n");
printf("====================================\n");
save_to_file();
printf("\n是否立即召唤铠甲?\n");
printf("1. 立即合体(登录)\n");
printf("2. 暂时离开\n");
printf("请选择: ");
int choice;
scanf("%d", &choice);
switch (choice)
{
case 1:
clearScreen();
login();
break;
case 2:
printf("「暂时的离别,是为了更好的重逢。」\n");
getchar(); getchar();
clearScreen();
break;
}
}
void showSeatMatrix(MonsterScene scene) {
if (scene < 0 || scene >= 7) {
printf("错误:无效的场景编号!无法显示座位矩阵\n");
return;
}
int row = sceneMatrixConfig[scene].row;
int col = sceneMatrixConfig[scene].col;
monster*** seatMatrix = (monster***)malloc(row * sizeof(monster**));
if (!seatMatrix) {
printf("内存分配失败!\n");
return;
}
for (int i = 0; i < row; i++) {
seatMatrix[i] = (monster**)malloc(col * sizeof(monster*));
if (!seatMatrix[i]) {
printf("内存分配失败!\n");
for (int j = 0; j < i; j++) free(seatMatrix[j]);
free(seatMatrix);
return;
}
for (int j = 0; j < col; j++) {
seatMatrix[i][j] = NULL;
}
}
monster* seat = monsterList;
int r = 0, c = 0;
while (seat != NULL && r < row) {
if (seat->scene == scene) {
seatMatrix[r][c] = seat;
c++;
if (c >= col) {
c = 0;
r++;
}
}
seat = seat->next;
}
printf("\n===== %s 座位矩阵(%d×%d)=====\n", sceneToString(scene), row, col);
printf(" ");
for (int c = 0; c < col; c++) {
printf(" 列%d ", c + 1);
}
printf("\n");
for (int r = 0; r < row; r++) {
printf("行%d ", r + 1);
for (int c = 0; c < col; c++) {
if (seatMatrix[r][c] == NULL) {
printf(" [ 空 ] ");
}
else {
char seatChar = seatMatrix[r][c]->isDefeated ? 'X' : 'O';
printf(" [%c]%2d ", seatChar, seatMatrix[r][c]->id);
}
}
printf("\n");
}
printf("说明:O=空座 | X=已占座/已封印 | 数字=怪兽ID | 空=无怪兽\n");
for (int i = 0; i < row; i++) {
free(seatMatrix[i]);
}
free(seatMatrix);
seatMatrix = NULL;
}
common.c
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "entity.h"
#include "dal.h"
#include"ui.h"
#include "bll.h"
void clearScreen() {
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
}
void inputPassword(char* password, int maxLen)
{
int i = 0;
char ch;
while (1)
{
ch = _getch();
if (ch == 13) {
password[i] = '\0';
break;
}
else if (ch == 8) {
if (i > 0) {
i--;
printf("\b \b");
}
}
else if (i < maxLen - 1) {
password[i++] = ch;
printf("*");
}
}
}
void formatTimestamp(time_t timestamp, char* outBuf, int bufSize) {
if (outBuf == NULL || bufSize < 20) {
strcpy(outBuf, "时间格式错误");
return;
}
struct tm* tinfo = localtime(×tamp);
if (tinfo == NULL) {
strcpy(outBuf, "无效时间");
return;
}
strftime(outBuf, bufSize, "%Y-%m-%d %H:%M:%S", tinfo);
}
main.c
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "entity.h"
#include "dal.h"
#include "bll.h"
#include"ui.h"
int main()
{
load_from_file();
int choice;
do {
printf("\n====================================\n");
printf(" 光影铠甲\n");
printf("====================================\n");
printf("你只能承诺你有把握的事情,不要冲动\n");
printf("\n");
printf("1. 铠甲召唤(登录)\n");
printf("2. 成为预备铠甲勇士(注册)\n");
printf("0. 铠甲解体(退出)\n");
printf("\n请选择你的行动: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
login();
break;
case 2:
reg();
break;
case 0:
save_to_file();
printf("\n====================================\n");
printf("「暂时的离别,是为了更好的重逢。」\n");
printf("「只要心中有信念,就没有过不去的坎。」\n");
printf("------炎龙侠\n");
printf("\n铠甲解体,期待你下次召唤!\n");
printf("====================================\n");
break;
default:
printf("\n「犹豫就会败北!」请重新选择!\n");
}
} while (choice != 0);
return 0;
}