免责声明
以下内容可能引起不适,请18岁以下儿童在大人配同下观看
主要内容:
设计并实现银行取号模拟系统,模拟取号的整个过程,实现取号、排队、服务、及管理等功能。系统能够记录用户及工作人员信息的统计和分析,可以进一步优化银行营业厅的排队问题,提高银行业务办理效率。
基本要求:
(1)首先设计一个含有多个菜单项主控菜单子程序,以链接系统的各项子功能,方便用户使用本系统。
(2)采用链式队列存储银行排队系统中的顾客号信息,用结构数组存放办理银行业务的窗口号信息。
(3)本系统分为一下6个功能模块,分别是:顾客到达,顾客离开,查看业务办理,查看排队情况,系统查询,退出。
关键问题描述
(1)如何将不同优先级的客户放入到对应最优窗口。
(2)如何模拟计算客户的到达,服务,离开的过程。
(3)如何判断当前时间下客户是否已经离开队列。
(4)如何模拟计算客户的等待时间。
(5)如何同一各队列的时间线
拟采用解决问题的方法
(1)建立不同的队列来存储不同优先及的客户,对于优先级相同的客户我们将队列在排人数排序确保客户进入最优队列。
(2)当客户进入时更新当前时间,并建立离开队列,检查客户是否离开,保证各队列的时间线统一。
(3)经验总结,通过大量的实践结合其中的具体情况,进行归纳与分析, 使之系统化、理论化,上升为经验。
各函数申明及作用
(1)bool comp1(user x, user y) //用于将顾客按到达时间排序
(2)bool comp2(Window x, Window y) //用于选择出最佳窗口
(3)void init() //初始化各变量
(4)void transform(int num) //时间转化
(5)void show() //查看当前各窗口人数
(6)void count_time(user& p) //计算离开时间和更新等待时间
(7)void check_leave(int time) //检查队列中是否有离开的人
(8)void enter_bank(user& p) //进入银行取票
(9)void charts(int n) //打印表单
(10)void automatic() //自动模式
(11)void manual() //手动模式
(12)int manual_interface() //手动模式下的界面
(13)void welcome() //欢迎界面
(14)void strat_interface()//开始动画
(15)main()//主函数
源码
strat_interface.h(开机动画可不要)
#pragma once
#include<iostream>
#include <windows.h>
#include <deque>
#include <vector>
void SetWindowSize(int cols, int lines){//设置窗口大小system("title 银行");//设置窗口标题char cmd[30];sprintf_s(cmd, "mode con cols=%d lines=%d", cols * 2, lines);//一个图形■占两个字符,故宽度乘以2system(cmd);//system(mode con cols=88 lines=88)设置窗口宽度和高度
}void SetCursorPosition(const int x, const int y){//设置光标位置COORD position;position.X = x * 2;position.Y = y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);
}void SetColor(int colorID){//设置文本颜色SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colorID);
}void SetBackColor(){//设置文本背景色SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE |BACKGROUND_BLUE |BACKGROUND_GREEN |BACKGROUND_RED);
}class Point{
public:Point() {}Point(const int x, const int y) : x(x), y(y) {}void Print();void PrintCircular();void Clear();void ChangePosition(const int x, const int y);bool operator== (const Point& point) { return (point.x == this->x) && (point.y == this->y); }int GetX() { return this->x; }int GetY() { return this->y; }
private:int x, y;
};void Point::Print(){//输出方块SetCursorPosition(x, y);std::cout << "■";
}void Point::PrintCircular(){//输出圆形SetCursorPosition(x, y);std::cout << "●";
}void Point::Clear(){//清除输出SetCursorPosition(x, y);std::cout << " ";
}void Point::ChangePosition(const int x, const int y){//改变坐标this->x = x;this->y = y;
}class StartInterface{
public:StartInterface() : speed(35) {startsnake.emplace_back(Point(0, 14));//Éßstartsnake.emplace_back(Point(1, 14));startsnake.emplace_back(Point(2, 15));startsnake.emplace_back(Point(3, 16));startsnake.emplace_back(Point(4, 17));startsnake.emplace_back(Point(5, 18));startsnake.emplace_back(Point(6, 17));startsnake.emplace_back(Point(7, 16));startsnake.emplace_back(Point(8, 15));startsnake.emplace_back(Point(9, 14));textsnake.emplace_back(Point(-22, 14));//Btextsnake.emplace_back(Point(-22, 15));textsnake.emplace_back(Point(-22, 16));textsnake.emplace_back(Point(-22, 17));textsnake.emplace_back(Point(-22, 18));textsnake.emplace_back(Point(-21, 14));textsnake.emplace_back(Point(-21, 16));textsnake.emplace_back(Point(-21, 18));textsnake.emplace_back(Point(-20, 14));textsnake.emplace_back(Point(-20, 16));textsnake.emplace_back(Point(-20, 18));textsnake.emplace_back(Point(-19, 15));textsnake.emplace_back(Point(-19, 16));textsnake.emplace_back(Point(-19, 17));textsnake.emplace_back(Point(-17, 18));//Atextsnake.emplace_back(Point(-17, 17));textsnake.emplace_back(Point(-16, 16));textsnake.emplace_back(Point(-15, 15));textsnake.emplace_back(Point(-15, 16));textsnake.emplace_back(Point(-14, 14));textsnake.emplace_back(Point(-14, 16));textsnake.emplace_back(Point(-13, 15));textsnake.emplace_back(Point(-13, 16));textsnake.emplace_back(Point(-12, 16));textsnake.emplace_back(Point(-11, 17));textsnake.emplace_back(Point(-11, 18));textsnake.emplace_back(Point(-9, 14));//Ntextsnake.emplace_back(Point(-9, 15));textsnake.emplace_back(Point(-9, 16));textsnake.emplace_back(Point(-9, 17));textsnake.emplace_back(Point(-9, 18));textsnake.emplace_back(Point(-8, 15));textsnake.emplace_back(Point(-7, 16));textsnake.emplace_back(Point(-6, 17));textsnake.emplace_back(Point(-5, 14));textsnake.emplace_back(Point(-5, 15));textsnake.emplace_back(Point(-5, 16));textsnake.emplace_back(Point(-5, 17));textsnake.emplace_back(Point(-5, 18));textsnake.emplace_back(Point(-7 - 1 + 5, 14));//Ktextsnake.emplace_back(Point(-7 - 1 + 5, 15));textsnake.emplace_back(Point(-7 - 1 + 5, 16));textsnake.emplace_back(Point(-7 - 1 + 5, 17));textsnake.emplace_back(Point(-7 - 1 + 5, 18));textsnake.emplace_back(Point(-6 - 1 + 5, 16));textsnake.emplace_back(Point(-5 - 1 + 5, 15));textsnake.emplace_back(Point(-5 - 1 + 5, 17));textsnake.emplace_back(Point(-4 - 1 + 5, 14));textsnake.emplace_back(Point(-4 - 1 + 5, 18));}void PrintFirst();void PrintSecond();void PrintThird();void PrintText();void ClearText();void Action();
private:std::deque<Point> startsnake;//开始动画中的bankstd::vector<Point> textsnake;//开始动画中的文字int speed;//动画的速度
};void StartInterface::PrintFirst(){for (auto& point : startsnake){point.Print();Sleep(speed);}
}void StartInterface::PrintSecond(){for (int i = 10; i != 40; ++i){int j = (((i - 2) % 8) < 4) ? (15 + (i - 2) % 8) : (21 - (i - 2) % 8);startsnake.emplace_back(Point(i, j));startsnake.back().Print();startsnake.front().Clear();startsnake.pop_front();Sleep(speed);}
}void StartInterface::PrintThird(){while (!startsnake.empty() || textsnake.back().GetX() < 33) {if (!startsnake.empty()) {startsnake.front().Clear();startsnake.pop_front();}ClearText();//清除已有文字PrintText();//绘制更新位置后的文字Sleep(speed);}
}void StartInterface::PrintText(){for (auto& point : textsnake){if (point.GetX() >= 0)point.Print();}
}void StartInterface::ClearText(){for (auto& point : textsnake){//清除的同时将文字整体向右移动一格if (point.GetX() >= 0)point.Clear();point.ChangePosition(point.GetX() + 1, point.GetY());}
}void StartInterface::Action(){PrintFirst();PrintSecond();PrintThird();
}
LinkQueue.h
#pragma oncetemplate <typename T> struct QueueNode {T data;//值域QueueNode* prev;QueueNode* next;
};template <typename T> class LinkQueue {
private:QueueNode<T>* head;//头标志QueueNode<T>* tail;//尾标志int _size;//队列中元素个数void Init();//初始化
public:LinkQueue() { Init(); };//构造函数~LinkQueue();//析构函数bool empty()const { return _size == 0; };//判断是否为空int size()const { return _size; };//返回队列元素个数void push(const T&);//加入队列void pop();//弹出队列T front();//返回队列首元素T back();//返回队列末元素
};template <typename T> void LinkQueue<T>::Init() {head = new QueueNode <T>;//创建头标志tail = new QueueNode <T>;//创建尾标志head->prev = NULL;head->next = tail;tail->prev = head;tail->next = NULL;_size = 0;
}template <typename T> LinkQueue<T>::~LinkQueue() {while (_size != 0) {QueueNode<T>* t;t = head->next;head->next = head->next->next;head->next->prev = head;delete t;_size--;}
}template <typename T> void LinkQueue<T>::push(const T& e) {QueueNode<T>* t = new QueueNode<T>;//t->data = e;//值域存放传入元素t->prev = tail->prev;//新加入队列的上一位是之前的对尾t->next = tail;//新加入队列的下一位是对尾tail->prev->next = t;//尾标志的前一位的下位一位是新加入队列的元素tail->prev = t;//尾标志的前一位是新加入队列的元素_size++;
}template <typename T> void LinkQueue<T>::pop() {if (_size != 0) {QueueNode<T>* t;t = head->next;//临时变量t指向队首元素head->next = head->next->next;//改变队头head->next->prev = head;//队首元素的下一位的上一位是头标志delete t;_size--;//维护_size变量}
}template <typename T> T LinkQueue<T>::front() {//if (_size==0)return (T)NULL;return head->next->data;
}template <typename T> T LinkQueue<T>::back() {//if (_size == 0)return (T)NULL;return tail->prev->data;
}
main.cpp
#include <iostream>
#include"LinkQueue.h"
#include"strat_interface.h"
#include<algorithm>
#include<time.h>
#include<string>
#include<cstdio>
#include<conio.h>
using namespace std;
struct user {string name;//用户编号int arrive_time;//用户到达时间bool identity;//顾客身份int cost_time;//办理业务花费时间int leave_time;//离开时间int enter_window;//进入的窗口3代表VIP窗口int wait_time;//等待时间
};struct Window {int num;//窗口号int wait_user;//窗口等待人数
};LinkQueue<user> window_normal[3];//普通队列
LinkQueue<user> window_VIP;//VIP队列
LinkQueue<user> leave;//记录每个人离开队列的时间,用于判断顾客是否离开
user Person[1000];//实例化顾客对象
int time_now;//记录当前时间,时间从9:00-17:00
int person_num;//记录顾客人数//将顾客按到达时间排序
bool comp1(user x, user y) {return x.arrive_time < y.arrive_time;
}//选择出最佳窗口
bool comp2(Window x, Window y) {if (x.wait_user == y.wait_user) {//若窗口等待人数相同时按窗口号大小排序return x.num < y.num;}return x.wait_user < y.wait_user;//否则按窗口等待人数排序
}//初始化各变量
void init() {time_now = 0;//设置开始时间为0person_num = 0;while (!window_normal[0].empty()) { window_normal[0].pop(); }while (!window_normal[1].empty()) { window_normal[1].pop(); }while (!window_normal[2].empty()) { window_normal[2].pop(); }while (!window_VIP.empty()) { window_VIP.pop(); }while (!leave.empty()) { leave.pop(); }
}//时间转化
void transform(int num) {cout << 9 + num / 60 << ":" << num % 60 + 1;//cout << int(num) << ":" << (num*100-(int)num*100);
}//查看当前各窗口人数
void show() {cout << "●●■■■■■■■■■■■●●" << endl;cout << "■■目前各窗口排队情况如下■■" << endl;;cout << "●●■■■■■■■■■■■●●" << endl;cout << "●● VIP窗口等待人数:" << window_VIP.size() << "人 ●●"<<endl;cout << "●● 1号窗口等待人数:" << window_normal[0].size() << "人 ●●" << endl;cout << "●● 2号窗口等待人数:" << window_normal[1].size() << "人 ●●" << endl;cout << "●● 3号窗口等待人数:" << window_normal[2].size() << "人 ●●" << endl;cout << "●●●●●●●●●●●●●●●" << endl;
}//计算离开时间和更新等待时间
void count_time(user& p) {if (p.enter_window == 3) {//进入的窗口为VIP窗口if (!window_VIP.empty()) {//离开时间=队列中上一位用户离开时间+花费时间if (window_VIP.back().leave_time < p.arrive_time)p.leave_time = p.arrive_time + p.cost_time;else p.leave_time = window_VIP.back().leave_time + p.cost_time;}else p.leave_time = p.arrive_time + p.cost_time;//队列为 空离开时间=花费时间p.wait_time = p.leave_time - p.arrive_time - p.cost_time;//更新等待时间}else {//为普通窗口if (!window_normal[p.enter_window].empty()) {if (window_normal[p.enter_window].back().leave_time < p.arrive_time)p.leave_time = p.arrive_time + p.cost_time;else p.leave_time = window_normal[p.enter_window].back().leave_time + p.cost_time;}else p.leave_time = p.arrive_time + p.cost_time;//队列为空 离开时间=到达时间+花费时间p.wait_time = p.leave_time - p.arrive_time - p.cost_time;//更新等待时间}
}//检查队列中是否有离开的人
void check_leave(int time) {int t_size1 = window_VIP.size();while (t_size1--) {user temp = window_VIP.front();if (temp.leave_time <= time_now) {window_VIP.pop();cout << "用户" << temp.name << "在"; transform(temp.leave_time); cout << "离开了VIP号窗口" << endl;}else break;}for (int i = 0; i < 3; i++) {int t_size2 = window_normal[i].size();while (t_size2--) {user temp = window_normal[i].front();if (temp.leave_time <= time_now) {window_normal[i].pop();cout << "用户" << temp.name << "在"; transform(temp.leave_time); cout << "离开了" << temp.enter_window + 1 << "号窗口" << endl;}else break;}}
}//进入银行取票
void enter_bank(user& p) {time_now = p.arrive_time;//新用户到达更新当前时间check_leave(time_now);//检查当前时间下各窗口的情况cout << "用户" << p.name << "在"; transform(p.arrive_time); cout << "到达了银行,";cout << "办理业务需要花费" << p.cost_time << "分钟,用户身份是";p.identity ? cout << "VIP用户" << endl : cout << "普通用户" << endl;show();//展示当前时间各个窗口的情况if (p.identity) {//若为VIP用户p.enter_window = 3;count_time(p);if (p.leave_time > 480) {cout << "银行关门前不能办理完您的业务,请您次日再来" << endl << endl;}else {cout << "用户" << p.name << "为VIP用户,进入了VIP窗口" << endl << endl;cout << "您排在VIP窗口的第" << window_VIP.size() + 1 << "号,大约需要等待" << p.wait_time << "分钟,请您耐心等候" << endl;window_VIP.push(p);//加入到VIP队列中show();cout << endl << endl;}}else {Window t[3];t[0].wait_user = window_normal[0].size(); t[0].num = 0;t[1].wait_user = window_normal[1].size(); t[1].num = 1;t[2].wait_user = window_normal[2].size(); t[2].num = 2;sort(t, t + 3, comp2);cout << "当前最少用户的窗口号是" << t[0].num + 1 << "号窗口" << endl;p.enter_window = t[0].num;count_time(p);if (p.leave_time > 480) {cout << "银行关门前不能办理完您的业务,请您次日再来" << endl << endl;}else {cout << "用户" << p.name << "进入了" << p.enter_window + 1 << "号窗口" << endl;cout << "您排在普通窗口" << p.enter_window + 1 << "的第" << window_normal[p.enter_window].size() + 1 << "号,大约需要等待" << p.wait_time << "分钟,请您耐心等候" << endl ;window_normal[t[0].num].push(p);//加入到相应的窗口队列中show();cout << endl << endl;}}
}//打印表单
void charts(int n) {cout << "●●●●●●●●●●●●●●" << endl;cout << "●今日总共为" << n << "位顾客办理●" << endl;cout << "●●●●●●●●●●●●●●" << endl;cout << "用户名\t到达时间\t等待时间\t花费时间\t离开时间\t办理窗口\t\t评价" << endl;for (int i = 0; i < n; i++) {cout << Person[i].name << "\t";transform(Person[i].arrive_time); cout << "\t\t";cout << Person[i].wait_time << "\t\t";cout << Person[i].cost_time << "\t\t";transform(Person[i].leave_time); cout << "\t\t";int num = Person[i].wait_time;if (Person[i].enter_window == 3)cout << "VIP窗口\t\t\t";else cout << "普通窗口" << Person[i].enter_window + 1 << "\t\t";if (0 <= num && num <= 5)cout << "*****" << endl;else if (6 <= num && num <= 10)cout << "****" << endl;else if (11 <= num && num <= 15)cout << "***" << endl;else if (16 < num && num <= 20)cout << "**" << endl;else cout << "*" << endl;}
}//自动模式
void automatic() {srand(time(0));person_num = rand() % 150 + 150;//每天用户数量最少150最多300for (int i = 0; i < person_num; i++) {//随机构造用户Person[i].arrive_time = rand() % 480;//9:00-17:00//Person[i].arrive_time = (rand()%9)+8.0+double((rand()%60)/100.0);Person[i].cost_time = (rand() % 8) + 2.0;int t_is = rand();Person[i].identity = (t_is % 3 == 0) && (t_is % 5 == 0);Person[i].name = to_string(i);}sort(Person, Person + person_num, comp1);//对构造的用户按时间进行排序for (int i = 0; i < person_num; i++) {//依次将用户放入银行enter_bank(Person[i]);}system("pause");system("cls");charts(person_num);
}int manual_interface();
//手动模式
void manual() {while (1) {double t;cout << "■■■■■■■■■■■■■■■■■" << endl;cout << "■ 姓 名 ■"; cin >> Person[person_num].name;cout << "■ 到达时间(如13.05) ■"; cin >> t;double temp = int(t - 9.0) * 60 + (t - int(t)) * 100;if (temp < time_now) {cout << "请按时间先后顺序输入" << endl;system("pause");system("cls");continue;}Person[person_num].arrive_time = temp;cout << "■ 花费时间 ■"; cin >> Person[person_num].cost_time;cout << "■ 顾客身份(0-普通,1-VIP) ■"; cin >> Person[person_num].identity;cout << "■■■■■■■■■■■■■■■■■" << endl;system("pause");system("cls");enter_bank(Person[person_num]);person_num++;int n = manual_interface();if (n == 4)break;}
}//手动模式下的界面
int manual_interface() {cout << "■■■■■■■■■■■■■■■●●●●●欢迎光临天地银行●●●●●■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■ 1 客户进入 ■■■■■■■■■■■■■■■■" << endl;cout << "■ ■■■■■■ ■■■■ ■ ■■■■ ■■ ■■■ ■" << endl;cout << "■ ■■ ■■■■ ■■■ 2 查看当排队情况 ■ ■ ■■■ ■■ ■■ ■■" << endl;cout << "■ ■■■ ■■■ ■■ ■ ■■ ■■ ■■ ■ ■■■" << endl;cout << "■ ■■ ■■ ■ 3 系统查询 ■ ■■■ ■ ■■ ■■ ■■" << endl;cout << "■ ■■■ ■■■■■ ■ ■ ■■■■ ■■ ■■■ ■" << endl;cout << "■■■■■■■■■■■■■■■ 4 退 出 ■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■ 提示:请按回车键进行下一步操作 ■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■●●●●●欢迎光临天地银行●●●●●■■■■■■■■■■■■■■■■" << endl;cout << "请输入:";int n;cin >> n;system("cls");if (n == 1)manual();else if (n == 2) {show();system("pause");system("cls");manual_interface();}else if (n == 3) {charts(person_num);system("pause");system("cls");manual_interface();}else return 4;
}//欢迎界面
void welcome() {cout << "■■■■■■■■■■■■■■■●●●●●欢迎光临天地银行●●●●●■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■" << endl;cout << "■ ■■■■■■ ■■■■ 1 自动模式 ■ ■■■■ ■■ ■■■ ■" << endl;cout << "■ ■■ ■■■■ ■■■ ■ ■ ■■■ ■■ ■■ ■■" << endl;cout << "■ ■■■ ■■■ ■■ 2 手动模式 ■ ■■ ■■ ■■ ■ ■■■" << endl;cout << "■ ■■ ■■ ■ ■ ■■■ ■ ■■ ■■ ■■" << endl;cout << "■ ■■■ ■■■■■ ■ 3 退 出 ■ ■■■■ ■■ ■■■ ■" << endl;cout << "■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■ 提示:请按回车键进行下一步操作 ■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■" << endl;cout << "■■■■■■■■■■■■■■■●●●●●欢迎光临天地银行●●●●●■■■■■■■■■■■■■■■■" << endl;cout << "请输入:";int n;cin >> n;system("cls");if (n == 1)automatic();else if (n == 2) manual_interface();}//开始动画
void strat_interface() {SetColor(2);//设置开始动画颜色StartInterface* start = new StartInterface();//动态分配一个StartInterface类startstart->Action();//开始动画delete start;//释放内存空间/*设置关标位置,并输出提示语,等待任意键输入结束*/SetCursorPosition(20, 20);std::cout << "欢迎来到天地银行";SetCursorPosition(20, 21);system("pause");system("cls");//system("color 9B");//system("color C1");
}int main() {strat_interface();init();welcome();return 0;
}
运行效果展示
总结
我们本次实训课题为“银行排队系统”开发此系统从本质上改善传统排队系统所存在的拥挤、嘈杂、混乱现象,避免各种不必要的纠纷。进一步优化银行营业厅的排队问题,提高银行业务办理效率。通过半个月的数据结构课程设计,深入的理解了队列,链表,包括结构体的运用,对于数据结构的理解又进入了另一个层次。也让我们感觉到学习数据结构,学习书本上的知识是远远不够的,我们更应该多做实践练习,在学习的过程中我们要多动脑,多动手,数据结构有一定的难度,只有在不断实践练习中才能领悟它的思想。在实践练习中才能更好的记牢知识点。在程序的调试方面收获也很大,在调试程序的过程中形象的了解了程序的运行流程,对于将来设计出好的程序打了夯实的基础。
优点:
1、开发的程序是面向对象,面向用户设计的应用软件。
2、系统代码简单,因为运用了栈和队列。
3、银行排队系统可以对添加数据、查询数据。
不足:
1、在信息输入界面每次都需手输入信息。
2、程序代码繁赘,为运用类的封装和继承。
3、当录入的信息错误时,无法对信息进行修改只能重新输入。
4、不能存储图片等。