1. #include <stdio.h>
  2.  
  3. #define NODEBUG
  4.  
  5. enum states { I0_S0 = 0, I0_S1, I0_S2, I1_S0, I1_S1, I1_S2, I2_S0};
  6. char s_states[7][6] = {"I0_S0", "I0_S1", "I0_S2", "I1_S0", "I1_S1", "I1_S2", "I2_S0"};
  7. enum events {E_UP = 0, E_DOWN, E_LEFT, E_RIGHT};
  8. char s_events[4][12] = {"E_UP", "E_DOWN", "E_LEFT", "E_RIGHT"};
  9.  
  10. char M_I0_S0[] = "Item One";
  11. char M_I0_S1[] = "Item One - Sub Left";
  12. char M_I0_S2[] = "Item One - Sub Right";
  13. char M_I1_S0[] = "Item Two";
  14. char M_I1_S1[] = "Item Two - Sub Left";
  15. char M_I1_S2[] = "Item Two - Sub Right";
  16. char M_I2_S0[] = "Item Three";
  17.  
  18. void msg_i0_s0 ( void )
  19. {
  20.   printf("%s \n",M_I0_S0);
  21. }
  22.  
  23. void msg_i0_s1 ( void )
  24. {
  25.   printf("%s \n",M_I0_S1);
  26. }
  27.  
  28. void msg_i0_s2 ( void )
  29. {
  30.   printf("%s \n",M_I0_S2);
  31. }
  32.  
  33. void msg_i1_s0 ( void )
  34. {
  35.   printf("%s \n",M_I1_S0);
  36. }
  37.  
  38. void msg_i1_s1 ( void )
  39. {
  40.   printf("%s \n",M_I1_S1);
  41. }
  42.  
  43. void msg_i1_s2 ( void )
  44. {
  45.   printf("%s \n",M_I1_S2);
  46. }
  47.  
  48. void msg_i2_s0 ( void )
  49. {
  50.   printf("%s \n",M_I2_S0);
  51. }
  52.  
  53.  
  54. class StateMachine
  55. {
  56.   private:
  57.     enum states state_curr;                                 // Current state
  58.     struct branch
  59.     {
  60.         int event_type;
  61.         enum states state_new;
  62.     void (*do_func)();
  63.     };
  64.     static struct branch transition_table[7][4];           // Transition map
  65.  
  66.   public:
  67.     StateMachine(states state_init)                       // Constructor with starting state
  68.     {
  69.       state_curr = state_init;
  70.     }
  71.          
  72.     void process_event(int c)
  73.     {
  74.       if(c == '\n')  // Enter Key
  75.         return;
  76.  
  77.       #ifdef DEBUG
  78.         printf("\nCurrent State:   %s \n", s_states[state_curr]);
  79.       #endif
  80.  
  81.       int idx;
  82.       if(c == 0x77)  // w
  83.         idx = E_UP;
  84.       if(c == 0x73)  // s
  85.         idx = E_DOWN;
  86.       if(c == 0x61)  // a
  87.         idx = E_LEFT;
  88.       if(c == 0x64)  // d
  89.         idx = E_RIGHT;  
  90.       #ifdef DEBUG  
  91.         printf("Event Recieved:  %s \n", s_events[idx]);
  92.       #endif
  93.  
  94.       struct branch *b = &transition_table[state_curr][idx];
  95.       state_curr = b->state_new;
  96.       #ifdef DEBUG
  97.         printf("Next State:      %s \n", s_states[state_curr]);
  98.       #endif
  99.  
  100.       if(b->do_func)
  101.       {
  102.         void (*pFunc)() = b->do_func;
  103.         #ifdef DEBUG
  104.           printf("pFunc Address:  0x%0X \n\n", pFunc);
  105.         #endif
  106.         pFunc();
  107.       }
  108.     }
  109. };
  110.  
  111. struct StateMachine::branch StateMachine::transition_table[7][4] =
  112. {
  113.  
  114.   /* Current state
  115.        Recieved event, New state, pFunc to exec */
  116.  
  117.   { // State: I0_S0
  118.     {E_UP   , I0_S0, &msg_i0_s0},
  119.     {E_DOWN , I1_S0, &msg_i1_s0},
  120.     {E_LEFT , I0_S1, &msg_i0_s1},
  121.     {E_RIGHT, I0_S2, &msg_i0_s2}
  122.   },
  123.   { // State: I0_S1
  124.     {E_UP   , I0_S1, &msg_i0_s1},
  125.     {E_DOWN , I0_S1, &msg_i0_s1},
  126.     {E_LEFT , I0_S1, &msg_i0_s1},
  127.     {E_RIGHT, I0_S0, &msg_i0_s0},
  128.   },
  129.   { // State: I0_S2
  130.     {E_UP   , I0_S2, &msg_i0_s2},
  131.     {E_DOWN , I0_S2, &msg_i0_s2},
  132.     {E_LEFT , I0_S0, &msg_i0_s0},
  133.     {E_RIGHT, I0_S2, &msg_i0_s2},
  134.   },
  135.   { // State: I1_S0
  136.     {E_UP   , I0_S0, &msg_i0_s0},
  137.     {E_DOWN , I2_S0, &msg_i2_s0},
  138.     {E_LEFT , I1_S1, &msg_i1_s1},
  139.     {E_RIGHT, I1_S2, &msg_i1_s2},
  140.   },
  141.   { // State: I1_S1
  142.     {E_UP   , I1_S1, &msg_i1_s1},
  143.     {E_DOWN , I1_S1, &msg_i1_s1},
  144.     {E_LEFT , I1_S1, &msg_i1_s1},
  145.     {E_RIGHT, I1_S0, &msg_i1_s0},
  146.   },
  147.   { // State: I1_S2
  148.     {E_UP   , I1_S2, &msg_i1_s2},
  149.     {E_DOWN , I1_S2, &msg_i1_s2},
  150.     {E_LEFT , I1_S0, &msg_i1_s0},
  151.     {E_RIGHT, I1_S2, &msg_i1_s2},
  152.   },
  153.   { // State: I2_S0
  154.     {E_UP   , I1_S0, &msg_i1_s0},
  155.     {E_DOWN , I2_S0, &msg_i2_s0},
  156.     {E_LEFT , I2_S0, &msg_i2_s0},
  157.     {E_RIGHT, I2_S0, &msg_i2_s0},
  158.   },
  159. };
  160.  
  161. int main(void)
  162. {
  163.   int c;
  164.   StateMachine FSM(I0_S0);                              // Create & initlize state machine
  165.  
  166.   while((c = getchar()) != '\33')                        // Read input untill ESC is recieved
  167.   {
  168.     FSM.process_event(c);
  169.   }
  170.  
  171.   return 0;
  172. }