【影院票务管理系统】

ui.h

cs 复制代码
#ifndef UI_H
#define UI_H
#include "entity.h"

void usermenu();
void adminmenu();
void clearScreen();
void inputPassword(char* password, int maxLen);
void formatTimestamp(time_t t, char* buf, int size);
void browseMovies();
void searchMovie();
void view_all_users();
void findPassword();
void showSeatMatrix(int hallId, int timeIdx);

#endif

ui.c

cs 复制代码
#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"

// 管理员菜单
void adminmenu() {
	int choice;
	do {
		clearScreen();
		printf("\n====================================\n");
		printf("      - 管理员控制面板\n");
		printf("====================================\n");
		printf("【座位状态说明】\n");
		printf("  O: 空座(可选择)\n");
		printf("  X: 已占座(有人坐)\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: {
			int movieChoice;
			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", &movieChoice);

				switch (movieChoice) {
				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 (movieChoice != 0);
			break;
		}
		case 2:
			clearScreen();
			updateSeatStatus();
			break;
		case 3: {
			clearScreen();
			int sysChoice;
			do {
				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_users(); break;
				case 2: changePassword(); break;
				case 3:
					initSeatList();
					printf("座位列表初始化完成!\n");
					getchar(); getchar();
					break;
				case 0: clearScreen(); break;
				default:
					clearScreen();
					printf("输入错误!请选择0-3的数字!\n");
					getchar(); getchar();
					clearScreen();
					break;
				}
			} while (sysChoice != 0);
			break;
		}
		case 0: clearScreen(); printf("管理员已退出登录!\n"); getchar(); break;
		default:
			clearScreen();
			printf("输入错误!请选择0-3的数字选项!\n");
			getchar(); getchar();
			break;
		}
	} while (choice != 0);
}
void usermenu() {
	int choice;
	do {
		clearScreen();
		printf("╔════════════════════╗\n");
		printf("║     用户菜单        ║\n");
		printf("╠════════════════════╣\n");
		printf("║ 1. 浏览电影信息     ║\n");
		printf("║ 2. 搜索电影         ║\n");
		printf("║ 3. 购票             ║\n");
		printf("║ 4. 我的订单         ║\n");
		printf("║ 5. 查看座位         ║\n");
		printf("║ 6. 退票             ║\n");
		printf("║ 7. 修改密码         ║\n");
		printf("║ 0. 退出登录         ║\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();
			int h, t;
			printf("请选择要查看的影厅(1-%d):", HALLS);
			scanf("%d", &h);

			printf("请选择场次(1-%d):1=10:00 2=14:00 3=18:00 4=21:00\n", TIMES);
			scanf("%d", &t);

			if (h >= 1 && h <= HALLS && t >= 1 && t <= TIMES) {
				int hallId = h - 1;
				int timeIdx = t - 1; // 转换为链表索引

				// 查找节点
				SeatNode* node = findSeatNode(hallId, timeIdx);
				if (!node) {
					// 节点不存在,初始化影厅场次
					initSeatList();
					node = findSeatNode(hallId, timeIdx);
					if (!node) {
						printf("场次初始化失败!\n");
						getchar(); getchar();
						break;
					}
				}

				showSeatMatrix(hallId, timeIdx);
			}
			else {
				printf("输入错误!影厅或场次超出范围。\n");
			}

			getchar(); getchar(); // 等待回车
			break;
		}

		case 6: clearScreen(); refundTicket(); break;
		case 7: clearScreen(); changePassword(); break;
		case 0: clearScreen(); printf("正在退出登录...\n"); break;
		default:
			clearScreen();
			printf("输入错误!请选择0-%d之间的数字\n", 7);
			getchar(); getchar();
		}
	} while (choice != 0);
}
//// 显示:当前影厅 + 当前场次 的座位矩阵(独立座位)
//void showSeatMatrix(int hallId, int timeIdx)
//{
//	// 找到当前场次的座位链表节点
//	SeatNode* node = findSeatNode(hallId, timeIdx);
//	if (!node)
//	{
//		printf("场次未初始化!\n");
//		return;
//	}
//
//	printf("\n=======================================\n");
//	printf("          影厅 %d | 场次 %d\n", hallId + 1, timeIdx + 1);
//	printf("=======================================\n");
//
//	printf("   ");
//	for (int j = 0; j < COLS; j++)
//	{
//		printf("%2d ", j + 1);
//	}
//	printf("\n");
//
//	for (int i = 0; i < ROWS; i++)
//	{
//		printf("%c  ", 'A' + i);
//		for (int j = 0; j < COLS; j++)
//		{
//			printf("%c  ", node->seats[i][j] ? 'X' : 'O');
//		}
//		printf("\n");
//	}
//	printf("=======================================\n");
//	printf("          O = 可售    X = 已售\n");
//	printf("=======================================\n\n");
//}
// 忽略大小写子串匹配
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("请选择搜索方式:");
	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上映状态\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;
		default:
			printf(" 搜索方式错误!\n");
			getchar();
			clearScreen();
			return;
		}

		if (match) {
			found = 1;
			time_t now = time(NULL);
			const char* status = (now >= p->startTime && now <= p->endTime) ? "正在上映" : "未上映/已下映";
			printf("%-6d%-15s%-8.2f%-12s%-20s\n", p->id, p->title, p->price, p->type, status);
		}
		p = p->next;
	}

	if (!found) {
		printf("\n 未找到符合「%s」条件的电影\n", keyword);
	}

	printf("\n按任意键继续...\n");
	getchar();
	clearScreen();
}

// 查看所有用户
void view_all_users() {
	clearScreen();
	user* p = head;
	if (p == NULL) {
		printf("暂无注册用户\n");
		printf("按任意键继续...\n");
		getchar(); getchar();
		clearScreen();
		return;
	}

	printf("用户ID\t用户名\t\t身份\n");
	printf("--------------------------------\n");

	while (p != NULL) {
		printf("%-6d%-16s%-10s\n", p->id, p->name, p->isAdmin ? "管理员" : "普通用户");
		p = p->next;
	}

	printf("\n按任意键继续...\n");
	getchar(); getchar();
	clearScreen();
}

// 登录
void login() {
	clearScreen();
	char name[50];
	char password[50];
	int trycount = 0;
	const int maxtry = 5;
	user* p = NULL;

	while (p == NULL) {
		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) {
			printf("用户不存在!请重新输入用户名\n");
		}
	}

	trycount = 0;
	while (trycount < maxtry) {
		printf("请输入密码: ");
		inputPassword(password, 15);
		printf("\n");

		if (strcmp(p->password, password) == 0) {
			printf("登录成功!\n");
			currentUser = p;
			clearScreen();
			p->isAdmin ? adminmenu() : usermenu();
			return;
		}
		else {
			trycount++;
			printf("密码错误!剩余 %d 次机会\n", maxtry - trycount);
		}
	}

	printf("登录失败!密码错误次数过多\n");
	while (getchar() != '\n');
	clearScreen();
}

// 注册
void reg() {
	clearScreen();
	int admin;
	printf("\n====================================\n");
	printf("         用户注册\n");
	printf("====================================\n");
	printf("0. 管理员\n1. 普通用户\n选择:");
	scanf("%d", &admin);

	char name[50];
	printf("用户名: ");
	scanf("%s", name);

	user* 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));
	memset(newuser, 0, sizeof(user));
	newuser->isAdmin = (admin == 0) ? 1 : 0;

	int count = 0;
	p = head;
	while (p) { count++; p = p->next; }
	newuser->id = count + 1;

	char password[50];
	printf("设置密码:");
	inputPassword(password, 15);
	printf("\n");

	getchar();
	printf("密保问题:");
	fgets(newuser->securityQuestion, 100, stdin);
	newuser->securityQuestion[strcspn(newuser->securityQuestion, "\n")] = 0;

	printf("密保答案:");
	fgets(newuser->securityAnswer, 100, stdin);
	newuser->securityAnswer[strcspn(newuser->securityAnswer, "\n")] = 0;

	strcpy(newuser->name, name);
	strcpy(newuser->password, password);
	newuser->next = head;
	head = newuser;

	printf("注册成功!\n");
	save_to_file();

	printf("1. 立即登录\n2. 稍后\n选择:");
	int ch;
	scanf("%d", &ch);
	if (ch == 1) {
		clearScreen();
		login();
	}
	else {
		getchar(); getchar();
		clearScreen();
	}
}

// 找回密码
void findPassword() {
	clearScreen();
	char name[50];
	printf("请输入用户名:");
	scanf("%s", name);

	user* p = head;
	while (p) {
		if (strcmp(p->name, name) == 0) {
			printf("\n密保问题:%s\n", p->securityQuestion);
			char ans[100];
			getchar();
			printf("答案:");
			fgets(ans, 100, stdin);
			ans[strcspn(ans, "\n")] = 0;

			if (!strcmp(ans, p->securityAnswer)) {
				printf("验证成功!新密码:");
				inputPassword(p->password, 50);
				printf("\n修改成功!\n");
				save_to_file();
			}
			else {
				printf("答案错误!\n");
			}
			getchar();
			return;
		}
		p = p->next;
	}
	printf("用户不存在!\n");
	getchar();
}

// 电影浏览(自动分 热映 / 即将 / 下架)
void browseMovies() {
	clearScreen();
	time_t now = time(NULL);

	printf("===== 正在热映 =====\n");
	for (movie* p = movieList; p; p = p->next)
		if (now >= p->startTime && now <= p->endTime)
			printf("%d. %s  %s  %d分钟  厅:%d\n",
				p->id, p->title, p->type, p->duration, p->fixedHall + 1);

	printf("\n===== 即将上映 =====\n");
	for (movie* p = movieList; p; p = p->next)
		if (now < p->startTime)
			printf("%d. %s\n", p->id, p->title);

	printf("\n===== 已下架 =====\n");
	for (movie* p = movieList; p; p = p->next)
		if (now > p->endTime)
			printf("%d. %s\n", p->id, p->title);

	printf("\n按回车返回...\n");
	while (getchar() != '\n'); getchar();
	clearScreen();
}

影院票务管理系统功能与用户界面设计总结

本项目实现了一个完整的影院票务管理系统,覆盖管理员和普通用户的操作功能,提供电影管理、购票、座位管理、订单管理及用户账户管理等功能。本文将结合系统 UI 模块详细说明各功能模块及交互流程。


系统角色与操作界面;管理员与普通用户

系统主要角色:

  • 管理员:具备电影信息管理、座位总控、用户及系统管理权限

  • 普通用户:可浏览电影信息、搜索电影、购票、退票、查看订单及修改密码

界面设计采用 菜单式交互,分为管理员菜单和用户菜单,使用清晰的编号选择操作。


管理员菜单;电影、座位与系统管理

管理员菜单功能:

  1. 电影管理

    ;浏览电影:展示当前电影列表,包括热映、即将上映、已下架

    ;新增电影:填写电影名称、票价、类型、上映时间、导演、主演及固定影厅

    ;删除电影:根据电影ID删除指定电影

    ;修改电影信息:可修改上映时间、状态及其他信息

  2. 影厅座位总控

    ;管理员可查看和修改任意影厅×场次座位状态

    ;座位矩阵显示:O=可售X=已占座

    ;支持动态初始化场次座位节点

  3. 系统管理

    ;查看所有注册用户及身份信息

    ;修改管理员密码

    ;初始化座位列表,确保所有影厅×场次座位节点完整

操作流程使用循环菜单,输入数字选择功能,错误输入提供提示并重新输入。


用户菜单;购票与订单管理

普通用户菜单功能:

  1. 浏览电影信息

    ;自动区分热映、即将上映、已下架

  2. 搜索电影

    ;支持按电影名称或类型搜索

    ;忽略大小写匹配,提高搜索容错性

  3. 购票

    ;选择电影 → 场次 → 座位

    ;生成订单及唯一取票码

  4. 我的订单

    ;显示用户所有购票记录

  5. 查看座位

    ;显示影厅×场次座位矩阵

    ;自动初始化未存在的场次节点

  6. 退票

    ;根据订单ID退票,并释放座位

  7. 修改密码

    ;支持安全验证并修改密码

用户菜单同样采用编号选择操作,确保交互简洁、直观。


登录、注册与找回密码;安全与便捷

  • 登录

    ;用户名验证 → 密码验证(5次机会限制)

    ;管理员登录进入管理员菜单,普通用户进入用户菜单

  • 注册

    ;设置用户名、密码、密保问题与答案

    ;选择身份(管理员或普通用户)

    ;注册成功后可立即登录

  • 找回密码

    ;根据用户名显示密保问题

    ;验证答案正确后可修改密码

    ;保证账户安全性


电影浏览与搜索;智能分类

  • 浏览电影

    ;系统根据当前时间自动将电影分类为热映、即将上映、已下架

    ;显示电影ID、名称、类型、时长及固定影厅

  • 搜索电影

    ;支持按名称或类型搜索

    ;使用忽略大小写的子串匹配函数 isSubsequenceIgnoreCase

    ;结果展示电影ID、名称、价格、类型及上映状态

这种设计便于用户快速查找感兴趣的电影,提高操作体验。


座位管理与可视化;直观操作

  • 使用二维数组 seats[ROWS][COLS] 表示座位

  • 座位显示矩阵清晰标注 O=可选座位X=已售

  • 用户和管理员都可查看座位状态

  • 管理员可修改座位状态,实现灵活控制

座位节点通过链表管理,保证多影厅、多场次场景下的灵活扩展。


系统交互设计亮点;友好与安全

  • 菜单式操作:数字选择,简洁明了

  • 输入验证:对数字范围、座位选择、密码输入均做有效性判断

  • 安全性:登录限制次数、密保找回密码、管理员权限控制

  • 交互提示:操作结果明确,成功或错误信息及时反馈

  • 灵活扩展:座位初始化、动态生成订单、自动分类电影

这些设计保证了系统使用的便捷性与安全性,同时方便后续扩展功能,如在线支付、优惠活动等。


总结;系统价值与使用体验

本项目通过合理的模块化设计,完成了一个功能完善的影院票务管理系统:

  • 支持管理员与普通用户不同角色操作

  • 提供全面的电影、座位及订单管理功能

  • 交互清晰,易于操作

  • 数据安全与持久化保障系统稳定性

  • UI模块与业务逻辑层、数据访问层紧密结合

系统不仅适合作为 C语言项目练手,也可作为小型影院管理系统的原型,具有较高的实用价值与学习参考意义。

entity.h

cs 复制代码
#ifndef ENTITY_H
#define ENTITY_H
#include <time.h>

#define HALLS 7
#define TIMES 4
#define ROWS 5
#define COLS 8

typedef enum {
    HALL_1, HALL_2, HALL_3, HALL_4, HALL_5, HALL_6, HALL_7
} HallScene;

typedef struct user {
    int id;
    char name[50];
    char password[50];
    int isAdmin;
    char securityQuestion[100];
    char securityAnswer[100];
    struct user* next;
} user;

typedef enum {
    MOVIE_AVAILABLE = 1,
    MOVIE_PLAYING,
    MOVIE_PREVIEW,
    MOVIE_OFF
} MovieStatus;

typedef struct movie {
    int id;
    char title[50];
    float price;
    char type[50];
    MovieStatus status;
    time_t startTime;
    time_t endTime;
    int duration;
    char director[50];
    char actor[100];
    HallScene fixedHall;
    struct movie* next;
} movie;

// ======================
// 你要的:场次座位节点
// ======================
typedef struct SeatNode {
    int hallId;          // 影厅编号
    int timeIdx;         // 场次编号
    int seats[ROWS][COLS];// 本场次座位矩阵
    struct SeatNode* next;
} SeatNode;

typedef struct order {
    int id;
    int userId;
    int movieId;
    char movieName[50];
    int quantity;
    float totalPrice;
    int hallId;
    int timeIdx;
    int row;
    int col;
    time_t timestamp;
    char ticketCode[10];
    struct order* next;
} order;

extern user* head;
extern user* currentUser;
extern movie* movieList;
extern order* orderList;
extern SeatNode* seatList;  // 场次座位链表

#endif

common.c

cs 复制代码
#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) {
	// 1. 安全判断
	if (outBuf == NULL || bufSize <= 0) {
		return;
	}

	// 2. 先清空缓冲区,防止乱码
	memset(outBuf, 0, bufSize);

	// 3. 缓冲区太小直接返回
	if (bufSize < 20) {
		strcpy(outBuf, "时间格式错误");
		return;
	}

	// 4. 获取时间
	struct tm* tinfo = localtime(&timestamp);
	if (tinfo == NULL) {
		strcpy(outBuf, "无效时间");
		return;
	}

	// 5. 标准格式,不严格、不报错
	strftime(outBuf, bufSize, "%Y-%m-%d %H:%M:%S", tinfo);
}

源.c

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "entity.h"
#include "dal.h"
#include "ui.h"
#include"bll.h"

int main()
{
    load_from_file();

    int choice;
    do {
        clearScreen();
        printf("\n====================================\n");
        printf("        影院票务管理系统\n");
        printf("====================================\n");
        printf(" 1. 用户登录\n");
        printf(" 2. 用户注册\n");
        printf(" 3. 找回密码\n");
        printf(" 0. 退出系统\n");
        printf("====================================\n");
        printf("请选择:");

        scanf("%d", &choice);
        while (getchar() != '\n');

        switch (choice)
        {
        case 1: login(); break;
        case 2: reg(); break;
        case 3: findPassword(); break;
        case 0:
            save_to_file();
            printf("\n已保存数据,欢迎下次使用!\n");
            break;
        default:
            printf("\n输入错误,请重新选择!\n");
            getchar();
            break;
        }
    } while (choice != 0);

    return 0;
}

肝不动了,好累,明天加工

相关推荐
笨笨马甲2 小时前
Qt 嵌入式开发快速搭建交叉编译环境
开发语言·qt
春日见2 小时前
Matlab快速入门 基础语法教学
java·开发语言·驱动开发·matlab·docker·计算机外设
张人玉2 小时前
C# 中的 MVC、MVP、MVVM 模式详解
开发语言·c#·mvc·mvvm·mvp
dgfhf2 小时前
高性能计算资源调度
开发语言·c++·算法
Lhan.zzZ2 小时前
Qt绘图探秘:如何避免多QPainter冲突引发的程序崩溃
开发语言·c++·qt
Ralph_Y2 小时前
C++:迭代器失效
开发语言·c++
smart margin2 小时前
Python安装教程
开发语言·python
weixin_307779132 小时前
OpenClaw-CN 安全增强方案:从理念到落地的全面剖析
开发语言·人工智能·算法·安全·语言模型
new code Boy2 小时前
前端核心基础汇总
开发语言·javascript·原型模式