Buenas!
Estoy muy muy liado... voy hasta arriba en el trabajo durante esta semana, y aún tengo que adelantar la parte de VB.net
No obstante intento sacar ratos libres para escribir. Tened paciencia, espero terminar la siguiente entrada pronto!
Saludos y
Hasta la próxima...
Pongamos a prueba todo lo que conocemos.
Huyamos de todo lo establecido y exploremos por nuestra cuenta.
El escepticismo aplicado a la informática, aquí.
@ESC_ILU (on Twitter)
Alters
A buscar M!nas: MSAccess - SQL
Buenas!
Empezamos por fin la parte de programación. Esta sección ocupará tres entradas, en las cuales ampliaremos todo el proyecto.
Pues bien, empecemos ya mismo con la primera parte: el SQL.
La primera tarea que tenemos que hacer es crear algunas sentencias SQL para crear las tablas, partiendo del modelo normalizado de la anterior entrada (lo siento, se me pasó un error; éste es el modelo bueno):
He querido hacer la parte de creación desde SQL, y dejar la parte de las restricciones. Esta parte la veremos con MSAccess directamente (así variamos un poco las cosas).
Pues bien, vamos a crear nuestra base de datos.
Primero abrimos MSAccess, seleccionamos "Nueva base de datos en blanco", le cambiamos el nombre (yo le pondré "BuscaminaX"), y apretamos "enter" o le damos a "crear" (img1).
Ahora tendremos una tabla por defecto, tabla1. De momento no le prestamos atención.
Vamos a la sección "Crear", y de ahí vamos a "Diseño de consulta" (img2).
Nos saldrá una ventana nueva y una ventana emergente. Cerramos la ventana emergente y pulsamos, en el menú, la opción "SQL" (img3).
Borramos el contenido ("SELECT;") y copiamos, una por una, las sentencias de creación. Tras escribir una sentencia pulsamos el botón de ejecutar. Esto hará que se creen las tablas.
Una vez ejecutadas todas las sentencias deberemos tener algo similar a la "img4".
La siguiente tarea es asignar las PK. Para ello pulsamos en una tabla, y se nos abrirá el editor. Vamos a la pestaña inicio y pulsamos el icono "ver". Seleccionamos los campos necesarios y pulsamos la opción "Clave principal (img5). Repetimos esto para todas las tablas, y ya tendremos nuestras PK.
Finalmente nos falta establecer las FK. Para ello vamos a la sección "Herraminentas de base de datos" y pulsamos sobre "Relaciones". Esto nos abrirá una nueva ventana con una nueva ventana emergente. Seleccionamos todas las tablas y le damos a intro (o a agregar). Veremos cómo aparecen en la ventana; hecho esto cerramos la ventana emergente, y nos quedará algo como la img6.
Ahora arrastramos los campos: de PK a FK (por ejemplo, de email.idE a usuario.idE). Recordad que debéis cerrar y guardar el resto de ventanas (MSAccess nos dará la lata continuamente con esto).
Al intentar crear una FK nos saldrá un cuadro; revisamos que los atributos sean los correctos, y marcamos "Exigir integridad referencial" (img7).
Cuando todas las relaciones estén completadas, nos quedará el panorama como en la img8.
Siento la ingente cantidad de fotos, la verdad es que no sabía muy bien como cuadrarlas...
Pero bueno, creo que no queda tan mal :-P
Hemos terminado la parte de SQL (por ahora). Solo tenemos que guardar nuestra base de datos y podemos cerrar MSAccess hasta la entrega de gestión (dentro de dos entregas).
En la próxima veremos cómo ampliamos nuestro juego de VB.net para hacer que todo esto sirva para algo.
¡Hasta la próxima!
Empezamos por fin la parte de programación. Esta sección ocupará tres entradas, en las cuales ampliaremos todo el proyecto.
Pues bien, empecemos ya mismo con la primera parte: el SQL.
La primera tarea que tenemos que hacer es crear algunas sentencias SQL para crear las tablas, partiendo del modelo normalizado de la anterior entrada (lo siento, se me pasó un error; éste es el modelo bueno):
usuario(nick, nombre, apellido1, apellido2, idE, password)
email(idE, email)
estadistica(gana, tiempo, dificultad, opcion, autenticacion, minas, clicks, id_estadistica)
juego(nick, id_estadistica, fecha)
juego(nick, id_estadistica, fecha)
CREATE TABLE usuario(
nick varchar(50),
nombre varchar(50),
apellido1 varchar(50),
apellido2 varchar(50),
idE int,
password varchar(16)
);
CREATE TABLE email(
idE int,
email varchar(100)
);
CREATE TABLE estadistica(
gana int,
tiempo int,
dificultad int,
opcion int,
autenticacion int,
minas int,
clicks int,
id_estadistica int
);
CREATE TABLE juego(
nick varchar(50),
id_estadistica int,
fecha varchar(14)
);
He querido hacer la parte de creación desde SQL, y dejar la parte de las restricciones. Esta parte la veremos con MSAccess directamente (así variamos un poco las cosas).
Pues bien, vamos a crear nuestra base de datos.
Primero abrimos MSAccess, seleccionamos "Nueva base de datos en blanco", le cambiamos el nombre (yo le pondré "BuscaminaX"), y apretamos "enter" o le damos a "crear" (img1).
img1 |
Vamos a la sección "Crear", y de ahí vamos a "Diseño de consulta" (img2).
Nos saldrá una ventana nueva y una ventana emergente. Cerramos la ventana emergente y pulsamos, en el menú, la opción "SQL" (img3).
img2 |
img3 |
La siguiente tarea es asignar las PK. Para ello pulsamos en una tabla, y se nos abrirá el editor. Vamos a la pestaña inicio y pulsamos el icono "ver". Seleccionamos los campos necesarios y pulsamos la opción "Clave principal (img5). Repetimos esto para todas las tablas, y ya tendremos nuestras PK.
img4 |
img5 |
img6 |
Ahora arrastramos los campos: de PK a FK (por ejemplo, de email.idE a usuario.idE). Recordad que debéis cerrar y guardar el resto de ventanas (MSAccess nos dará la lata continuamente con esto).
Al intentar crear una FK nos saldrá un cuadro; revisamos que los atributos sean los correctos, y marcamos "Exigir integridad referencial" (img7).
img7 |
Cuando todas las relaciones estén completadas, nos quedará el panorama como en la img8.
img8 |
Siento la ingente cantidad de fotos, la verdad es que no sabía muy bien como cuadrarlas...
Pero bueno, creo que no queda tan mal :-P
Hemos terminado la parte de SQL (por ahora). Solo tenemos que guardar nuestra base de datos y podemos cerrar MSAccess hasta la entrega de gestión (dentro de dos entregas).
En la próxima veremos cómo ampliamos nuestro juego de VB.net para hacer que todo esto sirva para algo.
¡Hasta la próxima!
A buscar M!nas: MSAccess - normalización
Buenas!
Nos adentramos de lleno en la fase final de la construcción de nuestra base de datos primitiva.
Así, hoy veremos el paso final antes de implementar nuestro modelo; la normalización.
Este proceso, como su nombre indica, "normaliza" el modelo relacional, de manera que será más definido y útil.
El proceso es gradual, es decir, no se puede llegar a una forma normal (FN) si no está en la FN anterior (y así recursivamente...)
Conceptos previos:
Antes de entrar en el proceso, vamos a definir unos conceptos, que nunca viene mal:
Ahora que tenemos los términos básicos definidos, podemos pasar a definir qué es una dependencia funcional:
Vista esta pequeña introducción, podemos pasar a la normalización:
Normalización:
Como comentaba, se trata de un proceso progresivo. De esta manera, empezaré con la primera forma normal (1FN) e iré avanzando hacia modelos más normalizados. Empecemos:
Ahora ya sabemos en qué consiste normalizar; vamos a aplicarlo a nuestro modelo:
usuario(nick, nombre, apellido1, apellido2, email, password)
estadistica(gana, tiempo, dificultad, opcion, autenticacion, minas, clicks, id_estadistica)
juego(nick, id_estadistica, fecha)
usuario(nick, nombre, apellido1, apellido2, email, password) ==> usuario(nick, nombre, apellido1, apellido2, idE, password) email(idE, email)
Con esto dejamos la base preparada para el próximo paso: la programación.
Así, en la próxima entrega veremos cómo pasar este esquema al SQL, y más adelante haremos las ampliaciones necesarias en nuestro juego de VB.net.
Espero no se os haya hecho muy pesada la lectura.
¡Hasta la próxima!
Nos adentramos de lleno en la fase final de la construcción de nuestra base de datos primitiva.
Así, hoy veremos el paso final antes de implementar nuestro modelo; la normalización.
Este proceso, como su nombre indica, "normaliza" el modelo relacional, de manera que será más definido y útil.
El proceso es gradual, es decir, no se puede llegar a una forma normal (FN) si no está en la FN anterior (y así recursivamente...)
Conceptos previos:
Antes de entrar en el proceso, vamos a definir unos conceptos, que nunca viene mal:
- O: durante esta entrada, para referirnos a un conjunto de valores originales usaremos la letra "o" mayúscula (no confundir con cero).
- I: se trata de un conjunto imagen.
- Intención: es la descripción "fija" de una tabla. Contiene los descriptores de la tabla así como las restricciones. Se puede representar como R(A1, A2, A3, ... , An)
- Extensión: es el conjunto de tuplas ("filas") de una tabla en un momento determinado.
Ahora que tenemos los términos básicos definidos, podemos pasar a definir qué es una dependencia funcional:
- Dependencia funcional: Restricción sobre una relación con intención R(A1, A2, A3, ... , An) que representa un esquema {x} -> {y} donde {x} e {y} son subconjuntos de la intención que garantiza que dado un valor de {x}, es determinado de manera única un valor de {y}*.
* Esto se puede representar (de un modo aproximado) como;
[{x}, {y} c (A1, A2, A3, ... , An) | Xi <-> Yj]
Vista esta pequeña introducción, podemos pasar a la normalización:
Normalización:
Como comentaba, se trata de un proceso progresivo. De esta manera, empezaré con la primera forma normal (1FN) e iré avanzando hacia modelos más normalizados. Empecemos:
- 1FN: se dice que una relación está en 1FN si ningún atributo de la relación es en si mismo una relación, es decir, si todo atributo de la relación es atómico, no descomponible y no es un grupo repetitivo (solo tiene ciertos valores)
Ejemplificando: supongamos la siguiente tabla: Alumno(DNI, nombre, notas). En este caso, las notas son algo no atómico, descomponible y tiene parte de grupo repetitivo. Ampliando la información, sería:
- No atómico: "notas" es un registro que puede estar repetido dentro de un mismo registro. Por ejemplo para el DNI1 puede haber algo así como "castellano primer trimestre: 5, inglés primer trimestre..." dentro del mismo registro.
- Descomponible: se puede dividir en varias secciones. Por ejemplo: nota, asignatura, trimestre.
- Grupo repetitivo: las asignaturas, la nota y el trimestre son de por sí grupos repetitivos.
Alumno(DNI, nombre, notas) ==> Alumno(DNI, nombre, asignatura, nota, trimestre)
Al normalizar se ha tenido que expandir la PK, para que no haya duplicados.
- 2FN: se dice que una relación está en 2FN si está en 1FN y todo atributo no clave depende funcionalmente, en forma completa de la PK.
Esto quiere decir que todo aquel atributo que dependa de algo que no sea la TOTALIDAD de la PK de la tabla tendrá que ser modificado, de manera que ese atributo pasará a ser una tabla. La tabla que fue normalizada incorporará como FK la PK de la nueva tabla.
- 3FN: se dice que una relación está en 3FN si está en 2FN y ningún atributo no clave depende funcionalmente de ningún otro conjunto de atributos no clave.
¿Qué significa esto? Puede parecer algo lioso, pero de vez en cuando se ve. Veamos un ejemplo:
Direccion(ID, calle, ciudad, provincia)
En este caso (y refiriéndonos a un modelo local, es decir, suponiendo que solo se tiene en cuenta un país) sabiendo la ciudad se sabe la provincia. Por eso, esta tabla no está en 3FN.
Direccion(ID, calle, ciudad, provincia) ==> Direccion(ID, calle, idCiudad) Ciudad(ciudad, provincia)
Se crea una nueva tabla y se asigna una nueva FK
Se crea una nueva tabla y se asigna una nueva FK
- FNBC: esta forma normal es "especial", ya que está a caballo entre la 3FN y la 4FN. Normalmente se acepta una base de datos normalizada hasta la FNBC. No obstante nosotros veremos hasta la 5FN.
La FNBC dice que dada una dependencia funcional {x} -> {y}, todo elemento de "x" es considerado como clave candidata.
Una definición así cuesta ver, así que dejo un ejemplo:
Notas(DNI, codAsig, codMatr, nota)
En esta tabla, DNI y codAsig son la PK. No obstante, el atributo "codMatr" es una clave candidata (es decir, podría servir como PK). Así, surgen cuatro opciones para normalizar esta situación:
a) Notas(DNI, codAsig, nota)
Alumno(DNI, codMatr)
b) Notas(DNI, codAsig, nota)
Alumno(codMat, DNI)
c) Notas(DNI, codAsig, nota)
Alumno(codMat, DNI)
d) Notas(DNI, codAsig, nota)
Alumno(DNI, codMat)
- 4FN: para saber si una relación está en 4FN tenemos que comprobar que no existan DMI (Dependencia Multievaluada Independiente) y está en FNBC.
Una DMI se define como:
Sea "R" una relación con esquema R(A1, A2, A3, ..., An), y siendo {x}, {y} y {z} atributos de "R", se dará la DMI {x} ->> {y} si y solo si el conjunto de valores posibles de {y} para un par {x, z} depende únicamente del valor de "x" y es independiente del valor de "z".
Visto desde el punto de vista relacional, significa simplemente que las relaciones "n-arias" pasan a ser "n" relaciones con relación "n : n".
- 5FN: una relación está en 5FN si y solo si está en 4FN y cumple que no tiene PK descomponible.
Para verlo mejor, un ejemplo:
Profesor(ID, nombre)
Asignatura(ID, nombre)
Centro(ID, nombre)
Ensenanza(IdPro, IdAsi, IdCen) ==> PA(IdPro, IdAsig) PC(IdPro, IdCen)
Ahora ya sabemos en qué consiste normalizar; vamos a aplicarlo a nuestro modelo:
usuario(nick, nombre, apellido1, apellido2, email, password)
estadistica(gana, tiempo, dificultad, opcion, autenticacion, minas, clicks, id_estadistica)
juego(nick, id_estadistica, fecha)
- 1FN: en la tabla estadistica tenemos varios grupos repetitivos: "gana", "dificultad", "opcion", "autenticacion", "minas"). A continuación se describen los grupos repetitivos:
- Gana:
* Sí (1)
* No (2)
- Dificultad:
* Fácil (1)
* Medio (2)
* Difícil (3)
- Opción:
* Opción 1 (1)
* Opción 2 (2)
- Autenticación:
* Registrado (1)
* Anónimo (2)
- Minas:
* 10 (1)
* 40 (2)
* 99 (3)
Para deshacer los grupos repetitivos trasladamos todos los valores a numéricos, empezando siempre por 1 y llegando hasta el último valor disponible. Éstos valores se colocan arriba entre paréntesis.
- 2FN: El modelo está en 2FN.
- 3FN: Se puede apreciar en la tabla usuario cómo el campo "email", si no es nulo sirve para identificar a un usuario. Por ello realizamos la siguiente modificación:
usuario(nick, nombre, apellido1, apellido2, email, password) ==> usuario(nick, nombre, apellido1, apellido2, idE, password) email(idE, email)
- FNBC: Se ha eliminado la clave candidata (email) en la tabla usuario (realmente no era clave candidata puesto que podría ser un dato vacío). Por tanto, estamos en FNBC.
- 4FN: Está en 4FN
- 5FN: Está en 5FN.
De este modo, tenemos por fin nuestro modelo relacional normalizado, siendo el siguiente:
usuario(nick, nombre, apellido1, apellido2, idE, password)
email(idE, email)
estadistica(gana, tiempo, dificultad, opcion, autenticacion, minas, clicks, id_estadistica)
juego(nick, id_estadistica, fecha)
juego(nick, id_estadistica, fecha)
Con esto dejamos la base preparada para el próximo paso: la programación.
Así, en la próxima entrega veremos cómo pasar este esquema al SQL, y más adelante haremos las ampliaciones necesarias en nuestro juego de VB.net.
Espero no se os haya hecho muy pesada la lectura.
¡Hasta la próxima!
A buscar M!nas: MSAccess - modelo relacional
Buenas!
Entramos de lleno ya en el tema del diseño. Para diseñar una buena base de datos, partiendo del modelo E - R expuesto en la entrada anterior, necesitamos realizar un proceso de "relacionalización".
Y, ¿En qué consiste? Básicamente se trata de "pasar" las tablas a notación relacional (una sintaxis más cercana al SQL).
Pero, sin embargo, debemos (o deberíamos) aplicar una serie de normas y patrones antes y después de hacer la transformación. Aplicarlas sirve para preparar la futura base de datos para que sea más sencilla de comprender, y a la larga que todo sea más fácil e intuitivo.
PRETECAR
A los pasos previos a la creación del modelo relacional las conozco como PRETECAR (es un acrónimo de Previa REgla de Transformación del Esquema Conceptual A Relacional).
De estas reglas hay dos (PRETECAR 1 y PRETECAR 2). A saber:
En este caso, un libro puede estar escrito por varios autores. Así, deberíamos aplicar la PRETECAR 1.
Un atributo compuesto es todo aquel que pueda ser divisible, como por ejemplo "Dirección", "Nombre completo"...
Ahora ya sabemos cuál es el problema que eliminan las PRETACAR 1 y 2. Pero falta saber cómo lo hacen:
En la entrada anterior dejamos ver que la relación era "1 : n", por lo que tenemos que aplicar la RETECAR 3. Del mismo modo, y como hay un atributo de relación (aunque no lo especifiqué), procederemos a usar la RETECAR 3.2.
Entonces, quedaría así:
Leyenda:
Entramos de lleno ya en el tema del diseño. Para diseñar una buena base de datos, partiendo del modelo E - R expuesto en la entrada anterior, necesitamos realizar un proceso de "relacionalización".
Y, ¿En qué consiste? Básicamente se trata de "pasar" las tablas a notación relacional (una sintaxis más cercana al SQL).
Pero, sin embargo, debemos (o deberíamos) aplicar una serie de normas y patrones antes y después de hacer la transformación. Aplicarlas sirve para preparar la futura base de datos para que sea más sencilla de comprender, y a la larga que todo sea más fácil e intuitivo.
PRETECAR
A los pasos previos a la creación del modelo relacional las conozco como PRETECAR (es un acrónimo de Previa REgla de Transformación del Esquema Conceptual A Relacional).
De estas reglas hay dos (PRETECAR 1 y PRETECAR 2). A saber:
- Eliminación de atributos múltiples
- Eliminación de atributos compuestos
La primera casi nunca tendremos que aplicarla, mientras que la segunda es más usual tener que aplicarla. Explico más a fondo las reglas:
Un atributo múltiple es aquel que puede tener más de un valor. Es decir, un atributo que pueda ser tomado como lista o array.
Un ejemplo sería el caso en que tenemos la siguiente tabla:
LIBRO
ISBN
Título
Autor
En este caso, un libro puede estar escrito por varios autores. Así, deberíamos aplicar la PRETECAR 1.
Un atributo compuesto es todo aquel que pueda ser divisible, como por ejemplo "Dirección", "Nombre completo"...
Ahora ya sabemos cuál es el problema que eliminan las PRETACAR 1 y 2. Pero falta saber cómo lo hacen:
- PRETECAR 1: Extrapolamos el atributo múltiple a una entidad débil por existencia, dependiente de la clase de la que se segrega. Ambas clases guardarán una relación "n : n".
- PRETECAR 2: Se crean los atributos que fueren necesarios, y se vuelve a comprobar la PRETECAR 2 (a veces los elementos compuestos tienen "dentro" más elementos compuestos).
Una pequeña aclaración: una entidad débil por existencia es aquella que depende de otra, pero tiene "sentido" que exista de por sí. Una entidad débil por existencia es, en el caso anterior (LIBRO), Autor, ya que es un atributo múltilpe, y por PRETECAR 1 sería una entidad débil por existencia.
Como se ve, el término "Autor" y lo que ello representa tiene significado; pero en este caso está supeditado a la clase LIBRO.
El otro caso de entidad débil (entidad débil por identificación) es aquella que depende de la entidad fuerte para ser un ente. Es el caso de la relación "Factura - Línea". En este caso, "Línea" sería la entidad débil, y no tiene razón de ser si no se relaciona con una factura.
RETECAR
El siguiente paso, tras preparar nuestro modelo E - R para pasar a modelo relacional, es hacerlo mediante las llamadas RETECAR. Son sencillas reglas que permiten que el paso a modelo relacional sea estándar y rápido. Son:
- RETECAR 1: Todas las entidades presentes en el esquema conceptual se transforman en relaciones en el esquema relacional, manteniendo el número y tipo de atributos así como el identificador.
- RETECAR 2: Se divide en tres opciones:
- RETECAR 2.1: Si en una relación binaria el grado es "1 : 1" y ambas son obligatorias, entonces, se procede:
- RETECAR 2.1.1: Si ambas tienen el mismo identificador se creará una sola tabla formada por la agregación de los atributos de ambas entidades, siendo la PK el identificador común.
- RETECAR 2.1.2: Si ambas tienen identificadores diferentes, cada entidad se transformará en una tabla, usando la RETECAR 1, y cada tabla tendrá como PK el identificador de la propia entidad, y como FK la PK de la otra tabla.
- RETECAR 2.2: Si en la relación binaria "1 : 1" hay una entidad obligatoria y la otra opcional, cada entidad se transformará en una tabla usando la RETECAR 1, y adicionalmente se procederá por una de estas dos vías:
- RETACAR 2.2.1: El identificador de la opcional pasa como FK a la entidad obligatoria
- RETECAR 2.2.2: Se construye una nueva tabla correspondiente a la relación formada por los atributos identificadores de las dos entidades y siendo la PK el identificador de la entidad opcional.
- RETECAR 2.3: Si ambas entidades son opcionales, se crean sendas tablas por RETECAR 1, añadiendo una de estas dos posibilidades:
- RETECAR 2.3.1: Los id. de cada entidad pasan a formar parte como FK de la otra tabla.
- RETECAR 2.3.2: Se construye una nueva tabla correspondiente a la relación cuyos atributos serán los identificadores de las dos entidades, y la PK será uno de los dos identificadores de la tabla.
- RETECAR 3: Se divide en dos opciones:
- RETECAR 3.1: Si es una relación binaria de grado "1: n" o "n : 1", ambas entidades participan obligatoriamente o la entidad de grado "n" participa de manera opcional, cada entidad se transformará en una tabla por RETECAR 1, y el identificador de la entidad de grado "1" pasará a ser FK de la tabla de grado "n"
- RETECAR 3.2: Si es una relación binaria de grado "1: n" o "n : 1", siendo ambas entidades opcionales o solamente la de grado "1", cada entidad se transforma por RETECAR 1, y se genera una nueva tabla correspondiente a la relación formada por los atributos identificadores de ambas tablas y los atributos de la relación.
- RETECAR 4: En una relación binaria "n : n", o cualquier relación "n-aria", cada entidad pasa a ser una tabla, por RETECAR 1, y adicionalmente se genera una tabla para representar la relación. Esta nueva tabla estará formada por las PK de las entidades y los atributos de la relación, siendo la PK la agregación de las PK de las dos entidades.
- RETECAR 5: En una relación jerárquica, se desestimará la entidad supertipo, transfiriendo todos los atributos de ésta a cada una de las entidades subtipo. Las relaciones que tenía la entidad supertipo pasarán a ser consideradas por cada entidad subtipo.
- RETECAR 6: Se desestimarán las entidades subtipo, transfiriéndose todos los atributos de éstas a la entidad supertipo, así como cada una de las relaciones que las entidades subtipo mantenían
- RETECAR 7: La relación jerárquica se transformará en tantas relaciones "1 : 1" como entidades subtipo estén presente.
Nota: De las tres últimas RETECAR (5, 6, y 7) solo se aplica una por cada relación jerárquica, dependiendo de lo que el analista vea conveniente.
Con esto termina la teoría. Es el momento de aplicar estos pasos a nuestro prototipo de modelo E - R:
Para realizar el proceso, primero aplicaré las dos PRETECAR, y después usaré las reglas para usar las RETECAR.
a) PRETECAR:
- Cambiamos el atributo "Apellidos" por dos: "apellido1" y "apellido2" -> PRETECAR 2.
Hasta aquí va todo bien. El modelo está preparado para ser transformado. Pero antes una anotación: es muy usual juntar los atributos de apellido (al igual que de nombre) en uno solo, pues hay gente que tiene un apellido, hay gente que tiene dos... y lo mismo con los nombres.
Yo soy partidario de separarlos siempre que sea posible (es decir, que no resulte "molesto"). En este caso irá bien separarlos, pero cuando pidamos los datos tendremos que tener en cuenta que deberemos pedir los apellidos por separado.
Ahora que está todo preparado, aplicamos a ambas entidades la RETECAR 1, quedando así:
usuario(nick, nombre, apellido1, apellido2, email, password)
estadistica(gana, tiempo, dificultad, opcion, autenticacion, minas, clicks, id_estadistica)
En la entrada anterior dejamos ver que la relación era "1 : n", por lo que tenemos que aplicar la RETECAR 3. Del mismo modo, y como hay un atributo de relación (aunque no lo especifiqué), procederemos a usar la RETECAR 3.2.
Entonces, quedaría así:
usuario(nick, nombre, apellido1, apellido2, email, password)
estadistica(gana, tiempo, dificultad, opcion, autenticacion, minas, clicks, id_estadistica)
juego(nick, id_estadistica, fecha)
estadistica(gana, tiempo, dificultad, opcion, autenticacion, minas, clicks, id_estadistica)
juego(nick, id_estadistica, fecha)
Leyenda:
- Negrita y cursiva: nombre tabla
- Subrayado: clave primaria (PK)
- Cursiva: clave foránea (FK)
- Negrita y subrayado: clave primaria y clave foránea (PK/FK)
Finalmente, hacer un par de anotaciones: he añadido un atributo (id_estadistica) para poder distinguir todos los registros entre ellos. También, como he dicho antes, olvidé mencionar la fecha, pero es algo que no es obligatorio; sin embargo da mucho más juego y utilidad tenerlo.
Bien, de momento tenemos el modelo relacional. En la próxima entrega lo normalizaremos. Aunque vamos a intentar normalizarlo hasta la quinta forma normal (5FN), lo normal es hacerlo hasta la forma normal de Boyce-Codd (FNBC).
Y, con esta reflexión, os dejo.
¡Hasta la próxima!
A buscar M!nas: MSAccess - Modelo E-R
Buenas de nuevo!
En esta entrada trataremos el modelo entidad - relación (E - R) en base a los requerimientos expuestos en la entrada anterior.
De los datos marcados, podemos ver como hay dos tablas: por una parte tenemos los usuarios, y por otra, las estadísticas.
De la primera tabla guardaremos:
En esta entrada trataremos el modelo entidad - relación (E - R) en base a los requerimientos expuestos en la entrada anterior.
De los datos marcados, podemos ver como hay dos tablas: por una parte tenemos los usuarios, y por otra, las estadísticas.
De la primera tabla guardaremos:
- Nick
- Nombre
- Apellidos
- Password
De la segunda:
- Si ha ganado
- Tiempo
- Dificultad
- Clicks
- Minas marcadas
- Autenticación
- Opción
Leyendo el texto, también podemos deducir la relación; un usuario tiene un registro único de estadísticas, y un registro de estadísticas corresponde a un usuario (si es un usuario anónimo, ese usuarios puede ser varios a la vez).
¿Ésto cómo se traduce? Bien, a nivel de base de datos, un registro de estadísticas estará compuesto por varias entradas. Por tanto, deducimos que la relación será 1 : *
He creado un pequeño esquema de las dos tablas y la relación que tienen. Os lo adjunto:
![]() |
Modelo E - R |
De momento esto es todo para esta entrega.
En la próxima empezaremos con la teoría del modelo relacional. Haremos todo el proceso en una entrega, de manera que así me veré forzado a no extenderme demasiado con la teoría (en realidad es bastante rápido, incluso automático cuando te lo aprendes).
Hasta la próxima!
A buscar M!nas: MSAccess - Requerimientos
Buenas!
Empezamos ya con la primera mejora para nuestro juego de M!nas. Esta mejora servirá como base para las próximas mejoras.
Tal como indiqué en la entrada anterior (en el índice), en esta entrada redactaré de forma textual los requerimientos de nuestra aplicación.
Para ello describiré la "aplicación ideal". Posteriormente extraeremos la información útil y la adaptaremos a un modelo E-R adaptado a un modelo local..
Empecemos, pues:
Esta es la especificación de requerimientos, en un modo textual. De este texto se puede extraer toda la información necesaria para crear la base de datos. Toda la información ha sido destacada de la siguiente manera:
Los nombres de tablas están en azul y negrita
Los nombres de campos están en verde y negrita
Se puede apreciar a simple vista que el futuro modelo Entidad - Relación será pequeño. Pero esto no quiere decir que se pueda hacer a la ligera.
Tenemos que proceder siempre con cautela y cuidado, para intentar cometer siempre el mínimo número de errores.
Estas medidas pueden parecer inútiles y contraproducentes, pero es todo lo contrario; es preferible estar seis u ocho horas analizando un problema y luego dos horas programando que empezar a programar y luego parchear todo a base de debug. Además, el analizar las cosas nos proporciona una vista más amplia del problema y nos permite subdividirlo de manera que las funciones y clases que hagamos serán realmente útiles.
Después de esta pequeña reflexión, voy a preparar la siguiente entrada. De momento lo dejamos aquí.
¡Hasta la próxima!
Empezamos ya con la primera mejora para nuestro juego de M!nas. Esta mejora servirá como base para las próximas mejoras.
Tal como indiqué en la entrada anterior (en el índice), en esta entrada redactaré de forma textual los requerimientos de nuestra aplicación.
Para ello describiré la "aplicación ideal". Posteriormente extraeremos la información útil y la adaptaremos a un modelo E-R adaptado a un modelo local..
Empecemos, pues:
La idea es tener una aplicación con un sistema de base de datos.
La aplicación (el juego de las M!nas) enviará información diversa para registrarla.
Así, una ejecución normal del juego consistiría en:
La aplicación (el juego de las M!nas) enviará información diversa para registrarla.
Así, una ejecución normal del juego consistiría en:
- Se abre el ejecutable
- Un pop-up pide un modo de autenticación:
- Usuario y password
- Anónimo
- Crear cuenta
- Una vez entrado el modo de autenticación, se pide la dificultad y la opción.
- Se carga el juego
- Al finalizar el juego se envían estadísticas. Esto es
- Si ha ganado o perdido
- Tiempo transcurrido
- Dificultad
- Opción
- Usuario jugado
- Modo de autenticación
- Minas marcadas
- Número de clicks
Cada usuario será único. En caso de que el usuario sea anónimo, significa que no está registrado, y por tanto puede ser cualquiera (es decir, dos personas diferentes pueden usar los mismos datos).
De este modo, un usuario registrado tendrá un registro único de estadísticas, mientras que un usuario anónimo puede tener varios registros, estando en el mismo registro físico.
Para registrar un usuario hace falta un nick, un nombre, apellidos, correo electrónico y un password. Para un usuario anónimo se pedirá un nick.
Esta es la especificación de requerimientos, en un modo textual. De este texto se puede extraer toda la información necesaria para crear la base de datos. Toda la información ha sido destacada de la siguiente manera:
Los nombres de tablas están en azul y negrita
Los nombres de campos están en verde y negrita
Se puede apreciar a simple vista que el futuro modelo Entidad - Relación será pequeño. Pero esto no quiere decir que se pueda hacer a la ligera.
Tenemos que proceder siempre con cautela y cuidado, para intentar cometer siempre el mínimo número de errores.
Estas medidas pueden parecer inútiles y contraproducentes, pero es todo lo contrario; es preferible estar seis u ocho horas analizando un problema y luego dos horas programando que empezar a programar y luego parchear todo a base de debug. Además, el analizar las cosas nos proporciona una vista más amplia del problema y nos permite subdividirlo de manera que las funciones y clases que hagamos serán realmente útiles.
Después de esta pequeña reflexión, voy a preparar la siguiente entrada. De momento lo dejamos aquí.
¡Hasta la próxima!
A buscar M!nas: MSAccess - preámbulo
Buenas de nuevo!
Como os dije, empezamos el tema de MSAccess.
La idea es crear una pequeña base de datos para mejorar la experiencia de juego de nuestro recién creado juego.
A diferencia de la primera parte, a partir de este punto yo no tengo nada hecho, así que iré haciendo las cosas sobre la marcha.
El planning para estas entradas es el siguiente:
MSAccess
Como os dije, empezamos el tema de MSAccess.
La idea es crear una pequeña base de datos para mejorar la experiencia de juego de nuestro recién creado juego.
A diferencia de la primera parte, a partir de este punto yo no tengo nada hecho, así que iré haciendo las cosas sobre la marcha.
El planning para estas entradas es el siguiente:
MSAccess
- Análisis
- Requerimientos (textual)
- Modelo entidad - relación
- Diseño
- Modelo relacional
- PRETECAR
- PRETECAR 1
- PRETECAR 2
- RETECAR
- RETECAR 1
- RETECAR 2
- RETECAR 3
- RETECAR 4
- RETECAR 5
- RETECAR 6
- RETECAR 7
- Normalización
- Conceptos previos
- Terminología
- Dependencias funcionales
- Normalizando:
- 1FN
- 2FN
- 3FN
- FNBC
- 4FN
- 5FN
- Programación
- SQL
- Ampliando VB.net
- ADO.net
- Diseño de consultas
- Hacer que funcione
- Gestión desde MSAccess
- Diseño de pantallas
- Creando las pantallas
- Update exe (link)
Como véis, en esta serie de entregas me dedicaré también un poco a profundizar más en ciertos conceptos teóricos; no iré tan al meollo de la cuestión. Esto me servirá para poder llevar al día los proyectos (es decir, no tendré que improvisar tanto o estar días y días sin publicar nada) y también me vendrá bien para repasar la teoría del Grado Superior de Desarrollo de Aplicaciones Informáticas.
Una anotación: es posible que aquellos que conozcáis las técnicas de normalización no os suenen de nada las "RETECAR" u otras cosas. Llegado su momento veréis que igual las conocéis con otro nombre... a mí me lo enseñaron así, y así es como os lo quiero enseñar yo a vosotros :-P
En fin... como esta entrada es bastante larga, empezaré con el primer punto en la próxima entrada.
Saludos a todos y...
¡Hasta la próxima!
Varios
Buenas a todos de nuevo!
Esta entrada será un poco de "bypass". Os haré un poco de resumen de las próximas entradas y os comentaré algunas cosas de más.
Primero las novedades; hoy me han comprado el teclado de mis sueños:
Razer Black Widow Elite
Os dejo aquí una imagen de la maravilla.
Un teclado como cualquier otro, podéis pensar... la cosa es que quizás lo parece, pero no.
¿Qué tiene de bueno?
- Sistema de tecleo mecánico: nunca me lo había pasado tan bien tecleando... es totalmente diferente a los teclados convencionales
- Las teclas reaccionan a una fuerza de 50g: solo hace falta eso, un pequeño empujón de 50g para pulsar una tecla. Ahora escribo a la velocidad de la luz (jejeje)
- Teclas iluminadas: ya no tendré que encender la luz para ver las teclas
- Captura macros "On-the-fly": le puedes dar a "grabar", ejecutar un comando de teclas y asignarlo a una tecla. Y ya está!!
- 5 Teclas de función adicional: cuenta con 5 teclas en el lateral. Son 100% configurables (en realidad TODAS las teclas son configurables)
- Acceso a multimedia: puedes poner pause, play, subir y bajar el volumen... desde el teclado.
- Modo gamer: con esta función puedes desactivar la tecla de inicio (a quién no le ha pasado...)
- Plugs de audio, micro y USB en el lateral: pues eso... me he quedado a cuadros!
El único "inconveniente" es que el layer es el estándar de USA, por lo que no tengo el carácter ">", pero lo he asignado a una tecla de función :-P.
En fin... desde aquí darle las gracias a mi chica ( <3) por regalármelo.
Más novedades: he visto (por mediafire y google analytics) que la gente empieza a seguir mi blog, incluso se descarga los archivos que subo... ha sido una MUY MUY GRATA sorpresa verlo.
Desde este rincón de mi casa (de donde os escribo siempre) me gustaría agradeceros a todos los que habéis visto alguna entrada de mi blog, o lo seguís.
Bien bien bien... y ahora a por el tema de las próximas entradas. El tema está animado. Tuve una pequeña idea, así que os comento:
Por ahora tenemos visto el tema de crear el juego de las M!nas con VB.net. ¿Qué será lo siguiente? Os dejo una lista de "mini-proyectos" que se verán en próximas entradas para mejorar el juego.
- MSAcces: crearemos una pequeña base de datos con Access para nuestro juego. La idea es poder almacenar usuarios (es decir, emular que hay usuarios "registrados" que juegan y puntúan).
Sobre estos usuarios guardaremos muy poca información personal: un email, nombre, nick y password.
El tema está en que haremos estadísticas globales sobre el juego (mejores jugadores, tiempos por nivel, porcentaje de aciertos/fallos...) y también haremos una utilidad que permita seleccionar imágenes personales para cada usuario.
- COBOL: le sacaremos jugo al mini-curso de COBOL, y trasladaremos la base de datos a ficheros COBOL. Esto le dará mucho más rendimiento al juego a la hora de tratar datos, y servirá de refuerzo para nuestras lecciones de COBOL.
- PHP: intentaré coger un pequeño hosting (de esos gratuitos) y haré un pequeño portal web. Ahí subiré el ejecutable completo, para que lo descarguéis. También tendrá un portal de acceso para usuarios registrados (ya no estarán en la base de datos de manera local) con sus típicas opciones; modificar datos, conectar con FB, ver los mejores jugones, galería de imágenes...
Como veis, es un proyecto ambicioso, ya que no se basa solo en el típico "vamos a hacer un programa", sino que lo haremos evolucionar.
Cómo se distribuirá cada apartado es algo que todavía no he terminado. Desde luego, antes de cada lote de entradas haré una entrada de "bypass" (como esta) para introducir a la siguiente fase.
Espero que el planning sea de vuestro agrado. Recordad que siempre podéis dejar comentarios para cualquier duda o sugerencia.
Y, una vez más, y como digo siempre...
¡Hasta la próxima!
Esta entrada será un poco de "bypass". Os haré un poco de resumen de las próximas entradas y os comentaré algunas cosas de más.
Primero las novedades; hoy me han comprado el teclado de mis sueños:
Razer Black Widow Elite
Os dejo aquí una imagen de la maravilla.
Mi nuevo teclado |
¿Qué tiene de bueno?
- Sistema de tecleo mecánico: nunca me lo había pasado tan bien tecleando... es totalmente diferente a los teclados convencionales
- Las teclas reaccionan a una fuerza de 50g: solo hace falta eso, un pequeño empujón de 50g para pulsar una tecla. Ahora escribo a la velocidad de la luz (jejeje)
- Teclas iluminadas: ya no tendré que encender la luz para ver las teclas
- Captura macros "On-the-fly": le puedes dar a "grabar", ejecutar un comando de teclas y asignarlo a una tecla. Y ya está!!
- 5 Teclas de función adicional: cuenta con 5 teclas en el lateral. Son 100% configurables (en realidad TODAS las teclas son configurables)
- Acceso a multimedia: puedes poner pause, play, subir y bajar el volumen... desde el teclado.
- Modo gamer: con esta función puedes desactivar la tecla de inicio (a quién no le ha pasado...)
- Plugs de audio, micro y USB en el lateral: pues eso... me he quedado a cuadros!
El único "inconveniente" es que el layer es el estándar de USA, por lo que no tengo el carácter ">", pero lo he asignado a una tecla de función :-P.
En fin... desde aquí darle las gracias a mi chica ( <3) por regalármelo.
Más novedades: he visto (por mediafire y google analytics) que la gente empieza a seguir mi blog, incluso se descarga los archivos que subo... ha sido una MUY MUY GRATA sorpresa verlo.
Desde este rincón de mi casa (de donde os escribo siempre) me gustaría agradeceros a todos los que habéis visto alguna entrada de mi blog, o lo seguís.
Bien bien bien... y ahora a por el tema de las próximas entradas. El tema está animado. Tuve una pequeña idea, así que os comento:
Por ahora tenemos visto el tema de crear el juego de las M!nas con VB.net. ¿Qué será lo siguiente? Os dejo una lista de "mini-proyectos" que se verán en próximas entradas para mejorar el juego.
- MSAcces: crearemos una pequeña base de datos con Access para nuestro juego. La idea es poder almacenar usuarios (es decir, emular que hay usuarios "registrados" que juegan y puntúan).
Sobre estos usuarios guardaremos muy poca información personal: un email, nombre, nick y password.
El tema está en que haremos estadísticas globales sobre el juego (mejores jugadores, tiempos por nivel, porcentaje de aciertos/fallos...) y también haremos una utilidad que permita seleccionar imágenes personales para cada usuario.
- COBOL: le sacaremos jugo al mini-curso de COBOL, y trasladaremos la base de datos a ficheros COBOL. Esto le dará mucho más rendimiento al juego a la hora de tratar datos, y servirá de refuerzo para nuestras lecciones de COBOL.
- PHP: intentaré coger un pequeño hosting (de esos gratuitos) y haré un pequeño portal web. Ahí subiré el ejecutable completo, para que lo descarguéis. También tendrá un portal de acceso para usuarios registrados (ya no estarán en la base de datos de manera local) con sus típicas opciones; modificar datos, conectar con FB, ver los mejores jugones, galería de imágenes...
Como veis, es un proyecto ambicioso, ya que no se basa solo en el típico "vamos a hacer un programa", sino que lo haremos evolucionar.
Cómo se distribuirá cada apartado es algo que todavía no he terminado. Desde luego, antes de cada lote de entradas haré una entrada de "bypass" (como esta) para introducir a la siguiente fase.
Espero que el planning sea de vuestro agrado. Recordad que siempre podéis dejar comentarios para cualquier duda o sugerencia.
Y, una vez más, y como digo siempre...
¡Hasta la próxima!
A buscar M!nas: programación
Buenas!
Entramos en la recta final de la parte de VB.net; en esta entrada programaremos "a saco". Al final de ésta os dejaré un link para que podáis bajaros el proyecto y probar.
Os dejaré el código sin más. Este código es la "traducción" de los algoritmos previamente explicados con pseudo-código (hay un par de modificaciones, pero son poca cosa).
Dividiré los bloques por archivos, para que se lea un poco mejor.
BuscaminaX.vb
Diff.vb
Global_var.vb
BX_module.vb
Con esto queda plasmado todo el código respectivo al proyecto de VB.net
Os dejo un link de descarga para el proyecto completo. Recordad leer el "LEEME.TXT", y si compartís el paquete recordad ser buenos y citar el post original (este) y/o su autor orignial (yo).
http://www.mediafire.com/?8y7d8old8blrxh2
La próxima serie de entradas se basarán en una serie de ampliaciones del proyecto, usando MSAccess (por ahora...).
Saludos, y
¡Hasta la próxima!
Entramos en la recta final de la parte de VB.net; en esta entrada programaremos "a saco". Al final de ésta os dejaré un link para que podáis bajaros el proyecto y probar.
Os dejaré el código sin más. Este código es la "traducción" de los algoritmos previamente explicados con pseudo-código (hay un par de modificaciones, pero son poca cosa).
Dividiré los bloques por archivos, para que se lea un poco mejor.
BuscaminaX.vb
Public Class BuscaminaX
Public time As Integer
Private Sub BuscaminaX_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Diff.ShowDialog()
If Global_Var.getGen.Equals(0) Then
Me.Close()
Else
BX_module.Cargar()
BX_module.Dibujar()
Me.Timer1.Enabled = True
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Application.DoEvents()
Me.time += 1
Me.ToolStripStatusLabel1.Text = "Time: " + Me.time.ToString()
Me.ToolStripStatusLabel2.Text = "Mines: " + BX_module.minas.ToString()
End Sub
End Class
Public time As Integer
Private Sub BuscaminaX_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Diff.ShowDialog()
If Global_Var.getGen.Equals(0) Then
Me.Close()
Else
BX_module.Cargar()
BX_module.Dibujar()
Me.Timer1.Enabled = True
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Application.DoEvents()
Me.time += 1
Me.ToolStripStatusLabel1.Text = "Time: " + Me.time.ToString()
Me.ToolStripStatusLabel2.Text = "Mines: " + BX_module.minas.ToString()
End Sub
End Class
Diff.vb
Public NotInheritable Class Diff
Private Sub Diff_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.Button1.Enabled = False
End Sub
Private Sub RadioButton1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton1.CheckedChanged, RadioButton2.CheckedChanged, _
RadioButton3.CheckedChanged, RadioButton4.CheckedChanged, _
RadioButton5.CheckedChanged
Dim en As Boolean = False
If (Me.RadioButton1.Checked Or Me.RadioButton2.Checked) And _
(Me.RadioButton3.Checked Or Me.RadioButton4.Checked Or Me.RadioButton5.Checked) Then
en = True
End If
Me.Button1.Enabled = en
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim gen As Integer = 1
Dim dif As Integer = 0
If Me.RadioButton2.Checked Then
gen = 2
End If
If Me.RadioButton4.Checked Then
dif = 1
ElseIf Me.RadioButton5.Checked Then
dif = 2
End If
Global_Var.setDif(dif)
Global_Var.setGen(gen)
Me.Close()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.Close()
End Sub
End Class
Private Sub Diff_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.Button1.Enabled = False
End Sub
Private Sub RadioButton1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton1.CheckedChanged, RadioButton2.CheckedChanged, _
RadioButton3.CheckedChanged, RadioButton4.CheckedChanged, _
RadioButton5.CheckedChanged
Dim en As Boolean = False
If (Me.RadioButton1.Checked Or Me.RadioButton2.Checked) And _
(Me.RadioButton3.Checked Or Me.RadioButton4.Checked Or Me.RadioButton5.Checked) Then
en = True
End If
Me.Button1.Enabled = en
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim gen As Integer = 1
Dim dif As Integer = 0
If Me.RadioButton2.Checked Then
gen = 2
End If
If Me.RadioButton4.Checked Then
dif = 1
ElseIf Me.RadioButton5.Checked Then
dif = 2
End If
Global_Var.setDif(dif)
Global_Var.setGen(gen)
Me.Close()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.Close()
End Sub
End Class
Global_var.vb
Module Global_Var
Private dif As Integer
Private gen As Integer
Private min As Integer
Private anc As Integer
Private alt As Integer
Private img As Integer
Private anB As Double
Private alB As Double
Private fil As Integer
Private col As Integer
Private pos(99) As Integer
Private coM() As Integer
Private imF As Image
Public Sub setDif(ByVal pDif As Integer)
dif = pDif
End Sub
Public Sub setGen(ByVal pGen As Integer)
gen = pGen
End Sub
Public Sub setMin(ByVal pMin As Integer)
min = pMin
End Sub
Public Sub setAnc(ByVal pAnc As Integer)
anc = pAnc
End Sub
Public Sub setAlt(ByVal pAlt As Integer)
alt = pAlt
End Sub
Public Sub setImg(ByVal pImg As Integer)
img = pImg
End Sub
Public Sub setAnB(ByVal pAnB As Double)
anB = pAnB
End Sub
Public Sub setAlB(ByVal pAlB As Double)
alB = pAlB
End Sub
Public Sub setFil(ByVal pFil As Integer)
fil = pFil
End Sub
Public Sub setCol(ByVal pCol As Integer)
col = pCol
End Sub
Public Sub setPos(ByVal pPos() As Integer)
pos = pPos
End Sub
Public Sub setCoM(ByVal pCoM() As Integer)
coM = pCoM
End Sub
Public Sub setImF(ByVal pImF As Image)
imF = pImF
End Sub
Public Function getDif() As Integer
Return dif
End Function
Public Function getGen() As Integer
Return gen
End Function
Public Function getMin() As Integer
Return min
End Function
Public Function getAnc() As Integer
Return anc
End Function
Public Function getAlt() As Integer
Return alt
End Function
Public Function getImg() As Integer
Return img
End Function
Public Function getAnB() As Double
Return anB
End Function
Public Function getAlB() As Double
Return alB
End Function
Public Function getFil() As Integer
Return fil
End Function
Public Function getCol() As Integer
Return col
End Function
Public Function getPos() As Integer()
Return pos
End Function
Public Function getCoM() As Integer()
Return coM
End Function
Public Function getImF() As Image
Return imF
End Function
End Module
Private dif As Integer
Private gen As Integer
Private min As Integer
Private anc As Integer
Private alt As Integer
Private img As Integer
Private anB As Double
Private alB As Double
Private fil As Integer
Private col As Integer
Private pos(99) As Integer
Private coM() As Integer
Private imF As Image
Public Sub setDif(ByVal pDif As Integer)
dif = pDif
End Sub
Public Sub setGen(ByVal pGen As Integer)
gen = pGen
End Sub
Public Sub setMin(ByVal pMin As Integer)
min = pMin
End Sub
Public Sub setAnc(ByVal pAnc As Integer)
anc = pAnc
End Sub
Public Sub setAlt(ByVal pAlt As Integer)
alt = pAlt
End Sub
Public Sub setImg(ByVal pImg As Integer)
img = pImg
End Sub
Public Sub setAnB(ByVal pAnB As Double)
anB = pAnB
End Sub
Public Sub setAlB(ByVal pAlB As Double)
alB = pAlB
End Sub
Public Sub setFil(ByVal pFil As Integer)
fil = pFil
End Sub
Public Sub setCol(ByVal pCol As Integer)
col = pCol
End Sub
Public Sub setPos(ByVal pPos() As Integer)
pos = pPos
End Sub
Public Sub setCoM(ByVal pCoM() As Integer)
coM = pCoM
End Sub
Public Sub setImF(ByVal pImF As Image)
imF = pImF
End Sub
Public Function getDif() As Integer
Return dif
End Function
Public Function getGen() As Integer
Return gen
End Function
Public Function getMin() As Integer
Return min
End Function
Public Function getAnc() As Integer
Return anc
End Function
Public Function getAlt() As Integer
Return alt
End Function
Public Function getImg() As Integer
Return img
End Function
Public Function getAnB() As Double
Return anB
End Function
Public Function getAlB() As Double
Return alB
End Function
Public Function getFil() As Integer
Return fil
End Function
Public Function getCol() As Integer
Return col
End Function
Public Function getPos() As Integer()
Return pos
End Function
Public Function getCoM() As Integer()
Return coM
End Function
Public Function getImF() As Image
Return imF
End Function
End Module
BX_module.vb
Imports System.IO
Module BX_module
Public minas As Integer
Private cuadros As Integer
Public Sub Cargar()
Dim min As Integer = 10
Dim fil As Integer = 9
Dim col As Integer = 9
Dim anc As Integer
Dim alt As Integer
Dim img As Integer
Dim anB As Double
Dim alB As Double
Dim pos(99) As Integer
Dim res() As Integer
Dim imF As Image
Dim Random As New Random()
img = Random.Next(0, 12)
If Global_Var.getGen = 2 Then
img += 12
End If
imF = Image.FromFile(Application.StartupPath.ToString + "\BX_IMG\BX_" + img.ToString + ".jpg")
anc = imF.Width
alt = imF.Height
If Global_Var.getDif = 1 Then
min = 40
fil = 16
col = 16
ElseIf Global_Var.getDif = 2 Then
min = 99
fil = 16
col = 30
End If
anB = anc / col
alB = alt / fil
pos = LlenarMinas(fil * col, min)
res = ComprobarMinas(fil * col, col, pos, min)
minas = min
cuadros = (fil * col) - min
Global_Var.setMin(min)
Global_Var.setFil(fil)
Global_Var.setCol(col)
Global_Var.setAnc(anc)
Global_Var.setAlt(alt)
Global_Var.setImg(img)
Global_Var.setAnB(anB)
Global_Var.setAlB(alB)
Global_Var.setPos(pos)
Global_Var.setImF(imF)
Global_Var.setCoM(res)
End Sub
Private Function LlenarMinas(ByVal max As Integer, ByVal min As Integer) As Integer()
Dim pos(99) As Integer
Dim num As Integer
Dim pass As Boolean
Dim Random As New Random()
For i = 0 To min - 1
pass = True
num = Random.Next(0, max + 1)
For j = 0 To pos.Length - 1
If pos(j) = num Then
pass = False
End If
Next
If pass Then
pos(i) = num
Else
i -= 1
End If
Next
Return pos
End Function
Private Function ComprobarMinas(ByVal max As Integer, ByVal col As Integer, ByVal pos() As Integer, ByVal min As Integer) As Integer()
Dim ret(max) As Integer
For i = 0 To max - 1
Dim num As Integer
For j = 0 To min - 1
If i Mod col = 0 Then
If pos(j) = i - col Or pos(j) = i - (col - 1) Or _
pos(j) = i + 1 Or _
pos(j) = i + col Or pos(j) = i + (col + 1) Then
num += 1
ElseIf pos(j) = i Then
num = 10
Exit For
End If
ElseIf i Mod col = col - 1 Then
If pos(j) = i - (col + 1) Or pos(j) = i - col Or _
pos(j) = i - 1 Or _
pos(j) = i + (col - 1) Or pos(j) = i + col Then
num += 1
ElseIf pos(j) = i Then
num = 10
Exit For
End If
Else
If pos(j) = i - (col + 1) Or pos(j) = i - col Or pos(j) = i - (col - 1) Or _
pos(j) = i - 1 Or pos(j) = i + 1 Or _
pos(j) = i + (col - 1) Or pos(j) = i + col Or pos(j) = i + (col + 1) Then
num += 1
ElseIf pos(j) = i Then
num = 10
Exit For
End If
End If
Next
ret(i) = num
num = 0
Next
Return ret
End Function
Public Sub Dibujar()
Dim max As Integer = Global_Var.getFil() * Global_Var.getCol()
Dim t As Double = 0
Dim l As Double = 0
Dim h As Double = Global_Var.getAlB
Dim w As Double = Global_Var.getAnB
Dim c As Integer = Global_Var.getCol
Dim f As Integer = Global_Var.getFil
Dim o As Label
Dim p As Button
Dim con(max * 2) As Control
For i = 0 To max - 1
o = New Label()
p = New Button()
o.Top = t
o.Left = l
o.Height = h
o.Width = w
o.Name = "L" + i.ToString
o.Visible = True
o.BackColor = Color.Transparent
o.Font = New Font("Times new Roman", 10, FontStyle.Regular, GraphicsUnit.Pixel)
p.Top = t
p.Left = l
p.Height = h
p.Width = w
p.Name = "B" + i.ToString
p.Visible = True
AddHandler p.MouseDown, AddressOf p_click
AddHandler o.MouseEnter, AddressOf o_mouseEnter
AddHandler o.MouseLeave, AddressOf o_mouseLeave
con(i) = p
con(i + max) = o
If i Mod c = c - 1 Then
l = 0
t += h
Else
l += w
End If
Next
BuscaminaX.Controls.AddRange(con)
BuscaminaX.Height = Global_Var.getAlt() + 57
BuscaminaX.Width = Global_Var.getAnc() + 13
BuscaminaX.MaximumSize = BuscaminaX.Size
BuscaminaX.MinimumSize = BuscaminaX.Size
BuscaminaX.BackgroundImage = Global_Var.getImF()
BuscaminaX.ToolStripStatusLabel1.Text = Global_Var.getMin.ToString
End Sub
Private Sub p_click(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If e.Button = MouseButtons.Left Then
cuadros -= 1
If cuadros = 0 Then
MsgBox("Has ganado")
BuscaminaX.Controls.Clear()
End If
sender.Visible = False
If Global_Var.getCoM()(sender.name.SubString(1)) = 10 Then
MsgBox("PUM!")
Fail.ShowDialog()
End If
ElseIf e.Button = MouseButtons.Right Then
If sender.text.Equals("X") Then
sender.text = ""
sender.backColor = Color.WhiteSmoke
minas += 1
Else
sender.Text = "X"
sender.backColor = Color.Red
minas -= 1
End If
BuscaminaX.ToolStripStatusLabel1.Text = "Time: " + BuscaminaX.time.ToString()
BuscaminaX.ToolStripStatusLabel2.Text = "Mines: " + minas.ToString()
End If
End Sub
Private Sub o_mouseEnter(ByVal sender As Object, ByVal e As System.EventArgs)
sender.BackColor = Color.White
sender.text = Global_Var.getCoM()(sender.name.SubString(1))
End Sub
Private Sub o_mouseLeave(ByVal sender As Object, ByVal e As System.EventArgs)
sender.text = ""
sender.backcolor = Color.Transparent
End Sub
End Module
Module BX_module
Public minas As Integer
Private cuadros As Integer
Public Sub Cargar()
Dim min As Integer = 10
Dim fil As Integer = 9
Dim col As Integer = 9
Dim anc As Integer
Dim alt As Integer
Dim img As Integer
Dim anB As Double
Dim alB As Double
Dim pos(99) As Integer
Dim res() As Integer
Dim imF As Image
Dim Random As New Random()
img = Random.Next(0, 12)
If Global_Var.getGen = 2 Then
img += 12
End If
imF = Image.FromFile(Application.StartupPath.ToString + "\BX_IMG\BX_" + img.ToString + ".jpg")
anc = imF.Width
alt = imF.Height
If Global_Var.getDif = 1 Then
min = 40
fil = 16
col = 16
ElseIf Global_Var.getDif = 2 Then
min = 99
fil = 16
col = 30
End If
anB = anc / col
alB = alt / fil
pos = LlenarMinas(fil * col, min)
res = ComprobarMinas(fil * col, col, pos, min)
minas = min
cuadros = (fil * col) - min
Global_Var.setMin(min)
Global_Var.setFil(fil)
Global_Var.setCol(col)
Global_Var.setAnc(anc)
Global_Var.setAlt(alt)
Global_Var.setImg(img)
Global_Var.setAnB(anB)
Global_Var.setAlB(alB)
Global_Var.setPos(pos)
Global_Var.setImF(imF)
Global_Var.setCoM(res)
End Sub
Private Function LlenarMinas(ByVal max As Integer, ByVal min As Integer) As Integer()
Dim pos(99) As Integer
Dim num As Integer
Dim pass As Boolean
Dim Random As New Random()
For i = 0 To min - 1
pass = True
num = Random.Next(0, max + 1)
For j = 0 To pos.Length - 1
If pos(j) = num Then
pass = False
End If
Next
If pass Then
pos(i) = num
Else
i -= 1
End If
Next
Return pos
End Function
Private Function ComprobarMinas(ByVal max As Integer, ByVal col As Integer, ByVal pos() As Integer, ByVal min As Integer) As Integer()
Dim ret(max) As Integer
For i = 0 To max - 1
Dim num As Integer
For j = 0 To min - 1
If i Mod col = 0 Then
If pos(j) = i - col Or pos(j) = i - (col - 1) Or _
pos(j) = i + 1 Or _
pos(j) = i + col Or pos(j) = i + (col + 1) Then
num += 1
ElseIf pos(j) = i Then
num = 10
Exit For
End If
ElseIf i Mod col = col - 1 Then
If pos(j) = i - (col + 1) Or pos(j) = i - col Or _
pos(j) = i - 1 Or _
pos(j) = i + (col - 1) Or pos(j) = i + col Then
num += 1
ElseIf pos(j) = i Then
num = 10
Exit For
End If
Else
If pos(j) = i - (col + 1) Or pos(j) = i - col Or pos(j) = i - (col - 1) Or _
pos(j) = i - 1 Or pos(j) = i + 1 Or _
pos(j) = i + (col - 1) Or pos(j) = i + col Or pos(j) = i + (col + 1) Then
num += 1
ElseIf pos(j) = i Then
num = 10
Exit For
End If
End If
Next
ret(i) = num
num = 0
Next
Return ret
End Function
Public Sub Dibujar()
Dim max As Integer = Global_Var.getFil() * Global_Var.getCol()
Dim t As Double = 0
Dim l As Double = 0
Dim h As Double = Global_Var.getAlB
Dim w As Double = Global_Var.getAnB
Dim c As Integer = Global_Var.getCol
Dim f As Integer = Global_Var.getFil
Dim o As Label
Dim p As Button
Dim con(max * 2) As Control
For i = 0 To max - 1
o = New Label()
p = New Button()
o.Top = t
o.Left = l
o.Height = h
o.Width = w
o.Name = "L" + i.ToString
o.Visible = True
o.BackColor = Color.Transparent
o.Font = New Font("Times new Roman", 10, FontStyle.Regular, GraphicsUnit.Pixel)
p.Top = t
p.Left = l
p.Height = h
p.Width = w
p.Name = "B" + i.ToString
p.Visible = True
AddHandler p.MouseDown, AddressOf p_click
AddHandler o.MouseEnter, AddressOf o_mouseEnter
AddHandler o.MouseLeave, AddressOf o_mouseLeave
con(i) = p
con(i + max) = o
If i Mod c = c - 1 Then
l = 0
t += h
Else
l += w
End If
Next
BuscaminaX.Controls.AddRange(con)
BuscaminaX.Height = Global_Var.getAlt() + 57
BuscaminaX.Width = Global_Var.getAnc() + 13
BuscaminaX.MaximumSize = BuscaminaX.Size
BuscaminaX.MinimumSize = BuscaminaX.Size
BuscaminaX.BackgroundImage = Global_Var.getImF()
BuscaminaX.ToolStripStatusLabel1.Text = Global_Var.getMin.ToString
End Sub
Private Sub p_click(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If e.Button = MouseButtons.Left Then
cuadros -= 1
If cuadros = 0 Then
MsgBox("Has ganado")
BuscaminaX.Controls.Clear()
End If
sender.Visible = False
If Global_Var.getCoM()(sender.name.SubString(1)) = 10 Then
MsgBox("PUM!")
Fail.ShowDialog()
End If
ElseIf e.Button = MouseButtons.Right Then
If sender.text.Equals("X") Then
sender.text = ""
sender.backColor = Color.WhiteSmoke
minas += 1
Else
sender.Text = "X"
sender.backColor = Color.Red
minas -= 1
End If
BuscaminaX.ToolStripStatusLabel1.Text = "Time: " + BuscaminaX.time.ToString()
BuscaminaX.ToolStripStatusLabel2.Text = "Mines: " + minas.ToString()
End If
End Sub
Private Sub o_mouseEnter(ByVal sender As Object, ByVal e As System.EventArgs)
sender.BackColor = Color.White
sender.text = Global_Var.getCoM()(sender.name.SubString(1))
End Sub
Private Sub o_mouseLeave(ByVal sender As Object, ByVal e As System.EventArgs)
sender.text = ""
sender.backcolor = Color.Transparent
End Sub
End Module
Con esto queda plasmado todo el código respectivo al proyecto de VB.net
Os dejo un link de descarga para el proyecto completo. Recordad leer el "LEEME.TXT", y si compartís el paquete recordad ser buenos y citar el post original (este) y/o su autor orignial (yo).
http://www.mediafire.com/?8y7d8old8blrxh2
La próxima serie de entradas se basarán en una serie de ampliaciones del proyecto, usando MSAccess (por ahora...).
Saludos, y
¡Hasta la próxima!
Suscribirse a:
Entradas (Atom)