COMPARTE ESTE ARTÍCULO

En esta entrada te presento un ejercicio completo de programación orientada a objetos en C#, ideal como simulacro de examen para estudiantes de programación de videojuegos. El objetivo es poner en práctica conceptos como herencia, encapsulamiento, estructuras de datos y uso de listas.

🧩 Enunciado del Ejercicio

En un videojuego ambientado en una ciudad futurista habitada por robots autónomos, diseña las siguientes clases y métodos siguiendo buenas prácticas de programación orientada a objetos:

  1. La ciudad se extiende desde la coordenada (0,0) hasta (XMax, YMax).
  2. Un Robot tiene una posición (x, y), una batería inicial de 100 unidades, y pertenece a una ciudad. Puede moverse aleatoriamente entre -2 y 2 unidades en cada eje, sin salirse del mapa y gastando 1 unidad de batería por movimiento. Tiene un método virtual Actuar().
  3. Un RobotVigilante sobrescribe el método Actuar() para devolver aleatoriamente uno de estos mensajes:
    • “¡Intruso detectado!”
    • “Todo en orden”
    • “Escaneando…”
      (Solo si tiene batería positiva).
  4. Un RobotRecolector mantiene una lista de objetos Recurso. Tiene un método Recolectar() (simulado) y sobrescribe Actuar() para eliminar y devolver aleatoriamente un recurso. Si no hay recursos, devuelve cadena vacía.
  5. Implementa el método DescargarEnergia(List<Robot> robots, int x0, int y0, int n) para reducir batería a los robots cercanos a una posición. Si un robot queda sin batería, se elimina de la lista.
  6. Implementa MensajesRecolectores(Robot[] robots) para concatenar los resultados de Actuar() de todos los recolectores.
  7. Implementa NRobotsMasCargados(int n, Robot[] robots) para devolver los n robots con más batería.
  8. Implementa FiltrarVigilantes(List<Robot> robots) de forma recursiva para obtener los vigilantes de una lista mixta.
  9. Crea una pila de robots usando nodos encadenados (PilaNodosRobots) con métodos Push(Robot r), Pop() y Count.

💻 Código C# Completo

Aquí tienes la implementación completa del ejercicio en C#:

👉 Ver el código completo del ejercicio en GitHub (puedes subirlo a un repositorio público y enlazarlo aquí)
O puedes copiarlo directamente desde aquí:

using System;
using System.Collections.Generic;

public class Ciudad
{
    public int XMax { get; }
    public int YMax { get; }

    public Ciudad(int xMax, int yMax)
    {
        XMax = xMax;
        YMax = yMax;
    }
}

public class Robot
{
    public int X { get; protected set; }
    public int Y { get; protected set; }
    public int Bateria { get; protected set; }
    public Ciudad Ciudad { get; }

    private static Random rnd = new Random();

    public Robot(Ciudad ciudad)
    {
        Bateria = 100;
        Ciudad = ciudad;
        X = rnd.Next(0, ciudad.XMax + 1);
        Y = rnd.Next(0, ciudad.YMax + 1);
    }

    public virtual string Actuar()
    {
        return "";
    }

    public void Desplazarse()
    {
        int dx = rnd.Next(-2, 3);
        int dy = rnd.Next(-2, 3);

        X = Math.Clamp(X + dx, 0, Ciudad.XMax);
        Y = Math.Clamp(Y + dy, 0, Ciudad.YMax);
        Bateria--;
    }
}

public class RobotVigilante : Robot
{
    public RobotVigilante(Ciudad ciudad) : base(ciudad) { }

    public override string Actuar()
    {
        if (Bateria <= 0) return "";

        string[] frases = { "¡Intruso detectado!", "Todo en orden", "Escaneando…" };
        return frases[new Random().Next(frases.Length)];
    }
}

public class Recurso
{
    public string Descripcion { get; set; }

    public Recurso(string desc)
    {
        Descripcion = desc;
    }
}

public class RobotRecolector : Robot
{
    private List<Recurso> recursos = new List<Recurso>();

    public RobotRecolector(Ciudad ciudad) : base(ciudad) { }

    public void Recolectar(Recurso recurso)
    {
        recursos.Add(recurso);
    }

    public override string Actuar()
    {
        if (recursos.Count == 0) return "";

        int index = new Random().Next(recursos.Count);
        Recurso eliminado = recursos[index];
        recursos.RemoveAt(index);
        return eliminado.Descripcion;
    }
}

public static class Utilidades
{
    public static void DescargarEnergia(List<Robot> robots, int x0, int y0, int n)
    {
        robots.RemoveAll(r =>
        {
            bool cerca = Math.Abs(r.X - x0) < n && Math.Abs(r.Y - y0) < n;
            if (cerca)
            {
                r.Bateria -= n;
            }
            return r.Bateria < 0;
        });
    }

    public static string MensajesRecolectores(Robot[] robots)
    {
        string resultado = "";
        foreach (var r in robots)
        {
            if (r is RobotRecolector recolector)
                resultado += recolector.Actuar();
        }
        return resultado;
    }

    public static Robot[] NRobotsMasCargados(int n, Robot[] robots)
    {
        Array.Sort(robots, (a, b) => b.Bateria.CompareTo(a.Bateria));
        int length = Math.Min(n, robots.Length);
        Robot[] top = new Robot[length];
        Array.Copy(robots, top, length);
        return top;
    }

    public static List<RobotVigilante> FiltrarVigilantes(List<Robot> robots)
    {
        if (robots.Count == 0)
            return new List<RobotVigilante>();

        List<Robot> sublista = new List<Robot>(robots);
        Robot actual = sublista[0];
        sublista.RemoveAt(0);
        List<RobotVigilante> resto = FiltrarVigilantes(sublista);
        if (actual is RobotVigilante vig)
        {
            resto.Insert(0, vig);
        }
        return resto;
    }
}

public class NodoRobot
{
    public Robot R;
    public NodoRobot Anterior;

    public NodoRobot(Robot r)
    {
        R = r;
        Anterior = null;
    }
}

public class PilaNodosRobots
{
    private NodoRobot tope;
    private int contador;

    public void Push(Robot r)
    {
        NodoRobot nuevo = new NodoRobot(r);
        nuevo.Anterior = tope;
        tope = nuevo;
        contador++;
    }

    public Robot Pop()
    {
        if (tope == null) return null;

        Robot r = tope.R;
        tope = tope.Anterior;
        contador--;
        return r;
    }

    public int Count => contador;
}

🛠️ ¿Qué Aprendemos con Este Ejercicio?

  • Cómo modelar entidades de un videojuego usando clases.
  • Uso de herencia para personalizar comportamiento (Actuar()).
  • Control de posiciones dentro de un mapa.
  • Listas genéricas, acceso aleatorio y eliminación.
  • Recursividad con listas.
  • Implementación de una estructura tipo pila enlazada.

📚 Recomendación para Estudiantes

Este simulacro es ideal para preparar evaluaciones de Programación Orientada a Objetos o Lógica de Videojuegos. Puedes practicar:

  • Extender las clases con más funcionalidades (e.g., ataques, energía renovable).
  • Simular interacciones entre robots.
  • Usar una interfaz gráfica sencilla con WinForms o Unity.

🧑‍🏫 ¿Eres Profesor?

Puedes usar este ejercicio como base para exámenes o prácticas. Está diseñado para evaluar conocimientos de:

  • Diseño orientado a objetos.
  • Recursividad.
  • Estructuras de datos.
  • Buenas prácticas de codificación en C#.

✍️ ¿Te gustaría más ejercicios como este?

Déjalo en los comentarios o contáctame directamente. También puedes suscribirte para recibir notificaciones de nuevas prácticas, tutoriales y simulacros de examen.


¿Quieres que este post incluya imágenes o fragmentos destacados con formato WordPress (código, bloques, etc.)?

Contenido restringido

Acceso de usuarios existentes
   
Registro de un nuevo usuario
*Campo necesario

Categories:

Tags:

Comments are closed

Estado de acceso
ESTADO DE ACCESO
TRADUCTORES
COMPARTENOS
error: CONTENIDO PROTEGIDO