Buenas!
Soy un estudiante de programación en la universidad online y los profesores no prestan ayuda mas allá de los temarios que envían.
El ejercicio trata de crear un juego en el que puedan jugar mínimo 2 jugadores, los cuales cada uno tiene una baraja de cartas mezcladas aleatoriamente. Los jugadores extraen cada carta a partir de un botón que he creado. La cosa es que puedo crear tantos jugadores como quiera pero a la hora de mostrar la partida de cada jugador siempre muestra la baraja del ultimo, sin importar a qué botón de jugador se clique.
(https://scontent.fbcn4-1.fna.fbcdn.net/v/t1.15752-9/32260650_10216714853491535_4016280650712612864_n.jpg?_nc_cat=0&oh=95cc303af17257e779514b57a6e273a9&oe=5B8E4C0D)
(https://scontent.fbcn4-1.fna.fbcdn.net/v/t1.15752-9/32222491_10216714853331531_4773290725649416192_n.jpg?_nc_cat=0&oh=fa73976909d6efdc91e62cc6d5da42b9&oe=5B88AE68)
(https://scontent.fbcn4-1.fna.fbcdn.net/v/t1.15752-9/32266317_10216714853211528_454544824251449344_n.jpg?_nc_cat=0&oh=e02495d61ea18235bb7020bf18fa878f&oe=5B52C22E)
Sin más explicaciones... asumo que no mantienes referencias de turnos.
Lo primero es que debes mantener la ronda, tanda.
Una ronda es una fase donde cada jugador hace 'su apuesta', jugada, etc... cuando todos la han hecho, se pasa a la siguiente ronda, etc...
En una ronda, según el juego, cada jugador puede o bien jugar siempre en un orden concreto o no. Sea como sea, a cada jugador se le otorga su 'turno', indistintamente de que jueguen en un orden específico o no.
Una ronda entonces se compone de un simple array del tamaño del número de jugadores. Si juegan 6, ronda tiene 6 elementos, si juegan 8 jugadores ronda tiene 8 elementos.
Cada elemento de la ronda mantiene una referencia a cada jugador... dicha referencia puede ser a un objeto jugador, o como mínimo a un índice que relaciona únivocamente a un jugador con (por ejemplo), un array de jugadores...
Entonces cuando quieras conocer el estado de cada uno, basta consultar el objeto ronda, recorrerlo, para tener acceso a cada jugador.
Ronda puede se rmás o menos sencillo o complejo, según lo que necesites y quiera shacer desde ese objeto... lo mínimo sería.
Ronda() array de bytes //string, objetos jugador, etc..
Turno, Numjugadores byte
evento NuevaRonda
evento SuTurno(byte jugador) // string, objeto jugador, etc...
byte = Propiedad lectura TurnoJugador
devolver Turno
fin propiedad
byte = Propiedad lectura CantidadJugadores
devolver NumJugadores
fin propiedad
buleano = Funcion FinRonda
devolver (turno = (NumJugadores-1))
fin funcion
// Creando una nueva instancia del objeto.
funcion Nuevo(byte jugadores)
NumJugadores = jugadores
Redimencionar array Ronda(0 a NumJugadores -1)
Turno = 0
fin funcion
// Se reclama que se permita jugar al siguiente jugador
funcion SiguienteTurno
Si (turno < (NumJugadores-1))
Turno + =1
Sino
Turno = 0
disparar evento NuevaRonda
Fin si
disparar evento SuTurno(Turno)
Fin funcion
Como ves en el ejemplo, no hacemos uso del array... si solo se guía el objeto por un valor que señala un índice, y ese es siempre incremental, esto es sucede siempre en orden, no se precisa.
En tal caso este objeto lo instancia la 'base del juego' (podría ser o llamarse objeto 'banca'). Así cuando se dispara el evento turno, la base del juego recibe el evento y como mantiene referencia a cada jugador sabrá derivar el turno al jugador que corresponda.
Esto es sencillo, si se la forma de interacción fuera más complejo, porque os jugadores no precisan jugar por turnos, es cuando se precisa hacer uso del array... También en este caso quizás sea preferible que no sea el objeto banca quien utilice este objeto directamente, simplemente lo crea y luego pasa una referencia del mismo a cada jugador que se 'inscribe' en el juego, y es luego el jugador quien directamente haga su juego y lo anuncia a este objeto...
No haré algo exhausitvo ni muy grande, solo lo suficiente para reflejar esta última idea...
Ronda() array de bytes //string, objetos jugador, etc..
Turno, Numjugadores byte
evento NuevaRonda
//evento SuTurno(byte jugador) // string, objeto jugador, etc...
byte = Propiedad lectura TurnosJugados // en la Ronda actual
devolver Turno
fin propiedad
byte = Propiedad lectura CantidadJugadores
devolver NumJugadores
fin propiedad
buleano = Funcion FinRonda
devolver (Turno = (NumJugadores-1))
fin funcion
// Creando una nueva instancia del objeto.
funcion Nuevo(byte jugadores)
NumJugadores = jugadores
Redimencionar array Ronda(0 a NumJugadores -1)
Turno = 0
fin funcion
// Un jugador reclama su turno de jugada...
// solo será posible si no ha jugado ya su turno en esta ronda...
buleano = funcion TurnoJugador(byte Jugador)
Si (Turno = (NumJugadores-1)) // se acabó la ronda actual?, si sí, siguiente ronda
Turno = 0
bucle para k desde a NumJugadores -1
Ronda(k) = 0
siguiente
disparar evento NuevaRonda
Fin si
Si (Ronda(jugador)= 0) // si no ha jugado en esta ronda, se le permite
Ronda(Jugador) = 1 // ma
Turno + =1
// disparar evento SuTurno(Turno)
Devolver True // el evento queda remplazado por la devolución de la llamada.
Sino // este jugador ya jugó en esta ronda.
devolver FALSE
Fin si
Fin funcion
Como ves, el código es casi el mismo, estos son las diferencias:
- Se ha cambiado el nombre de la propiedad: TurnoJugador por TurnosJugados
- el evento SuTurno, no se requiere.
- La funcion TurnoJugador:
----- Ahora devuelve un bulenao en vez de dispara el evento 'suTurno'
----- Recibe como parámetro el índice del jugador que pretende jugar.
----- El array Rondas, mantiene quien ha jugado en esta ronda y quien no, sea cual sea el orden en que jueguen.
Finalmente puedes usar un sencillo negociado con este objeto, en vez de usarlo solamente para obtener turno y recordar que jugadores jugaron ya en la ronda, también puedes añadir un método que recuerde 'la apuesta' del jugador... así la consulta como debe hacerse sí sí aquí, ya se tiene la respuesta sin una consulta posterior al jugador...
En el siguiente pseudocodigo, solo pongo las ideas, los cambios que fueren precisos al resto queda a tu esfuerzo...
verás (por ejemplo) que ahora el array en vez de ser de tipo byte es del tipo de una estructura de 'datos'...
enumeracion EstadoDeTurno
TURNO_NO_JUGADO = 0
TURNO_JUGANDO = 1
TURNO_YA_JUGADO =2
Fin enumeracion
estructura Datos
EstadoDeTurno Estado // del tipo de la enumeración justo recién declarada.
byte Carta
fin estructura
Ronda() array de Datos // de la estructura recién declarada.
// ofrecer el turno de juego a un jugador...
buleano = funcion TurnoJugador(byte Jugador)
Si (Ronda(jugador).Estado = TURNO_NO_JUGADO) // si no ha jugado en esta ronda, se le permite
Ronda(Jugador).Estado = TURNO_JUGANDO
//Turno + =1
// disparar evento SuTurno(Turno)
Devolver True // el evento queda remplazado por la devolución de la llamada.
Sino // este jugador ya jugó en esta ronda.
devolver FALSE
Fin si
Fin funcion
// jugador comunica su apuesta en esta ronda...
funcion ApuestaJugador(byte Jugador, byte Carta)
Si (Ronda(jugador).Estado = TURNO_JUGANDO)
Ronda(Jugador).Estado = TURNO_YA_JUGADO
Ronda(Jugador).Carta = Carta
Turno + =1
Si (Turno = (NumJugadores-1)) // se acabó la ronda actual?, si sí, siguiente ronda
disparar evento RondaTerminada // Último momento para consultar, luego se borrarán los datos...
Turno = 0
bucle para k desde a NumJugadores -1
Ronda(k).Estado = TURNO_NO_JUGADO
Ronda(k).Carta = 0 //equivale a ninguna
siguiente
fin si
Fin si
Fin funcion
// Devuelve la apuesta dle jugador, (0 si todavía no apostó/jugó su turno...
// la consulta se puede hacer en cualquier momento, pero mejor cuando se lanza el evento RondaTerminada
byte = funcion ConsultarApuesta(byte Jugador)
devolver Ronda(Jugador).Carta
fin funcion
Ahora el evento cambio de nombre, porque sucede justo al término de la ronda... pero antes de borrar los datos de la ronda, para dar ocasión a consultar la jugada de cada jugador...
Si carta = 0 es para señalar que no ha jugado, los valores de cartas deberán comenzar de 1 en adelante, si es forzado que deba empezar en 0, usar el valor 255 para indicar que el jugador no ha apostado aún...
Nota que ahora ase ha añadido además un método de consulta, y que el array Ronda ahora tiene pleno sentido... frente al primer pseudocódigo, quersultaba inútil, o en el segundo, que permitía ya liberar el orden de juego de los turnos, ahora... es más útil mantiendo info de la ronda actual... si eres inquieto, sabrás darle más utilidad.
Un objeto ronda, pués puede ser muy útil para mantener los datos de la ronda actual...
...y bueno, para tú no haber puesto ni una línea de código, creo que yo ya he puesto suficiente pseudocódigo para aclarar alguna de tus dudas...
Muchas gracias, en casa pongo en practica todo lo que me comentas.
El problema es que cada jugador tiene un array con sus cartas pero a la hora de jugar su turno todos los jugadores usan las cartas del array del jugador en ultimo lugar.
La baraja de cartas, debe mantenerla 'la banca'. El jugador a lo sumo debe mantener las suyas propias... aunque si (el juego) no es muy complejo, no resulta difícil hacer que la banca mantenga o sepa a quien pertenece cada carta que ha salido (esto libera en parte a cada jugador de dicha tarea (es más sencillo aquí), pero solo si resulta conveniendte según la dinámica del juego):
estructura Cartas
byte Numero // por ejemplo de 1 a 40... esto se asigna una sola vez cuando se crea el juego.
byte Jugador // valor 0, carta aún en poder de la banca, otro valor pertenece al jugador cuyo indice se indica
fin estructura
byte NumCartas
constante MaxCartas = 40
Array de Cartas Baraja (0 a maxcartas -1)
Cuando una carta es retirada por un jugador, no es preciso moverla a otro array, se intercambia por la última 'accesible' en el array... veámoslo (parcialmente) en un método de la banca...
Nota que dependeindo del tipo de juego, el jugador toma la 'siguiente carta' que le reparten o a veces puede elegir él mismo, se asume el primer caso... están barajadas y sedescnoce cuales son.
evento PartidaTerminada
// Esta función solo podría ser llamada si como resultado del código de arriba al jugador se le permite jugar su turno...
// entrega la siguiente carta al jugador
byte Funcion Apuesta(byte Jugador)
byte tmp
cartas crt //tipo cartas, la estructura...
Si (NumCartas > 0) //' si quedan cartas que repartir
// Haciendo esta resta ahora en vez de al final, nos evita el -1, en las 3 ocasiones que aquí se usa...
numCartas -= 1 // restamos una carta disponible... al principio eran 40, cuando llegue a 0, la partida acaba.
tmp = Random(entre 0 y numCartas)
// intercambiar la carta índice tmp por la carta índice numcartas
crt = Baraja(tmp)
Baraja(tmp) = Baraja(numCartas)
Baraja(numCartas) = crt
crt.Jugador = jugador //esta carta se marca pertenececiente (apostada, elegida, designada) a éste jugador
devolver crt.Numero //devolve rla carta... el número puede ser referencia del valor
// Así el 1 al 10 pueden ser oros, del 11 al 20, copas, del 21 al 30 espadas y del 31 al 40 bastos... o cualquier otra disposición... según tu preferencia, o que uses cartas de pokér y requieras 52 cartas, etc...
sino
Disparar evento PartidaTerminada //ofrece la posibilidad de escrutar qien ganó la partida, mostrar resultados etc...
// No estaría demás aquí solicitar si se desea jugar otra partida, en vez de asumir que es así...
//Si jugadoresquierenOtraPartida
NumCartas = MaxCartas
BarajarCartas // pone a 0 el apartado .jugador de cada carta y luego desordena las cartas...
BorrarDatosPartida // los que pueda tener la banca y los jugadores, pero no un computo global del juego, si lo hay...
//sino
//juego terminado, mostrar el ganador absoluto de todas las partidas (mejor mostrar la lista de ordenada de jugadores con nº de partidas ganadas, puntuación etc...
//fin si
fin si
fin funcion