Foros del Web » Programación para mayores de 30 ;) » C/C++ »

No me corre juego tres rayas

Estas en el tema de No me corre juego tres rayas en el foro de C/C++ en Foros del Web. #include <stdio.h> char matriz [3][7]; int op=0, gana=0, emp=1, pla1=0, pla2=0, pjug=1, repe1; coordx=0, coordy=0; void valores() { gana=0; emp=0; pjug=1; int i, j; for ...
  #1 (permalink)  
Antiguo 25/05/2013, 22:09
Avatar de andre18agf  
Fecha de Ingreso: mayo-2007
Mensajes: 13
Antigüedad: 16 años, 11 meses
Puntos: 0
No me corre juego tres rayas

#include <stdio.h>
char matriz [3][7];
int op=0, gana=0, emp=1, pla1=0, pla2=0, pjug=1, repe1; coordx=0, coordy=0;


void valores()
{
gana=0; emp=0; pjug=1;
int i, j;
for (i=0; i<=2; i++)
for (j=0; j<=6; j++)
matriz[i][j] =' ';
}
void casillas()
{
char oc;
if (pjug == 1)
oc='X';
else
oc='O';
switch (op) {
case 1 : if (matriz[0][0] != ' ') { repe1=1; break; } else {matriz[0][0]=oc; emp++; break;}
case 2 : if (matriz[0][1] != ' ') { repe1=1; break; } else {matriz[0][1]=oc; emp++; break;}
case 3 : if (matriz[0][2] != ' ') { repe1=1; break; } else {matriz[0][2]=oc; emp++; break;}
case 4 : if (matriz[0][3] != ' ') { repe1=1; break; } else {matriz[0][3]=oc; emp++; break;}
case 5 : if (matriz[0][4] != ' ') { repe1=1; break; } else {matriz[0][4]=oc; emp++; break;}
case 6 : if (matriz[0][5] != ' ') { repe1=1; break; } else {matriz[0][5]=oc; emp++; break;}
case 7 : if (matriz[0][6] != ' ') { repe1=1; break; } else {matriz[0][6]=oc; emp++; break;}
case 8 : if (matriz[0][7] != ' ') { repe1=1; break; } else {matriz[0][7]=oc; emp++; break;}
case 9 : if (matriz[1][0] != ' ') { repe1=1; break; } else {matriz[1][0]=oc; emp++; break;} }
}

void jug1()
{
printf("Jugador 1 - Introduce el numero: ");
scanf("\n&d","&d",&coordx, &coordy);
while (coordx>3 || coordy>7) {
printf("Opcion NO VALIDA, introduce una correcta: ");
scanf("\n&d","&d",&coordx, &coordy); }
casillas();
if (repe1 == 1) {
printf("Casilla ya elegida! ");
repe1=0;
jug1();}

pjug=2;
}

void jug2()
{
printf("Jugador 2 - Introduce el numero: ");
scanf("\n&d","&d",&coordx, &coordy);
while ( coordx>3 || coordy>7) {
printf("Opcion NO VALIDA, introduce una correcta: ");
scanf("\n&d","&d",&coordx, &coordy); }
casillas();
if (repe1 == 1) {

printf("Casilla ya elegida! ");
repe1=0;
jug1();}
pjug=1;
}

int opcion (){
int op=0;
If (coordx==0 && coordy==0)
op=0+1;
If (coordx==0 && coordy==1)
op=2;
If (coordx==0 && coordy==2)
op=3;
If (coordx==0 && coordy==3)
op=4;
If (coordx==0 && coordy==5)
op=5;
If (coordx==0 && coordy==6)
op=6;
If (coordx==0 && coordy==7)
op=7;
If (coordx==1 && coordy==0)
op=8;
return (op);
}
int cuadro(){

printf("\n\n 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | \n");
printf("---------------------------------------\n");
printf(" 1 | %c | %c | %c | %c | %c | %c | %c |\n",matriz[0][0],matriz[0][1],matriz[0][2],matriz[0][3],matriz[0][4],matriz[0][5],matriz[0][6],matriz[0][7]);
printf("---------------------------------------\n");
printf(" 2 | %c | %c | %c | %c | %c | %c | %c |\n",matriz[1][0],matriz[1][1],matriz[1][2],matriz[1][3],matriz[1][4],matriz[1][5],matriz[1][6],matriz[1][7]);
printf("---------------------------------------\n");
printf(" 3 | %c | %c | %c | %c | %c | %c | %c |\n",matriz[2][0],matriz[2][1],matriz[2][2],matriz[2][3],matriz[2][5],matriz[2][6],matriz[2][7],matriz[2][7]);
printf("---------------------------------------\n");

return;
}

main()
{
valores();
while (gana == 0)
{
cuadro();
switch(pjug)
{
case 1 : jug1(); break;
case 2 : jug2(); break;
}
}
}


Se me detiene en la funcion Opcion, nose que ocurre.
  #2 (permalink)  
Antiguo 26/05/2013, 10:42
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: No me corre juego tres rayas

Antes de nada tienes varias cosas a corregir: en la linea de declaracion de enteros tiene un ; enmedio que provoca que las siguientes declaraciones se interpreten como tipos no definidos. Otro error son todos los If con mayusculas (en C van en minuscula). Despues tienes la declaracion del main que aunque el compilador lo rellene por defecto tienes que declararlo tal como es: una funcion de tipo entero que retorna un entero (0 por defecto). Aparte de eso deberia indentar un poco el codigo, mas que nada porque te será util a la hora de diferenciar cada parte del codigo (por eso de la claridad y no se que mas) y ademas será amigable para toda la gente que pueda ayudarte con los problemas que te surjan. Con esto tambien me refiero a usar todas las llaves { } que sean necesarias y a separar las instrucciones por lineas (tu funcion 'casillas()' es un ejemplo de como no se debe codificar).

Ademas de todo eso tienes algunos errores de copiar/pegar: en la funcion 'jug2()' cuando se cumple la condicion 'repe1' (es decir, cuando el jugador 2 selecciona una casilla ocupada) haces un llamada a 'jug1()' cuando deberias instar al jugador 2 a corregir ok?

Mas cosas: la cadena de formato para enteros en el scanf es %d o %i, no &d; el & se usa para referenciar una posicion de memoria pero no para indicar formato:

Código C:
Ver original
  1. //esto es lo que tienes
  2. scanf("\n&d","&d",&coordx, &coordy);
  3.  
  4. //y esto es lo correcto
  5. scanf("\n%d %d", &coordx, &coordy);
  6.  
  7. //o si quieres entrar con coma
  8. scanf("\n%d,%d", &coordx, &coordy);

Aun otra cosa, en la funcion 'opcion ()' echa otro vistazo a las tres primeras lineas:

Código C:
Ver original
  1. int op = 0;
  2. if (coordx == 0 && coordy == 0)
  3.     op = 0 + 1;

No ves nada raro por ahi?

Echa tambien un vistazo a los casos de la funcion 'casillas()': sabes que 'op' solo puede ser un valor en cada llamada por lo que para cada caso obligatoriamente sales del switch, entonces no hace falta que pongas dos breaks dentro de los casos

Código C:
Ver original
  1. switch (op) {
  2.     case 1 :
  3.         if (matriz[0][0] != ' ') {
  4.             repe1=1;
  5.         }
  6.         else {
  7.             matriz[0][0] = oc;
  8.             emp++;
  9.         }
  10.     break;
  11.         ...

Y aun otra observacion: si la matriz tiene 3 filas de 7 columnas, la coordenada x puede llagar a 7 ok? Revisa las condiciones que tienes despues del scanf:

Código C:
Ver original
  1. while ( coordx > 3 || coordy > 7) {

Y ahora lo que seguramente mas te interesa: porque el valor 'op' siempre es 0? Ese valor se determina dentro de la funcion 'opcion()', pero cuando se ejecuta la llamada a esa funcion? Y en caso de que llames a 'opcion()' antes de llamar a 'casillas()' en jug1() y jug2(), que pasa si la coordenada x es mayor que 2?

Supongo que en 'opcion()' no vas a mapear todas las posibles posiciones ok? Has echo una funcion de 20 lineas y solo permite trabajar sobre coordx igual a 0, o coordx = 1 en caso que coordy = 0; como ya te puedes imaginar esta no es la solucion. Y lo mismo te sucede en la funcion 'casillas()', no puedes mapear los 21 casos entre matriz[0][0] y matriz[3][7].

Una solucion: las coordenadas que entra el usuario deben ser las posiciones dentro de la matriz pero adaptadas para basarlas en 0

Código:
//el usuario selecciona 1,2
coordx = 1
coordy = 2

//adaptas
posicionx = coordx - 1;
posiciony = coordy - 1;

//y escribes dentro de la matriz
matriz[posicionx][posiciony] = 'X';
De esta forma evitas tener que mapear todas las opciones. Lo unico que deberas tener en cuenta (que es lo que tienes despues de escanear la entrada de usuario) es que las posiciones seleccionadas existan (lo que tienes, que esten entre 1 y 7 para las horz, y entre 1 y 3 para las vert).

La otra solucion es la mas clasica en videojuegos de tiles: consiste en usar una matriz simple de 21 elementos, de forma que las coordenadas del usuario indicaran una fila/columna imaginaria:

Código:
#define ROWS 3
#define COLS 7
#define WORLDSIZE (ROWS * COLS)

char matriz[WORLDSIZE];
Para determinar la posicion dentro de la matriz imaginaria debes usar un minialgoritmo que para convertir la coordenada columna/fila a indice; el algoritmo basico para videojuegos de tiles dice que el indice es (columnas * y) + x, readaptado para trabajar con valores de usuario entre 1 y 7 queda que debes restar 1 a la fila y la columna entrada por el usuario; lo clavas en una funcion independiente y ya tienes la forma de determinar la posicion:

Código:
int getpos(int x, int y) {
	return (COLS * (y - 1)) + (x - 1);
}
Ahora reescribes la funcion 'casillas()' para que trabaje con la matriz simple:

Código:
void casillas() {
	char oc, pos;
	
	oc = (pjug == 1)? 'X':'O';
	pos = getpos(coordx, coordy);
	matriz[pos] = oc;
}
Y finalmente reescribes la funcion que pinta el tablero; ya que estas programando que menos que hacerlo de forma programana ok?

Código:
void cuadro() {
	int v, h, pos;
	
	for(v = 0; v <= ROWS; v++) {
		for(h = 0; h <= COLS; h++) {
			if(v) {
				if(h) {
					pos = getpos(h, v);
					printf("%c | ", matriz[pos]);
				}
				else {
					printf("%d | ", v);
				}
			}
			else {
				if(!h) {
					printf("0 | ");
				}
				else if(h >= COLS) {
					continue;
				}
				printf("%d | ", h+1);
			}
		}
		
		printf("\n");
		for(h = 0; h < (COLS*strlen("0 | ")) + strlen(" | "); h++) {
			printf("-");
		}
		printf("\n");
	}
}
Saludos
vosk

Última edición por vosk; 26/05/2013 a las 10:50
  #3 (permalink)  
Antiguo 27/05/2013, 17:48
Avatar de andre18agf  
Fecha de Ingreso: mayo-2007
Mensajes: 13
Antigüedad: 16 años, 11 meses
Puntos: 0
Respuesta: No me corre juego tres rayas

Hola vosk, he hecho esto. Pero ahora la el procedimiento Jug me deberia intercambiar los jugadores y se queda en el jugador dos.

Código C:
Ver original
  1. #include <stdio.h>
  2. #define ROWS 3
  3. #define COLS 7
  4. #define WORLDSIZE (ROWS * COLS)
  5.  
  6. char matriz[WORLDSIZE];/*La matriz de tres en raya*/
  7. int  emp=1, pjug=1, repe1, coordx=0, coordy=0;
  8. char oc;
  9.  
  10. void valores()/*inicializador de valores*/
  11. {
  12.     emp=0; pjug=1;
  13.     int i, j;
  14.     for (i=0; i<=WORLDSIZE; i++)
  15.             matriz[i] =' ';
  16. }
  17. int getpos(int x, int y) {
  18.     return (COLS * (x - 1)) + (y - 1);
  19. }
  20. void casillas(int posicion)
  21. {
  22.     if (pjug == 1)
  23.         oc='X';
  24.     else
  25.         oc='O';
  26.     if (matriz[posicion] != ' '){
  27.         repe1=1; }
  28.     else{
  29.         matriz[posicion]=oc;
  30.         emp++;}
  31. }
  32.  
  33. void Jug(int Njug)
  34. {
  35.     int pos=0;
  36.     printf("Jugador %d - Introduce el numero: ",Njug);
  37.     scanf("\n%d,%d",&coordx, &coordy);
  38.     while (coordx>3 || coordy>7) {
  39.         printf("Opcion NO VALIDA, introduce una correcta: ");
  40.         scanf("\n%d,%d",&coordx, &coordy); }
  41.     pos = getpos(coordx, coordy);
  42.     casillas(pos);
  43.     if (repe1 == 1) {
  44.         printf("Casilla ya elegida! ");
  45.         repe1=0;
  46.         Jug(pjug);}
  47.             if(Njug){
  48.             pjug=2;}
  49.             else
  50.             pjug=1;
  51. }
  52.  
  53.  
  54. int cuadro(){
  55.  
  56. printf("\n\n 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | \n");
  57. printf("--------------------------------\n");
  58. printf(" 1 | %c | %c | %c | %c | %c | %c | %c |\n",matriz[0],matriz[1],matriz[2],matriz[3],matriz[4],matriz[5],matriz[6]);
  59. printf("--------------------------------\n");
  60. printf(" 2 | %c | %c | %c | %c | %c | %c | %c |\n",matriz[7],matriz[8],matriz[9],matriz[10],matriz[11],matriz[12],matriz[13]);
  61. printf("--------------------------------\n");
  62. printf(" 3 | %c | %c | %c | %c | %c | %c | %c |\n",matriz[14],matriz[15],matriz[16],matriz[17],matriz[18],matriz[19],matriz[20]);
  63. printf("--------------------------------\n");
  64.  
  65. return;
  66. }
  67. int main()
  68. {
  69.     int g=0;
  70. valores();
  71. while (WORLDSIZE)
  72. {
  73. cuadro();
  74. switch(pjug)
  75. {
  76. case 1 : Jug(pjug); break;
  77. case 2 : Jug(pjug); break;
  78. }
  79. }
  80. }
  #4 (permalink)  
Antiguo 28/05/2013, 08:24
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: No me corre juego tres rayas

Solo lo he mirado por encima: una comparacion de entero contra nulo solo es cierta cuando el entero es 0, para cualquier otro valor siempre es falsa

Código:
//if(Njug) { //en tu codigo esto siempre se cumple porque Njug solo será 1 o 2
if(Njug == 1) {//ahora comparas contra
    pjug = 2;
}
else {
    pjug = 1;
}

//dicho de otra forma
pjug = (Njug == 1)? 1 : 2;
Este tipo de comparacion solo sirve cuando uno de los valores es 0, puedes hacerlo para simplificar el codigo pero tendras que añadir algo mas:

Código:
enum L_PLAYERS {
    PLAYER1,
    PLAYER2
};

//inicias asignando turno al jugador 1
pjug = PLAYER1;

//y en Jug cambias segun el valor tal como tenias
if(Njug) pjug = PLAYER2;
else pjug = PLAYER1;

//que es lo mismo que
pjug = (NJug)? PLAYER2 : PLAYER1;
De esta forma puedes crear una lista de textos para guardar los nombres de los jugadores y acceder a ellos de forma directa (de forma directa el primer elemento de una lista es el 0).

Saludos
vosk
  #5 (permalink)  
Antiguo 28/05/2013, 12:37
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: No me corre juego tres rayas

Una cosa: tienes las coordenadas invertidas, fijate bien en la funcion 'getpos()' que te colgué en el otro post

indice = (numero de columnas * coordenada y) + coordenada x

En tu juego como los valores inician en 1 añado la adaptacion de restar 1 a las coordenadas para basarlas en 0 que es tal como funciona este truco. Tal como lo tienes tu tendrias que cambiar el numero de columnas por el numero de filas, pero entonces se interpreta como que la lista se recorre de arriba a abajo y de izquierda a derecha. Esto es importante porque cuando pintas el tablero estas mostrando las celdas de izquierda a derecha y de arriba a abajo; junto con esto deberas modificar los limites de las coordenadas: las coordenadas x son las horizontales y pueden estar entre 1 y 7 (extremos incluidos), luego las coordenadas y serán las verticales y pueden estar entre 1 y 3 ok? Ahora sabiendo esto y sabiendo que esas coordenadas se convirten en un indice lineal (la matriz simple), no es necesario que pongas limites, con solo comprobar que la posicion basada en las coordenadas esté dentro del rango de la matriz (entre 0 y 20, ambos incluidos).

Algo mas: el bucle infinito para el juego es una buena idea pero está mal diseñado, no podras salir nunca del juego a menos que mates la aplicacion. Tienes que usar un flag de estado, que suena muy profesional pero no es mas que una variable que indica si el ciclo continua o no:

Código:
//lo declaras con las globales
char running;

//lo inicias en 'valores()'
running= 1;

//y lo usas como control del ciclo
while (running) {
    ...
}
Esto te sirve para controlar desde cualquier sitio de la aplicacion el bucle del juego. Supongamos que añades un menu del tipo 'pulse 1 para nueva partida y 2 para salir', en la condicion de salida simplemente asignas 0 al flag y sales limpiamente. Tambien te sirve para cuando se de la condicion de juego ganado: supongo que pondras algun mensaje del tipo 'quieres otra partida?', si no quieres continuar solo asignas 0 al flag y dejas que lo demas se haga solo.

Aun otra cosa: cuando inicias los valores puedes usar la funcion memset para reiniciar el tablero:

Código:
memset(matriz, ' ', sizeof(matriz));
Una ultima cosa: deberias reorganizar tu codigo para quitar las llamadas recursivas a 'Jug()' en el caso de casilla ocupada. Puedes poner un flag en la funcion que se ejecute mientras no se produjo ningun error, de forma que inicias con flag 1, recoges las coordenadas, pides la posicion, compruebas que es valida, si no es valida lanzas un continue para que reinicie el ciclo, si es valida intentas insertarla, si ya esta ocupada lanzas otro continue, y al final antes de salir del bucle si todo fue bien asignas 0 al flag y dejas que salga limpio, algo asi:

Código:
void Jug(int Njug) {
	int pos = 0;
	char done = 0;
	
	while(!done) {
		//entrada de datos
		printf("Jugador %d - Introduce el numero: ", Njug);
		scanf("\n%d,%d", &coordx, &coordy);
		
		//comprovacion de coordenadas
		pos = getpos(coordx, coordy);
		if(pos < 0 || pos >= WORLDSIZE) {
			printf("err 1\n");
			continue;
		}
		
		//comprovacion de casilla
		if(!is_empty(pos)) {
			printf("err 2\n");
			continue;
		}
		
		//ejecutas jugada
		casillas(pos);
		
		//cambias de jugador
		switch_player();
		
		//finalizas el estado de jugada para el player actual
		done = 1;
	}
}

//esta funcion solo comprueba que este libre
char is_empty(int pos) {
	return (matriz[pos] != ' ')? 0 : 1;
}

//y esta cambia el turno
void switch_player() {
	pjug = (pjug == 1)? 2 : 1;
}
Es importante que separes cada cosa en varias funciones: esto te proporciona una ventaja a la hora de hacer modificaciones y de encontrar errores.

Saludos
vosk

Etiquetas: corre, funcion, int, juego, rayas, tres
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 20:18.