Skip to content

红绿灯代码逻辑的实现

前言

在面试过程中,做任何的算法题前,先做一下算法分析,这一方面有助于加强面试官对你逻辑能力的印象分,另一方面能让你更轻松的实现具体的功能。

算法分析

  1. 红灯,绿灯,黄灯
  2. 三灯状态互斥
  3. 每个灯的时间不一样
  4. 红灯完了之后,显示绿灯,绿灯完了之后显示黄灯,黄灯完了之后显示红灯
  5. 假设可横向扩展,即:灯的数量可以新增减少
  6. 交警可以快速调控灯的颜色,安全性角度上考虑需要延时执行这个任务
  7. 综上可定义一个简单的结构:
[
    { light: 'red', time: 30 },
    { light: 'green', time: 40 },
    { light: 'yellow', time: 10 }
]

代码设计

  1. 为了实现上述第四点的逻辑,可采用循环链表的逻辑来做, red => green => yellow => red
javascript
/** 用于创建循环链表 */
function createLoopHead(array) {
  let head = {
    val: array[0],
    next: null
  }
  let pFirst = head
  let p = head
  for(let i = 1; i < array.length; i++) {
    let obj = {
      val: array[i],
      next: null
    }
    p.next = obj
    p = p.next
    if (i === array.length - 1) {
      obj.next = pFirst
    }
  }
  return head
}

/** 红绿灯控制中心 */
const lightControl = (array) => {
    /** 当前状态 */
    const lightState = {
        light: '',
        time: 0
    }
    /** 控制器状态 */
    let controllerState = 'stop'
    /** 由于链表需要不停往下执行,所以需要递归 */
    function recursionLight (head) {
        /** 获取总时间 */
        let time = head.val.time
        let IntervalTimer, TimeoutTimer
        IntervalTimer = setInterval(() => {
            changeLight(head.val.light, time)
            if (time > 0) {
                time--
            } else {
                clearInterval(IntervalTimer)
            }
        }, 1000)
        TimeoutTimer = setTimeout(() => {
            /** 递归实现调用 */
            clearInterval(IntervalTimer)
            recursionLight(head.next)
            clearTimeout(TimeoutTimer)
        }, head.val.time * 1000 + 1000)
    }

    /** 红绿灯的实际执行显示,如打印值,改变Dom上的颜色显示一类 */
    function changeLight(light, time) {
        console.log(light, time)
        lightState.time = time
        if (lightState.light != light) {
            lightState.light = light
            /** 可在此注入方法进行真实的灯和时间切换操作 */
            return
        }
        /** 在此只需注入做时间改变真实印射的操作 */
    }
    /** 启动红绿灯 */
    function startLight() {
        /** 数据类型:循环链表 */
        const linkedHead = createLoopHead(array)
        controllerState = 'begin'
        /** 启动红绿灯 */
        recursionLight(linkedHead)
    }
    /** 停止红绿灯 */
    function stopLight() {
        lightState.light = ''
        lightState.time = 0
        controllerState = 'stop'
    }
    return {
        startLight,
        stopLight,
    }
}

const lightControlData = [
  { light: 'red', time: 10 },
  { light: 'green', time: 5 },
  { light: 'yellow', time: 2 }
]

const lightControlInstance = lightControl(lightControlData)
lightControlInstance.startLight()