简介
经常用美团app买电影票,不禁对它的推荐选座功能产生了好奇,于是打算自己实现一个类似的算法,美团app的推荐选座界面如下
本demo采用Vue-cli搭建,github地址点此,clone后直接npm start即可进行具体操作
算法思考过程
对于这个推荐座位算法,我尝试了不同场次的电影进行推荐选座,总结出以下几点
(1)推荐算法首先从影院中间排数的后一排的正中间开始搜索
如下图
(2)优先向后排方向进行搜索,后排搜索完成后再从中间起始位置向前排搜索
这个大多数情况是对的,如下图,偶尔会出现不同
(3)后排搜索完成后,每一行都会有一个结果(每一行的结果是最靠近中轴线的那一组座位),取这些结果中距离中轴线最小的那个结果作为最终结果,而不是距离屏幕越近的
这一点也是大多数情况是对的,有些情况不对,很奇怪
(4)只考虑并排且连续的座位,不能不在一排或者一排中间有分隔,比如过道之类的
这一条可以理解,毕竟坐一排肯定观影体验好得多
影院座位数据结构
可以肯定的是用一个二维数组seatArray
代表影院座位,注意到影院座位分布是不规则的,因此需要确定一个seatRow
和seatCol
来确定影院座位的数组尺寸,分别代表行列数,对于那些没有座位的地方,seatArray
对应的位置填-1,下面是座位具体的值和代表的含义
-1 非座位
0 可选座位 (白色)
1 已选座位 (绿色)
2 已购票座位 (红色)
复制代码
然后在mounted中初始化座位,初始值都为0(可选座位),如下代码
//初始座位数组
initSeatArray: function(){
let seatArray = Array(this.seatRow).fill(0).map(()=>Array(this.seatCol).fill(0));
this.seatArray = seatArray;
//均分父容器宽度作为座位的宽度
this.seatSize = this.$refs.innerSeatWrapper
? parseInt(parseInt(window.getComputedStyle(this.$refs.innerSeatWrapper).width,10) / this.seatCol,10)
:0;
//初始化不是座位的地方
this.initNonSeatPlace();
},
//初始化不是座位的地方
initNonSeatPlace: function(){
for(let i=0;i<9;i++){
this.seatArray[i][0]=-1;