一个闯关游戏相关的算法总结:js判断一个数是否在一个区间内或者是否等于它

607 阅读2分钟

业务场景

此算法源于项目中要实现一个下单闯关业务,根据用户累计的下单金额,判断用户目前处于哪一关,解锁对应的福利

游戏的步骤与金额都配置在前端,每一关对应一个累计金额,总共4关(多少关都无所谓,主要是思路哈哈)

思路

用数组数据结构存储用户每关的累计金额数,根据用户当前的累计金额总数判断用户所处的关卡

let step=[1000, 2500, 5000, 7000, 10000, 12500, 15000, 20000]

比如::

当用户累计是100元,100<1000,关卡未解锁,在第一关处提醒用户所差的金额;

当累计1000元,1000==1000,此时第一关已处于解锁状态,需要在第二关处提醒用户离解锁第二关所差的金额;

当累计2600时,2600>2500,第二关卡已解锁,需在第三关处提醒用户,离解锁第三关所差的金额数;

以此类推......

效果图

微信截图_20210521182644.png

由此可见,还缺少一个标识,记录用户此关是否已通过。设置一个isOver属性,如果金额大于等于此关的金额数,则此关为通过状态,isOver=true

继续思路整理

一开始觉得要用用户的累计金额在数组每个元素的前后作个判断,后来发现只要做一个过滤即可,过滤出小于等于累计金额的数组元素,求其数组的长度就是用户所处的关卡数,然后根据用户是否已通过所处的关卡,设置下一关的提示。

实现代码

//根据累积金额算出所处的关卡
	_onStep(num) {
        let stepData = [1000, 2500, 5000, 7000, 10000, 12500, 15000, 20000]
        let step = stepData.filter(item => item <= num).length
        return step || 1 //当小于第一关的金额1000元时,符合条件的元素为空,长度是0,手动设置处于第一关卡的位置
    },


	//处理数据,用作页面结果渲染
	_initStep(){
      let { payMoney=0}=this.$route.query  //用户累计金额
	  //用对象数据结构,方便读取并设置每一关的值,对象存储比数组存储更节省内存,虽然也没多少数据哈哈
      let stepData= stepData: {
        1:{//第一关
          step:'one',  //为设置每一关图标所处的不同位置class类
          num:1000,    //每关的关卡金额数
          tip:'',      //关卡提示
          isOver:false //是否已通过本关
        },
        2:{//第二关
          step:'two',
          num:2500,
          tip:'',
          isOver:false
        },
       3: {//第三关
          step:'three',
          num:5000,
          tip:'',    
          isOver:false
        },
        4: {//第四关
          step:'four',
          num:7000,
          tip:'',         
          isOver:false
        }]
      payMoney=parseFloat(payMoney)
      let step=this._onStep(payMoney)
      step=Number(step)
      
      for(let key in stepData){
        if(key<=step){
          let flag=payMoney>=stepData[key].num
          stepData[key].isOver=flag
          stepData[key].tip=flag?'':`距离奖励仍差:¥ ${ this._handleFloat(stepData[key].num-payMoney)}元`
        }
      }
      //当用户通过当前关卡时,设置好下一关卡的提示信息
      if(step<8&&stepData[step].isOver){
        let next=Number(step)+1
        stepData[next].tip= `距离奖励仍差:¥ ${ this._handleFloat(stepData[next].num-payMoney) }元`
      }
    },
    _handleFloat(number){
      if(!number) return 
      return parseFloat(number).toFixed(2)
    },
	

总结

前端会在本次存储用户下单的累计金额(是调用后台接口后存储在本地storage中),下次进入页面时获取后台最新的累计金额跟前端本地的作比较,后台>本地 时,提醒用户所处的关卡数 挺好玩的一种业务类型,用到了一个数组算法,已知一个数值,判断在数组中所处的位置

	_onStep(num) {
            let stepData = [1000, 2500, 5000, 7000, 10000, 12500, 15000, 20000]
            let step = stepData.filter(item => item <= num).length
            return step || 1 
        },

最近公司比较忙,趁着稍有空闲,积累下所做的,有所学,有所得,每天都进步~~~ 加油!