C语言实现:影院票务管理系统(铠甲怪兽管理系统)(详细解析+效果展示)C语言实现:影院票务管理系统(铠甲怪兽管理系统)(详细解析+效果展示)

C语言实现:影院票务管理系统(铠甲怪兽管理系统)(详细解析+效果展示)C语言实现:影院票务管理系统(铠甲怪兽管理系统)(详细解析+效果展示)

目录


效果展示

影院票务管理系统(铠甲怪兽管理系统)

项目背景

这个项目是一个用 C 编写的台程序,原本是要求写一个影院票务管理系统,但是主播魔改了一下,改成了铠甲打怪项目:


概念对照表

光影铠甲概念 影院票务概念 说明
铠甲 (movie) 电影 每个铠甲就是一部电影,有名称、类型、属性、授权价格(票价)、状态
怪兽 (monster) 座位 封印状态表示座位是否被占用
场景 (MonsterScene) 影厅 不同场景对应不同影厅
用户 (user) 观众/管理员 普通用户是观众,管理员是影院管理者
授权/购票 (order) 购票记录 用户购买铠甲授权 → 购票记录
出战 (battle) 入场观影 铠甲出战怪兽 → 观众入场观影
座位矩阵 (showSeatMatrix) 座位布局 可视化显示座位状态
属性克制 (attr) 电影类型/座位策略 不同铠甲属性可克制怪兽 → 可类比座位策略或优惠策略
密码/登录 (login) 用户验证 登录验证身份
注册 (reg) 会员注册 新用户注册
数据持久化 (save/load) 数据库 保存用户/电影/座位/订单信息

系统功能分析

用户功能

  1. 注册与登录

    • 注册成为预备铠甲勇士(会员)
    • 登录后可访问系统功能
  2. 浏览与搜索铠甲(电影)

    • 查看所有铠甲信息
    • 按名称、类型、属性搜索
  3. 授权/购票

    • 选择铠甲(电影)
    • 选择授权时长(电影时长)
    • 选择座位(怪兽)和场次(影厅)
  4. 查看订单

    • 可召唤铠甲(闲置铠甲/未出战)
    • 所有授权记录显示
  5. 退票与密码修改

    • 退未出战订单
    • 修改用户登录密码
  6. 铠甲出战(观影)

    • 铠甲属性克制怪兽(座位)
    • 战斗胜利 → 封印怪兽(占座成功)
    • 战斗失败 → 铠甲破损(座位被占/失败)

管理员功能

  1. 铠甲管理(电影管理)

    • 浏览、添加、删除、修改铠甲
  2. 场景座位矩阵管理(影厅管理)

    • 设置矩阵行列数
    • 查看场景座位布局
    • 修改怪兽封印状态(座位占用情况)
  3. 系统管理

    • 查看所有用户
    • 修改管理员密码
    • 初始化怪兽列表(座位数据重置)

源码展示

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, &timestamp) == 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(&timestamp);
	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;
}
相关推荐
2301_789015622 小时前
DS进阶:红黑树
c语言·开发语言·数据结构·c++·算法·r-tree·lsm-tree
枫叶丹42 小时前
【HarmonyOS 6.0】Camera Kit 微距状态监听能力详解
开发语言·华为·harmonyos
daxi1502 小时前
C语言从入门到进阶——第13讲:深入理解指针(3)
c语言·开发语言·数据结构·算法
冰糖雪梨dd2 小时前
【JavaScript】 substring()方法详解
开发语言·前端·javascript
AsDuang2 小时前
Python 3.12 MagicMethods - 45 - __rpow__
开发语言·python
liuyao_xianhui2 小时前
动态规划_简单多dp问题_打家劫舍_打家劫舍2_C++
java·开发语言·c++·算法·动态规划
老鱼说AI2 小时前
祖师爷KR的C语言讲解:第6期-输入与输出
c语言·开发语言
小鸡脚来咯2 小时前
SQL表连接
java·开发语言·数据库
大鹏说大话2 小时前
消息队列 Kafka/RabbitMQ/RocketMQ 怎么选?业务场景对比指南
开发语言