Foros aprenderaprogramar.com

Aprender a programar => C, C++, C#, Java, Visual Basic, HTML, PHP, CSS, Javascript, Ajax, Joomla, MySql y más => Mensaje iniciado por: TonyG797 en 05 de Mayo 2019, 16:17

Título: juego Gomoku C++ tablero comprobar linea = caracter vertical horizontal diagonal
Publicado por: TonyG797 en 05 de Mayo 2019, 16:17
Hola, buena tarde. ¿Podrían ayudarme a hacer esta condición más eficiente? Estoy realizando un juego llamado Gomoku para mi primera clase de programacion.

Pero se me hace demaciado ineficiente la condición que coloqué aquí. Básicamente verfica en el arreglo si hay una línea de 5 con el mismo caracter en vertical, horizontal y diagonales. Habrá una forma de hacerlo más dinámico. Este esta hecho para hasta comparar seis jugadores.

Código: [Seleccionar]
if (((tablero[y][x]=='X' && tablero[y][x+1]=='X' && tablero[y][x+2]=='X' && tablero[y][x+3]=='X' && tablero[y][x+4]=='X')||
(tablero[y][x]=='X' && tablero[y+1][x]=='X' && tablero[y+2][x]=='X' && tablero[y+3][x]=='X' && tablero[y+4][x]=='X')||
(tablero[y][x]=='X' && tablero[y+1][x+1]=='X' && tablero[y+2][x+2]=='X' && tablero[y+3][x+3]=='X' && tablero[y+4][x+4]=='X')||
(tablero[y][x]=='X' && tablero[y+1][x-1]=='X' && tablero[y+2][x-2]=='X' && tablero[y+3][x-3]=='X' && tablero[y+4][x-4]=='X'))

Sería de gran ayuda. Gracias.
Título: Re:Ayuda con comparacion en C++
Publicado por: Kabuto en 07 de Mayo 2019, 22:06
Hola.

Yo lo que haría sería usar 4 funciones distintas: una para comprobar lineas horizontales, otra comprueba lineas verticales, otra comprueba diagonal ascendente y la última diagonal descendente.

Serían funciones booleanas, así por cada posicion del tablero, compruebo a ver que me devuelve cada una de estas funciones. Si alguna devuelve true, es que he encontrado una linea de 5 válida.

Mira, supongamos este tablero 10x10 de ejemplo:

Código: [Seleccionar]
char tablero[10][10] = { {'X',' ',' ',' ','X',' ','X','X','X','X'},
         {' ',' ',' ','X',' ',' ',' ',' ',' ',' '},
         {' ',' ','X',' ',' ','X','X','X','X','X'},
         {' ','X',' ',' ',' ',' ',' ',' ',' ',' '},
         {'X',' ',' ',' ',' ',' ',' ',' ',' ',' '},
         {' ',' ','X',' ',' ',' ',' ','X',' ',' '},
         {'X',' ',' ','X',' ',' ',' ','X',' ','X'},
         {'X',' ',' ',' ','X',' ',' ','X','X',' '},
         {'X',' ',' ',' ',' ','X',' ','X','X','X'},
         {'X',' ',' ',' ',' ',' ','X','X','X',' '},
};

Ahí he puesto 4 lineas válidas, una de cada tipo, más unas cuantas X que no forman líneas válidas.

Ahora declaro mis 4 funciones:
Código: [Seleccionar]
bool buscaLineaVertical(int, int); //Busca lineas verticales
bool buscaLineaHorizontal(int, int); //Busca lineas horizontales
bool buscaLineaDiagonalAscen(int, int); //Busca lineas diagonales ascendentes
bool buscaLineaDiagonalDescen(int, int); //Busca lineas diagonales descendentes

Fíjate que a cada una le pasaré dos int, estos serán las posiciones a comprobar en el tablero.

En la función main() uso dos bucles anidados para recorrer el tablero y como dije antes, para cada posición consulto a ver que me devuelven estas funciones.
En realidad, según que posiciones, no llamaré a algunas funciones.

Por ejemplo, solo buscaré lineas verticales si la variable i es menor o igual que 5. Porque si vale 6 o más, no van a haber casillas suficientes para encontrar una linea de cinco 'X', así que entonces no vale la pena llamar a la funcion.
Por eso en el if donde pregunto por lineas verticales, una condición previa es que i <= 5

Código: [Seleccionar]
int main()
{
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++) {

if ( i <= 5 && buscaLineaVertical(i, j))
cout << "Encontrada linea VERTICAL en posicion X:" << i << " Y:" << j << "\n";

if (j <= 5 && buscaLineaHorizontal(i, j))
cout << "Encontrada linea HORIZONTAL en posicion X:" << i << " Y:" << j << "\n";

if ( (i <= 5 && j >= 4) && buscaLineaDiagonalAscen(i, j))
cout << "Encontrada linea DIAGONAL ASCENDENTE en posicion X:" << i << " Y:" << j << "\n";

if ( (i <= 5 && j <= 5) && buscaLineaDiagonalDescen(i, j))
cout << "Encontrada linea DIAGONAL DESCENDENTE en posicion X:" << i << " Y:" << j << "\n";
}
system("PAUSE");
}

Visto el main(), ahora vamos a ver el detalle de las funciones, que es lo interesante.
Son muy sencillas en realidad, básicamente son un bucle for que incrementa un indice de 0 a 5.
Este indice se lo sumo o resto, a las posiciones X y/o Y, según cada caso.
Y cada vez que incremento, pregunto si aún estoy encontrando el caracter 'X'.
Si ya no lo encuentro, retorno false y la función termina.
Si aún estoy encontrando dicho caracter, no hago nada, dejo que el bucle se repita para aumentar el incremento y volver a preguntar.

Si este bucle for termina sin haber retornado false, es que he encontrado los 5 caracteres necesarios para componer una línea, así que retornaré true.

Para buscar líneas verticales, tengo que incrementar la x

Código: [Seleccionar]
bool buscaLineaVertical(int x, int y) {
//Buscaremos en vertical hacia abajo, por lo que incrementaremos la x
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y] != 'X') //Si no hay una 'X' es que no hay línea
return false; //así que retornamos false poniendo fín a este método
};
//Si el bucle for a logrado finalizar sin retornar false...
return true; //...es que tenemos una línea de 5, así que retornamos true
}

Para las horizontales, incremento la Y:
Código: [Seleccionar]
bool buscaLineaHorizontal(int x, int y) {
//Búsqueda horizontal, incrementaremos la y
for (int i = 0; i < 5; i++) {
if (tablero[x][y + i] != 'X')
return false;
};

return true;
}

Para diagonales ascendentes, incremento X y DECRemento la Y.
Código: [Seleccionar]
bool buscaLineaDiagonalAscen(int x, int y) {
//Se incrementa x, se decrementa y
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y - i] != 'X')
return false;
};

return true;
}

Y para diagonales descendentes, incrementamos ambos.
Código: [Seleccionar]
bool buscaLineaDiagonalDescen(int x, int y) {
//Se incrementan x e y
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y + i] != 'X')
return false;
};

return true;
}

No se si esta es la forma más eficiente. Por mi parte, siempre prefiero "modular" tanto como sea posible y tener así funciones encargadas de tareas muy específicas.
Prueba y revisa mi código, a ver si te sirve o al menos te da nuevas ideas.

Te lo pongo aquí de nuevo el código completo juntito, por si quieres copiar y pegar:

Código: [Seleccionar]
using namespace std;

char tablero[10][10] = { {'X',' ',' ',' ','X',' ','X','X','X','X'},
{' ',' ',' ','X',' ',' ',' ',' ',' ',' '},
{' ',' ','X',' ',' ','X','X','X','X','X'},
{' ','X',' ',' ',' ',' ',' ',' ',' ',' '},
{'X',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ','X',' ',' ',' ',' ','X',' ',' '},
{'X',' ',' ','X',' ',' ',' ','X',' ','X'},
{'X',' ',' ',' ','X',' ',' ','X','X',' '},
{'X',' ',' ',' ',' ','X',' ','X','X','X'},
{'X',' ',' ',' ',' ',' ','X','X','X',' '},
};

bool buscaLineaVertical(int, int); //Busca lineas verticales
bool buscaLineaHorizontal(int, int); //Busca lineas horizontales
bool buscaLineaDiagonalAscen(int, int); //Busca lineas diagonales ascendentes
bool buscaLineaDiagonalDescen(int, int); //Busca lineas diagonales descendentes

int main()
{
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++) {

if ( i <= 5 && buscaLineaVertical(i, j))
cout << "Encontrada linea VERTICAL en posicion X:" << i << " Y:" << j << "\n";

if (j <= 5 && buscaLineaHorizontal(i, j))
cout << "Encontrada linea HORIZONTAL en posicion X:" << i << " Y:" << j << "\n";

if ( (i <= 5 && j >= 4) && buscaLineaDiagonalAscen(i, j))
cout << "Encontrada linea DIAGONAL ASCENDENTE en posicion X:" << i << " Y:" << j << "\n";

if ( (i <= 5 && j <= 5) && buscaLineaDiagonalDescen(i, j))
cout << "Encontrada linea DIAGONAL DESCENDENTE en posicion X:" << i << " Y:" << j << "\n";
}
system("PAUSE");
}

bool buscaLineaVertical(int x, int y) {
//Buscaremos en vertical hacia abajo, por lo que incrementaremos la x
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y] != 'X') //Si no hay una 'X' es que no hay línea
return false; //así que retornamos false poniendo fín a este método
};
//Si el bucle for a logrado finalizar sin retornar false...
return true; //...es que tenemos una línea de 5, así que retornamos true
}

bool buscaLineaHorizontal(int x, int y) {
//Búsqueda horizontal, incrementaremos la y
for (int i = 0; i < 5; i++) {
if (tablero[x][y + i] != 'X')
return false;
};

return true;
}

bool buscaLineaDiagonalAscen(int x, int y) {
//Se incrementa x, se decrementa y
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y - i] != 'X')
return false;
};

return true;
}

bool buscaLineaDiagonalDescen(int x, int y) {
//Se incrementan x e y
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y + i] != 'X')
return false;
};

return true;
}