05 noviembre 2011

Sobrecargando operadores en C++

Una de las ventajas de la programación orientada a objetos es el polimorfismo (como expliqué aquí hace años).  Esto quiere decir que puedes tener varias funciones con el mismo nombre, pero con diferentes parámetros y/o tipos que devuelve.  Entonces en tu programa, al llamar a la función, va a elegir la versión de la función que necesitas.  Eso te ahorra mucho código.
Algo similar se pueden hacer con los operadores (que técnicamente no es polimorfismo como tal).  Por ejemplo, el operador + está definido en C y C++ para sumar dos números (sea int, double, float u otro tipo de dato numérico).  Pero C++ agrega una clase string que sobrecarga el operador + para que, cuando trabaje con objeto de tipo string, los concatene (o sea que “Tony ” + “Valderrama” = “Tony Valderrama”).  De la misma forma lo puedo hacer con diferentes clases para que estas operaciones funcionen de forma lógica con otros tipos de datos.
Para ejemplificar esto, hice una clase que almacena Fechas (llamada sabiamente Fecha, jeje) que permite sumar dos fechas (operador +), agregar un día (operador ++ postfijo) y por medio de una función amiga modifico el comportamiento del operador de flujo de salida (<<, tipo que se usa para la instrucción cout).  Como te imaginarás, sumar fechas es diferente a sumar dos números porque hay que validar que los números de meses sean correctos (hay meses de 31, 30, 28 o 29), que los meses no pasen de 12, etc.  Aquí está la definición de la clase:
00-Class Fecha
Aquí declaro dos constructores: uno de ellos, el default, que no lleva parámetros y otro al que se le pueden pasar 3 enteros (para asignarle día, mes y año, respectivamente) para inicializarlo desde que crea el objeto.  Luego viene la función que sobrecarga el operador +, luego el que sobrecarga la operación ++ postfijo.  ¿Pero qué es postfijo?  Es cuando el operador ++ lo escribes después del nombre de la variable/objeto.  Como saben, no es exactamente los mismo ++x (prefijo) que x++ (postfijo) porque en el primero se encarga de incrementar la variable antes de realizar la operación, mientras que el segundo primero hace la operación y luego incrementa.  Ejemplo:
int x=3;
cout << ++x;     // Esto imprime 4 porque incrementa antes del cout
cout << x++;     // Imprime 4 y luego incrementa el valor de x
Una vez declarada la versión postfijo, sobrecargo el mismo operador ++ pero ahora el prefijo.  Si te fijas hay solo 2 diferencias entre la declaración de uno y otro: el postfijo devuelve un objeto Fecha y recibe de parámetro un int; mientras el otro devuelve un apuntador al objeto Fecha y no recibe parámetros. Más adelante en el código se verá la diferencia más clara (espero). Después de esto, declaro una función amiga (friend) que se va a encargar de sobrecargar el operador <<, otra que sobrecarga el operador >> y otras dos funciones: una que devuelve el día máximo de acuerdo al mes y año (necesitamos el año por aquello de los años bisiestos) y otra función que le asigna valores al día, mes y año (este lo usé para probar la asignación antes de sobrecargar el operador >>).
Cabe recalcar que los operadores >> y << no son funciones miembro de la clase y devuelven streams (istream es Input stream o flujo de entrada y ostream es Output stream o flujo de salida).  Son muy similares en su función a los strings pero mucho más versátiles para algunos usos.
Volviendo al código puedes observar que los constructores no tienen ningún chiste.  Aquí está el código:
01-Constructores
El primer operador que sobrecargo es el +.  Aquí está el código:
02-Operador
Supongamos que en mi función main() declaro dos objetos te tipo fecha llamados A, B y C.  Si escribo la operación C=A+B se ejecuta esta función.  El valor de A sería el “local”, es decir, cuando hago referencia a dia, mes y anio, estoy accesando estas variables del objeto A.  El parámetro que le paso (llamado x) tendría los valores almacenados en B. así que, cuando hago referencia a x.dia, x.mes y x.anio me estoy refiriendo a estos campos en el objeto B.
Una vez aclarado de los parámetros, pasemos a ver qué hace esta función.  En x recibe el valor de la fecha que se le va a sumar (días, meses y años).  Luego declaro un objeto Fecha (Temp) donde voy a realizar la suma de las fechas.  La variable mex es temporal para el cálculo de meses.  Sumo los días y años en Temp y luego calculo los meses: si el día es mayor al número máximo de días que corresponde al mes, le resto el número de días máximo aceptados, incremento el número de meses y si corresponda cambiar de año, incrementa el año y le resta 12 meses.  Al final del ciclo le sumo los meses y vuelvo a verificar si toca cambio de año.  Al final devuelvo la variable Temp que contiene la suma.
Ahora pasamos al operador ++ postfijo.  Aquí está el código:
03-Operador
Si se fijan, el parámetro de tipo int no me sirve para nada, bueno, sirve para distinguir el ++ postfijo del prefijo como ya argumenté con anterioridad.  Ni siquiera le pongo nombre de variable porque no lo voy a usar.  Creo una Fecha, llamado Temp, para hacer el cálculo de la fecha más un día.  El apuntador this es una forma elegante de referirse a esta misma clase y lo uso para inicializar a Temp.  Altero los valores de ésta clase (apuntador this) para incrementar un día y luego revisar si toca cambio de mes, y si toca, incremento el año.  Al final devuelvo Temp y ya terminé.
El código del operador ++ prefijo es idéntico.  Lo único que cambia es que devuelve la referencia (apuntador) a un objeto Fecha y no recibe un entero como parámetro.  Aquí está:
04-Operador
Ahora una función muy simple para devolver el número máximo de días que tiene cada mes.  Lo uso mucho para validaciones.  La idea es que enero, marzo, mayo, julio, agosto, octubre y diciembre tienen 31 días, mientras que abril, junio, septiembre y noviembre tienen 30.  Como saben el mes especial es febrero que puede tener 29 o 29 días dependiendo si el año es bisiesto o no.  Aquí está el código:
05-MaxDiaMes
Otra función que no tiene chiste es el que te permite asignar fecha.  Aquí está:
06-AsignaFecha
Ahora voy a hablar de la función amiga que sirve para sobrecargar el operador <<.  Aquí está el código:
07-Operador ostream
El objeto de tipo ostream es igual al que recibe la función cout.  Así que básicamente debo hacer lo mismo que haría en un cout para dejar el texto como quiero, pero en lugar de enviarlo al cout, lo mando a x.  Esta función devuelve una referencia al objeto ostream que hice.
Para terminar con las funciones, falta el que sobrecarga al operador .  Hagan de cuenta que ahora estoy trabajando con el cin (el objeto de tipo istream es el mismo tipo de objeto que cin).  La función ignore de la clase istream se encarga de ignorar el siguiente caracter del istream (en mi caso es una diagonal entre día y mes, y otra diagonal entre mes y año).  Aquí está el código:
08-Operador istream
Para terminar, hice la función main() que prueba todo lo anterior.  Aquí está:
09-main
Este ejemplo fue hecho con Visual C++ 2010 y puedes descargar el proyecto en formato RAR aquí.  ¡Saludos!

12 octubre 2011

Videojuegos y Educación

Como algunos sabrán, hace unos días terminé la maestría.  Mi tema de investigación fue desde el principio el uso de videojuegos en ambientes educativos, ver lo que aprenden los muchachos al jugar.  A raíz de este interés, una vez los invité a un par de conferencias que di en la Univa: los Piratas del Bicentenario y Jugando a los Negocios.  Concretamente acerca de resultados de mi tesis, les había compartido la presentación que hice en la Univa (que se centra más en lo educativo) y el “trailer” (avance cinematográfico) de mi presentación en el ITESO, pero ahora les quiero compartir lo que expuse ese día.  Aquí les dejo un video (casi 22 minutos) de la pura presentación que hice.  Espero que les sirva como reflexión acerca de lo que se puede hacer e investigar en este campo.  La idea, más que platicar de lo que hice, era la de hablar sobre cuestiones que giran en torno a mi tesis.  Les comparto el video y más abajo les pongo la presentación.

 

Mi presentación en el ITESO: la “lectura transversal” de mi texto

 

06 octubre 2011

Arreglos con Visual Basic .net

Arreglos es un tema que ya he cubierto varias veces con anterioridad, ya sea en Visual Basic 6, C y C++, y hasta en Java (lenguaje del que no soy gran experto).  Te recomiendo que leas estos artículos (sobre todo el de Visual Basic 6) para entender mejor de lo que estaré hablando.  De todos modos aquí les dejo un video introductorio:

Y aquí hay un ejemplo:

¿Tienes dudas o comentarios?  ¡Deja un comentario!

Not Tetris 2: Un tetris del mundo real

notetrisHace un momento leí en el blog de contecti.ca la noticia de esta nueva versión de Tetris al que le agregaron reglas de la física de nuestro mundo lo cual le añade un dimensión totalmente diferente al juego.  Aquí les dejo el video y la liga para descargarlo.  ¡Que lo disfruten!

 

30 septiembre 2011

Sonidos y Visual Basic

20091123-musicaAlgo que es indispensable para muchos programas (especialmente si estamos programando un videojuego) es el sonido.  Imagínate estar jugando Lego Star Wars sin el sonido de la respiración de Darth Vader, el sonido de los light sabers, el ruidito que hace R2D2 o la música de la marcha imperial.  Hay miles de estudios que muestran que el sonido afecta nuestra percepción, estado de ánimo, etc. y es muy aprovechado por el cine, TV, etc. para transmitir drama, suspenso, etc.  En conclusión: habrán momentos en que necesitamos que nuestros programas incluyan audio.  Pero, ¿cómo le hago?  Eso precisamente es de lo que voy a hablar en este post.

Para cosas sencillas Visual Basic .NET cuenta con la clase System.Media.SoundPlayer.  Es limitado y no tiene muchas funciones, pero para efectos de tocar un WAV, basta y sobra.  Tal vez pienses que con la popularidad que tiene el formato MP3 estos archivos ya no se usan, pero generalmente todos los efectos especiales que puedes descargar en línea están en este formato.  Así que es una clase muy útil.

Lo primero que se tiene que hacer es declarar un objeto:

Dim sonidito As System.Media.SoundPlayer

Si al principio del código agregamos System.Media (con la instrucción Imports), podemos escribir simplemente SoundPlayer.  Tiene dos constructores: con uno podemos cargar el archivo WAV directamente:

sonidito=New SoundPlayer(“sonido.wav”)

O bien, puedo usar el constructor default (sin parámetros) y usar las propiedades SoundLocation para definir el archivo y Load para cargarlo a la memoria:

sonidito=New SoundPlayer()
sonidito.SoundLocation(“sonido.wav”)
sonidito.Load()

NOTA: si de plano el archivo WAV es demasiado grande y dura unos segundo en cargar, puedes usar la función SoundPlayer.LoadAsync para cargar el sonido y SoundPlayer.IsLoadComplete para saber si ya terminó de cargar a la memoria.  Esto es útil porque si tu programa tarda unos segundos en cargar el sonido, es probable que el usuario piense que el programa dejó de responder y lo cierre.

Para que comiencen a sonar las bocinas con tu WAV, solo basta usar la función Play()para que se escuche:

sonidito.Play()

¿Qué sucedería si alguien elimina el archivo WAV de la carpeta donde lo necesitas?  Como te imaginarás, deja de funcionar.  Una forma de evitar esto es incluir el archivo WAV como parte del proyecto, es decir, que sea un recurso del programa.  Antes que nada, hay que incluir un archivo de recurso al proyecto.  En el proyecto, elige del menú Project la opción Add new item.  Aparece la siguiente ventana:

00-VentanaAddNew

En esta ventana, selecciona la opción Resources File (está en esta ventana o en el grupo General [los grupos están de lado izquierdo]).  Después de esto, se agrega un archivo llamado Resources1.resx al proyecto (a menos que le hayas cambiado el nombre).  Debería abrirse en automático.  Si no , haz doble clic sobre el archivo en la ventana de la solución.  Haz clic sobre el tipo de recurso (ahorita dice Strings) y selecciona Audio.  Después haz clic en Add Resource, Add Existing File y selecciona el archivo WAV que quieres incluir.  Aquí se ven las opciones:

01-AgregarRecursoAudio
02-AgregarRecursoAudio
     

Nota: para ahorrarte esto, podrías simplemente arrastrar un archivo WAV desde Windows hasta esta ventana.

Una vez agregado el recurso, es hora de echarlo a andar.  Tomando en cuenta que mi recurso (otro archivo WAV) se llama Sonidito2 y que al principio importé Microsoft.VisualBasic para no escribir tanto, el código quedaría así:

Dim sonidito2 As Devices.Audio
sonidito2 = New Devices.Audio
sonidito2.Play(My.Resources.Resource1.Sonidito2,AudioPlayMode.Background)

Aunque estos dos objetos nos dejan escuchar sonido, son medios limitados.  En un futuro post trataré del uso de Windows Media Player en Visual Basic .net (particularmente en la versión 2010).  ¡Hasta la próxima!

P.D. Imagen de la música con ecuaciones tomada del blog de The All-Knowing 4.  Las demás imágenes las hice yo.  Parte del material aquí expuesto viene del libro Visual Basic Game Programming for Teens.

26 septiembre 2011

El Rap del Photoshop, parte II

No es que yo sea muy fan del rap, pero hace tiempo incursioné en el género como una idea de mis alumnos y lo aproveché para explicar los conceptos básicos de la programación orientada a objetos en C++ (tanto la letra y música como en video).  Luego me topé con un rap tutorial de Photoshop y hoy vi la segunda parte que les comparto.  Parece broma, pero explica bastante bien lo de los canales de color.  ¡Que lo disfruten!

Originalmente es de CollegeHumor, pero yo lo vi en el blog de MakeUseOf.

21 septiembre 2011

Teclado verde

solarkeyboard

Hace rato vi en el blog de Lifehacker este teclado que me parece una idea eco-maravillosa.  Se trata el teclado Logitech Wireless Keyboard K750 y es un teclado inalámbrico que no usa pilas AA sino que tiene dos paneles solares que lo cargan.  Supuestamente si lo dejas cargado, puede pasar un mes funcionando sin problemas hasta volverlo a cargar.  También tiene una aplicación que monitorea como se está cargando para que puedas jugar un poco con las posiciones de tu lámpara o lo que sea que esté iluminando el teclado para conseguir la recarga más rápida.  Buena idea: comodidad, tecnología y ecológico.

A ver cuando me compro uno Sonrisa.

20 septiembre 2011

Apple, desde sus inicios (infografía)

Ayer vi en el blog de conecti.ca una infografía que resume la historia de Apple, misma que comparto con ustedes (haz clic sobre la imagen para verlo en grande en otra ventana/pestaña).  Se me hizo interesante y espero que les sea informativa.

history_of_apple-1000px

13 septiembre 2011

Historia de la PC

Parece que ando haciendo un blog de historia de las computadoras, pero últimamente me he topado con historias en imágenes que se me han hecho muy interesantes.  Por ejemplo, hoy me encontré con esta imagen en el blog de conecti.ca que muestra como ha evolucionado la computadora PC.  Aunque faltan muchos pormenores, de todos modos es un buen resumen de la historia de este aparatejo que ha cambiado la faz del mundo (bueno, exageré… pero de todos modos sí ha cambiado nuestra forma de jugar, trabajar, investigar, comunicarnos, dibujar y diseñar, y otras mil cosas que terminan con ar).

Una de las cosas que me parece novedoso en comparación a otras historias, pone el precio de las computadoras en dólares actuales.  HAz clic sobre la imagen para verlo en tamaño natural en otra ventana.

Espero que les sea ilustrativo Sonrisa

11 septiembre 2011

Evolución de las Supercomputadoras

supercomputersHace rato vi en el blog de MakeUseOf una imagen interesante que muestra la forma en que han evolucionado las supercomputadoras.  Se me hizo muy interesante, sobre todo para comprender mejor la historia de la computación.

Aquí les comparto la imagen (haz clic sobre él para que se vea más grande Lengua fuera).

¡Espero que les guste!

07 septiembre 2011

Heroes of Newerth: Un juego multijugador de estrategia en línea

intro15Hace rato en el blog de MakeUseOf me encontré con un nuevo juego que parece estar muy interesante.  Es un juego de estrategia en tiempo real basado en WarCraft, multijugador y funciona tanto en Windows, MacOX y Linux.  Originalmente era software comercial (tenías que comprarlo), pero ahora ya es gratuito.

En este videojuego los jugadores se dividen en 2 equipos: Legion ó Hellbourne que están ubicados en lados opuestos de un mapa similar a los que hay en la versión original de Warcraft donde cada equipo debe defender una base para no perder.

Puedes descargar el juego aquí.  Dependiendo de la versión que bajes, pero generalmente las descargas están alrededor de 600 Mb.  ¡Que se diviertan!

05 septiembre 2011

Vectores, iteradores y STL…

C  Hace unos días escribí acerca del uso del contenedor vector para poder manejar una lista en C++.  Aunque el vector es muy útil, resulta más interesante y de mayor utilidad si agregamos el uso de iteradores (iterators).  Los iteradores (no sé si esa sea la traducción correcta, pero es lo que más “le suena”) son importantes porque nos permiten accesar de forma fácil a los elementos del contenedor (en este caso un vector), algo así como los apuntadores, solo que más sencillos de manejar y menos susceptibles a errores por parte del programador.  También es importante saber usarlos porque son necesarios para poder usar una serie de algoritmos que ya están programados en la STL y que toman iteradores como parámetros.
Pero, como dijo Jack el destripador: “vámonos por partes”.  Primero voy a decir cómo declarar un iterador, luego como recorrer el vector usándolo, luego funciones que pueden ser de utilidad.

Declarando un iterador

No hay que incluir ninguna librería nueva porque el vector ya lo contiene.  Para declarar uno, la sintaxis sería la siguiente:
vector<tipo>::iterator nombre;
por ejemplo
vector<string>::iterator miIterador;
declara un iterador a un vector de elementos que son de tipo string llamado miIterador.  También es posible declarar iteradores constantes, es decir, que no pueden cambiar de valor.  Esto se haría así:
vector<string>::const_iterator it;
Este ejemplo declara un iterador constante llamado it.

Recorriendo el vector

Si recuerdas en el programa anterior (y si no recuerdas, lee el post anterior que es vital para entender este rollo) podía recorrer el vector manejándolo como si fuera un arreglo.  El código que cumplía tal fin era este (suponiendo que inventario es un vector):
for (unsigned int i = 0; i < inventario.size(); ++i) {
    cout << inventario[i] << endl;
}

Esto está bien, pero con un iterador, puedo hacerlo de la siguiente manera (suponiendo que it es un iterador):
for (it = inventario.begin(); it != inventario.end(); ++it) {
    cout << *it << endl;
}

Fíjate en el operador * que funciona igual que con los apuntadores.

Modificando elementos del vector

También es posible cambiar un elemento del vector.  Supongamos que quiero cambiar lo que tengo de inventario en el primer elemento.  Esto lo podría hacer posicionando el iterador en el primer elemento y usar la notación * para cambiar el valor.  Claro que si quieres cambiar otro elemento, lo tienes que encontrar primero.
it = inventario.begin();
*it = “Guadaña”;

Funciones y elementos del vector

Es posible hacerlo con la misma notación que los apuntadores.  Es decir, si quiero saber el número de elementos del vector inventario puedo hacerlo de cualquiera de estas maneras: (*it).size() o it->size()

Insertando elementos en cualquier posición

Para esto me sirve la función insert.  Supongamos que quiero poner antes del primer elemento un objeto que acabo de encontrar.  Entonces haría lo siguiente:
inventario.insert(inventario.begin(), "Botella llena de Curare");
Claro que si lo quieres insertar en otro lugar, solo posiciona un iterador en el lugar en donde quieres insertarlo y escribe eso en lugar del inventario.begin().

Eliminando cualquier elemento

El contenedor vector tiene la función pop_back para eliminar el último elemento, pero nada más.  ¿Y si quiero eliminar lo que tengo en la posición 3 de mi inventario?  Con iteradores puedo hacerlo de la siguiente manera:
inventario.erase((inventario.begin() + 2));

Y para terminar, referencias y atracciones futuras

Con esto más o menos cubrí lo que puedes hacer con un iterador con el contenedor vector.  Faltaría ver como usar algoritmos de la STL para hacernos la vida todavía más sencilla porque puedo aprovechar funciones ya creadas para ordenar, mezclar, etc.
Para crear este artículo, me basé en el mismo libro de la vez anterior (vuelvo a poner la referencia abajo) y la imagen del C++ chuvidubis es cortesía del blog de Etienne GT.  ¡Hasta la próxima!

02 septiembre 2011

Videojuegos y educación. Explorando aprendizaje entre adolescentes.

wa3ftLes anuncio a todos que por fin voy a terminar mi maestría.  Si, entré en agosto del 2005 y mi última materia fue a principios de este año, es decir que una maestría que generalmente se hace en 2 años yo lo hice en 5.5 años.  Mi examen recepcional será el lunes 3/Oct a las 12:30pm en la sala B del edificio R (el administrativo) del ITESO.  Para que se vayan dando cuenta de lo que se va a tratar, te dejo este avance cinematográfico de mi tesis.

Si puedes, allá nos veremos.  Hasta habrá un poco de vino tinto para brindar al terminar.  Si me dan el título de maestro, brindamos por eso y si no, por lo menos con el alcohol se nos olvida un poco Risa.

Avance cinematográfico de mi Tesis :)

01 septiembre 2011

El número de videojuegos para móviles

Ayer vi en el blog de Conecti.ca me topé con esta infografía que me parece muy interesante.  Se trata de la forma en que está actualmente el mercado de los videojuegos para dispositivos móviles (concretamente celulares, nada del DS, 3DS, PSP, ni de otras consolas de videojuegos portátiles).

La imagen original salió en DailyMobile.  Puedes hacer clic sobre la imagen para verlo en grandote en otra ventana o pestaña Sonrisa.

¡Se divierten (y si es con un juego en dispositivo móvil, mejor tantito)!

31 agosto 2011

Librería estándar (STL) y Vector

vectorx¿Para qué reinventar la rueda si a alguien ya se le ocurrió?  Es mejor usarla, ¿o no?  Este mismo argumento aplica para los programadores: ¿para qué programar cosas que ya están hechas de forma muy eficiente por otros programadores?  Sería una pérdida de tiempo.
Por eso los programadores podemos aprovechar la Standard Template Library, conocido como STL, o librería estándar de plantillas (se oye pésimo en español, pero esa es la traducción).  El STL contiene varios contenedores (valga la redundancia) que te permiten hacer diferentes cosas.  Hay contenedores para arreglos dinámicos (vector), colas (queue), heap (heap), listas ligadas (list), árboles (set), pilas (stack), etc.  Claro que cada uno de estos contiene un chorro de algoritmos que facilitan la vida para usarlos, manipularlos, llenarlos y casi cualquier otra cosa que termine con “arlos”, jeje.
En este artículo voy a hablar un poco sobre el uso del contenedor vector (tocayo del memorable malvado de la película “Mi villano favorito”, que aparece en la imagen de este mensaje).  Básicamente es un arreglo dinámico, es decir, un arreglo que puede cambiar de tamaño (uno de los inconvenientes de los arreglos comunes y corrientes).
Usar el contenedor vector tiene muchas ventajas sobre los arreglos, por ejemplo:
  • Los vectores pueden crecer y los arreglos no.
  • Los vectores pueden usar algoritmos programados en el STL.  Los arreglos no.
Aunque no todo es pura dulzura porque hay también algunas desventajas en el uso de vectores:
  • Necesitan más memoria.
  • Cuando los vectores crecen mucho, disminuya el rendimiento.
  • Los vectores no están disponibles en todas las plataformas.

Antes de empezar…

Antes que nada, hay que incluir la librería que contiene al contenedor (valga la redundancia) vector.  Como está en el namespace std, no hace falta incluir el “.h”.
#include <vector>

Declarar un vector

Para declarar un vector, la sintaxis básica es la siguiente:
vector<tipo_de_dato> nombre_de_variable;
Por ejemplo, si quiero declarar un vector de tipo string con nombre inventario, escribo:
vector<string> inventario;
También puedo decirle que comience con 10 elementos en el vector así:
vector<string> inventario(10);
Y si quiero inicializar los 10 elementos con la cadena “Nada”, escribiría:
vector<string> inventario(10,”Nada”);
Finalmente, si quiero inicializar mi vector con el contenido de un arreglo (en este ejemplo, se llama Arr), escribiría:
vector<string> inventario(Arr);

Funciones

Las funciones más usuales de este contenedor son las siguientes:
  • push_back – agrega un elemento al final del vector.
  • size – devuelve el número de elementos que están almacenados en el vector.
  • pop_back – elimina el último elemento del vector.  esto hace que el vector cambie de tamaño (se hace más pequeño).
  • clear – elimina todos los elementos del vector.
  • empty – Devuelve un valor de verdadero si el vector carece de elementos.

Ejemplo que usa el contenedor Vector

Aquí les presento código hecho en Visual C++ 2010.  Es un ejemplo simple que pone en práctica todo lo que escribí con anterioridad.  Si necesitas, aquí puedes descargar un archivo comprimido con todos los archivos y carpetas que conforman la solución.
CódigoVector

Atracciones futuras

Para que puedas trabajar mejor con vectores y que se puedan aprovechar mejor, es importante hablar de iterators (¿iteradores?).  De éstos hablaré en mi próximo post de C++.

Referencias para mayor información

Si quieres saber más, te recomiendo el sitio de GabaWiki sobre STL Vector.  Abajo pongo la referencia a un libro que me ayudó a crear este post.
La imagen de Vector que aparece al principio es cortesía de USA Today.

30 agosto 2011

10 videojuegos más pirateados

PiracySoy fan de los videojuegos.  Para los que me conocen hasta saben que mi tesis de maestría tiene que ver con ellos.  Por eso me llamó mucho la atención un post en el blog de MakeUseOf que quiero compartir con ustedes.  Se trata de los videojuegos más pirateados de todos los tiempos.  Generalmente los juegos más pirateados también son los más vendidos lo cual hace difícil basarse en información de ventas y es por esto que James Bruce (autor del artículo original) se basó en el número de veces que han sido descargados (incluso pone la fecha, misma que yo transcribo, en que obtuvo ese dato).  Así que sin más preludio, ahí va la lista.

  1. Call of Duty: Black Ops4.27 millones de descargas (Noviembre 2010).  Esta no es novedad.  Según mis alumnos (yo no soy muy fan de este género de videojuegos) es el mejor FPS que hay en el mercado.  La calidad de los FPS se basan en comparación con este.  Ya veremos qué mejoras se les ocurre para el 22 de octubre cuando está programado que salga la nueva versión a la venta.
  2. Call of Duty: Modern Warfare4.1 millones de descargas (Noviembre 2009).  Este es muy similar al anterior, solo que fue creado por un estudio diferente y no está tan avanzado (sobre todo en lo que respecta a subir de niveles y los premios).
  3. Battlefield: Bad Company 23.96 millones de descargas (Marzo 2010).  Otro juego de combate, pero enfocado más en la estrategia que en el combate personal como en los FPS (como los dos anteriores).
  4. Mafia 23.55 millones de descargas (Agosto 2010).  Es una mezcla de manejar autos, disparadera y combate cuerpo a cuerpo.  Según los críticos (como Eurogamer y 2KGames) es un juego pésimo.  sin embargo, pese a su fracaso en el mercado, el número de descargas dice que muchos lo juegan.
  5. Mass Efect 2 - 3.24 millones de descargas (Enero 2010).  Es un RPG que te permite explorar un mundo virtual con elementos de un FPS.  La primera versión presentó algunas fallas técnicas, pero ya tenía una narrativa muy interesante.  Esta versión corrige todos esos detalles.  Aunque no lo he jugado, parece un excelente juego.
  6. Sims 33.2 millones de descargas (Junio 2009).  Los Sims han sido uno de los juegos más vendidos y que han marcado época.  Una simulación del mundo real… algo así como un universo paralelo donde el jugador puede vivir una vida alterna en un mundo virtual.
  7. Starcraft 23.12 millones de descargas (Julio 2010).  Es un juego de estrategia fenomenal que construye sobre el juego Starcraft original con mejores gráficos y nuevas funciones y personajes que lo hace bastante adictivo.
  8. Prototype2.35 millones de descargas (Junio 2009).  Es un juego donde el usuario se desenvuelve en un mundo virtual abierto, tipo Grand Theft Auto, con una narrativa intrigante y muchas misiones diferentes y variados.  Puedes manejar tanques y mandar otros carros volando, o también puedes tomar el papel de alguno de los personajes.
  9. Need for Speed: Shift2.1 millones de descargas (Septiembre 2009).  Pese a lo que digan algunos, es uno de los mejores juegos de carreras de autos.
  10. Street Fighter IV – 1.85 millones de descargas (Julio 2009).  En lo personal no me gusta este juego, pero no por eso deja de ser popular.  Es una actualización con mejores gráficos que el juego original Street Fighter que está en todos los changarritos alrededor del país.

Algo que es extraño es que no apareciera Grand Theft Auto 4, pese a que rompió un record Guiness por ser el juego que mayor ingreso ha obtenido en 24 horas después de su lanzamiento en mayo del 2008.  En fin, no se les puede dar gusto a todos…

Nota: esta información es meramente informativa.  De ninguna manera estoy intentando decir que piratear juegos es lo mejor.  En otras palabras, di no a la piratería, jejeje.

28 agosto 2011

Bitmaps y Visual Basic

super-mario-bros-8bitEn mensajes anteriores he hablado de la forma de aprovechar el GDI+ que viene con Visual Basic .net para usar la clase Graphics para dibujar líneas y cuadrados al azar, hacer un especie de Paint chafa y luego lo combinamos con menús para que la interfaz se viera bien.  En esta ocasión haré uso de la clase Bitmap y un PictureBox para crear una superficie que me permita dibujar sobre él mediante código.  Con esto podremos hacer animaciones basados en Sprites, lo cual es la base de todas las animaciones que se hacen en los videojuegos 2D.

Para dibujar mediante el código, se necesitan objetos de la clase Bitmap y Graphics, que puedo declarar de la siguiente manera:

Public superficie As Bitmap
Public disp as Graphics

Luego, suponiendo que tengo un PictureBox llamado PictureBox1, creo los objetos.  Aunque el PictureBox se puede crear a la hora de ejecución, en esta ocasión voy a hacerlo de forma manual (o sea, dibujándolo en la pantalla).  El código se vería así:

superficie = New Bitmap(Me.Size.Width,Me.Size.Height)
PictureBox1.Image = superficie
disp = Graphics.FromImage(superficie)

Con esto ya inicializamos los objetos que necesitamos para seguir.

Cargando un bitmap a la memoria

Para crear un nuevo bitmap (o mapa de bits en español), no hay una función que la cargue de forma automática.  Hay que hacer uso del constructor de la clase de la siguiente manera:

Public bmp As Bitmap
bmp = New Bitmap(“imagen.bmp”)

Aunque se podría declarar y llamar el constructor al mismo tiempo, no lo voy a hacer para tener mayor control sobre el proceso.  El hacerlo en 2 líneas (muy a pesar de que me gusta ahorrar líneas de código) me permite usar un bloque Try…Catch (ya en varios posts he explicado la forma en que nos podemos recuperar de errores con estas instrucciones) para asegurarme que se haya podido cargar a la memoria sin problemas.  El´código quedaría así:

Try 
    bmp = New Bitmap(“imagen.bmp”)
Catch ex As Exception
    MsgBox(“Error al cargar el archivo”)
End Try

Para simplificarnos la vida, sería conveniente hacer una función que cargue un mapa de bits a la memoria y devolviera un objeto Bitmap si lo puede abrir o un Nothing (valor nulo) si no es posible (ya sea que no está el archivo o está dañado o lo que sea).  Una función de este tipo sería como esto:

Public Function CargaBitmap(ByVal NombreArchivo As String)
    Dim bmp As Bitmap
    Try
        bmp = New Bitmap(NombreArchivo)
    Catch ex As Exception
        MsgBox(“Error al cargar el archivo”)
    End Try
End Function
 

Creo que con una función como esta nos simplificamos la vida muchísimo.  Ahora, ¡a continuar con la aventura!

Dibujando un mapa de bits en la ventana

Hay varias versiones de la función Graphics.DrawImage() lo que en términos de la OOP (Programación Orientada a Objetos, por sus siglas en inglés) diríamos que son funciones sobrecargadas.  Independientemente del término rimbombante que le quieras poner, la versión más simple solo recibe las coordenadas horizontales (X), verticales (Y) y el mapa de bits a dibujar.  Por ejemplo, para dibujar un bitmap (suponiendo que estás usando los mismos nombres que he usado para objetos en este post) en la coordenada 15,20 escribiría lo siguiente:

disp.DrawImage(bmp,15,20)

Esta función también acepta otros dos enteros que indican el ancho y alto a los que se mostrará haciendo que la imagen cambie de tamaño (120 pixeles de ancho por 120 de alto):

disp.DrawImage(bmp,15,20,120,120)

Girando y volteando el mapa de bits

Además de cambiar el tamaño, hay otras cuantas maneras de manipular el mapa de bits en tu ventana.  Por ejemplo, se puede girar en 90, 180 y 270 grados y/o voltear tanto de forma horizontal o vertical.  Por ejemplo, si quiero girar un mapa de bits 90o escribiría:

bmp.RotateFlip(RotateFlipType.Rotate90FlipNone)

Para mayores informes sobre la función RotateFlip, qué mejor que preguntarle a Microsoft aquí y si quieres saber todas las opciones de giros, vueltas y revueltas (yo solo puse uno), fíjate en su información acerca de la enumeración RotateFlipType aquí para que seas capaz de hacer todo tipo de malabares con mapas de bits.

Accesando a los pixeles del mapa de bits

También es posible tener acceso a cada pixel del mapa de bits.  Para eso está la función GetPixel() a la que le paso las coordenadas y devuelve un objeto Color con el color que hay en esa posición.  De la misma manera funciona la función (valga la redundancia) SetPixel(), solo que éste último establece un color, lo “pinta” del color que quieres.  Por ejemplo, supongamos que quiero que un mapa de bits se vea como recién sacado de la Matrix (o sea en tono verde), podríamos hacerlo con este código:

For x = 0 To bmp.Width – 1
    For y = 0 To bmp.Height – 1
        Dim ColorActual As Color = bmp.GetPixel(x, y)
        Dim ColorNuevo As Color = Color.FromArgb(0, ColorActual.G, 0)
        bmp.SetPixel(x, y, ColorNuevo)
    Next
Next

Solo una cosa que recordar antes de terminar.  Pese a que Visual Basic 2010 tiene muchas funciones para manipular mapas de bits, tiene sus límites.  No es un programa de diseño ni de dibujo. No se compara al Photoshop ni siquiera al pinchurriento Paint que viene con Windows.  Dicho esto, creo que terminé.

Agradecimientos y referencias

Imagen de Mario en 8 bits cortesía de T&S Web Design.  Y gran parte de lo que escribí aquí, fue asesorado por este libro:

24 agosto 2011

Números aleatorios en C++

numeros-300x290Los números aleatorios son de gran importancia en la programación.  Necesitas números aleatorios para hacer girar unos dados, repartir cartas, posicionar enemigos en la pantalla y tal vez hasta controlar sus movimientos.  Sin embargo, crear un algoritmo para generar números aleatorios es todo un problema porque, ¿quién sabe cómo le hace para pensar en un número al azar?  ¿Acaso sigue algunos pasos?  No, es un proceso mental fácil de realizar, pero que no lleva algún procedimiento preciso y esto hace que sea casi imposible hacerlo en la computadora.  Lo más cercano es una función matemática que calcula números al azar.  Aquí voy a presentar un ejemplo que puede ser útil para generar números aleatorios usando funciones de C++.
Antes de empezar de lleno, honor a quien honor merece.  Este ejemplo y parte de la explicación es una traducción/adaptación de un artículo que leí en la página de daniweb.com, escrito por un tal Bob (¿acaso será el constructor?  Bueno, mal chiste…).  Voy a ir explicando funciones, constantes y una que otra monería y al final viene un programa que ejemplifica su uso.
La funciones que se necesitan para generar números al azar se encuentran en la librería cstdlib, así que hay que incluirlo al principio del código.  Para generar el número aleatorio se hace uso de la función rand, misma que genera un número al azar entre 0 y la constante RAND_MAX (que vale generalmente 32,767 pero puede variar según el compilador de C++ que estés usando).
rand funciona de maravilla, pero el problema es que cada vez que ejecutes el programa, te va a mostrar exactamente la misma secuencia de números, lo cual puede resultar interesante la primera vez, pero pierde chiste en las ejecuciones subsecuentes del programa.  Para remediar esto, se puede inicializar el generador de números aleatorios con la función srand, misma que recibe un número entero que inicia el pseudogenerador de números aleatorios.  Pero si cada vez lo inicializas con el mismo entero, el problema no se quita: sigues generando la misma serie de números.  Lo mejor es usar el reloj del sistema para que te dé la hora actual, lo conviertes a entero y así cada vez es diferente.  Para eso usamos la función time que está en la librería ctime.
Una vez resuelto el problema de generar una secuencia de números aleatorios únicos, ahora hay que abordar la manera de generar números en un cierto rango.  La fórmula para hacerlo sería la siguiente:
numero_aleatorio=rango_inferior+int(rango*rand()/(RAND_MAX+1.0))
donde rango_inferior es el valor mínimo del rango del que se desea un número y rango es la diferencia entre el valor mayor y el menor.  Por ejemplo, si quiero generar un número aleatorio entre 6 y 15 y guardarlo en un entero que declaré con el nombre de X, la instrucción sería:
X=6+int((15-6)*rand()/(RAND_MAX+1.0))
Creo que con esta explicación ya puedes generar los números aleatorios que necesites para cualquier aplicación.  Aquí les dejo el código fuente de un programa que ejemplifica todo lo anterior.  ¡Hasta la próxima!
(Imagen de los números aleatorios cortesía del blog “La aventura de las matemáticas”)

aleatorio.cpp

13 agosto 2011

Fotos del semestre Enero-Junio 2011

Tarde, pero sin sueño.  Les dejo las fotos que nos tomamos en la última semana de clases el semestre pasado.  Les agradezco a todos por aguantarme y por dejar que me divierta en el aula.

Hagan clic sobre cada foto para verla grande y con mejor resolución.

2do semestre, grupo B, técnico Comunicación (2B TCM)
Materia: TICs II

2B TCM 0     2B TCM

2do semestre, grupo C, técnico Comunicación (2C TCM)
Materia: TICs II

2C TCM

2do semestre, técnico Programador (2 TPO)
Materia: Software de Aplicación

2 TPO

4to semestre, técnico Programador (4 TPO)
Materia: Bases de Datos y Lenguaje C

4 TPO

6to semestre, técnico Informática Administrativa (6 TIA)
Materia: Aplicaciones para Internet

6 TIA     6 TIA 0

6to semestre, técnico Programador (6 TPO)
Materia: TICs II

6 TPO

12 agosto 2011

Historia de los Sistemas Operativos

Hoy me topé con esta infografía que me pareció padrísimo para explicar como han cambiado los sistemas operativos de las computadoras.  Aquí se los comparto (haz clic sobre la imagen para verlo en su tamaño real).  Es cortesía del blog conecti.ca, quien a su vez lo tomó del blog de MakeUseOf.

muo-history-operating-systems

02 agosto 2011

Presentación de Videojuegos y Educación en la Univa

videojuegosparatodosAunque es un poco tarde para contarles, estaré presentando algunos resultados de mi tesis de maestría en la preparatoria Univa el día de hoy (2/Ago/2011) alrededor de la 1pm (el coloquio de investigación comienza a las 12pm, pero soy el último).  Si puedes, allí te espero.

No es mi examen recepcional (aún) y va más enfocada a la educación que a la comunicación (cosa que reservo para mi titulación del a maestría).  Seguramente volarán muchas piedras… espero que no te caiga ninguno.

¡Allá los espero!

También les dejo hasta abajo el Prezi que voy a usar, por si lo quieren ver.  Claro que falta todo el choro que voy a decir en el coloquio, pero te puede dar una idea de lo que voy a hablar.

(Imagen cortesía de CinismoIlustrado).

31 mayo 2011

Listas Simplemente Ligadas

Las listas simplemente ligadas son una estructura de datos que nos permite almacenar cualquier cantidad de datos.  La ventaja principal es que la memoria que ocupa es solamente la necesaria a diferencia de un arreglo que puede desperdiciar memoria que no está en uso (como la memoria que se desperdicia con los arreglos: generalmente declaras un arreglo del tamaño máximo que se podría llegar a usar aunque muchas veces no se llena).
La lista simplemente ligada puede ser usada para crear estructuras de datos más complejos.  Consiste en una secuencia de nodos, donde cada nodo contiene información y un apuntador al nodo que sigue.  El último nodo apunta a un valor nulo (NULL) lo cual indica que es el final de la lista.  De esta manera se puede recorrer la lista de forma secuencial siempre y cuando tengas un apuntador al primer elemento de la lista, como se ve la siguiente imagen (tomada del blog de xrom):
lista
O, si quieres, puedes conceptualizarlo como un tren de vagones donde el tienes un apuntador a la locomotora y el apuntador al siguiente que hay en cada nodo es el mecanismo con el que se engancha al vagón que le sigue (Imagen cortesía de Medieducativos):
t106-tren-cuatro-vagones
En este post me voy a enfocar en 3 cosas: agregar un nuevo nodo a la lista (al final), mostrar todos los nodos (recorrerlo) y eliminar un nodo de la lista.  Antes de entrar a estos temas, hay que ver como se declara la estructura y la forma en que se usa.  En este ejemplo, estoy haciendo una lista que guarda algunos datos de videojuegos.  Aquí está la declaración de la estructura y una variable global que apunta al primer nodo de la lista:
LSL-01
La función principal del programa (main) no tiene mayor ciencia.  Básicamente solo muestra un menú y pide una opción.  En base a la opción deseada manda llamar funciones para dar de alta, consultar todos o eliminar alguno.   Una nota antes de seguir: este programa lo hice usando el compilador Dev-C++ varsión 4.9.9.2.  Este es el código (haz clic sobre la imagen para verlo más grande):
LSL-02
Voy a comenzar hablando de la función que da de alta un nodo al final de la lista.  Primero declaro dos apuntadores a struct nodo: Temp y Temp2.  Uso la función malloc para apartar RAM para almacenar la estructura de forma dinámica.  Si necesitas saber más sobre el malloc, al final de este post hay ligas a páginas que son referencias para que despejes dudas sobre su sintaxis y función.  Pero a grandes rasgos, el malloc sirve para asignarle memoria y devolver un apuntador hacia el espacio reservado.  Una vez apartada la memoria, lleno el nuevo nodo con los datos (que son los parámetros nom, plat y pre) y al campo Sig le asigno el valor de NULL porque va a ser el último de la lista.  Al final debo reorganizar los apuntadores: el apuntador Sig del elemento anterior debe apuntar a este nuevo nodo.  El código que lo realiza es el siguiente:
LSL-03
Una vez resuelto el problema de dar de alta nodos, voy a explicar la forma en que se puede recorrer la lista y mostrar los elementos.  Esto lo hice en la función llamada MuestraTodo.  Declaro un apuntador llamado Temp (para no perder la costumbre, jeje) con el que voy a recorrer la lista.  Uso la variable i para mostrar el número de nodo en el que voy.  Al principio igualo Temp a Inicio  para comenzar el recorrido.  Y mientras no llego al final (o sea, Temp es diferente de NULL), muestro lo que contiene el nodo.  Fíjate como se accesa un elemento por medio de un apuntador ya que difiere de la forma en que se hace cuando no usas apuntador.  En lugar del punto (.), se usa una especie de flecha compuesta por el guión y el signo mayor que (->).  Aquí está el código:
LSL-04
Ahora lo  único que falta es mostrar la función que elimina un nodo de la lista.  Esto es relativamente sencillo y creo que el código se explica por si solo (le puse un montón de comentarios).  Básicamente es igual que la función MuestraTodo solo que esta vez, en lugar de mostrar el elemento, veo si es igual al que busco.  En caso que sea igual, veo si es el primero de la lista.  Si es el primero, solo cambio el valor de Inicio para que apunte al siguiente, y en caso contrario, modifico el apuntador Sig del elemento anterior (convenientemente apuntado por Anterior) para que apunte al que sigue.  Una vez arreglado los apuntadores, libero la memoria usando la instrucción free.  Al final viene más ayuda sobre free, pero básicamente libera la memoria que es apuntada por un apuntador (valga la redundancia).  Al final devuelve un 1 si lo encontró y lo pudo borrar y un 0 si no lo encuentra.  Este es el código de la función Eliminalo:
LSL-05
Estas son ligas donde puedes encontrar más información sobre malloc y free (y algunas otras funciones que te pueden resultar muy útiles).  ¡Hasta la próxima!
Related Posts Plugin for WordPress, Blogger...