Skip to content

Instantly share code, notes, and snippets.

@noidi
Created March 5, 2010 07:05
Show Gist options
  • Save noidi/322517 to your computer and use it in GitHub Desktop.
Save noidi/322517 to your computer and use it in GitHub Desktop.
/* A simple state machine in C: The enemy moves left, then to the
* right, and finally stops. */
#include <stdio.h>
/* Enemy forward declaration, so that EnemyState can refer to it */
struct Enemy;
/* Enemy state type */
typedef struct EnemyState {
void (*update)(struct Enemy* enemy);
void (*shout)(struct Enemy* enemy);
} EnemyState;
/* Enemy type */
typedef struct Enemy {
int position;
const EnemyState* state;
} Enemy;
/* Enemy state forward declarations, so that the states can refer to
* each other. */
const EnemyState enemy_moving_left;
const EnemyState enemy_moving_right;
const EnemyState enemy_stopped;
/* Enemy state 1: Moving Left */
void enemy_moving_left_update(Enemy* enemy) {
enemy->position -= 1;
if (enemy->position <= -3) {
enemy->state = &enemy_moving_right;
}
}
void enemy_moving_left_shout(Enemy* enemy) {
printf("I'm moving to the left! Yarrr!\n");
}
const EnemyState enemy_moving_left = {
enemy_moving_left_update,
enemy_moving_left_shout
};
/* Enemy state 2: Moving Right */
void enemy_moving_right_update(Enemy* enemy) {
enemy->position += 1;
if (enemy->position >= 3) {
enemy->state = &enemy_stopped;
}
}
void enemy_moving_right_shout(Enemy* enemy) {
printf("I'm moving to the right! Whee!\n");
}
const EnemyState enemy_moving_right = {
enemy_moving_right_update,
enemy_moving_right_shout
};
/* Enemy state 3: Stopped */
void enemy_stopped_update(Enemy* enemy) {
}
void enemy_stopped_shout(Enemy* enemy) {
printf("I'm not moving anywhere!\n");
}
const EnemyState enemy_stopped = {
enemy_stopped_update,
enemy_stopped_shout
};
/* Finally we can use the state machine. */
int main(int argc, char* argv[]) {
/* Create an enemy in the middle, moving left */
Enemy enemy = {0, &enemy_moving_left};
/* Let the enemy update itself and shout, until it reaches the
* stopped state. */
do {
enemy.state->update(&enemy);
enemy.state->shout(&enemy);
} while (enemy.state != &enemy_stopped);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment