C#多人抢票模拟器,假设高铁有seatCount个座位

C#多人抢票模拟器

火车票站点、订票、C#多人抢票模拟器【多线程】_ylq1045的专栏-CSDN博客

上次 抢票模拟器 假定高铁只有一个座位,现在设置高铁共有seatCount个座位

整体模拟程序如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TrainPathBookingDemo
{
    class Program
    {
        /// <summary>
        /// 该高铁共有座位总个数
        /// </summary>
        static int seatCount = 3;
        static void Main(string[] args)
        {
            LinkedList<string> stationList = new LinkedList<string>(new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N" });
            Console.WriteLine($"链表的首节点为【{stationList.First.Value}】");
            Console.WriteLine($"链表的尾节点为【{stationList.Last.Value}】");
            Tuple<string, string> route1 = Tuple.Create("C", "J");
            Tuple<string, string> route2 = Tuple.Create("E", "M");
            Console.WriteLine($"路线1【{route1.Item1}-->{route1.Item2}】 与 路线2【{route2.Item1}-->{route2.Item2}】是否相交:【{IntersectWith(stationList, route1, route2)}】");
            route1 = Tuple.Create("B", "G");
            route2 = Tuple.Create("G", "L");
            Console.WriteLine($"路线1【{route1.Item1}-->{route1.Item2}】 与 路线2【{route2.Item1}-->{route2.Item2}】是否相交:【{IntersectWith(stationList, route1, route2)}】");

            //四元组:第一项为订票人 第二项代表是否订票成功,第三项代表路线【起始站点】,第四项代表路线【终止站点】
            List<Tuple<string, bool, string, string>> list = new List<Tuple<string, bool, string, string>>();
            list.Add(Tuple.Create("甲", false, "A", "E"));
            list.Add(Tuple.Create("乙", false, "B", "H"));
            list.Add(Tuple.Create("丙", false, "E", "M"));
            list.Add(Tuple.Create("丁", false, "K", "N"));
            list.Add(Tuple.Create("戊", false, "C", "L"));
            list.Add(Tuple.Create("己", false, "A", "N"));
            list.Add(Tuple.Create("庚", false, "F", "J"));
            list.Add(Tuple.Create("辛", false, "M", "N"));
            list.Add(Tuple.Create("壬", false, "A", "F"));
            list.Add(Tuple.Create("癸", false, "A", "G"));

            Console.WriteLine($"------------下面模拟【{list.Count}】个人一起抢高铁票,假设本班高铁【链表】共有【{seatCount}】个座位了------------");
            for (int i = 0; i < list.Count; i++)
            {
                int index = i;
                Task.Run(() => 
                {
                    FightTicket(stationList, list, list[index].Item1);
                });
            }
            Console.ReadLine();
        }

        /// <summary>
        /// 加锁
        /// </summary>
        static int lockedValue = 0;

        /// <summary>
        /// 抢票
        /// </summary>
        /// <param name="stationList">链表:高铁站点</param>
        /// <param name="list">抢票人与路线 集合</param>
        /// <param name="bookingPerson">当前抢票人</param>
        static void FightTicket(LinkedList<string> stationList, List<Tuple<string, bool, string, string>> list, string bookingPerson) 
        {
            //加锁
            while (Interlocked.Exchange(ref lockedValue, 1) != 0) 
            { }            
            Thread.Sleep(new Random((int)DateTime.Now.Ticks).Next(100, 500));
            try
            {
                int index = list.FindIndex(tuple => tuple.Item1 == bookingPerson);
                if (index == -1)
                {
                    throw new Exception($"列表中不存在key,抢票人【{bookingPerson}】");
                }
                if (list[index].Item2)
                {
                    //已经抢票成功,不能再次订票
                    Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】-路线【{list[index].Item3}-->{list[index].Item4}】已订票,不能再次订票!");
                    return;
                }
                //查找出所有已经抢票成功的
                List<Tuple<string, bool, string, string>> fightSuccessList = list.FindAll(tuple => tuple.Item2);
                if (fightSuccessList.Count == 0)
                {
                    //如果没有发现订票成功的,直接订票成功
                    list[index] = Tuple.Create(bookingPerson, true, list[index].Item3, list[index].Item4);
                    Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】-路线【{list[index].Item3}-->{list[index].Item4}】已抢票成功");
                    return;
                }
                //存在已经抢票成功的,则检查所有路线是否存在相交冲突的
                List<Tuple<string, bool, string, string>> tupleIntersect = fightSuccessList.FindAll(element =>
                 IntersectWith(stationList, Tuple.Create(element.Item3, element.Item4), Tuple.Create(list[index].Item3, list[index].Item4)));
                if (tupleIntersect == null || tupleIntersect.Count == 0)
                {
                    //如果没有发现路线相交的,订票成功
                    list[index] = Tuple.Create(bookingPerson, true, list[index].Item3, list[index].Item4);
                    Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】-路线【{list[index].Item3}-->{list[index].Item4}】已抢票成功");
                }
                else 
                {
                    //斯内科 2022-03-06 增加余票个数查询逻辑
                    //发现存在路线相交的,则查询订票成功个数 是否大于等于 座位总个数,如果true【无剩余票】,则订票失败
                    if (tupleIntersect.Count >= seatCount)
                    {
                        Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】订票失败,无余票!当前座位数【{seatCount}】,已抢票数【{tupleIntersect.Count}】,路线【{list[index].Item3}-->{list[index].Item4}】");
                        int bookingIndex = 0;
                        tupleIntersect.ForEach(tuple => Console.WriteLine($"    已订票人{++bookingIndex}:【{tuple.Item1}】路线【{tuple.Item3}-->{tuple.Item4}】"));
                    }
                    else 
                    {
                        //如果有余票,则订票成功
                        list[index] = Tuple.Create(bookingPerson, true, list[index].Item3, list[index].Item4);
                        Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】-路线【{list[index].Item3}-->{list[index].Item4}】已抢票成功,当前座位数【{seatCount}】,已抢票数【{tupleIntersect.Count + 1}】");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}抢票时出现异常【{ex.Message}】,抢票人【{bookingPerson}】");
            }
            finally
            {
                //解锁
                Interlocked.Exchange(ref lockedValue, 0);
            }
        }

        /// <summary>
        /// 指定的两条路线是否相交,元组的第一个元素代表起始站,第二个元素代表终点站
        /// </summary>
        /// <param name="stationList"></param>
        /// <param name="route1">路线1</param>
        /// <param name="route2">路线2</param>
        /// <returns></returns>
        static bool IntersectWith(LinkedList<string> stationList, Tuple<string, string> route1, Tuple<string, string> route2)
        {
            //元组的第一项代表起点,第二项代表终点
            LinkedListNode<string> startNode1 = stationList.Find(route1.Item1);
            LinkedListNode<string> endNode1 = stationList.Find(route1.Item2);

            LinkedListNode<string> startNode2 = stationList.Find(route2.Item1);
            LinkedListNode<string> endNode2 = stationList.Find(route2.Item2);
            if (startNode1 == null || endNode1 == null || startNode2 == null || endNode2 == null) 
            {
                //如果节点不存在,直接返回NG
                return false;
            }
            if (startNode1.Value == startNode2.Value || endNode1.Value == endNode2.Value) 
            {
                //如果是同一起始节点 或者 同一结束节点
                return true;
            }
            bool existIntersect = false;
            while (startNode1 != null)
            {
                startNode1 = startNode1.Next;
                if (startNode1 != null && startNode1.Value == endNode1.Value) 
                {
                    //循环从开始节点到终止节点 结束
                    break;
                }
                if (startNode1 != null && (startNode1.Value == startNode2.Value || startNode1.Value == endNode2.Value)) 
                {
                    //如果第二个起始节点在第一个元组的【From,To】之间 或者 第二个终点节点在第一个元组的【From,To】之间
                    existIntersect = true;
                    break;
                }
            }
            if (existIntersect) 
            {
                return true;
            }
            //查看 第一个起始节点在第二个元组的【From,To】之间 或者 第一个终点节点在第二个元组的【From,To】之间
            while (startNode2 != null)
            {
                startNode2 = startNode2.Next;
                if (startNode2 != null && startNode2.Value == endNode2.Value)
                {
                    //循环从开始节点到终止节点 结束
                    break;
                }
                if (startNode2 != null && (startNode2.Value == startNode1.Value || startNode2.Value == endNode1.Value))
                {
                    //如果第二个起始节点在第一个元组的【From,To】之间 或者 第二个终点节点在第一个元组的【From,To】之间
                    existIntersect = true;
                    break;
                }
            }
            return existIntersect;        
        }
    }
}

程序运行如图:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值