Autor Tema: juego Gomoku C++ tablero comprobar linea = caracter vertical horizontal diagonal  (Leído 2343 veces)

TonyG797

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 1
    • Ver Perfil
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.
« Última modificación: 06 de Junio 2020, 13:52 por Ogramar »

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re:Ayuda con comparacion en C++
« Respuesta #1 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;
}
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".