Vue实现美团app的影院推荐选座功能【推荐】(2)

//推荐选座,参数是推荐座位数目 smartChoose: function(num){ //找到影院座位水平垂直中间位置的后一排 let rowStart = parseInt((this.seatRow-1)/2,10)+1; //先从中间排往后排搜索 let backResult = this.searchSeatByDirection(rowStart,this.seatRow-1,num); if(backResult.length>0){ this.chooseSeat(backResult); return } //再从中间排往前排搜索 let forwardResult = this.searchSeatByDirection(rowStart-1,0,num); if(forwardResult.length>0) { this.chooseSeat(forwardResult); return } //提示用户无合法位置可选 alert('无合法位置可选!') },

第一步是找到影院座位水平垂直中间位置的后一排,然后调用 this.searchSeatByDirection 进行该方向的搜索,先从中间排往后排搜索,再从中间排往前排搜索。如果任意一个方向搜索到结果,直接返回,否则提示用户无合法位置, chooseSeat 用于改变座位的状态

重点就是 searchSeatByDirection 的实现,代码如下

//向前后某个方向进行搜索的函数,参数是起始行,终止行,推荐座位个数 searchSeatByDirection: function(fromRow,toRow,num){ /* * 推荐座位规则 * (1)初始状态从座位行数的一半处的后一排的中间开始向左右分别搜索,取离中间最近的,如果满足条件, * 记录下该结果离座位中轴线的距离,后排搜索完成后取距离最小的那个结果作为最终结果,优先向后排进行搜索, * 后排都没有才往前排搜,前排逻辑同上 * (2)只考虑并排且连续的座位,不能不在一排或者一排中间有分隔 * */ /* * 保存当前方向搜索结果的数组,元素是对象,result是结果数组,offset代表与中轴线的偏移距离 * { * result:Array([x,y]) * offset:Number * } */ let currentDirectionSearchResult = []; //确定行数的大小关系,从小到大进行遍历 let largeRow = fromRow>toRow?fromRow:toRow, smallRow = fromRow>toRow?toRow:fromRow; //逐行搜索 for(let i=smallRow;i<=largeRow;i++){ //每一排的搜索,找出该排里中轴线最近的一组座位 let tempRowResult = [], minDistanceToMidLine=Infinity; for(let j=0;j<=this.seatCol - num;j++){ //如果有合法位置 if(this.checkRowSeatContinusAndEmpty(i,j,j+num-1)){ //计算该组位置距离中轴线的距离:该组位置的中间位置到中轴线的距离 let resultMidPos = parseInt((j+num/2),10); let distance = Math.abs(parseInt(this.seatCol/2) - resultMidPos); //如果距离较短则更新 if(distance<minDistanceToMidLine){ minDistanceToMidLine = distance; //该行的最终结果 tempRowResult = this.generateRowResult(i,j,j+num-1) } } } //保存该行的最终结果 currentDirectionSearchResult.push({ result:tempRowResult, offset:minDistanceToMidLine }) } //处理后排的搜索结果:找到距离中轴线最短的一个 //注意这里的逻辑需要区分前后排,对于后排是从前往后,前排则是从后往前找 let isBackDir = fromRow < toRow; let finalReuslt = [],minDistanceToMid = Infinity; if(isBackDir){ //后排情况,从前往后 currentDirectionSearchResult.forEach((item)=>{ if(item.offset < minDistanceToMid){ finalReuslt = item.result; minDistanceToMid = item.offset; } }); }else{ //前排情况,从后往前找 currentDirectionSearchResult.reverse().forEach((item)=>{ if(item.offset < minDistanceToMid){ finalReuslt = item.result; minDistanceToMid = item.offset; } }) } //直接返回结果 return finalReuslt },

代码有点长,不过逻辑不难,就是前面那几条规则的实现,对于每一行的搜索,是可能存在多个合理的座位结果的

 

我这里采用的是从左往右遍历,如果是推荐5个座位,先判断1-5位置是否合理,如果合理则记录下其中间位置(3号)到中轴线的距离以及座位结果数组,然后再右移一位检查2-6位置是否合理,如果合理则比较2-6位置的中间位置(4号)距离中轴线的距离和之前的距离,取最短的一个,同时更新座位结果数组。 这样遍历下来,该行的最终结果就能确定, 每一行的最佳结果会存放在currentDirectionSearchResult数组中
然后后排方向的所有排遍历完后,就得到了由每一行最佳结果组成的数组currentDirectionSearchResult,再遍历这个数组根据规则取距离中轴线最近的一个作为 最终返回的结果

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/2af084c17b29f640ef7d406947c59ae9.html