Imaginemos un pequeño robot que recogerá diez objetos colocados al azar. Si en algún momento el robot empieza a quedarse sin batería, tendrá que ir a recoger una nueva. Si el robot se queda por completo sin batería, se muere.
Observamos los estados necesarios:
- Estado de búsqueda en el cual el robot se dirija hacia el objeto.
- Estado en el que decida cuál es el siguiente objeto a recoger.
- Estado en el cual el robot deberá ir a por una batería nueva.
- Estado en que llega a la batería y recarga energía.
- Estado en el que el robot muere por falta de energía.
- Estado en el que el robot se mueve al azar ya que no hay mas objetos que recoger.
Transiciones:
Si se encuentra en el estado de búsqueda, puede seleccionar un nuevo objeto que buscar si ya llegó al objeto buscado, o dirigirse hacia la batería si su cantidad de energía es menor a 400 unidades.
Si se encuentra en el estado en el que escoge el siguiente objeto por buscar, puede cambiar de estado. Se cambia a búsqueda cuando haya seleccionado el nuevo objeto. Si no hay más objetos para recoger, entonces se pasa al estado de movimiento aleatorio.
En el estado aleatorio, se lleva a cabo la transición hacia el esta de muerto cuando la energía en la batería llega a cero. El estado de muerto no tiene transición a ningún otro estado.
Cuando se dirige a la batería y la energía de ésta llega al valor cero, entonces también la transición es hacia el estado de muerto. Si llega a la batería antes de que esto suceda, se pasa al estado donde recarga. En el estado de recargar la batería, hay una transición hacia el estado de búsqueda, para completar el ciclo de estados finitos de nuestro robot.
Enlace de descarga del proyecto completo:
https://code.msdn.microsoft.com/Maquina-de-Estados-Finitos-94da3a96
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace MEF
{
public class Form1 : Form
{
private MainMenu mainMenu1;
private MenuItem menuItem1;
private MenuItem mnuSalir;
private MenuItem menuItem3;
private MenuItem mnuInicio;
private MenuItem mnuParo;
private Timer timer1;
private IContainer components;
// Creamos un objeto para la maquina de estados finitos
private CMaquina maquina = new CMaquina();
// Objetos necesarios
public S_objeto[] ListaObjetos = new S_objeto[10];
public S_objeto MiBateria;
public Form1()
{
//
// Necesario para admitir el Diseñador de Windows Forms
//
InitializeComponent();
//
// Inicializamos los objetos
// Cremos un objeto para tener valores aleatorios
Random random = new Random();
// Recorremos todos los objetos
for (int n = 0; n < 10; n++)
{
// Colocamos las coordenadas
ListaObjetos[n].x = random.Next(0, 639);
ListaObjetos[n].y = random.Next(0, 479);
// Lo indicamos activo
ListaObjetos[n].activo = true;
}
// Colocamos la bateria
MiBateria.x = random.Next(0, 639);
MiBateria.y = random.Next(0, 479);
MiBateria.activo = true;
maquina.Inicializa(ref ListaObjetos, MiBateria);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
static void Main()
{
Application.Run(new Form1());
}
private void mnuSalir_Click(object sender, System.EventArgs e)
{
// Cerramos la ventana y finalizamos la aplicacion
this.Close();
}
private void mnuInicio_Click(object sender, System.EventArgs e)
{
timer1.Enabled = true;
}
private void mnuParo_Click(object sender, System.EventArgs e)
{
timer1.Enabled = false;
}
private void timer1_Tick(object sender, System.EventArgs e)
{
// Esta funcion es el handler del timer
// Aqui tendremos la logica para actualizar nuestra maquina de estados
// Actualizamos a la maquina
maquina.Control();
// Mandamos a redibujar la pantalla
this.Invalidate();
}
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
// Creamos la fuente y la brocha para el texto
Font fuente = new Font("Arial", 16);
SolidBrush brocha = new SolidBrush(Color.Black);
// Dibujamos el robot
if (maquina.EstadoM == (int)CMaquina.estados.MUERTO)
e.Graphics.DrawRectangle(Pens.Black, maquina.CoordX - 4, maquina.CoordY - 4, 20, 20);
else
e.Graphics.DrawRectangle(Pens.Green, maquina.CoordX - 4, maquina.CoordY - 4, 20, 20);
// Dibujamos los objetos
for (int n = 0; n < 10; n++)
if (ListaObjetos[n].activo == true)
e.Graphics.DrawRectangle(Pens.Indigo, ListaObjetos[n].x - 4, ListaObjetos[n].y - 4, 20, 20);
// Dibujamos la bateria
e.Graphics.DrawRectangle(Pens.IndianRed, MiBateria.x - 4, MiBateria.y - 4, 20, 20);
// Indicamos el estado en que se encuentra la maquina
e.Graphics.DrawString("Estado -> " + maquina.EstadoM.ToString(), fuente, brocha, 10, 10);
}
}
}