Mostrando entradas con la etiqueta C/C++. Mostrar todas las entradas
Mostrando entradas con la etiqueta C/C++. Mostrar todas las entradas

Algoritmo para desordenar un arreglo en C/C++

jueves, julio 31, 2008

Imagina que deseas implementar un algoritmo en C++ donde necesites desordenar aleatoriamente un arreglo; por ejemplo: en un juego donde utilices un mazo de cartas y debas barajarlo. El siguiente código puede ayudarte en esa tarea:

int mazo_ordenado[44];
int mazo_barajado[44];
bool usado[44];

for (int i=0; i < 44; i++)
usado[i]=false;

int index=0;
for (int i=0; i < 44; i++){
do{
index = (rand() % 44);
while (usado[index]);
mazo[i] = mazo_ordenado[index];
usado[index]=true;
}

Ahora, explicaré el código paso a paso. La intención es desordenar un arreglo de 44 elementos (puede ser de cualquier tamaño, solo basta reemplazar el 44 por el número de su elección). El arreglo ordenado lo tenemos en la variable mazo_ordenado. Luego creamos otros dos arreglo con la misma cantidad de elementos, uno llamado mazo_barajado donde almacenaremos el arreglo desordenado y otro llamado usado en donde guardaremos el estado de cada elemento del mazo original.

int mazo_ordenado[44];
int mazo_barajado[44];
bool usado[44];

La idea es recorrer en orden creciente el arreglo desordenado y depositar en cada uno de sus elementos un elemento aleatorio del arreglo ordenado. Con el arreglo de booleanos usado llevaremos la cuenta de cuáles elementos del arreglo original se han usado y cuáles no (con la finalidad de no duplicar elementos), por eso debemos inicializar todos sus elementos en false

for (int i=0; i < 44; i++)
usado[i]=false;

Usando la función rand() generamos índices aleatorios para obtener los elementos del arreglo original; pero debemos comprobar el valor de usado[indice] para saber si el elemento ha sido usado o no. Si el elemento ya está usado, el valor de usado[indice] será true y tendremos que generar otro índice hasta que consigamos uno no usado.

do{
index = (rand() % 44);
while (usado[index]);

Si no hemos usado el elemento apuntado por indice, el valor de usado[indice] será false y entonces procedemos a almacenar el elemento en el arreglo desordenado y cambiamos el valor de usado[indice] a true.

mazo[i] = mazo_ordenado[index];
usado[index]=true;

Esto debemos hacerlo para los 44 elementos del arreglo desordenado así que debe ir dentro de un for y con la respectiva inicialización de la variables:

int index=0;
for (int i=0; i < 44; i++){
do{
index = (rand() % 44);
while (usado[index]);
mazo[i] = mazo_ordenado[index];
usado[index]=true;
}

A la salida del for tendremos un arreglo desordenado listo para usar :D.

Prueben el código, agreguen unos cuantos printf para imprimir los valores de los mazos antes y después del for y comenten sus resultados. Si tienen alguna sugerencia o corrección posteenla también que será bien recibida. Espero que les haya sido de utilidad.

Eventos de ratón en el QGraphicsView

miércoles, julio 16, 2008

El QGraphicsView es una clase de Qt4 que proporciona un widget para mostrar una escena QGraphicsScene. La escena es una superficie que nos permite manejar un montón de elementos 2D, sin embargo ninguno de estos controles trae habilitado por defecto la captura de eventos de ratón.

Para interceptar (y manejar) estos eventos debemos hacer una subclase, bien sea, de QGraphicsScene o de QGraphicsView y redefinir el método mousePressEvent. Pero como QGraphicsView contiene a la escena (digamos que es el widget padre) entonces lo tomaremos como base para esta explicación.

Vamos a definir una subclase válida de un QGraphicsView llamada GraphicsView y que tenga una señal llamada mousePressed con dos argumentos enteros:
#include <QGraphicsView>
#include <QObject>

class GraphicsView : public QGraphicsView{
Q_OBJECT
public:
GraphicsView(QWidget *parent = 0);
void mousePressEvent(QMouseEvent *event);
signals:
void mousePressed(int x, int y);
};

El método mousePressEvent se llamará cada vez que el usuario haga clic en un botón del ratón encima del GraphicsView. Para implementar otros eventos de ratón podemos redefinir (de la misma manera) las funciones mouseMoveEvent, mouseReleaseEvent, mouseDoubleClickEvent o wheelEvent.

La reimplementación de la clase quedaría de la siguiente forma:
GraphicsView::GraphicsView(QWidget *parent) : QGraphicsView(parent) {
/* Aquí se coloca todo el código necesario para la creación e
inicialización del widget */
}

/* Redefinición del método mousePressEvent para tomar las coordenadas x e y del
ratón y almacenarlas en las variables enteras xRaton y yRaton respectivamente */

void GraphicsView::mousePressEvent(QMouseEvent *event){
int xRaton = event->pos().x();
int yRaton = event->pos().y();

//emitir la señal mousePressed
emit mousePressed(xRaton, yRaton);
}

Para utilizar esta subclase solo debemos instanciarla y conectar la señal mousePressed a un slot de nuestra preferencia, por ejemplo:
GraphicsView *visor; //Instanciamos un puntero a un elemento GraphicsView
visor = new GraphicsView(this);

connect(visor, SIGNAL(mousePressed(int, int)), this, SLOT(slot_prara_manejar_raton(int, int)));

Con esto tendremos un QGraphicsView que soporta eventos de ratón :D

NetBeans con C++ y Qt

NetBeans es un IDE que aparte de ser gratuito y open-source es muy completo. Lo he usado para varios proyectos que he desarrollado en Java y nunca me ha dejado mal.

Pero ¿qué pasa si queremos esa funcionalidad para programar en C++ usando las librerías gráficas de Qt? Pues solo hace falta seguir estos sencillos pasos y tendremos a NetBeans configurado como IDE para C++/Qt. Esta explicación se hará bajo un sistema operativo GNU/Linux y suponiendo que ya tenemos el NetBeans instalado (sino puede visitar la página de NetBeans, descargarlo e instalarlo).

Configuración del Editor
  1. Instalar el plugin para C/C++: Vamos al menú Tools->Plugins, en la pestaña Available Plugins buscamos el de C/C++, lo marcamos y hacemos clic en instalar.



    Luego hacemos clic en Next, aceptamos la licencia y comenzará la descarga del plugin



  2. Incluir las librerias de C++ y Qt: Para esto vamos al menú principal, en Tools->Options y nos ubicamos en la pestaña Code Assistance.



    Aquí debemos agregar las siguientes rutas para que el editor reconozca las librerias de C++

    /usr/include/c++/4.2
    /usr/include/c++/4.2/i486-linux-gnu
    /usr/include/c++/4.2/backward
    /usr/local/include
    /usr/lib/gcc/i486-linux-gnu/4.2.3/include
    /usr/include

    Y estas otras para que reconozca las librerias de Qt

    /usr/include/qt4
    /usr/include/qt4/Qt
    /usr/include/qt4/QtCore
    /usr/include/qt4/QtGui
    /usr/include/qt4/QtSql
    /usr/include/qt4/QtNetwork

    Si está usando un sistema operativo distinto de GNU/Linux debe buscar el equivalente de estas rutas.

Si todo ha salido bien al hacer clic en el menú File->New Project deberíamos tener una ventana como la que se muestra a continuación, donde se observa claramente la nueva opción de C/C++ en las categorías de proyectos.



Configuración del Proyecto

Con lo que hemos hecho hasta ahora NetBeans sabe como crear, compilar y ejecutar un proyecto en C/C++ e incluso sabe dónde están las librerías estándar de C/C++ y Qt, pero aún no tiene idea de cómo compilar y ejecutar una aplicación para Qt.

NetBeans usa un archivo Makefile para cada proyecto (generado automáticamente) donde se encuentran las reglas para la compilación. Las aplicaciones Qt no usan las mismas reglas que las aplicaciones C/C++ estándares, así que la solución para esto la tenemos en estos sencillos pasos

  1. Generar el Makefile: Debemos generar nuestro propio Makefile indicándole a NetBeans las reglas para compilar nuestros proyectos Qt. Las aplicaciones Qt se compilan de la siguiente forma:

    qmake -project (para generar el proyecto, es decir el archivo .pro)
    qmake (para generar el Makefile)
    make (para compilar la aplicación usando el Makefile de arriba)


    Es decir, solo tenemos que agregar las dos instrucciones con qmake antes del make correspondiente. Sin embargo aquí se presenta un problema, NetBeans trabaja con un archivo Makefile y qmake trabaja con otro archivo Makefile, ambos son diferentes pero con el mismo nombre. Si compilamos el proyecto de esta forma el Makefile generado por qmake sobreescribirá al Makefile del NetBeans y tendremos que estar reescribiendo este archivo cada vez que queramos generar el proyecto. Para evitar eso basta con hacer que qmake genere su archivo con otro nombre, eso lo logramos agregando la opción -o al qmake. El nuevo Makefile del Netbeans (el único Makefile que debería queda a este punto) podría ser algo como:

    # build
    build: QMake
    make -f QMakefile

    # clean
    clean: QMake
    make distclean -f QMakefile
    rm *.pro -f
    rm QMakefile -f

    # all
    all: build

    QMake:
    qmake -project
    qmake -o QMakefile

    Nota: Antes de cada instrucción DEBE ir un tabulador.

    En el código anterior se nota claramente la definición de la regla QMake, que se encargará de manejar todo lo referente al qmake, además pasamos el parámetro -o al qmake para que genere un archivo de nombre QMakefile y no sobreescriba el Makefile de NetBeans. En el build se llama a la regla QMake (para que qmake genere el .pro y el QMakefile) y luego se hace el make del QMakefile, en el clean llamamos a la regla QMake (para que qmake limpie todo), hacemos la limpieza con make y luego borramos el .pro y el QMakefile para asegurarnos de que se crearan nuevamente la próxima vez que generemos el proyecto

  2. Especificar la ruta del ejecutable: NetBeans ubica los ejecutables en una ruta que depende de la forma en la que generamos el proyecto (Debug o Release) pero qmake coloca el ejecutable en la misma ruta donde se encuentra el proyecto (.pro). Para lograr que NetBeans pueda ejecutar nuestra aplicación debemos especificar la ruta en la que se encuentra nuestro ejecutable. Para ello vamos a las propiedades del proyecto (en la ventana de proyectos hacemos clic sobre el nombre de nuestro proyecto y luego clic derecho -> Properties). Acá buscamos la opción Linker->General y editamos el atributo Output; solo debemos colocar el nombre de la carpeta del proyecto (con mayúsculas y minúsculas)


Con esto ya pueden disfrutar de un completo IDE para C/C++ y Qt.