Para
hacerlo aún más completo, vamos a hacer que el juego nos indique un ganador,
con lo cual dibujará una línea horizontal, vertical o diagonal, cuando un
jugador lo haya logrado.
Para
lograr esto, lo que voy a hacer es sumar las filas, columnas o diagonales de la
matriz, recordemos que las X valen 1 mientras que los O valen 9, por lo tanto
si completo por ejemplo una fila de X, entonces la suma será de 3, en cambio si
completo una de O la suma será 27. Para manejar estos datos crearé una subrutina
a la cual llamaré “SumaMatriz”
Sub SumaMatriz'Y raya final
'raya horizontal superior
If matriz[1][1] + matriz[1][2] + matriz[1][3] = 3 Or matriz[1][1] + matriz[1][2] + matriz[1][3] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(50,85,320,85)
EndIf
EndSub
(Nota:
La condición if debe estar en una sola línea. Por cuestiones de espacio
horizontal es que se ve en dos líneas)
Como
se puede ver, dejé una línea comentada indicando “raya horizontal superior” lo
cual indica que este código es para dibujar una línea en la primera fila. Esta
subrutina detecta que si la suma de los valores de la primera fila es igual a 3
o 27, entonces dibujará una línea. A esta subrutina la invoco desde
aquí:
'ubicacion 1,1
If gmX >= 85 And gmX <= 145 And gmY >= 65 And gmY <= 105 Then
If matriz[1][1] = 0 Then
GraphicsWindow.DrawLine(100,70,130,100)
GraphicsWindow.DrawLine(100,100,130,70)
matriz[1][1] = 1
inter()
SumaMatriz()
EndIf
EndIf
'ubicacion 1,2
If gmX >= 155 And gmX <= 215 And gmY >= 65 And gmY <= 105 Then
If matriz[1][2] = 0 Then
GraphicsWindow.DrawLine(170,70,200,100)
GraphicsWindow.DrawLine(170,100,200,70)
matriz[1][2] = 1
inter()
SumaMatriz()
EndIf
EndIf
'ubicacion 1,3
If gmX >= 225 And gmX <= 285 And gmY >= 65 And gmY <= 105 Then
If matriz[1][3] = 0 Then
GraphicsWindow.DrawLine(240,70,270,100)
GraphicsWindow.DrawLine(240,100,270,70)
matriz[1][3] = 1
inter()
SumaMatriz()
EndIf
EndIf
La ubicación 1,1 a la 1,3 corresponde a la
primera línea, por lo tanto, cada vez que se dibuje una figura en estas
casillas, se estará comprobando la suma de la fila.
Veamos ahora como funciona. Ejecutemos el
programa y comprobemos la primera línea:
Se ve que funciona, así que haremos lo mismo
para cada una de las filas restantes, columnas y diagonales.
Entonces, esto quedaría de la siguiente
manera:
Sub SumaMatriz'Y raya
final****************************************************
'raya horizontal superior
If matriz[1][1] + matriz[1][2] + matriz[1][3] = 3 Or matriz[1][1] + matriz[1][2] + matriz[1][3] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(50,85,320,85)
EndIf
'raya horizontal media
If matriz[2][1] + matriz[2][2] + matriz[2][3] = 3 Or matriz[2][1] + matriz[2][2] + matriz[2][3] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(50,140,320,140)
EndIf
'raya horizontal inferior
If matriz[3][1] + matriz[3][2] + matriz[3][3] = 3 Or matriz[3][1] + matriz[3][2] + matriz[3][3] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(50,195,320,195)
EndIf
'raya vertical izquierda
If matriz[1][1] + matriz[2][1] + matriz[3][1] = 3 Or matriz[1][1] + matriz[2][1] + matriz[3][1] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(115,30,115,250)
EndIf
'raya vertical centro
If matriz[1][2] + matriz[2][2] + matriz[3][2] = 3 Or matriz[1][2] + matriz[2][2] + matriz[3][2] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(185,30,185,250)
EndIf
'raya vertical derecha
If matriz[1][3] + matriz[2][3] + matriz[3][3] = 3 Or matriz[1][3] + matriz[2][3] + matriz[3][3] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(255,30,255,250)
EndIf
'raya diagonal sup. izq. a der.
If matriz[1][1] + matriz[2][2] + matriz[3][3] = 3 Or matriz[1][1] + matriz[2][2] + matriz[3][3] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(90,60,280,220)
EndIf
'raya diagonal inf. izq. a der.
If matriz[3][1] + matriz[2][2] + matriz[1][3] = 3 Or matriz[3][1] + matriz[2][2] + matriz[1][3] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(90,220,280,60)
EndIf
EndSub
No olvidar llamar a la subrutina
SumaMatriz() desde las subrutinas figuraX y figuraO, así como en el siguiente
ejemplo:
If gmX >= 85 And gmX <= 145 And gmY >= 65 And gmY <= 105 Then
If matriz[1][1] = 0 Then
GraphicsWindow.DrawLine(100,70,130,100)
GraphicsWindow.DrawLine(100,100,130,70)
matriz[1][1] = 1
inter()
SumaMatriz()
EndIf
EndIf
Al
ejecutar el programa podemos ver que funciona tanto en sus lineas horizontales,
verticales y diagonales, pero hay otro pequeño inconveniente. Y es que luego de
que el juego ha “finalizado” dibujando la raya, lo jugadores aún pueden seguir
seleccionando casillas. Es como si en un partido de futbol, el arbitro da por finalizado el partido pero los
jugadores siguen pateando la pelota. Para solucionar este pequeño
inconveniente, se me ocurre marcar las casillas que quedaron disponibles (en
realidad lo que hago es marcarlas todas) ya que esas casillas, al tener un
valor de cero, pueden ser escritas, pero si modifico su valor al finalizar el
juego, entonces los jugadores no podrán hacer clic y marcarlas porque no se
cumpliría la condición (De que la casilla tenga valor de cero). Por eso, crearé
una nueva subrutina que me permita re escribir la matriz, rellenandola con un
valor distinto de cero, por ejemplo 2.
Sub RellenaMatriz
For fila = 1 To 3
For columna = 1 To 3
matriz[fila][columna]
= 2
EndFor
EndFor
EndSub
Ahora, lo que voy a hacer es llamar a esta
subrutina justo después de crear la raya que da por finalizado el juego, así
los jugadores no podrán seleccionar las casillas que quedaron disponible.
If matriz[1][1] + matriz[1][2] + matriz[1][3] = 3 Or matriz[1][1] + matriz[1][2] + matriz[1][3] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(50,85,320,85)
RellenaMatriz()
EndIf
Al ejecutar el programa, podemos ver que una
vez finalizado el juego, los jugadores ya no podrán seguir rellenando las
casillas vacías.
REINICIANDO EL JUEGO
Ahora que el juego ya ha decidido un ganador,
lo ideal sería poder reiniciarlo y no tener que cerrarlo y volverlo a ejecutar
para seguir jugando otra ronda.
Para ello voy a crear un botón que me permita
reiniciar el juego cuando este ha concluido.
Para que este botón no se encuentre visible
sino hasta que el juego finalice, debe estar dentro de una subrutina. La que
voy a crear es la siguiente:
Sub Reinicio
Controls.AddButton("Reiniciar",150,240)
Controls.ButtonClicked = BtnReinicio
EndSub
Entonces, lo que este botón hará será borrar
la pantalla y luego llamar a la subrutina inicio() para volver a empezar desde
el principio. Esto quedaría más o menos así:
Sub BtnReinicio
GraphicsWindow.Clear()
inicio()
EndSub
Ahora, solo queda llamar a la subrutina
Reinicio() cuando un jugador gane la partida. Esto se hará bajo estas líneas de
código:
'raya horizontal superior
If matriz[1][1] + matriz[1][2] + matriz[1][3] = 3 Or matriz[1][1] + matriz[1][2] + matriz[1][3] = 27 Then
GraphicsWindow.PenWidth = 5
GraphicsWindow.DrawLine(50,85,320,85)
RellenaMatriz()
Reinicio()
EndIf
En primer lugar vamos a probar si funciona el
código con la primera fila. Ejecutemos el código:
Muy bien, probado el código podemos ver que
se genera el botón y que además permite reiniciar el juego. Entonces solo queda
agregar la llamada a la subrutina Reinicio() desde las otras condiciones que
finalizan el juego.
Un detalle que me di cuenta al estar probando
el juego, fue que hace falta agregar un botón "reiniciar" si se
produce un empate.
¿Pero cómo le indicamos al programa que se
produjo un empate? Se me ocurren varias
alternativas, una puede ser el crear un sistema de puntajes, donde al iniciar
el juego, ambos empiezan con cero puntos, si uno de ellos gana entonces se le
asigna un valor de 1 y se produce un empate si los puntajes se mantienen en
cero... Otra alternativa (que es la que ocuparé) es un poco más sencilla y
consiste en contar la cantidad de clics válidos, aprovechando de que ya tenemos
un contador de clics. Agreguemos nuevamente una línea TextWindow para ver en
qué valor termina nuestro contador al producirse un empate.
Sub inter
interruptor = interruptor + 1
TextWindow.WriteLine(interruptor)
EndSub
Al ejecutar el programa, esto es lo que
aparece:
Vemos que la variable "interruptor"
finaliza en 10 al producirse un empate. Entonces usaremos ese valor para llamar
a la subrutina que contiene el botón. Lo vamos a hacer de la siguiente manera:
Sub inter
interruptor = interruptor + 1
If interruptor = 10 Then
Reinicio()
EndIf
EndSub
Al probar el juego y producir un empate,
vemos que el código funciona:
Ahora sí, la mecánica principal del juego se
encuentra lista. Ya se puede jugar y volver a reiniciar el juego cuantas veces
queramos.
Esto es todo por ahora, en el próximo tutorial agregaré la última parte que me falta y con eso se daría término a este proyecto, el cual en un futuro cercano pretendo actualizar. Saludos.
Gustavo J. Cerda Nilo
Julio 2016, Octubre 2016
No hay comentarios:
Publicar un comentario