4. 洗衣机程序

任务目标

设计一个洗衣机控制程序的状态机,包含注水、洗涤、漂洗、脱水四个核心状态,并支持暂停与取消操作。程序需能响应启动、暂停/继续、取消等外部事件,并在每个状态中模拟对应动作的执行。

状态与事件定义

洗衣机FSM包含以下状态与事件:

  • 状态:IDLE(待机)、FILL(注水)、WASH(洗涤)、RINSE(漂洗)、SPIN(脱水)、PAUSED(暂停)
  • 事件:START(启动)、PAUSE(暂停)、RESUME(继续)、CANCEL(取消)、COMPLETE(当前阶段完成)

状态转移规则:

  • IDLE + START → FILL
  • FILL + COMPLETE → WASH;FILL + PAUSE → PAUSED;FILL + CANCEL → IDLE
  • WASH + COMPLETE → RINSE;WASH + PAUSE → PAUSED;WASH + CANCEL → IDLE
  • RINSE + COMPLETE → SPIN;RINSE + PAUSE → PAUSED;RINSE + CANCEL → IDLE
  • SPIN + COMPLETE → IDLE(洗涤结束);SPIN + PAUSE → PAUSED;SPIN + CANCEL → IDLE
  • PAUSED + RESUME → 返回暂停前的状态;PAUSED + CANCEL → IDLE

完整实现代码

#include <stdio.h>
#include <stdlib.h>

typedef enum {
    IDLE, FILL, WASH, RINSE, SPIN, PAUSED
} State;

typedef enum {
    START, PAUSE, RESUME, CANCEL, COMPLETE
} Event;

typedef struct {
    State current;
    State paused_from;  // 记录暂停前的状态
} WasherFSM;

const char* state_name(State s) {
    switch (s) {
        case IDLE:   return "待机";
        case FILL:   return "注水";
        case WASH:   return "洗涤";
        case RINSE:  return "漂洗";
        case SPIN:   return "脱水";
        case PAUSED: return "暂停";
        default:     return "未知";
    }
}

void init_fsm(WasherFSM* fsm) {
    fsm->current = IDLE;
    fsm->paused_from = IDLE;
}

void handle_event(WasherFSM* fsm, Event ev) {
    State s = fsm->current;
    switch (s) {
        case IDLE:
            if (ev == START) {
                fsm->current = FILL;
                printf("启动:开始注水\n");
            }
            break;
        case FILL:
            if (ev == COMPLETE) {
                fsm->current = WASH;
                printf("注水完成,开始洗涤\n");
            } else if (ev == PAUSE) {
                fsm->paused_from = FILL;
                fsm->current = PAUSED;
                printf("注水阶段暂停\n");
            } else if (ev == CANCEL) {
                fsm->current = IDLE;
                printf("已取消,回到待机\n");
            }
            break;
        case WASH:
            if (ev == COMPLETE) {
                fsm->current = RINSE;
                printf("洗涤完成,开始漂洗\n");
            } else if (ev == PAUSE) {
                fsm->paused_from = WASH;
                fsm->current = PAUSED;
                printf("洗涤阶段暂停\n");
            } else if (ev == CANCEL) {
                fsm->current = IDLE;
                printf("已取消,回到待机\n");
            }
            break;
        case RINSE:
            if (ev == COMPLETE) {
                fsm->current = SPIN;
                printf("漂洗完成,开始脱水\n");
            } else if (ev == PAUSE) {
                fsm->paused_from = RINSE;
                fsm->current = PAUSED;
                printf("漂洗阶段暂停\n");
            } else if (ev == CANCEL) {
                fsm->current = IDLE;
                printf("已取消,回到待机\n");
            }
            break;
        case SPIN:
            if (ev == COMPLETE) {
                fsm->current = IDLE;
                printf("脱水完成,洗衣结束\n");
            } else if (ev == PAUSE) {
                fsm->paused_from = SPIN;
                fsm->current = PAUSED;
                printf("脱水阶段暂停\n");
            } else if (ev == CANCEL) {
                fsm->current = IDLE;
                printf("已取消,回到待机\n");
            }
            break;
        case PAUSED:
            if (ev == RESUME) {
                fsm->current = fsm->paused_from;
                printf("继续:回到%s阶段\n", state_name(fsm->current));
            } else if (ev == CANCEL) {
                fsm->current = IDLE;
                printf("已取消,回到待机\n");
            }
            break;
    }
}

int main() {
    WasherFSM washer;
    init_fsm(&washer);

    // 模拟一次完整洗衣流程:启动→注水→暂停→继续→洗涤→漂洗→脱水→结束
    handle_event(&washer, START);       // 待机 → 注水
    handle_event(&washer, COMPLETE);    // 注水 → 洗涤
    handle_event(&washer, PAUSE);       // 洗涤 → 暂停
    handle_event(&washer, RESUME);      // 暂停 → 洗涤
    handle_event(&washer, COMPLETE);    // 洗涤 → 漂洗
    handle_event(&washer, COMPLETE);    // 漂洗 → 脱水
    handle_event(&washer, COMPLETE);    // 脱水 → 待机

    printf("\n--- 测试取消功能 ---\n");
    init_fsm(&washer);
    handle_event(&washer, START);       // 待机 → 注水
    handle_event(&washer, CANCEL);      // 注水 → 待机

    return 0;
}

编译与运行

gcc -o washer_fsm washer_fsm.c
./washer_fsm

验证方法

程序运行后,观察输出是否符合以下预期流程:

  1. 启动后进入注水状态,输出“启动:开始注水”
  2. 注水完成后进入洗涤,输出“注水完成,开始洗涤”
  3. 洗涤中暂停输出“洗涤阶段暂停”,继续后输出“继续:回到洗涤阶段”
  4. 依次完成洗涤、漂洗、脱水,最终输出“脱水完成,洗衣结束”
  5. 取消测试中,注水阶段取消后输出“已取消,回到待机”

若输出与上述顺序一致,且程序正常退出(无崩溃),则判定FSM逻辑正确。

状态转移图

待机 注水 洗涤 漂洗 脱水 暂停 START COMPLETE COMPLETE COMPLETE COMPLETE PAUSE RESUME CANCEL CANCEL