viernes, 11 de julio de 2014

Configure NetBeans / SDL 2.0.3 / MinGW

I will reproduce here the steps to configure SDL2.0.3 library for Netbeans with MinGW in an intel i7 (x86_64 architecture) and Windows 7 64 bit SP1. I will assume you have downloaded already the neccesary packages (netbeans, mingw x86_64 and SDL 2.0.3) and know how to configure environment variables. If you don't just google "windows 7 set environment variables" and follow instructions; it's an easy and straightforward process.


  1. Install Netbeans (C/C++ version) from scratch. I installed stable version 7.4
  2. Install MinGW x86_64 version. The path where it was installed will be henceforth called %MINGWPATH%"
  3. Uncompress SDL tar file to %SDLPATH%
  4. Add "%MINGWPATH%/msys/1.0/bin" and "%MINGWPATH%/bin" to the PATH environment variable.
  5. Start netbeans; it should automatically detect your mingw tool collection. If it doesn't, go to tools -> Options -> c/c++ -> build tools tab and click on add collection. Select the /bin folder of the %MINGWPATH% as the base directory, and %MINGWPATH%/msys/1.0/bin for the make.exe if it's not automatically selected.
  6. Now create a new project and create a c++ application.
  7. In Project properties -> c++ compiler -> include directories and headers -> add folder %SDLPATH%/x86_64-w64-mingw32/bin
  8. Do not close the window; on the Linker section add %SDLPATH%/x86_64-w64-mingw32/lib to "additional library directories".
  9. Finally, add these libraries in this order: mingw32.a, SDL2main.a, SDL2.a. The first file can be found on the %MINGWPATH%/x86_64-w64-mingw32/lib and the other two in the %SDLPATH%/x86_64-w64-mingw32/lib.
Now you should be able to succesfully compile an application that can make use of the SDL API. To create SDL applications, google a bit more. :)

sábado, 28 de junio de 2014

Aprender C: desarrollando un juego de ajedrez (II)

En el anterior post comenté que el tablero es un array de punteros a una variable de tipo pieza. En un principio pensé en crear una variable para cada pieza del juego, pero enseguida deseché la idea. ¿Qué valor me aporta una pieza por sí sola, sin estar situada en una casilla de un tablero? Un array de punteros me facilita la vida; si el puntero apunta a NULL entonces puedo considerar que la casilla está vacía. De lo contrario, si apunta a una variable de tipo pieza, sé que una pieza de ese tipo ocupa esa casilla, que es al final de cuentas lo que a mí me interesa. Además, de esta forma sólo necesito crear una variable por cada tipo de pieza y color; un único peón blanco, un único peón negro, un caballo blanco, etc. La declaración de variables e inicialización es como sigue:

tPiece  pb, pn, tb, tn, cb, cn, ab, an, rb, rn, reyb, reyn;

void initPieces() {
    
    pb.color = tb.color = cb.color= ab.color= rb.color= reyb.color=WHITE;
    pn.color= tn.color = cn.color= an.color= rn.color= reyn.color=BLACK;
    pb.rol= pn.rol=PAWN;
    tb.rol= tn.rol = ROOK;
    cb.rol= cn.rol=KNIGHT;
    ab.rol= an.rol=BISHOP;
    rb.rol= rn.rol=QUEEN;
    reyn.rol= reyb.rol= KING;
    
}

Estas variables y procedimiento yo los he incluído en ficheros aparte llamado pieces.h y pieces.c.

Las piezas están declaradas como variables globales; esto no es especialmente elegante, pero sí efectivo.

El tablero también debe ser iniciado al principio de la ejecución del programa, puesto que un puntero declarado pero no inicializado apunta a direcciones aleatorias de memoria - y aunque probablemente el sistema operativo no nos permitiría andar modificando contenido aleatorio de nuestra memoria, es una buena práctica inicializar los punteros.

void initBoard(tPiece* t[][8], int alto, int ancho) {

    int i,j;
    for( i = 0; i < ancho; i++ ) {
        for( j = 0; j < alto; j++ ) {
            t[i][j] = NULL;
        }
    }
    
}

Bien, pues con esto ya tenemos nuestro tablero y piezas listos para ser usados.

jueves, 26 de junio de 2014

Aprendiendo C: desarrollando un juego de ajedrez

Como he decidido finalmente orientar mi carrera profesional a la industria del entretenimiento digital, y salí de la universidad con conocimientos de C muy bajos, he tomado la determinación de programar un juego de ajedrez en C para aprender (parte de) ese lenguaje.

Sin más dilación, hoy explicaré los tipos y estructuras de datos usadas.

Una pieza de ajedrez es un elemento del que (por el momento) nos interesa abstraer dos características: color y papel que juega. Mi declaración es la siguiente:

typedef struct {
   tColor color;
   tRol rol;
 } tPiece;

Tanto tColor como tRol son enumeraciones. En C una enumeración es un conjunto de elementos nombrados por el programador a los que el compilador asigna un valor en función de su orden. De esta manera,

typedef enum {WHITE, BLACK} tColor;
typedef enum {PAWN,ROOK, KNIGHT, BISHOP, QUEEN, KING} tRol;

A la hora de compilar, WHITE será sustituido por el valor 0, BLACK por 1. De igual modo, PAWN 0, ROOK 1, KNIGHT 2, etc.

Finalmente, el tablero es un array de 8x8. Ojo, es un array DE PUNTEROS a una variable de tipo tPiece:

tPiece* t[8][8];

Al por qué considero que debe ser un array de punteros, daré explicación en el siguiente post.

martes, 17 de enero de 2012

MYSQL: FOREIGN KEY (clave foránea)

La sentencia para añadir a una columna una clave ajena es la siguiente:

ALTER TABLE CRMACL ADD FOREIGN KEY (ACLEMP) REFERENCES CRMEMP(EMPIDE)

Hay que tener cuidado de que la columna de origen y la de destino tengan exactamente la misma configuración, y que ambas tablas hayan sido creadas con el motor InnoDB.

miércoles, 23 de marzo de 2011

MYSQL: importar una tabla en el proveedor de hosting 1and1

Partimos de una tabla en un servidor mysql local; lo que queremos es subir esta tabla a una base de datos ofrecida por nuestro proveedor de hosting, en este caso 1and1.

Primeramente hemos exportado nuestra tabla desde el administrador de mysql con una consulta de este tipo:

> mysqldump -p --user=root --add-drop-table crm crmemp > crmemp.txt

Si no devuelve ningún mensaje se habrá creado con éxito el archivo de comandos.

Ahora, dentro de la web de administración de 1and1, abrimos el gestor de MySql y seleccionamos la base de datos pertinente. Nos vamos al botón de SQL y le damos a "importar archivos".

Si seleccionamos el archivo y le damos a importar, es probable que nos devuelva un error del tipo:

consulta SQL:

--
-- Table structure for table `crmemp`
--
DROP TABLE IF EXISTS `crmemp`

MySQL ha dicho:

#1046 - No database selected

Con lo que si añadimos en el archivo .txt al principio la sentencia USE nombreBaseDatos al principio nos permitirá hacerlo.

OJO: a veces el volcado puede generar caracteres extraños que no aparezcan en el archivo; si arroja errores, asegurarse de que la consulta que está ejecutando no tiene caracteres raros.

miércoles, 2 de marzo de 2011

Primeros pasos con OpenGL

Usando mi Macbook Blanco Intel dual core 1.83Ghz, Ubuntu 10.10, Eclipse 3.5.2 y openGL (lenguaje C++):

- Instalar el plugin para eclipse de C/C++
- Instalar los paquetes freeglut3 y freeglut3-dev desde el repositorio
- Crear un proyecto nuevo
- En propiedades del proyecto -> C/C++ Build -> Settings -> GCC C++ Linker -> Libraries hay que añadir GLU y glut.

miércoles, 19 de enero de 2011

VISUAL BASIC 6: Trabajar con Strings

Function Len (s as string) as integer

----> Devuelve la longitud del string

Function Mid (s as string, posicionInicio as integer [, longitud as integer]) as string

----> Devuelve una subcadena

Function Left (s as string, longitud as integer) as string

----> Devuelve la subcadena empezando por la izquierda de longitud especificada

Function Right (s as string, longitud as integer) as string

----> Devuelve la subcadena empezando por la derecha de longitud especificada

Function Ucase (s as string) as string

----> Devuelve una cadena en mayúsculas

Function Lcase (s as string) as string

----> Devuelve una cadena en minúsculas

Function Instr ([inicio as integer,] s1 as string, s2 as string)

----> Devuelve la posición de s2 en s1, 0 si no existe.

Function InstrRev (s1 as string, s2 as string [,inicio as integer] )

----> Devuelve la posición de s2 en s1, 0 si no existe, empezando por el final.

Sub Replace (s1 as string, s2 as string, s3 as string)

----> Reemplaza en s1 todas las ocurrencias de s2 por s3.

Function StrReverse (s as string) as string

----> Devuelve s al revés.

Function LTrim(s as string) as string

----> Devuelve s sin los espacios del principio.

Function RTrim(s as string) as string

----> Devuelve s sin los espacios del final.

Function Trim(s as string) as string

----> Devuelve s sin los espacios del final y del principio.

Function asc(s as string) as integer

----> Devuelve el valor ascii del primer carácter de s.

Function Chr (i as integer) as char

----> Devuelve el carácter que corresponde a un valor ascii.

jueves, 28 de octubre de 2010

MYSQL: Modificar el tipo de datos de un campo

ALTER TABLE tabla
CHANGE COLUMN nombre_columna nombre_nuevo_columna tipo_datos atributos;

jueves, 14 de octubre de 2010

VISUAL BASIC 6: Leer de un archivo Excel 2003

Primero añadimos la referencia al Microsoft Excel 11.0 Object Library en Proyecto -> Referencias.

A continuación con el siguiente código abrimos la ruta a un fichero excel y leemos o escribimos en él con:

'Variable de tipo Aplicación de Excel
Dim objExcel As Excel.Application

'Una variable de tipo Libro de Excel
Dim xLibro As Excel.Workbook
Dim Col As Integer, Fila As Integer

'creamos un nuevo objeto excel
Set objExcel = New Excel.Application

'Usamos el método open para abrir el archivo que está en el directorio del programa llamado archivo.xls
Set xLibro = objExcel.Workbooks.Open(Path)

'Hacemos referencia a la Hoja

Dim i As Integer

Fila = 5
Col = 3
MsgBox xLibro.Sheets("Hoja1").Cells(Fila, Col)


xLibro.Close (True)

VISUAL BASIC 6: interfaz para elegir un archivo.

En nuestro proyecto Visual Basic 6 debemos añadir en Project -> Components el Microsoft Common Dialog Control 6.0 que nos permitirá abrir diálogos para elegir archivos. Veremos que aparece un botón nuevo en nuestra barra de componentes y arrastramos uno hasta nuestro form. El nombre por defecto es CommonDialog1.

Una vez añadido, el siguiente código nos abre una ventana para seleccionar un archivo con un filtro determinado:

'Añadir un filtro al dialog de elegir archivo
Private Sub AddFilter(ByVal dlg As CommonDialog, ByVal _
filter_title As String, ByVal filter_value As String)

Dim txt As String

txt = dlg.Filter
If Len(txt) > 0 Then txt = txt & "|"
txt = txt & filter_title & " (" & filter_value & ")|" & _
filter_value
dlg.Filter = txt

End Sub

Después, asociamos a un evento el siguiente código:

AddFilter CommonDialog1, "Excel files", "*.xls"
CommonDialog1.ShowOpen
Path = CommonDialog1.FileName

En la variable path tendremos la ruta al archivo.

lunes, 27 de septiembre de 2010

MS SQL 2005: Crear un disparador (TRIGGER) sobre una vista (VIEW) que mande un e-mail al DBA

Supongamos que queremos que nuestro gestor de bases de datos nos avise cuando se modifiquen ciertos datos. En este caso concreto, quiero recibir un email a mi cuenta cuando los datos de una tabla no concuerden con los datos de otra (es decir, que la cantidad de un artículo que hay en una tabla sea diferente a la cantidad de ese mismo artículo en otra tabla). Parece lioso, pero se ve rápido con un ejemplo:

TABLA datos_almacen

Codigo_articulo varchar(16)
Cantidad decimal(12,3)

TABLA datos_almacen_2

Codigo_articulo varchar(16)
Cantidad decimal(12,3)

Entonces, si la cantidad del mismo artículo es diferente para las dos tablas, quiero que me avise. Supongamos que tengo la siguiente vista que muestra todos los artículos con diferencias:

CREATE VIEW mi_vista AS
SELECT *
FROM datos_almacen a inner join datos_almacen_2 b
on a.codigo_articulo = b.codigo_articulo
and a.cantidad <> b.cantidad

Correcto, esta vista muestra las diferencias (recuerda que estamos suponiendo que ambas tablas tienen los mismos códigos de artículo, si en uno hubiese más que en otro habría que hacer un JOIN lateral). Ahora el trigger para que salte cuando aparezca alguna diferencia:

MS SQL 2005: Crear una vista

Lo que hace una vista es devolver el resultado de una consulta de selección como si se tratase de un select, pero de forma que podemos impedir al usuario el acceso a las tablas sobre las que se ejecuta la consulta.

Un ejemplo:

CREATE VIEW mi_vista AS
select *
from mi_tabla

Ahora podemos quitarle permisos a un usuario sobre la tabla 'mi_tabla' pero darle permisos sobre la vista 'mi_vista' y el usuario podría consultar los datos de la tabla (los que nosotros, DBAs, queramos, jeje) sin tener acceso directo a la misma.

martes, 27 de julio de 2010

MYSQL: dar permisos a usuarios

GRANT [SELECT | UPDATE | etc.. ] ON [basedatos | *].[nombretabla | *] TO nombreUsuario

MYSQL: crear y borrar usuarios

Crear:

CREATE USER nombreUsuario IDENTIFIED BY 'password';

Eliminar:

DROP USER nombreUsuario;

MS SQL 2005: importar datos de una hoja excel a una bbdd

Microsoft explica en esta página varios métodos para hacerlo. El que yo he seguido y me ha funcionado a la primera ha sido el siguiente:

Utilizar un servidor vinculado

Después de haber vinculado un servidor ya podemos hacer una consulta del tipo:

SELECT * FROM nombreAsignado...[nombreHoja$]

miércoles, 21 de julio de 2010

PHP: conexión a base datos MICROSOFT SQL

Conseguir las DLLs

Lo primero que nos hace falta es conseguir las DLLs para conectarnos a un SQL Server, por defecto estas DLLs no van en el paquete de instalación automática, así que tendrás que bajar, si no lo tienes ya, el paquete con la instalación completa.

Descomprime el paquete con la distribución completa y busca el fichero "php_mssql.dll" que está dentro del directorio "extensions", copia este fichero al directorio "dlls" en donde tengas instalado el PHP.

Editar el PHP.ini

Ahora hay que decirle al PHP que tiene una librería nueva y que la debe usar. Así que editaremos el PHP.ini con el Notepad, normalmente el PHP.ini está en el directorio C:\WINNT.

Busca la línea en la que pone "extension_dir = " y modifícala para que apunte al directorio donde hemos copiado la DLL. Con esto le indicamos al PHP donde están las DLL de extensión.

Ahora busca la línea ";extension=php_mssql.dll" y modifícala quitándole el ";" del principio.

Graba el fichero PHP.ini y ya está.

Ejemplo de conexión

Solo nos queda probar que funciona la conexión con el servidor SQL Server, para ello vamos a conectarnos con la base de datos “Northwind” que viene como ejemplo en la instalación de SQL Server. Listaremos el nombre del producto y el precio de la tabla productos.

$conectID = mssql_connect("NombreServidor","SA","");
mssql_select_db("Northwind");
$result=mssql_query("select * from products",$numero );
while ($row=mssql_fetch_array($result)) {
$counter++; $c1=$row["ProductName"];
$c2=$row["UnitPrice"];
echo ("$counter c1: $c1 c2: $c2\n");
}
mssql_close($conectID);

Gracias a http://www.webestilo.com/php/articulo.phtml?art=19

martes, 6 de julio de 2010

PHP: conocer los índices y los contenidos de un array

Dada una variable cualquiera $mi_array, sabemos que es un array pero no sabemos más. Para conocer los índices y los valores almacenados en cada uno de estos índices, podemos usar el siguiente bucle que recorrerá todos los índices del array:

foreach ($mi_array as $key => $value) {

// Sentencias

}

En $key tendremos el valor del índice, mientras que en $value tendremos el valor almacenado en dicho índice.

martes, 29 de junio de 2010

UBUNTU: modem HUAWEI K3765 en Lucid Lynx (10.04)

En principio basta con instalar el paquete "usb-modeswitch" (usando Synaptic, aptitude, apt o tu método favorito) y luego irse a Sistema -> Preferencias -> Conexiones de red -> Banda ancha móvil -> Agregar y metemos los datos que obtendremos de nuestro proveedor de servicios de red.

Gracias a digital nomad y a My brain is here.

Actualización 16/07/2010: Pues no ha resultado tan fácil... A las dos semanas me ha venido el comercial para decirme que no consigue conectarse usando el módem usb y efectivamente, al pincharlo lo reconoce como dispositivo de almacenamiento pero no como módem.. :S

lunes, 21 de junio de 2010

MYSQL: importar una tabla CSV en nuestra BBDD

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
-> FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
-> LINES TERMINATED BY '\n';

Gracias a deadlykyo.

jueves, 17 de junio de 2010

UBUNTU: instalar adobe flash plugin para Chrome

Para la versión Ubuntu 10.04 (imagino que para anteriores y posteriores no debe ser muy difícil) lo que he hecho para instalar el plugin de Adobe Flash Player (el que usa youtube para mostrar vídeos, por ejemplo) ha sido lo siguiente:

1) Ir a la página de descargas de Adobe Flash Player PLugin

2) Descargar el plugin (el paquete para Ubuntu debería valer, pero yo no conseguí descargarlo. En vez de eso descargué el .tar.gz para linux).

3) Descomprimir el fichero libflashplayer.so en la carpeta /opt/google/chrome/plugins (si la carpeta /plugins no existe la creamos).

4) Hay que decirle a Chrome que busque plugins al iniciar. Para ello hacemos click derecho en el botón Aplicaciones, Editar los menús, Internet -> Google Chrome, Propiedades y en comando tiene que decir lo siguiente:

/opt/google/chrome/google-chrome --enable-plugins %U

Con esto debería estar instalado. Gracias a Howtoforge.com