Cuatro en Línea

C/C++ GTK Proyecto



Especificaciones

  • Año: 2015
  • Categoría: Juegos
  • Interfaz Gráfica: Sí (GTK)
  • Lenguaje: C/C++
  • Plataforma: Linux

Enlaces

  • Código fuente en Github.
  • Archivo .exe de este proyecto.

Solicitud

Manteniendo los principios y fundamentos de los Sistemas de Operación, se pide realizar una aplicación que permita la interacción entre procesos a través de la implementación y desarrollo del juego "cuatro en línea", con modificaciones propias para la asignatura, para lo cual su nombre cambiará y se llamará “CuatroPID en Línea”. Los objetivos del proyecto son:

  • Familiarizarse con el ambiente Linux/Unix para la implementación de programas de bajo nivel realizados en C/C++.

  • Hacer uso de las sentencias fork, wait, waitpid, entre otras. Para la administración y/o generación de procesos.

  • Familiarizarse con la biblioteca multiplataforma QT, Gtk las cuales son ampliamente usadas para desarrollar aplicaciones con interfaz gráfica de usuario.

Reglas del Juego

El objetivo del Juego es alinear cuatro fichas sobre un tablero formado por seis (06) filas y siete (07) columnas. Cada jugador dispone de 21 fichas de un color (por lo general, rojas o amarillas). Por turnos, los jugadores deben introducir una ficha en la columna que prefieran (siempre que no esté completa) y ésta caerá a la posición más baja. Gana la partida el primero que consiga alinear cuatro fichas consecutivas de un mismo color en horizontal, vertical o diagonal. Si todas las columnas están llenas pero nadie ha hecho una fila válida, hay empate.

Este es un juego de estrategia abstracta donde los contrincantes disponen de información perfecta. Por norma general, el primer jugador tiene más posibilidades de ganar si introduce la primera ficha en la columna central. Si lo hace en las contiguas se puede forzar un empate, mientras que si la mete en las más alejadas del centro su rival puede vencerle con más facilidad.

Términos Asociados

  • Proceso Tablero
  • Proceso Marco
  • Proceso Bola

Aspectos Técnicos

El presente proyecto debe cumplir los siguientes lineamientos o requerimientos:

  • La ejecución del juego deberá realizarse mediante la personalización de un comando de GNU/Linux creado por el grupo y como parámetros ya en la interfaz gráfica, se deberá de solicitar la cantidad de filas y posteriormente la cantidad de columnas – parámetro calculado - (en ese respectivo orden). Por ejemplo:

    usuario@Debian: ~ $ cuatropenlinea

    Es importante tener en cuenta que el número de filas solo admitirá valores pares y el valor de las columnas será un parámetro calculado cuyo valor es:

    No Columnas = No filas + 1

    Donde: No Filas admitirá como valor mínimo cinco (05). Por estándar el tamaño del tablero es seis (6) x siete (7).

  • El juego iniciará mediante un sorteo entre los dos (02) jugadores para saber quien inicia.

  • El tablero será el proceso padre y los procesos bolas serán hijos del mismo.

  • Cada “marco de bola” será considerado un proceso hijo del proceso tablero.

  • Cuando una bola se aloje en un “marco de bola” se debe enviar una señal del proceso ‘bola’ al proceso ‘marco’ indicándole el PID del proceso que alojará.

  • Cada vez que se forme una línea (vertical, horizontal o diagonal) se envía una señal al proceso tablero quien deberá mantener la puntuación del juego. (ya que el juego no terminará al formar la primera línea).

  • Cada vez que se forme una línea (vertical, horizontal o diagonal) deberá formarse un nuevo proceso que formará una lista de ‘procesos puntos’ que al finalizar el juego deberán ser eliminados del sistema por parte del proceso padre ó el “proceso tablero”.

  • Cada vez que se forme una línea (vertical, horizontal o diagonal) y se forme el correspondiente ‘proceso punto’ los respectivos ‘marcos de bolas’ deberán eliminar el proceso alojado en cada uno de ellos y dejando caer todas las bolas ubicadas en sus posiciones superiores. Conociéndose dicho movimiento como ‘barrido de bolas’.

  • El juego finalizará una vez no queden ‘marcos de bolas’ disponibles. Por ende la cantidad de bolas por cada color no serán estáticas como ocurre en el juego normalmente.

  • El juego finalizará con la victoria de alguno de los dos (02) contrincantes o con un empate técnico.

  • Se deberá manejar un reloj que permita almacenar los mejores tiempos para formar líneas según su tipo: horizontal, vertical o diagonal. Así como las características que usted considere necesarias.

  • El juego “CuatroPID en Línea” deberá tener varios niveles de dificultad entre ellos: principiante y difícil.

  • El juego “CuatroPID en Línea” deberá tener tres (03) modos de interacción. PC Vs PC, PC Vs Usuario ó Usuario Vs Usuario.

  • Se debe tener un botón que permita reiniciar la partida.

Se desea que Ud. implemente una solución en Lenguaje C/C++ bajo una interfaz agradable (pudiera ser incluso en modo texto) en la Distribución Linux de su preferencia, tomando para ello las siguientes consideraciones o restricciones:

  1. Se deberán usar llamadas al sistema siempre que sea posible.

  2. No está permitido usar la función de biblioteca system.

  3. No se puede suponer que los PIDs de los procesos de una secuencia van a aparecer consecutivos. Puestos que, ni siquiera podemos suponer que estarán ordenados de menor a mayor (puede ocurrir que se agoten los PIDs y retome la cuenta partiendo de cero).

  4. No está permitido el uso de tuberías u otro mecanismo externo para transmitir información entre los procesos, salvo que se indique en el enunciado.

  5. Se tomará en cuenta la facilidad de uso, así como la validación y minimización de errores.

  6. Mientras se ejecuta la corrida del programa, se debe dar la posibilidad al usuario de poner en pausa (standby) la misma, a los fines de verificar la correcta creación de los procesos.

Adicionalmente se debe entregar un informe que describa el análisis, desarrollo y funcionamiento del programa, el mismo debe contener los siguientes puntos:

  • Marco Teórico.
  • Algoritmos Utilizados. Descomposición Modular.
  • Descripción de la Estructura de Datos Utilizada.
  • Especificaciones de Entrada.
  • Especificaciones de Salida.
  • Diccionario de Variables.
  • Tabla de Funciones Definidas.
  • Diagramas UML (Si Aplica).
  • Consideraciones.
  • Restricciones.
  • Conclusiones.

Respuesta

Marco Teórico

Sistema Operativo

Un Sistema Operativo (SO) es el software básico de una computadora que provee una interfaz entre el resto de programas del ordenador, los dispositivos hardware y el usuario.

Las funciones básicas del Sistema Operativo son administrar los recursos de la máquina, coordinar el hardware y organizar archivos y directorios en dispositivos de almacenamiento.

Los Sistemas Operativos más utilizados son Dos, Windows, Linux y Mac. Algunos SO ya vienen con un navegador integrado, como Windows que trae el navegador Internet Explorer.

El sistema operativo es el programa (o software) más importante de un ordenador. Para que funcionen los otros programas, cada ordenador de uso general debe tener un sistema operativo. Los sistemas operativos realizan tareas básicas, tales como reconocimiento de la conexión del teclado, enviar la información a la pantalla, no perder de vista archivos y directorios en el disco, y controlar los dispositivos periféricos tales como impresoras, escáner, etc. 

En sistemas grandes, el sistema operativo tiene incluso mayor responsabilidad y poder, es como un policía de tráfico, se asegura de que los programas y usuarios que están funcionando al mismo tiempo no interfieran entre ellos. El sistema operativo también es responsable de la seguridad, asegurándose de que los usuarios no autorizados no tengan acceso al sistema.

Procesos

Un proceso de unix es cualquier programa en ejecución y es totalmente independiente de otros procesos. El comando de unix ps nos lista los procesos en ejecución en nuestra máquina. Un proceso tiene su propia zona de memoria y se ejecuta "simultáneamente" a otros procesos. Es totalmente imposible en unix que un proceso se meta, a posta o por equivocación, en la zona de memoria de otro proceso. Esta es una de las características que hace de unix un sistema fiable. Un programa chapucero o malintencionado no puede fastidiar otros programas en ejecución ni mucho menos a los del sistema operativo. Si el programa chapucero se cae, se cae sólo él.

Dentro de un proceso puede haber varios hilos de ejecución (varios threads). Eso quiere decir que un proceso podría estar haciendo varias cosas "a la vez". Los hilos dentro de un proceso comparten todos la misma memoria. Eso quiere decir que si un hilo toca una variable, todos los demás hilos del mismo proceso verán el nuevo valor de la variable.

Un proceso es, por tanto, más costoso de lanzar, ya que se necesita crear una copia de toda la memoria de nuestro programa. Los hilos son más ligeros.

Señales

Una señal es un "aviso" que puede enviar un proceso a otro proceso. El sistema operativo unix se encarga de que el proceso que recibe la señal la trate inmediatamente. De hecho, termina la línea de código que esté ejecutando y salta a la función de tratamiento de señales adecuada. Cuando termina de ejecutar esa función de tratamiento de señales, continúa con la ejecución en la línea de código donde lo había dibujado.

El sistema operativo envía señales a los procesos en determinadas circunstancias.

Las señales van identificadas por un número entero.

Memoria Compartida

La memoria compartida es un recurso compartido que pone unix a disposición de los programas para que puedan intercambiarse información.

En C para unix es posible hacer que dos procesos (dos programas) distintos sean capaces de compartir una zona de memoria común y, de esta manera, puede ser accedida por múltiples programas, ya sea para comunicarse entre ellos o para evitar copias redundantes. La memoria compartida es un modo eficaz de pasar datos entre aplicaciones. Dependiendo del contexto, los programas pueden ejecutarse en un mismo procesador o en procesadores separados.

Algoritmos Utilizados

Al ejecutar el programa se debe pasar como parámetro la cantidad de filas del tablero (solo se admiten valores pares y que sean mayores a 5 y menores a 13), en caso de no pasarse este parámetro la cantidad de filas por defecto será igual a 6, cabe destacar que la cantidad de filas puede cambiarse en la ventana principal. La cantidad de columnas serán iguales a la cantidad de filas +1.

Una vez hecho esto se le mostrara al usuario una ventana con varias opciones a elegir modo de juego, dificultad y número de filas.

El modo de juego tiene 3 opciones J1 VS J2 (Jugador VS Jugador), J1 VS PC (Jugador VS Maquina), PC VS PC (Maquina).

En caso de elegir el modo de juego J1 VS PC (Jugador VS Maquina) o PC VS PC (Maquina) se le permitirá a el usuario escoger la dificultad fácil o difícil. En fácil la maquina jugara siempre de forma aleatoria, y si escoge difícil la maquina jugara de forma aleatoria hasta que vea 3 bolas de mismo color que sean adyacentes en esta caso jugara al lado (si es del mismo color lograra 4 en línea y sino bloqueara la jugada de su contrincante) de estas ya sea horizontal, vertical o diagonal.

El tablero será el proceso padre y los procesos bolas y marco de bola serán hijos del mismo.

Una vez escogido lo anteriormente mencionado, se le mostrara al jugador una pantalla que incluye el tablero que a su lado izquierdo le mostrara al usuario los puntos que lleva cada jugador, los botones de pausar partida, reiniciar partida y salir de la partida. En el tablero se indicara el número de cada columna y encima de ellas un botón para que sea presionado por el jugador si este desea jugar su bola en esa columna.

El primer turno será escogido de forma aleatoria.

Se le permitirá al jugador pausar y reiniciar la partida. Cabe destacar que de pausar la partida esto no afectara las probabilidades de una jugada de ser escogida como mejor tiempo, ya que el tiempo que el juego este pausado no se cuenta.

Cada vez que jugador escoja una columna a jugar se creara un proceso bola con el color que le corresponde a ese jugador, este proceso bola guardara su pid y color en la memoria compartida a la cual el proceso marco correspondiente accederá para poder guardar los datos (pid y color) del proceso bola.

Cada vez que se hace cuatro en línea se añade se actualiza una lista encargada de guardar los puntos de ambos jugadores. Y los procesos marcos de bola eliminan la información de la bola que alojan (quedando libres) y las bolas que se encuentran arriba de ellas caen.

Una vez el tablero este lleno (Es decir una vez no queden marcos de bolas desocupados) el juego finalizara. Una vez finalizando se mostrará al ganador o empate en caso de suceder. También se mostrarán los mejores tiempos para cada tipo de línea (Vertical, Horizontal, Diagonal Principal o Secundaria).

Estructuras de Datos

CASILLA: representa una casilla del tablero y guarda el pid del marco, el pid de la bola que esta almacenando (es -1 en caso de no estar ocupada por una bola), el color de la bola que lo está ocupado (en caso de estar ocupado es una cadena vacía) y una variable booleana que indica si está ocupada o no.

NODO: lista que se encarga de almacenar los puntos de los dos jugadores, cada vez que se hace un punto se crea otro nodo que guarda la puntuación actualizada.

RECORDS: tiene cuatro variables de tipo reales que se encarga de guardar los mejores tiempos para hacer una línea horizontal, vertical, diagonal principal y diagonal secundaria.

PUNTEROS: contiene punteros a distintas variables que se necesitan pasar a otras funciones.

Especificaciones de Entrada

Número de Filas: se pasa como parámetro del juego, aunque después de entrar en la pantalla inicial se puede cambiar, solo admite número pares y mayores a 5 y menores a 13, en caso de no pasarlo por parámetro se tomara por defecto el valor de 6 filas.

Modo de Juego: hay tres opciones a elegir J1vsPC (Jugador versus Maquina), J1vsJ2 (Jugador versus Jugador), PCvsPC (Máquina versus Máquina). En caso de elegir J1vsPC o PCvsPC habrá que elegir el grado de dificultad (principiante o difícil).

Nivel de Dificultad: como se dijo anteriormente en caso de elegir J1vsPC o PCvsPC habrá que elegir el grado de dificultad (principiante o difícil), esto representa el nivel de dificultad con el que jugara la computadora.

Botón Salir: Botón que se encuentra en la ventana principal y permita al usuario salir del programa.

Botón Columna: en cada columna se encontrara encima un botón que al ser presionado por el usuario jugara la bola en la posición más baja disponible de la misma.

Botón Pausar: Botón que se encuentra del lado izquierdo del tablero, cuando es presionado pausa la partida que se esté jugado en el momento.

Botón Reiniciar: Botón que se encuentra del lado izquierdo del tablero, cuando es presionado vuelve a comenzar la partida (perdiéndose lo que se había jugado anteriormente).

Especificaciones de Salida

Ventana Principal: ventana principal que se le muestra al usuario después de ejecutar el juego. En esta ventana se le permite escoger el modo de juego, dificultad y cambiar el número de filas.

Tablero: ventana en donde transcurre el juego, el usuario llegara en esta ventana se le permita al jugador elegir la columna en donde quiere jugar, se le mostrara también las puntuaciones y le indicara a que jugador le corresponde el turno.

Bolas: cada vez que el jugador escoja una columna se le mostrara la bola bajando hasta la fila más baja de esa columna.

Diccionario de Variables

  • casillaNueva-> inicializarTablero: variable de tipo Casilla que se usa para inicializar las casillas del tablero con valores por defecto.
  • I-> inicializarTablero: variable de tipo entero que se usa en el primer for para representar las filas del tablero.
  • j-> inicializarTablero: variable de tipo entero que se usa en el segundo for para representar las columnas del tablero.
  • pid-> inicializarTablero: variable de tipo entero que representa los pid de cada una de las casillas del tablero.
  • I-> imprimirCasillasvariable de tipo entero que se usa en el primer for para representar las filas del tablero.
  • j-> imprimirCasillas: variable de tipo entero que se usa en el segundo for para representar las columnas del tablero.
  • claveMemoria-> agruparBolaYMarco: variable de tipo key_t representa la clave de la memoria compartida.
  • idMemoria -> agruparBolaYMarco: variable de tipo entero que guarda el id de la memoria compartida.
  • buffer -> agruparBolaYMarco: variable de tipo Casilla que guarda el pid del marco.
  • i-> filaMasBajaLibre: variable de tipo entero que se usa en el for para poder recorrer las filas de una columna.
  • pid-> crearBola: variable de tipo entero que guarda el pid del proceso bola.
  • i-> visualizarTablero: variable de tipo entero que se usa para recorrer las filas del tablero.
  • j-> visualizarTablero: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • x-> visualizarTablero: variable de tipo entero que representa la posición en horizontal de la pantalla.
  • y-> visualizarTablero: variable de tipo entero que representa la posición en vertical de la pantalla.
  • pid-> inicializarPuntos: variable de tipo entero que guarda el pid del proceso de los puntos.
  • pid-> agregarPunto: variable de tipo entero que guarda el pid del proceso de los puntos.
  • i-> barridoDeBolas: variable de tipo entero que se usa para recorrer las filas del tablero.
  • j-> barridoDeBolas: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • faux-> barridoDeBolas: variable de tipo entero que se usa de forma auxiliar para las filas.
  • caux-> barridoDeBolas: variable de tipo entero que se usa de forma auxiliar para las columnas.
  • i->actualizarTiempo: variable de tipo entero que se usa para recorrer la estructura timeval.
  • resultado->actualizarTiempo: variable de tipo entero que guarda el tiempo.
  • i->procesarLineas: variable de tipo entero que se usa para recorrer las filas del tablero.
  • i->procesarLineas: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • fi->procesarLineas: variable de tipo entero se usa para guardar la fila donde comience un 4 en línea.
  • ci->procesarLineas: variable de tipo entero se usa para guardar la columna donde comience un 4 en línea.
  • tipoDeLinea ->procesarLineas: variable de tipo entero que representa el tipo de línea que se hizo (0 = ninguna, 1 = horizontal, 2 = vertical, 3 = diagonal principal y 4 = diagonal secundaria).
  • i-> tableroLleno: variable de tipo entero que se usa para recorrer las filas del tablero.
  • i-> tableroLleno: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • i-> inicializarTiemp: variable de tipo entero que se usa para recorrer la estructura timeval.
  • i-> reiniciar: variable de tipo entero que se usa para recorrer las filas del tablero.
  • i-> t reiniciar: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • i-> G_salir: variable de tipo entero que se usa para recorrer las filas del tablero.
  • i-> G_salir: variable de tipo entero que se usa en el forma para recorrer las columnas del tablero.
  • Buf->itoa: variable de tipo vector de caracteres.
  • i->itoa: variable de tipo vector de enteros.
  • i-> G_inicializarTablero: variable de tipo entero que se usa para recorrer las filas del tablero.
  • i-> G_inicializarTablero: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • color->G_inicializarTablero: variable de tipo GdkColor que representa el color del tablero.
  • i-> columnaATKoDEF: variable de tipo entero que se usa para recorrer las filas del tablero.
  • i-> columnaATKoDEF: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • resultado-> columnaATKoDEF: variable de tipo entero que representa la columna a jugar.
  • i-> G_juegaPC: variable de tipo entero que representa la columna a jugar.
  • i-> G_reiniciar: variable de tipo entero que se usa para recorrer las filas del tablero.
  • j-> G_reiniciar: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • color-> G_reiniciar: variable de tipo GdkColor que representa el color del tablero.
  • i-> G_inicialiarVentana: variable de tipo entero que se usa para recorrer las filas del tablero.
  • j-> G_inicialiarVentana: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • ventana-> G_inicialiarVentana: variable de tipo gtk_window_new.
  • contenedor-> G_inicialiarVentana: variable de tipo gtk_table_new.
  • ventana-> G_configuracionInicial: variable de tipo gtk_window_new.
  • contenedor-> G_configuracionInicial: variable de tipo gtk_table_new.
  • color->G_ponerBola: variable de tipo GdkColor que representa el color del tablero.
  • i-> G_actualizarTablero: variable de tipo entero que se usa para recorrer las filas del tablero.
  • j-> G_actualizarTablero: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • color-> G_actualizarTablero: variable de tipo GdkColor que representa el color del tablero.
  • nombre1->G_actualizarTablero: variable de tipo vector de caracteres.
  • nombre2->G_actualizarTablero: variable de tipo vector de caracteres.
  • columnaAJugar ->manejarJugada: variable de tipo entero que representa la columna que donde se va a poner la bola.
  • filaAJugar ->manejarJugada: variable de tipo entero que representa la fila que donde se va a poner la bola.
  • color->manejarJugada: variable de tipo char representa el color de la bola.
  • i->G_conectarBotonesDeJuego: variable de tipo entero que se usa para recorrer las columnas del tablero.
  • fila->main: variable entera que representa la cantidad de filas de el tablero.
  • columna->main: variable entera que representa la cantidad de filas del tablero.
  • turno->main: variable entera que indica a quien le corresponde el turno.
  • modo->main: variable entera que representa el modo de juego.
  • colorJ1->main: variable entera que representa el color de las bolas del jugador 1.
  • claveMemoria->main: variable de tipo key_t que representa la clave de acceso a la memoria compartida.
  • idMemoria->main: variable de tipo entero que guarda la dirección de la memoria compartida.
  • mejorTiempo->main: variable de tipo Records que guarda los mejores tiempos para cada jugada.
  • inicio->main: variable de tipo timeval.
  • inicio->main: variable de tipo timeval.
  • puntos->main: variable de tipo Nodo que guarda los puntos de cada jugador.
  • ventana->main: variable de tipo GtkWidget.
  • contenedor->main: variable de tipo GtkWidget.
  • hilo->main: variable de tipo pthread_t sirve para crear un hilo.
  • finalizarHilo->main: variable de tipo booleana que indica cuando debe finalizar el hilo.
  • dificultad->main: variable de tipo entera que representa el grado de dificultad.

Funciones Definidas

Funciones Definidas

Nombre

Tipo

Parámetros

Descripción

establecerDimensiones

Booleana

int argc, char **argv, int *fila, int *columna, GtkWidget *cboNroFilas

Dado el número filas calcula el número de columnas a utilizar de la siguiente manera No Columnas = No filas + 1. El número de filas solo puede ser par y no puede ser menor a 5 mayor a 12, de lo contrario retornara falso. Si el número de filas es válido retornara verdadero. Si no se da el número de filas las dimensiones por defecto serán de 6 filas y 7 columnas.

aislar

Vacía

 

Se encarga de pausar o asilar los procesos, con el fin de no saturar el procesador.

inicializarTablero

Vacía

int fila, int columna,Casilla tablero[fila][columna]

Se encarga de llenar el tablero de procesos casilla que después son aislados inmediatamente.

agruparBolaYMarco

Vacía

int pidMarco

Agrupa la bola y al marco a través de la memoria compartida

filaMasBajaLibre

Entera

int fila, int columna, Casilla tablero[fila][columna], int columnaDeseada

Se encarga de buscar la fila más baja libre en una columna del tablero.

imprimirCasillas

Vacía

int fila, int columna,Casilla tablero[fila][columna]

Imprime la información de todas y cada una de las casillas.

liberarBuffer

Vacía

int idMemoria,Casilla *buffer

Se encarga de vaciar la memoria compartida

actualizarTablero

Vacía

int fila, int columna, Casilla tablero[fila][columna], int filaDeseada, int columnaDeseada, Casilla *buffer

Pasa el pid del proceso bola almacenado en la memoria compartida para que sea guardado en el marco

inicializarMemoriaCompartida

Vacía

key_t *claveMemoria, int *idMemoria, Casilla **buffer

Crea la memoria compartida

crearBola

Vacia

int fila, int columna, Casilla tablero[fila][columna], int filaDeseada, int columnaDeseada, Casilla *buffer, char color

Crea un proceso bola y guarda su pid en la memoria compartida para después ser aislado

clrscr

Vacía

 

Limpia la pantalla

gotoxy

Vacía

int x,int y

Permite escribir en un lugar determinado de la pantalla

visualizarTablero

Vacía

int fila, int columna, Casilla tablero[fila][columna]

Permite visualizar el tablero en modo consola

inicializarPuntos

Vacía

Nodo **puntos

Inicializa los puntos de ambos jugadores en 0

agregarPunto

Vacía

int puntoParaJ1, int puntoParaJ2, Nodo **puntos

Suma los puntos correspondientes a cada jugador

liberarPuntos

Vacía

Nodo **puntos

Se vacía la lista encargada de guardar los puntos de ambos jugadores

barridoDeBolas

Vacía

barridoDeBolas

Elimina las bolas que hayan formado una línea

calcularTiempo

Real

struct timeval *inicio, struct timeval *fin

Calcula y devuelve el tiempo transcurrido entre dos períodos de tiempo

procesarLineas

Entera

int fila, int columna, Casilla tablero[fila][columna], Nodo** puntos, struct timeval inicio[5], struct timeval fin[5], Records *mejorTiempo, GtkWidget* G_tablero[fila+1][ columna+1]

Nos dice que tipo de línea se acaba de formar. Devuelve 1,2,3,4 o 0 si la línea formada es horizontal, vertical, diagonal principal, diagonal secundario o no se ha formado una línea respectivamente.

tableroLleno

Booleana

int fila, int columna, Casilla tablero[fila][columna]

Determina si el tablero está lleno. Devuelve Verdadero si está lleno, de lo contrario retornara falso

pausar

Vacía

struct timeval inicio[5], struct timeval fin[5], Records *mejorTiempo

Se encarga de pausar el juego

inicializarTiempo

Entera

struct timeval inicio[5], struct timeval fin[5], Records *mejorTiempo

Inicializa el tiempo de inicio y fin de la partida y de las mejores jugadas. Devuelve 1.

reiniciar

Vacía

int fila, int columna, Casilla tablero[fila][columna], Nodo **puntos, struct timeval inicio[5], struct timeval fin[5], Records *mejorTiempo

Inicia otra vez la partida,

mostrarGanadorYRecords

Vacía

Nodo *puntos, Records *mejorTiempo

Muestra el ganador de la partida y los mejores tiempos en los distintos tipos de jugada.

conectarPunteros

Vacía

Punteros *misPunteros, int *fila, int *columna, int *turno, int *modo, int *colorJ1, Casilla tablero[*fila][*columna], key_t *claveMemoria, int *idMemoria, Casilla *buffer, Records *mejorTiempo, struct timeval inicio[5], struct timeval fin[5], Nodo* puntos, GtkWidget* ventana, GtkWidget* contenedor, GtkWidget *G_tablero[*fila][*columna+1], pthread_t *hilo, bool *finalizarHilo, int *dificultad

Se usa para trasladar ciertas variables a otras funciones

G_salir

Vacía

int fila, int columna, Casilla tablero[fila][columna], Nodo* puntos

Manda a liberar los puntos y matar todos los procesos marco y bola

manejarSalida

Booleana

GtkWidget *widget, Punteros* misPunteros

Llama a la función G_salir y después sale del programa

manejarSalidaConfig

Booleana

GtkWidget *widget, gpointer data

Se encarga de salirse del programa

itoa

Carácter

int val, int base

Transforma un entero a un caracter

G_actualizarTurno

Vacía

int fila, int columna, GtkWidget* G_tablero[fila+1][columna+1], int *turno

Se encarga de mostrar a quien le toca jugar

G_inicializarTablero

Vacía

int fila, int columna, GtkWidget* G_tablero[fila+1][columna+1], int modo, int *turno, bool *finalizarHilo

Inicializa el tablero en modo gráfico

manejarPause

Vacía

GtkWidget* btnPausar, Punteros *misPunteros

Se encarga de manejar la pausa

columnaATKoDEF

Entera

int fila, int columna, Casilla tablero[fila][columna]

Determina y devuelve en qué columna debe jugar la maquina si hay 3 bolas del mismo color consecutivo esta de forma horizontal, vertical o diagonal, jugara en la columna contiguo, sino elegirá una columna al azar

G_juegaPC

Vacía

int fila, int columna, GtkWidget* G_tablero[fila+1][columna+1],Casill a tablero[fila][columna], int dificultad

Se encarga de elegir en donde jugar la maquina dependiendo de su dificultad, si es fácil será al azar, sino se usa la función columnaATKoDEF

G_PCvsPC

Vacía

Punteros *misPunteros

Se encarga de ejecutar el juego en el modo PC vs PC

G_reiniciar

Vacía

int fila, int columna, GtkWidget* G_tablero[fila+1][columna+1],int *turno, int modo, int colorJ1, pthread_t *hilo, bool *finalizarHilo, Punteros *misPunteros

Reinicia el juego en modo gráfico

G_cargarValoresPredeterminados

Vacía

Punteros *misPunteros

Llama a las funciones que se encargan de inicializar valores

G_configuracionInicial

Vacía

int argc, char **argv, int* fila, int* columna, int *modo, int* colorJ1, int* dificultad

Muestra la ventana principal donde se elige el número de filas, dificultad, modo de juego, color de las fichas,etc.

G_ponerBola

Vacía

int fila, int columna, GtkWidget* G_tablero[fila+1][columna+1],int filaAJugar, int columnaAJugar, int turno, GtkWidget* ventana

Pone la bola en la columna deseada en modo gráfico

G_actualizarTablero

Vacía

int fila, int columna, Casilla tablero[fila][columna], GtkWidget* G_tablero[fila+1][columna+1], Nodo* puntos, int *turno,int filaAJugar, int columnaAJugar

Actualiza el tablero en modo gráfico

manejarJugada

Entera

GtkWidget* btnPulsado, Punteros *misPunteros

Se encarga de administrar la jugada que se quiere hacer, sea un jugador o la PC.

G_conectarBotonesDeJuego

Vacía

int fila, int columna, GtkWidget *G_tablero[fila+1][ columna+1], Punteros *misPuntero

Se encarga de conectar los botones del juego con la acción que tienen que realizar una vez sean presionados

manejador

Vacía

int numSignal

Se encarga de manejar las señales, ya sea para quitar la pausa o agrupar a la bola y al marco.

actualizarTiempo

Vacía

int tipoLinea, struct timeval inicio[5], struct timeval fin[5], Records *mejorTiempo

Calcula el tiempo necesitado para realizar una línea desde que se hizo la ultima y determina si es el mejor tiempo para hacer ese tipo de línea

manejarReinicio

Vacía

GtkWidget* btnPausar, Punteros *misPunteros

Se encarga de manejar el reinicio del juego

G_inicializarVentana

Vacía

GtkWidget* ventana, GtkWidget* contenedor, int fila, int columna, GtkWidget* G_tablero[fila+1][ columna+1], Punteros *misPunteros

Inicializa la ventana de inicio

Consideraciones

  • En la ventana principal se podrá cambiar el número de filas.

  • El juego iniciará mediante un sorteo entre los dos (02) jugadores para saber quien inicia.

  • Cuando una bola se aloje en un marco de bola el proceso bola guarda su pid y color en la memoria compartida y se envía una señal del proceso bola al proceso marco indicándole que vaya a la memoria compartida a buscar el pid y el color del proceso bola que va a alojar.

  • El juego finalizará cuando el tablero este lleno.

  • Se maneja un reloj que permite almacenar los mejores tiempos para formar líneas según su tipo: horizontal, vertical o diagonal principal o secundaria.

  • También se indica a que jugador le corresponde su turno según su color de bola.

  • El juego tiene dos niveles de dificultad: principiante y difícil.

  • Tanto el ganador o empate como los mejores tiempos se muestran en la terminal.

  • Para quitar el pause se debe pulsar ctrl+c en la terminal.

Restricciones

  • No se podrá pausar el juego durante una partida en modo PCVSPC.

  • No se podrá compilar desde una pc con Debian ya que presentará fallas en el manejo las cadenas, debido a la incompatibilidad en el formato de codificación de caracteres utilizado para desarrollar el proyecto en Ubuntu, aunque si se podrá ejecutar y funcionar correctamente en ambos SO.

Conclusiones

Un proceso de unix es cualquier programa en ejecución y es totalmente independiente de otros procesos. Un proceso tiene su propia zona de memoria y se ejecuta "simultáneamente" a otros procesos. Es totalmente imposible en unix que un proceso se meta, a posta o por equivocación, en la zona de memoria de otro proceso. Esta es una de las características que hace de unix un sistema fiable. Un programa chapucero o malintencionado no puede fastidiar otros programas en ejecución ni mucho menos a los del sistema operativo. Si el programa chapucero se cae, se cae sólo él.

Dentro de un proceso puede haber varios hilos de ejecución (varios threads). Eso quiere decir que un proceso podría estar haciendo varias cosas "a la vez". Los hilos dentro de un proceso comparten todos la misma memoria. Eso quiere decir que si un hilo toca una variable, todos los demás hilos del mismo proceso verán el nuevo valor de la variable.

Un proceso, en el momento de lanzarlo, se hace independiente del nuestro, así que no deberíamos tener ningún problema, salvo que necesitemos comunicación entre ellos, que nos llevaría a programar memorias compartidas (con sus correspondientes semáforos), colas de mensajes, sockets o cualquier otro mecanismo de comunicación entre procesos unix.

Una señal es un aviso que puede enviar un proceso a otro proceso. El sistema operativo unix se encarga de que el proceso que recibe la señal la trate inmediatamente. De hecho, termina la línea de código que esté ejecutando y salta a la función de tratamiento de señales adecuada. Cuando termina de ejecutar esa función de tratamiento de señales, continúa con la ejecución en la línea de código donde lo había dibujado.

El sistema operativo envía señales a los procesos en determinadas circunstancias.