红绿灯代码逻辑的实现
前言
在面试过程中,做任何的算法题前,先做一下算法分析,这一方面有助于加强面试官对你逻辑能力的印象分,另一方面能让你更轻松的实现具体的功能。
算法分析
- 红灯,绿灯,黄灯
- 三灯状态互斥
- 每个灯的时间不一样
- 红灯完了之后,显示绿灯,绿灯完了之后显示黄灯,黄灯完了之后显示红灯
- 假设可横向扩展,即:灯的数量可以新增减少
- 交警可以快速调控灯的颜色,安全性角度上考虑需要延时执行这个任务
- 综上可定义一个简单的结构:
[
{ light: 'red', time: 30 },
{ light: 'green', time: 40 },
{ light: 'yellow', time: 10 }
]
代码设计
- 为了实现上述第四点的逻辑,可采用循环链表的逻辑来做, 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()