1. 交通信号灯控制
任务目标
实现一个三状态交通信号灯有限状态机:红灯亮30秒 → 绿灯亮25秒 → 黄灯亮5秒 → 回到红灯,循环往复。状态切换由定时器驱动,每个状态有独立的持续时间。
核心实现
#include <stdio.h>
#include <unistd.h>
typedef enum {
RED,
GREEN,
YELLOW
} LightState;
typedef struct {
LightState current;
int elapsed; // 当前状态已持续秒数
int duration; // 当前状态总持续时间
} TrafficLightFSM;
// 状态持续时间表(秒)
static const int DURATION_TABLE[] = {
[RED] = 30,
[GREEN] = 25,
[YELLOW] = 5
};
static const char* STATE_NAMES[] = {
[RED] = "红灯",
[GREEN] = "绿灯",
[YELLOW] = "黄灯"
};
void fsm_init(TrafficLightFSM* fsm) {
fsm->current = RED;
fsm->elapsed = 0;
fsm->duration = DURATION_TABLE[RED];
}
void fsm_tick(TrafficLightFSM* fsm) {
fsm->elapsed++;
if (fsm->elapsed >= fsm->duration) {
// 状态切换:RED -> GREEN -> YELLOW -> RED
switch (fsm->current) {
case RED: fsm->current = GREEN; break;
case GREEN: fsm->current = YELLOW; break;
case YELLOW: fsm->current = RED; break;
}
fsm->elapsed = 0;
fsm->duration = DURATION_TABLE[fsm->current];
}
}
int main(void) {
TrafficLightFSM fsm;
fsm_init(&fsm);
// 模拟运行 70 秒(覆盖完整一轮 30+25+5=60 秒 + 额外 10 秒)
for (int t = 0; t < 70; t++) {
printf("t=%2d秒: %s (已亮 %d/%d 秒)\n",
t, STATE_NAMES[fsm.current], fsm.elapsed, fsm.duration);
fsm_tick(&fsm);
}
return 0;
}
编译与运行
gcc -o traffic_light traffic_light.c
./traffic_light
验证方法
观察输出中状态切换的时间点:
- t=0~29秒为红灯(第30秒tick后切换)
- t=30~54秒为绿灯(第55秒tick后切换)
- t=55~59秒为黄灯(第60秒tick后切换)
- t=60秒起重新进入红灯,循环开始
若输出严格符合上述时间边界且状态顺序始终为“红灯→绿灯→黄灯→红灯”,则判定实现正确。
预期输出片段
t= 0秒: 红灯 (已亮 0/30 秒)
t=29秒: 红灯 (已亮 29/30 秒)
t=30秒: 绿灯 (已亮 0/25 秒)
t=54秒: 绿灯 (已亮 24/25 秒)
t=55秒: 黄灯 (已亮 0/5 秒)
t=59秒: 黄灯 (已亮 4/5 秒)
t=60秒: 红灯 (已亮 0/30 秒)
该FSM的核心逻辑集中在fsm_tick函数中:每次调用代表1秒流逝,当累计时间达到当前状态的持续时间后,按固定顺序迁移到下一状态并重置计时。状态转移表与持续时间表分离,便于后续扩展更多状态或调整时长。