Created
March 5, 2010 07:05
-
-
Save noidi/322517 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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