11/14/2016

Ejercicio 34

Elabore un juego como el rompecabezas deslizante, se debe tener en cuenta que la matriz puede ser de 3x3 hasta 9x9.

Rompecabezas deslizante

Para que el jugador pueda ganar, debe tener el rompecabezas en el siguiente orden: Para ganar el juego debes tener este orden

#include <iostream>
#include "Tablero.h"
/*
 * incluire la clase unistd.h  para poder utilizar el metodo  usleep()  para que el programa "duerma"
 * y realize una pequeña animacion por unos segundos que le asigne como parametro
 */ 
#include <unistd.h>

// defino dos constantes, 1 para la dimension minima que sera 3 y la otra para la dimension maxima que sera 9 
#define DIM_MIN 3
#define DIM_MAX 9

using namespace std;

// funciones prototipo, las funciones prototipo solo le dicen al compilador que utilizare esta funcion o metodo
// pero mas tarde 
void dibujar(Tablero *obj);
void creditos();

int main(void)
{
    // se crea un objeto de la clase Tablero  (Instanciaciación) 
    Tablero *obj = new Tablero();
    int dim;
    // con el ciclo do..while  me asegurare de que se ingrese una dimension adecuada 
    do
    {
        // pido en pantalla que se digite la dimension del tablero 
        cout << "Digite dimension del tablero" << endl;
        cout << ">> ";
        // guardo la dimension en la variable dim  
        cin >> dim;
        obj->setDimension(dim);
        // si la dimension que digito el usuario es menor que la dimension minima ó si la dimension es mayor que la dimension maxima 
        if (dim < DIM_MIN || dim > DIM_MAX)
        {
            // entonces se mostrara en pantalla que debe ingresaar una dimension valida 
            cout << "El tablero debe tener una dimension entre " << DIM_MIN << "x" << DIM_MIN << " y " << DIM_MAX << "x" << DIM_MAX << "." << endl;
        }
    }
    // repetira esto hasta que el usuario ingrese una dimension valida 
    while(dim < DIM_MIN || dim > DIM_MAX);

    // limpiare la pantalla 
    obj->limpiar();
    // mostrare los creditos 
    creditos();

    // inicializare el tablero 
    obj->iniciar();

    // repetire todas las intrucciones dentro del ciclo while  hasta que el usuario gane el juego 
    while (true)
    {
        // limpio la pantalla 
        obj->limpiar();
        // dibujo el estado actual del tablero 
        dibujar(obj);

        // compruebo si el usuario ha ganado el juego 
        if (obj->gano())
        {
            // si gana el juego, mostrara el texto en pantalla y rompera el programa 
            cout << " Has ganado!" << endl;
            break;
        }

        // pido un movimiento al usuario 
        cout << "Digita el numero del cuadro a donde quieres moverte" << endl;
        cout << ">> ";
        // creo la variable de tipo entero mov  (movimiento) 
        int mov;
        // y guardo el movimeinto que ingreso el usuario en la variable mov  
        cin >> mov;

        // se movera si es posible, pero sino entonces mostrara un mensaje de movimiento invalido 
        if (!obj->mover(mov))
        {
            cout << "\nEste movimiento no se puede hacer." << endl;
            // dormira por 500000 microsegundos 
            usleep(500000);
        }

        usleep(500000);
    }
}

/**
 * Imprimo el tablero en su estado actual.
 */ 
void dibujar(Tablero *obj)
{
    // recorreré toda la matriz con el ciclo for  
    for (int i = 0; i < obj->getDimension(); i++)
    {
        for (int j = 0; j < obj->getDimension(); j++)
        {
            // si el valor que esta en la posicion i , j  es 0, entonces: 
            if (obj->getTablero(i, j) == 0)
            {
                // imprimire la barrita que indica la posicion en donde se encuentra el usuario actualmente 
                cout << "\t _";
            }
            else
            {
                // sino, imprimire los datos que hay en el arreglo identados \t  
                cout << "\t|" << obj->getTablero(i, j) << "|";
            }
        }
        // dare dos saltos de linea para que se vea mas estetico la tabla del juego 
        cout << endl << endl;
    }
}

void creditos()
{
    //              0    1    2    3    4    5    6    7 
    char sim[8] = {201, 205, 187, 186, 200, 188, 204, 185};
    cout << sim[0];
    for (int i = 0; i < 51; i++)
        cout  << sim[1];
    cout << sim[2] << endl;

    cout << sim[3] << "    BIENVENIDO AL JUEGO ROMPECABEZAS DESLIZANTE    " << sim[3] << endl;
    cout << sim[6];
    for (int i = 0; i < 51; i++)
        cout  << sim[1];
    cout << sim[7] << endl;
    cout << sim[3] << "                                                   " << sim[3] << endl;
    cout << sim[3] << "         CREADO POR OMAR FLOREZ (Vlph7_7)          " << sim[3] << endl;
    cout << sim[3] << "                                                   " << sim[3] << endl;
    cout << sim[4];
    for (int i = 0; i < 51; i++)
        cout  << sim[1];
    cout << sim[5] << endl;
    usleep(900000);
}

#ifndef TABLERO_H
#define TABLERO_H
// defino dos constantes, 1 para la dimension minima que sera 3 y la otra para la dimension maxima que sera 9 
#define DIM_MIN 3
#define DIM_MAX 9

class Tablero
{
    public:
        Tablero();
        virtual ~Tablero();
        void limpiar();
        void iniciar();
        bool mover(int mov);
        bool gano();
        void setTablero(int fil, int col, int val);
        int getTablero(int fil, int col);
        void setDimension(int val);
        int getDimension();
    protected:

    private:
        // declaro una matriz o un vector multidimensional y le asigno las dimension maxima que haya ingresado el usuario 
        int tablero[DIM_MAX][DIM_MAX];
        // declaro la variable d, sera la dimension que ingresara el usuario 
        int d;
};

#endif // TABLERO_H 

#include "Tablero.h"
// incluire la clase stdlib.h  para poder utilizar el metodo system()  y poder limpiar la pantalla con el parametro "cls" 
#include <stdlib.h>

Tablero::Tablero()
{
    //ctor 
}

Tablero::~Tablero()
{
    //dtor 
}

/**
 * Limpio la pantalla
 */ 
void Tablero::limpiar()
{
    system("cls");
}

/**
 * Inicializa el tablero del juego con los movimientos numerados desde 1 a d *d  - 1
 * (es decir llena la matriz con valores, pero en realidad no los imprime)
 */ 
void Tablero::iniciar()
{
    // declaro la variable total  de tipo entero y le asignare el numero total de espacios de la matriz 
    int total = getDimension() * getDimension();

    // agrego los espacios o los cuadros en el tablero 
    for (int i = 0; i < getDimension(); i++)
    {
        for (int j = 0; j < getDimension(); j++)
        {
            // decremento el valor de total  en 1 y se lo asigno al arreglo tablero  en la posicion actual de i , j  
            setTablero(i, j, --total);
        }
    }

    // debo intercambiar 2 y 1 si el número de espacios en total del arreglo es par 
    if ((getDimension() * getDimension()) % 2 == 0)
    {
        setTablero(d-1, d-3, 1);
        setTablero(d-1, d-2, 2);
    }
}

/**
 * Si el cuadro esta al lado del espacio vacio _  entonces movera
 * el cuadro y devolvera true, sino devolvera false
 */ 
bool Tablero::mover(int mov)
{
    // compruebo si el movimiento es valido 
    if (mov > getDimension() * getDimension() - 1 || mov < 1)
    {
        return false;
    }

    // recorreré el tablero con el ciclo for  desde las filas y columnas 
    int fil = 0, col = 0;

    for (int i = 0; i < getDimension(); i++)
    {
        for (int j = 0; j < getDimension(); j++)
        {
            // si el cuadro que esta en posicion i , j  del tablero  es igual al movimeinto que ingreso el usuario 
            if (getTablero(i,j) == mov)
            {
                // entonces le asignare a fil  el valor de i  
                fil = i;
                // y a col  le asignare el valor de j  
                col = j;
            }
        }
    }

    // compruebo los espacios cercanos, si se logra encontrar uno se devolvera true de lo contrario devolvera false 
    if (fil - 1 >= 0 && getTablero(fil-1, col) == 0)
    {
        setTablero(fil-1, col, getTablero(fil, col));
        setTablero(fil, col, 0);
        return true;
    }
    else if (fil + 1 < getDimension() && getTablero(fil+1, col) == 0)
    {
        setTablero(fil+1, col, getTablero(fil, col));
        setTablero(fil, col, 0);
        return true;
    }
    else if (col - 1 >= 0 && getTablero(fil, col-1) == 0)
    {
        setTablero(fil, col-1, getTablero(fil, col));
        setTablero(fil, col, 0);
        return true;
    }
    else if (col + 1 < d && getTablero(fil, col+1) == 0)
    {
        setTablero(fil, col+1, getTablero(fil, col));
        setTablero(fil, col, 0);
        return true;
    }
    return false;
}

/**
 * Devolvere true si se gana el juego,
 * Sino devolvere false.
 */ 
bool Tablero::gano()
{
    // declaro una variable de tipo entero contador  y la inicializo en 0 
    int contador = 0;

    // revisaré cada cuadro para asegurarme de que esté en orden 
    for (int i = 0; i < getDimension(); i++)
    {
        for (int j = 0; j < getDimension(); j++)
        {
            // compruebo si el último punto es correcto y si no es el valor correcto 
            if (++contador != (d * d) && getTablero(i, j) != contador)
            {
                // si eso es verdadero entonces devolvere false y el jugador aun no habra ganado 
                return false;
            }
        }
    }
    // devolvere true y el jugador ganara el juego 
    return true;
}

// implementacion de los metodos Setters y Getters de los atributos de la clase Tablero 
void Tablero::setTablero(int fil, int col, int val)
{
    tablero[fil][col] = val;
}

int Tablero::getTablero(int fil, int col)
{
    return tablero[fil][col];
}

void Tablero::setDimension(int val)
{
    d = val;
}

int Tablero::getDimension()
{
    return d;
}

//Se importa paquete JOptionPane  para dibujar un cuadro de dialogo en pantalla
//que muestre información o para llenar información. 
import javax.swing.JOptionPane;

public class Main
{
    // imprimo el tablero en su estado actual. 
    public static String dibujar(Tablero obj)
    {
        // declaro la variable datos  de tipo string la utilizare para acumular todo el tablero 
        String datos = "";
        // recorreré toda la matriz con el ciclo for  
        for (int i = 0; i < obj.getDimension(); i++)
        {
            for (int j = 0; j < obj.getDimension(); j++)
            {
                // imprimo el tablero si el valor que esta esta en la posicion i , j  es 0 
                if (obj.getTablero(i, j) == 0)
                {
                    // le asigno a datos  el valor de datos  mas la barrita _  que indica la posicion en donde se encuentra el usuario actualmente 
                    datos = datos + "     _  ";
                }
                else
                {
                    // si el numero que esta en el tablero enta entre el rango de 1 y 9 
                    if (obj.getTablero(i, j) > 0 && obj.getTablero(i, j) < 10)
                    {
                        /**
                         * entonces le dare un espacio mas a los cuadros, por que los numeros 1,2,3,..9 
                         * se veran de esta forma |1| |2| pero si hay un numero como el |10| entonces quedan mal esteticamente
                         * en Java no he encontrado una forma de poder identar esto, ni siquiera con el \t 
                         */ 
                        datos = datos + "   | " + String.valueOf(obj.getTablero(i, j)) + " |";
                    }
                    else
                    {
                        // sino lo imprimo normal sin el espacio despues del "|" 
                        datos = datos + "   |" + String.valueOf(obj.getTablero(i, j)) + "|";
                    }
                }
            }
            // doy un salto de linea 
            datos = datos + "\n";
        }
        return datos;
    }

    public static String creditos()
    {
        String datos = "";
        datos = datos + "=====================================================================\n";
        datos = datos + "============   BIENVENIDO AL JUEGO ROMPECABEZAS DESLIZANTE   ============\n";
        datos = datos + "=====================================================================\n";
        datos = datos + "=====================================================================\n";
        datos = datos + "================   CREADO POR OMAR FLOREZ (Vlph7_7)   ===================\n";
        datos = datos + "=====================================================================\n";
        return datos;
    }
    
    public static void main(String[] args)
    {
        // se crea un objeto de la clase Tablero  (Instanciaciación) 
        Tablero obj = new Tablero();
        int dim;
        // con el ciclo do..while  me asegurare de que se ingrese una dimension adecuada 
        do
        {
            // pido en pantalla que se digite la dimension del tablero y la guardo en dim  
            dim = Integer.parseInt(JOptionPane.showInputDialog("Digite dimension del tablero:"));
            
            // encapsulo la variable dim  
            obj.setDimension(dim);
            // si la dimension que digito el usuario es menor que la dimension minima ó si la dimension es mayor que la dimension maxima 
            if (dim < 3 || dim > 9)
            {
                // entonces se mostrara en pantalla que debe ingresar una dimension valida 
                JOptionPane.showMessageDialog(null, "El tablero debe tener una dimension entre 3x3 y 9x9. \n");
            }
        }
        // repetira esto hasta que el usuario ingrese una dimension valida 
        while(dim < 3 || dim > 9);

        // mostrare los creditos 
        JOptionPane.showMessageDialog(null, creditos());

        // inicializare el tablero 
        obj.iniciar();

        // repetire todas las intrucciones dentro del ciclo while  hasta que el usuario gane el juego 
        while (true)
        {
            // compruebo si el usuario ha ganado el juego 
            if (obj.gano())
            {
                // si gana el juego, mostrara el texto en pantalla y rompera el programa 
                JOptionPane.showMessageDialog(null, " Has ganado! \n");
                break;
            }

            // creo la variable de tipo entero mov  (movimiento) 
            int mov;
            // pido un movimiento al usuario y guardo el movimiento que ingreso el usuario en la variable mov  
            
            mov = Integer.parseInt(JOptionPane.showInputDialog(dibujar(obj) + "\nDigita el numero del cuadro a donde quieres moverte:"));

            // se movera si es posible, pero sino entonces mostrara un mensaje de movimiento invalido 
            if (!obj.mover(mov))
            {
                JOptionPane.showMessageDialog(null, "Este movimiento no se puede hacer.");
            }
        }
    }
}

public class Tablero
{
    // declaro las variable constantes DIM_MIX  y le asigno 3 y DIM_MAX  y le asigno 9 
    private final int DIM_MIN = 3;
    private final int DIM_MAX = 9;
    // declaro una matriz o un vector multidimensional y le asigno las dimension maxima que haya ingresado el usuario 
    private int [][] tablero = new int[DIM_MAX][DIM_MAX];
    // declaro la variable d , sera la dimension que ingresara el usuario 
    private int d;

   /**
    * Se inicializa el tablero del juego con los movimientos numerados desde 1 a d *d  - 1
    * (es decir llena la matriz con valores, pero en realidad no los imprime)
    */ 
   public void iniciar()
   {
       // declaro la variable total  de tipo entero y le asignare el numero total de espacios de la matriz 
       int total = getDimension() * getDimension();

       // agrego los espacios o los cuadros en el tablero 
       for (int i = 0; i < getDimension(); i++)
       {
           for (int j = 0; j < getDimension(); j++)
           {
               // decremento el valor de total  en 1 y se lo asigno al arreglo tablero  en la posicion actual de i , j  
               setTablero(i, j, --total);
           }
       }

       // debo intercambiar 2 y 1 si el número de espacios en total del arreglo es par 
       if ((getDimension() * getDimension()) % 2 == 0)
       {
           setTablero(d-1, d-3, 1);
           setTablero(d-1, d-2, 2);
       }
   }

   /**
    * Si el cuadro esta al lado del espacio vacio _  entonces movera
    * el cuadro y devolvera true, sino devolvera false
    */ 
   public boolean mover(int mov)
   {
       // compruebo si el movimiento es valido 
       if (mov > getDimension() * getDimension() - 1 || mov < 1)
       {
           return false;
       }

       // recorreré el tablero con el ciclo for  desde las filas y columnas 
       int fil = 0, col = 0;

       for (int i = 0; i < getDimension(); i++)
       {
           for (int j = 0; j < getDimension(); j++)
           {
               // si el cuadro que esta en posicion i , j  del tablero  es igual al movimeinto que ingreso el usuario 
               if (getTablero(i,j) == mov)
               {
                   // entonces le asignare a fil  el valor de i  
                   fil = i;
                   // y a col  le asignare el valor de j  
                   col = j;
               }
           }
       }

       // compruebo los espacios cercanos, si se logra encontrar uno se devolvera true de lo contrario devolvera false 
       if (fil - 1 >= 0 && getTablero(fil-1, col) == 0)
       {
           setTablero(fil-1, col, getTablero(fil, col));
           setTablero(fil, col, 0);
           return true;
       }
       else if (fil + 1 < getDimension() && getTablero(fil+1, col) == 0)
       {
           setTablero(fil+1, col, getTablero(fil, col));
           setTablero(fil, col, 0);
           return true;
       }
       else if (col - 1 >= 0 && getTablero(fil, col-1) == 0)
       {
           setTablero(fil, col-1, getTablero(fil, col));
           setTablero(fil, col, 0);
           return true;
       }
       else if (col + 1 < d && getTablero(fil, col+1) == 0)
       {
           setTablero(fil, col+1, getTablero(fil, col));
           setTablero(fil, col, 0);
           return true;
       }
       return false;
   }

   /**
    * Devolvere true si se gana el juego,
    * Sino devolvere false.
    */ 
   public boolean gano()
   {
       // declaro una variable de tipo entero contador  y la inicializo en 0 
       int contador = 0;

       // revisaré cada cuadro para asegurarme de que esté en orden 
       for (int i = 0; i < getDimension(); i++)
       {
           for (int j = 0; j < getDimension(); j++)
           {
               // compruebo si el último punto es correcto y si no es el valor correcto 
               if (++contador != (d * d) && getTablero(i, j) != contador)
               {
                   // si eso es verdadero entonces devolvere false y el jugador aun no habra ganado 
                   return false;
               }
           }
       }
       // devolvere true y el jugador ganara el juego 
       return true;
   }

   // implementacion de los metodos Setters y Getters de la clase Tablero 
   public void setTablero(int fil, int col, int val)
   {
       tablero[fil][col] = val;
   }

   public int getTablero(int fil, int col)
   {
       return tablero[fil][col];
   }

   public void setDimension(int val)
   {
       d = val;
   }

   public int getDimension()
   {
       return d;
   }
}