C++课设:从零开始打造影院订票系统

news2025/6/9 12:22:50

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》
创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)
专栏介绍:《编程项目实战》

目录

    • 一、项目背景与需求分析
    • 二、系统架构设计与技术选型
      • 1. 三层架构设计
      • 2. 核心技术选型
      • 3. 数据结构设计
    • 三、核心类设计详解
      • 1. 电影信息类 (`Movie`)
      • 2. 影厅管理类 (`Cinema`)
      • 3. 座位状态管理
      • 4. 票务管理类 (`Ticket`)
    • 四、关键功能实现
      • 1. 智能选座算法
      • 2. 多票种优惠算法
      • 3. 票据生成与管理
      • 4. 退票机制实现
    • 五、完整代码展示
    • 六、总结与扩展建议
      • 1. 项目成果总结
      • 2. 性能优化建议
      • 3. 功能扩展方向
      • 4. 学习价值与应用场景

今天,将介绍如何使用C++开发一个功能完整的影院订票系统,包含电影排片展示、用户选座、票价结算、退票、多影厅管理等核心功能。代码完全兼容DevC++ 5.11,适合初学者学习和课程设计使用。

一、项目背景与需求分析

随着数字化时代的到来,传统的人工售票方式已经无法满足现代观众的需求。电影选座与订票系统的研究对于推动电影产业的数字化进程具有重要意义,一个高效便民的订票系统不仅能提升用户体验,还能为影院运营提供数据支持。

我们的影院订票系统需要满足以下核心功能需求

  • 🎬 电影信息管理:展示电影详情、时长、类型、票价等信息
  • 📅 排片管理:支持多影厅、多场次的排片安排
  • 💺 智能选座:提供可视化座位图,支持多座位选择
  • 💰 票价结算:支持成人票、学生票、老人票等不同优惠策略
  • 🎫 票务管理:生成电子票据,支持退票功能
  • 🏢 多影厅支持:管理不同规格的影厅布局

二、系统架构设计与技术选型

1. 三层架构设计

我们采用经典的三层架构模式,确保代码结构清晰、职责分离:

在这里插入图片描述

架构说明

  • 用户交互层:负责菜单展示、用户输入处理、界面显示
  • 业务逻辑层:核心功能实现,包括选座逻辑、票价计算、数据验证
  • 数据存储层:使用STL容器管理电影、影厅、场次、票据等数据

2. 核心技术选型

技术组件选择方案优势分析
容器管理vector<>动态数组,操作简单,内存连续
字符串处理string相比C字符串更安全便捷
枚举类型enum提高代码可读性和类型安全
输入输出iostream类型安全的输入输出流
格式化输出iomanip精确控制输出格式

3. 数据结构设计

核心数据实体关系

Movie(电影) ←→ ShowTime(场次) ←→ Cinema(影厅) ←→ Ticket(票据)
     ↑              ↑              ↑           ↑
   基础信息        排片信息        座位管理     交易记录

三、核心类设计详解

1. 电影信息类 (Movie)

设计思路:存储电影的基本属性,作为排片的基础数据。

class Movie {
public:
    string name;        // 电影名称
    string director;    // 导演
    int duration;       // 时长(分钟)
    string genre;       // 类型
    double basePrice;   // 基础票价
    
    // 构造函数支持快速初始化
    Movie(const string& n, const string& d, int dur, 
          const string& g, double price);
};

设计亮点

  • 使用const string&参数避免不必要的字符串拷贝
  • basePrice为基础价格,便于后续优惠计算

2. 影厅管理类 (Cinema)

设计思路:管理影厅布局和座位状态,提供座位操作的核心接口。

class Cinema {
private:
    vector<vector<SeatStatus> > seats;  // 二维座位矩阵
    
public:
    int cinemaId;      // 影厅编号
    string name;       // 影厅名称
    int rows, cols;    // 行数和列数
    
    void displaySeats() const;           // 显示座位图
    bool isSeatAvailable(int row, int col) const;  // 检查座位可用性
    void selectSeat(int row, int col);   // 选择座位
    void occupySeat(int row, int col);   // 占用座位
    void releaseSeat(int row, int col);  // 释放座位
};

技术细节

  • 使用二维vector模拟真实影厅布局
  • 座位状态使用枚举类型提高代码可读性
  • 提供完整的座位状态转换接口

3. 座位状态管理

enum SeatStatus {
    AVAILABLE = 0,  // 可用 - 绿色圆圈(O)
    OCCUPIED = 1,   // 已占用 - 红色叉号(X)  
    SELECTED = 2    // 已选择 - 黄色标记(S)
};

可视化座位图示例

在这里插入图片描述

4. 票务管理类 (Ticket)

设计思路:记录每张票的完整信息,支持退票查询。

class Ticket {
public:
    int ticketId;        // 票号(唯一标识)
    int showTimeId;      // 场次ID
    int row, col;        // 座位位置
    TicketType type;     // 票种(成人/学生/老人)
    double price;        // 实际票价
    string customerName; // 购票人姓名
    bool isValid;        // 票据有效性
};

四、关键功能实现

1. 智能选座算法

核心挑战:如何处理用户输入的座位格式(如"A5")并转换为数组索引?

// 座位输入解析算法
string seatInput;
cin >> seatInput;

char rowChar = seatInput[0];          // 获取行字母
int row = toupper(rowChar) - 'A';     // 转换为数组索引
int col = atoi(seatInput.substr(1).c_str()) - 1;  // 列号转索引

// 座位可用性检查
if (!cinema.isSeatAvailable(row, col)) {
    cout << "座位不可用!\n";
    continue;
}

算法优势

  • 支持大小写字母输入(toupper函数处理)
  • 使用atoisubstr精确解析数字部分
  • 自动处理数组索引转换(用户输入从1开始,数组从0开始)

2. 多票种优惠算法

业务逻辑:根据不同票种应用相应折扣策略。

TicketType ticketType;
double discount = 1.0;

switch (typeChoice) {
    case 1: ticketType = ADULT;   discount = 1.0; break;  // 成人票原价
    case 2: ticketType = STUDENT; discount = 0.8; break;  // 学生票8折
    case 3: ticketType = SENIOR;  discount = 0.6; break;  // 老人票6折
}

// 总价计算
double totalPrice = selectedSeats.size() * movie.basePrice * discount;

3. 票据生成与管理

设计思路:每张票都有唯一的票号,便于查询和退票操作。

// 批量生成票据
for (size_t i = 0; i < selectedSeats.size(); i++) {
    Ticket ticket;
    ticket.ticketId = nextTicketId++;          // 自增票号
    ticket.showTimeId = showChoice;
    ticket.row = selectedSeats[i].first;
    ticket.col = selectedSeats[i].second;
    ticket.type = ticketType;
    ticket.price = movie.basePrice * discount;
    ticket.customerName = customerName;
    ticket.isValid = true;
    
    tickets.push_back(ticket);
    cinema.occupySeat(ticket.row, ticket.col); // 同步更新座位状态
}

4. 退票机制实现

核心功能:通过票号快速定位并处理退票请求。

void refundTicket() {
    cout << "请输入要退票的票号: ";
    int ticketId;
    cin >> ticketId;
    
    // 线性查找票据
    for (size_t i = 0; i < tickets.size(); i++) {
        if (tickets[i].ticketId == ticketId && tickets[i].isValid) {
            Ticket& ticket = tickets[i];
            
            // 显示票据详情供用户确认
            displayTicketInfo(ticket);
            
            if (confirmRefund()) {
                ticket.isValid = false;                        // 标记票据无效
                cinemas[show.cinemaId].releaseSeat(           // 释放座位
                    ticket.row, ticket.col);
                cout << "退票成功!\n";
            }
            return;
        }
    }
    cout << "未找到有效票据!\n";
}

五、完整代码展示

下面是系统的完整源代码,可直接在DevC++ 5.11中编译运行:

#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <iomanip>
#include <algorithm>
#include <cstdlib>

using namespace std;

// 座位状态枚举
enum SeatStatus {
    AVAILABLE = 0,  // 可用
    OCCUPIED = 1,   // 已占用
    SELECTED = 2    // 已选择
};

// 票类型枚举
enum TicketType {
    ADULT = 0,      // 成人票
    STUDENT = 1,    // 学生票
    SENIOR = 2      // 老人票
};

// 电影信息类
class Movie {
public:
    string name;
    string director;
    int duration;  // 分钟
    string genre;
    double basePrice;
    
    Movie() : name(""), director(""), duration(0), genre(""), basePrice(0.0) {}
    
    Movie(const string& n, const string& d, int dur, const string& g, double price)
        : name(n), director(d), duration(dur), genre(g), basePrice(price) {}
};

// 场次信息类
class ShowTime {
public:
    int movieId;
    int cinemaId;
    string time;
    string date;
    
    ShowTime() : movieId(0), cinemaId(0), time(""), date("") {}
    
    ShowTime(int mid, int cid, const string& t, const string& d)
        : movieId(mid), cinemaId(cid), time(t), date(d) {}
};

// 票据类
class Ticket {
public:
    int ticketId;
    int showTimeId;
    int row;
    int col;
    TicketType type;
    double price;
    string customerName;
    bool isValid;
    
    Ticket() : ticketId(0), showTimeId(0), row(0), col(0), type(ADULT), 
               price(0.0), customerName(""), isValid(true) {}
};

// 影厅类
class Cinema {
public:
    int cinemaId;
    string name;
    int rows;
    int cols;
    vector<vector<SeatStatus> > seats;
    
    Cinema() : cinemaId(0), name(""), rows(0), cols(0) {}
    
    Cinema(int id, const string& n, int r, int c) 
        : cinemaId(id), name(n), rows(r), cols(c) {
        // 初始化座位
        seats.resize(rows);
        for (int i = 0; i < rows; i++) {
            seats[i].resize(cols, AVAILABLE);
        }
    }
    
    void displaySeats() const {
        cout << "\n======== " << name << " 座位图 ========\n";
        cout << "    ";
        for (int j = 0; j < cols; j++) {
            cout << setw(3) << (j + 1);
        }
        cout << "\n";
        
        for (int i = 0; i < rows; i++) {
            cout << setw(2) << (char)('A' + i) << "  ";
            for (int j = 0; j < cols; j++) {
                char symbol;
                switch (seats[i][j]) {
                    case AVAILABLE: symbol = 'O'; break;
                    case OCCUPIED:  symbol = 'X'; break;
                    case SELECTED:  symbol = 'S'; break;
                    default:        symbol = '?'; break;
                }
                cout << setw(3) << symbol;
            }
            cout << "\n";
        }
        cout << "\n图例: O-可选  X-已售  S-已选\n";
        cout << "================================\n";
    }
    
    bool isSeatAvailable(int row, int col) const {
        if (row < 0 || row >= rows || col < 0 || col >= cols) {
            return false;
        }
        return seats[row][col] == AVAILABLE;
    }
    
    void selectSeat(int row, int col) {
        if (isSeatAvailable(row, col)) {
            seats[row][col] = SELECTED;
        }
    }
    
    void occupySeat(int row, int col) {
        if (row >= 0 && row < rows && col >= 0 && col < cols) {
            seats[row][col] = OCCUPIED;
        }
    }
    
    void releaseSeat(int row, int col) {
        if (row >= 0 && row < rows && col >= 0 && col < cols) {
            seats[row][col] = AVAILABLE;
        }
    }
    
    void clearSelection() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (seats[i][j] == SELECTED) {
                    seats[i][j] = AVAILABLE;
                }
            }
        }
    }
};

// 订票系统主类
class TicketSystem {
private:
    vector<Movie> movies;
    vector<Cinema> cinemas;
    vector<ShowTime> showTimes;
    vector<Ticket> tickets;
    int nextTicketId;
    
public:
    TicketSystem() : nextTicketId(1) {
        initializeData();
    }
    
    void initializeData() {
        // 初始化电影数据
        movies.push_back(Movie("阿凡达2", "詹姆斯·卡梅隆", 192, "科幻", 45.0));
        movies.push_back(Movie("流浪地球3", "郭帆", 173, "科幻", 40.0));
        movies.push_back(Movie("你好,李焕英", "贾玲", 128, "喜剧", 35.0));
        movies.push_back(Movie("唐人街探案4", "陈思诚", 136, "悬疑", 38.0));
        
        // 初始化影厅数据
        cinemas.push_back(Cinema(1, "1号厅", 8, 12));
        cinemas.push_back(Cinema(2, "2号厅", 10, 15));
        cinemas.push_back(Cinema(3, "3号厅", 6, 10));
        
        // 初始化场次数据
        showTimes.push_back(ShowTime(0, 0, "09:30", "2025-06-08"));
        showTimes.push_back(ShowTime(0, 1, "14:20", "2025-06-08"));
        showTimes.push_back(ShowTime(1, 0, "11:45", "2025-06-08"));
        showTimes.push_back(ShowTime(1, 2, "16:10", "2025-06-08"));
        showTimes.push_back(ShowTime(2, 1, "19:30", "2025-06-08"));
        showTimes.push_back(ShowTime(3, 2, "21:15", "2025-06-08"));
        
        // 模拟一些已售座位
        cinemas[0].occupySeat(2, 5);
        cinemas[0].occupySeat(2, 6);
        cinemas[0].occupySeat(4, 3);
        cinemas[1].occupySeat(5, 7);
        cinemas[1].occupySeat(5, 8);
    }
    
    void displayMovies() const {
        cout << "\n========== 影片信息 ==========\n";
        for (size_t i = 0; i < movies.size(); i++) {
            cout << "影片 " << (i + 1) << ": " << movies[i].name << "\n";
            cout << "  导演: " << movies[i].director << "\n";
            cout << "  时长: " << movies[i].duration << "分钟\n";
            cout << "  类型: " << movies[i].genre << "\n";
            cout << "  票价: ¥" << fixed << setprecision(1) << movies[i].basePrice << "\n";
            cout << "------------------------------\n";
        }
    }
    
    void displayShowTimes() const {
        cout << "\n========== 排片信息 ==========\n";
        for (size_t i = 0; i < showTimes.size(); i++) {
            const ShowTime& show = showTimes[i];
            const Movie& movie = movies[show.movieId];
            const Cinema& cinema = cinemas[show.cinemaId];
            
            cout << "场次 " << (i + 1) << ": " << movie.name << "\n";
            cout << "  影厅: " << cinema.name << "\n";
            cout << "  时间: " << show.date << " " << show.time << "\n";
            cout << "  票价: ¥" << fixed << setprecision(1) << movie.basePrice << "\n";
            cout << "------------------------------\n";
        }
    }
    
    void bookTickets() {
        displayShowTimes();
        
        cout << "\n请选择场次 (1-" << showTimes.size() << "): ";
        int showChoice;
        cin >> showChoice;
        
        if (showChoice < 1 || showChoice > (int)showTimes.size()) {
            cout << "无效的场次选择!\n";
            return;
        }
        
        showChoice--; // 转换为数组索引
        const ShowTime& selectedShow = showTimes[showChoice];
        Cinema& cinema = cinemas[selectedShow.cinemaId];
        const Movie& movie = movies[selectedShow.movieId];
        
        cout << "\n您选择的场次:\n";
        cout << "电影: " << movie.name << "\n";
        cout << "影厅: " << cinema.name << "\n";
        cout << "时间: " << selectedShow.date << " " << selectedShow.time << "\n\n";
        
        // 显示座位图
        cinema.displaySeats();
        
        vector<pair<int, int> > selectedSeats;
        
        cout << "\n请选择座位 (输入行列,如 A5 表示A排5座,输入 0 结束选择):\n";
        string seatInput;
        while (true) {
            cout << "座位: ";
            cin >> seatInput;
            
            if (seatInput == "0") break;
            
            if (seatInput.length() < 2) {
                cout << "座位格式错误!请使用格式如 A5\n";
                continue;
            }
            
            char rowChar = seatInput[0];
            int row = toupper(rowChar) - 'A';
            int col = atoi(seatInput.substr(1).c_str()) - 1;
            
            if (!cinema.isSeatAvailable(row, col)) {
                cout << "座位不可用!\n";
                continue;
            }
            
            cinema.selectSeat(row, col);
            selectedSeats.push_back(make_pair(row, col));
            cinema.displaySeats();
        }
        
        if (selectedSeats.empty()) {
            cout << "未选择任何座位!\n";
            cinema.clearSelection();
            return;
        }
        
        // 选择票种和计算价格
        cout << "\n请选择票种:\n";
        cout << "1. 成人票 (原价)\n";
        cout << "2. 学生票 (8折)\n";
        cout << "3. 老人票 (6折)\n";
        cout << "选择 (1-3): ";
        
        int typeChoice;
        cin >> typeChoice;
        
        TicketType ticketType;
        double discount = 1.0;
        
        switch (typeChoice) {
            case 1: ticketType = ADULT; discount = 1.0; break;
            case 2: ticketType = STUDENT; discount = 0.8; break;
            case 3: ticketType = SENIOR; discount = 0.6; break;
            default: 
                cout << "无效选择,默认为成人票\n";
                ticketType = ADULT; 
                discount = 1.0; 
                break;
        }
        
        // 计算总价
        double totalPrice = selectedSeats.size() * movie.basePrice * discount;
        
        cout << "\n========== 订单确认 ==========\n";
        cout << "电影: " << movie.name << "\n";
        cout << "场次: " << selectedShow.date << " " << selectedShow.time << "\n";
        cout << "影厅: " << cinema.name << "\n";
        cout << "座位: ";
        for (size_t i = 0; i < selectedSeats.size(); i++) {
            cout << (char)('A' + selectedSeats[i].first) 
                 << (selectedSeats[i].second + 1);
            if (i < selectedSeats.size() - 1) cout << ", ";
        }
        cout << "\n";
        
        string typeStr;
        switch (ticketType) {
            case ADULT: typeStr = "成人票"; break;
            case STUDENT: typeStr = "学生票"; break;
            case SENIOR: typeStr = "老人票"; break;
        }
        cout << "票种: " << typeStr << "\n";
        cout << "数量: " << selectedSeats.size() << "张\n";
        cout << "总价: ¥" << fixed << setprecision(2) << totalPrice << "\n";
        cout << "==============================\n";
        
        cout << "确认购买?(y/n): ";
        char confirm;
        cin >> confirm;
        
        if (confirm == 'y' || confirm == 'Y') {
            cout << "请输入购票人姓名: ";
            string customerName;
            cin >> customerName;
            
            // 创建票据
            for (size_t i = 0; i < selectedSeats.size(); i++) {
                Ticket ticket;
                ticket.ticketId = nextTicketId++;
                ticket.showTimeId = showChoice;
                ticket.row = selectedSeats[i].first;
                ticket.col = selectedSeats[i].second;
                ticket.type = ticketType;
                ticket.price = movie.basePrice * discount;
                ticket.customerName = customerName;
                ticket.isValid = true;
                
                tickets.push_back(ticket);
                cinema.occupySeat(ticket.row, ticket.col);
            }
            
            cout << "\n购票成功!\n";
            cout << "票号: ";
            for (size_t i = tickets.size() - selectedSeats.size(); i < tickets.size(); i++) {
                cout << tickets[i].ticketId;
                if (i < tickets.size() - 1) cout << ", ";
            }
            cout << "\n请妥善保管票号,用于退票!\n";
        } else {
            // 取消购买,清除选择
            cinema.clearSelection();
            cout << "购买已取消!\n";
        }
    }
    
    void refundTicket() {
        if (tickets.empty()) {
            cout << "暂无票据记录!\n";
            return;
        }
        
        cout << "请输入要退票的票号: ";
        int ticketId;
        cin >> ticketId;
        
        bool found = false;
        for (size_t i = 0; i < tickets.size(); i++) {
            if (tickets[i].ticketId == ticketId && tickets[i].isValid) {
                Ticket& ticket = tickets[i];
                
                // 显示票据信息
                const ShowTime& show = showTimes[ticket.showTimeId];
                const Movie& movie = movies[show.movieId];
                const Cinema& cinema = cinemas[show.cinemaId];
                
                cout << "\n========== 票据信息 ==========\n";
                cout << "票号: " << ticket.ticketId << "\n";
                cout << "购票人: " << ticket.customerName << "\n";
                cout << "电影: " << movie.name << "\n";
                cout << "场次: " << show.date << " " << show.time << "\n";
                cout << "影厅: " << cinema.name << "\n";
                cout << "座位: " << (char)('A' + ticket.row) << (ticket.col + 1) << "\n";
                cout << "票价: ¥" << fixed << setprecision(2) << ticket.price << "\n";
                cout << "==============================\n";
                
                cout << "确认退票?(y/n): ";
                char confirm;
                cin >> confirm;
                
                if (confirm == 'y' || confirm == 'Y') {
                    ticket.isValid = false;
                    cinemas[show.cinemaId].releaseSeat(ticket.row, ticket.col);
                    cout << "退票成功!退款金额: ¥" << fixed << setprecision(2) << ticket.price << "\n";
                } else {
                    cout << "退票已取消!\n";
                }
                
                found = true;
                break;
            }
        }
        
        if (!found) {
            cout << "未找到有效票据!\n";
        }
    }
    
    void displayMyTickets() const {
        cout << "请输入购票人姓名: ";
        string name;
        cin >> name;
        
        cout << "\n========== " << name << " 的票据 ==========\n";
        bool hasTickets = false;
        
        for (size_t i = 0; i < tickets.size(); i++) {
            const Ticket& ticket = tickets[i];
            if (ticket.customerName == name && ticket.isValid) {
                const ShowTime& show = showTimes[ticket.showTimeId];
                const Movie& movie = movies[show.movieId];
                const Cinema& cinema = cinemas[show.cinemaId];
                
                cout << "票号: " << ticket.ticketId << "\n";
                cout << "电影: " << movie.name << "\n";
                cout << "场次: " << show.date << " " << show.time << "\n";
                cout << "影厅: " << cinema.name << "\n";
                cout << "座位: " << (char)('A' + ticket.row) << (ticket.col + 1) << "\n";
                cout << "票价: ¥" << fixed << setprecision(2) << ticket.price << "\n";
                cout << "------------------------------\n";
                hasTickets = true;
            }
        }
        
        if (!hasTickets) {
            cout << "未找到有效票据!\n";
        }
    }
    
    void displayMenu() const {
        cout << "\n========== 影院订票系统 ==========\n";
        cout << "1. 查看影片信息\n";
        cout << "2. 查看排片信息\n";
        cout << "3. 购票\n";
        cout << "4. 退票\n";
        cout << "5. 查看我的票据\n";
        cout << "0. 退出系统\n";
        cout << "=================================\n";
        cout << "请选择功能 (0-5): ";
    }
    
    void run() {
        cout << "欢迎使用影院订票系统!\n";
        
        int choice;
        do {
            displayMenu();
            cin >> choice;
            
            switch (choice) {
                case 1:
                    displayMovies();
                    break;
                case 2:
                    displayShowTimes();
                    break;
                case 3:
                    bookTickets();
                    break;
                case 4:
                    refundTicket();
                    break;
                case 5:
                    displayMyTickets();
                    break;
                case 0:
                    cout << "感谢使用影院订票系统!再见!\n";
                    break;
                default:
                    cout << "无效选择,请重新输入!\n";
                    break;
            }
            
            if (choice != 0) {
                cout << "\n按回车键继续...";
                cin.ignore();
                cin.get();
            }
            
        } while (choice != 0);
    }
};

int main() {
    TicketSystem system;
    system.run();
    return 0;
}

在这里插入图片描述

影片信息:

在这里插入图片描述

排片信息:

在这里插入图片描述

购票:

在这里插入图片描述

六、总结与扩展建议

1. 项目成果总结

通过本项目的开发,我们成功实现了一个功能完整的影院订票系统:

✅ 实现的核心功能

  • 电影信息展示与排片管理
  • 可视化座位图与智能选座
  • 多票种优惠策略与票价计算
  • 完整的购票流程与电子票据生成
  • 退票功能与座位状态同步更新
  • 多影厅支持与票据查询管理

2. 性能优化建议

🚀 算法优化

// 当前:线性查找票据 O(n)
// 优化:使用map<int, Ticket>按票号索引 O(log n)
map<int, Ticket> ticketMap;

// 当前:座位状态实时计算
// 优化:缓存可用座位数量,减少重复计算
int availableSeatsCount;

💾 数据持久化

// 扩展:文件存储支持
void saveToFile(const string& filename);
void loadFromFile(const string& filename);

// 扩展:JSON格式数据交换
void exportToJSON(const string& filename);
void importFromJSON(const string& filename);

3. 功能扩展方向

🎬 业务功能扩展

  1. 高级排片管理

    • 支持多日期排片
    • 自动计算场次间隔
    • 热门电影智能推荐位置
  2. 用户体验优化

    • 座位推荐算法(最佳观影位置)
    • 批量选座功能
    • 座位锁定机制(防止冲突)
  3. 商业功能完善

    • 会员积分系统
    • 套餐优惠(爆米花+饮料)
    • 团体票优惠策略

🔧 技术架构升级

// 设计模式应用
class TicketPriceStrategy {  // 策略模式
public:
    virtual double calculatePrice(double basePrice) = 0;
};

class Observer {  // 观察者模式
public:
    virtual void update(const string& event) = 0;
};

class TicketFactory {  // 工厂模式
public:
    static Ticket* createTicket(TicketType type);
};

4. 学习价值与应用场景

📚 教育价值

  • C++基础语法:类、继承、多态、STL容器
  • 软件工程实践:需求分析、架构设计、模块化开发
  • 算法与数据结构:二维数组、枚举、查找算法
  • 项目管理经验:版本控制、代码规范、文档编写

💡 小贴士:想要快速运行本项目?只需要:

  1. 打开DevC++ 5.11
  2. 新建项目,复制完整代码
  3. F11编译运行
  4. 开始体验完整的订票流程!

🔗 项目源码:完整代码已在文中提供,支持直接复制使用。如有问题,欢迎在评论区交流讨论!

创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2405351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【计算机网络】数据链路层-滑动窗口协议

数据链路层滑动窗口协议 1. 三种协议对比表 特性停止-等待协议GBN协议SR协议窗口大小发送 1&#xff0c;接收 1发送 W (1<W≤2ⁿ-1)&#xff0c;接收 1发送 C&#xff0c;接收 R确认方式单个确认累积确认选择性确认重传策略超时重传回退N帧重传选择性重传接收缓冲区…

在linux系统上,如何安装Elasticsearch?

1.问题描述 当尝试连接时报错&#xff0c;报错内容为&#xff1a; elastic_transport.ConnectionError: Connection error caused by: ConnectionError(Connection error caused by: NewConnectionError(<urllib3.connection.HTTPConnection object at 0x7fd808b179d0>:…

wpf Behaviors库实现支持多选操作进行后台绑定数据的ListView

<ListView ItemsSource"{Binding SchemeItems}" SelectionMode"Extended" VerticalAlignment"Stretch" HorizontalAlignment"Stretch"><ListView.ContextMenu><ContextMenu><MenuItem Header"删除" …

《Vuejs设计与实现》第 8 章(挂载与更新)

目录 8.1 挂载子节点与属性 8.2 HTML Attributes 与 DOM Properties 8.3 设置元素属性的正确方式 8.4 处理 class 属性 8.5 卸载操作 8.6 区分 vnode 类型 8.7 事件处理优化 8.8 事件冒泡与更新时机问题 8.9 子节点的更新 8.10 文本节点和注释节点 8.11 片段&#xf…

Ubuntu20.04中 Redis 的安装和配置

Ubuntu20.04 中 Redis 的安装和配置 Ubuntu 安装 MySQL 及其配置 1. Redis 的安装 更新系统包列表并安装 Redis &#xff1a; # 更新包管理工具 sudo apt update# -y&#xff1a;自动确认所有提示&#xff08;非交互式安装&#xff09; sudo apt install -y redis-server测…

实验四:图像灰度处理

实验四 图像处理实验报告 目录 实验目的实验内容 原理描述Verilog HDL设计源代码Testbench仿真代码及仿真结果XDC文件配置下板测试 实验体会实验照片 实验目的 在实验三的基础上&#xff0c;将图片显示在显示器上&#xff0c;并进行灰度处理。 实验内容 原理描述 1. 图片的…

解析“与此站点的连接不安全”警告:成因与应对策略

一、技术本质&#xff1a;SSL/TLS协议的信任链断裂 现代浏览器通过SSL/TLS协议建立加密通信&#xff0c;其核心在于证书颁发机构&#xff08;CA&#xff09;构建的信任链。当用户访问网站时&#xff0c;浏览器会验证服务器证书的有效性&#xff0c;包括&#xff1a; 证书链完…

⚡️ Linux Docker 基本命令参数详解

&#x1f433; Linux Docker 基本命令参数详解 &#x1f4d8; 1. Docker 简介 Docker 是一个开源的容器化平台&#xff0c;它通过将应用及其依赖打包到一个轻量级、可移植的容器中&#xff0c;从而实现跨平台运行。Docker 采用 C/S 架构&#xff0c;服务端称为 Docker Daemon&a…

做题笔记(ctfshow)

一。ctfshow web13 文件扫描 存在upload.php.bak <?php header("content-type:text/html;charsetutf-8");$filename $_FILES[file][name];$temp_name $_FILES[file][tmp_name];$size $_FILES[file][size];$error $_FILES[file][error];$arr pathinfo($fi…

Agent短期记忆的几种持久化存储方式

今天给大家讲一下关于Agent长期对话的几种持久化存储方式&#xff0c;之前的文章给大家说过短期记忆和长期记忆&#xff0c;短期记忆基于InMemorySaver做checkpointer&#xff08;检查点&#xff09;&#xff0c;短期记忆 &#xff08;线程级持久性&#xff09; 使代理能够跟踪…

Git 常见操作

目录 1.git stash 2.合并多个commit 3. git commit -amend (后悔药) 4.版本回退 5.merge和rebase 6.cherry pick 7.分支 8.alias 1.git stash git-stash操作_git stash 怎么增加更改内容-CSDN博客 2.合并多个commit 通过git bash工具交互式操作。 1.查询commit的c…

从 ClickHouse、Druid、Kylin 到 Doris:网易云音乐 PB 级实时分析平台降本增效

网易云音乐基于 Apache Doris 替换了早期架构中 Kylin、Druid、Clickhouse、Elasticsearch、HBase 等引擎&#xff0c;统一了实时分析架构&#xff0c;并广泛应用于广告实时数仓、日志平台和会员报表分析等典型场景中&#xff0c;带来导入性能提升 3&#xff5e;30 倍&#xff…

Facebook接入说明

Facebook 原生 Messenger 聊天消息接入到一洽对话中 1、创建 Facebook 主页 进入 https://www.facebook.com/pages/create 页面根据提示创建主页&#xff08;如果已经有待用主页&#xff0c;可跳过&#xff09; 2、授权对话权限 1、向您的一洽负责人获取 Facebook 授权链接 2、…

Grafana 地图本土化方案:使用高德地图API平替GeoMap地图指南

[ 知识是人生的灯塔&#xff0c;只有不断学习&#xff0c;才能照亮前行的道路 ] &#x1f4e2; 大家好&#xff0c;我是 WeiyiGeek&#xff0c;一名深耕安全运维开发&#xff08;SecOpsDev&#xff09;领域的技术从业者&#xff0c;致力于探索DevOps与安全的融合&#xff08;De…

3 个优质的终端 GitHub 开源工具

1、Oh My Zsh Oh My Zsh 是一个帮助你管理和美化 zsh 终端的开源工具。它让你的终端更炫酷、更高效。安装后&#xff0c;你可以快速使用各种插件和主题&#xff0c;比如常见的 git 命令简化、支持多种编程语言工具等&#xff0c;每次打开终端都会有惊喜。无论你是开发者还是普…

亚马逊AWS云服务器高效使用指南:最大限度降低成本的实战策略

对于初次接触云计算的企业或个人开发者而言&#xff0c;亚马逊云服务器&#xff08;Amazon EC2&#xff09;的配置与成本控制往往面临双重挑战&#xff1a;既要理解数百种实例规格的技术参数&#xff0c;又要避免因配置不当导致的资源浪费。本文将深入剖析AWS EC2的核心使用场景…

Android设备推送traceroute命令进行网络诊断

文章目录 工作原理下载traceroute for android推送到安卓设备执行traceroutetraceroute www.baidu.com Traceroute&#xff08;追踪路由&#xff09; 是一个用于网络诊断的工具&#xff0c;主要用于追踪数据包从源主机到目标主机所经过的路由路径&#xff0c;以及每一跳&#x…

github开源协议选择

文章目录 怎么选协议宽松型协议 Permissive Licenses传染型协议 怎么选协议 希望代码被广泛使用&#xff0c;允许闭源 MIT、Apache 2.0、BSD需要专利保护 Apache 2.0强制开源衍生作品 GPL、AGPL开发库&#xff0c;允许闭源调用 LGPL云服务项目&#xff0c;防止白嫖 AGPL企业级…

详解Jenkins Pipeline 中git 命令的使用方法

在 Jenkins Pipeline 中&#xff0c;git 命令是用于从版本控制系统&#xff08;如 Git&#xff09;拉取代码的核心步骤。其用法灵活&#xff0c;支持多种配置参数&#xff0c;但需要遵循 Jenkins 流水线语法规范。 一、基础语法 1. 声明式流水线&#xff08;Declarative Pipe…

【Mini-F5265-OB开发板试用测评】显示RTC日历时钟

一、前言 本章节承接上期的【Mini-F5265-OB开发板试用测评】硬件SPI方式驱动LCD屏帖子上。灵动微官方提供的“LibSamples_MM32F5260_V0.10.2”SDK中包含一个RTC日历的参考例程&#xff0c;因此将该功能移植到上期工程中&#xff0c;即可达成在LCD屏上显示RTC日历时钟。 官方提…