Pascal/Turbo Pascal - URGENTE Juego de domino en dev pascal

 
Vista:
sin imagen de perfil
Val: 6
Ha disminuido su posición en 13 puestos en Pascal/Turbo Pascal (en relación al último mes)
Gráfica de Pascal/Turbo Pascal

URGENTE Juego de domino en dev pascal

Publicado por Ces (1 intervención) el 02/07/2020 01:21:44
Hola, quisiera que alguien me orientara a crear un juego de domino en pascal. Puede ser de 2 hasta 4 jugadores. Por favor, que no se como hacer que el usuario juegue y como hacer que aparezca la cadena de fichas jugadas (con coherencia). Además, si las fichas de un jugador las tengo en un array de 1 a 7 de string, como hago para que cuando vaya a jugar la ficha la juegue por el lado correcto de esta?
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil
Val: 112
Bronce
Ha mantenido su posición en Pascal/Turbo Pascal (en relación al último mes)
Gráfica de Pascal/Turbo Pascal

URGENTE Juego de domino en dev pascal

Publicado por juanba (40 intervenciones) el 04/07/2020 10:37:16
Precioso problema. Más de Algoritmia que de programación Pascal, pero muy interesante de todos modos.
Voy a plantearte una posible solucion (sin desarrollarla hasta el final, que también tú tienes derecho a divertirte) usando estructuras de Conjunto (Set) que se adaptan bastante bien a la mano que lleva cada jugador como a las fichas ya colocadas en la partida. Las funciones Include y Exclude, que veo que existen en DevPascal, facilitan la entrada y salida de fichas al conjunto.
El problema es que para la representación de la ficha, la opción evidente es un array, un Record o un Object, pero son estructuras, no ordinales que es lo que se necesita para los elementos de un Set. De modo que hay que hacer una correspondencia entre las fichas presentadas como arrays o Records y un número ordinal. Hay muchas maneras de hacerlo, yo voy a intentar hacer algo rapidito y sobre todo lo más claro posible. Que no será mucho.
La cosa sería algo así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const MaxNumFicha = 28;
 type TExtremo = (Uno, Dos);   // O Izda-Dcha, o Norte-Sur, o Cerca-Lejos (remember kermit of sesame street?)
 type TValor = 0..6;
      TDobleValor = array[TExtremos] of TValor;
 type TFicha = TDobleValor;
 
 type TFicha = record
   FValorUno: TValor;
   FValorDos: TValor;
   end;
 
type TNumFicha = 1..MaxNumFicha;                                     // Numeros de orden de las fichas 1..28
type TMano = Set of TNumFicha;                                            // Fichas que tiene un jugador en su mano
type TManos = array[1..MaxJugador] of TMano;                    // Fichas de los cuatro jugadores
type TPartida = Set of Numficha;                                              // Fichas que ya están en la mesa
type TJugador = 2..MaxJugador;                                              // Rango del numero de jugadores
 
// Ahora voy a hacer la correspondencia de las fichas con una lista de ordinales:
// Primeramente creo una tabla de referencia en la que incluyo las 28 fichas:
 
var TablaRef: array[TNumFicha] of TFicha;
var Manos: TManos;                     // Conjuntos de fichas de los 4 jugadores
var Jugador: TJugador;
var Partida: TPartida;
var PartExtremo: TDobleValor;             // Extremos de la partida. Para controlar que fichas se pueden añadir.
  // Contiene el valor más a la izquierda (extremo uno)  y el más a la derecha (extremo dos) de la jugada actual.
 
procedure CrearTablaRef;
var IndUno, IndDos, Indice: integer;
begin
  Indice := 1;
  for IndUno := 0 to 6 do
    for IndDos := IndUno to 6 do
    begin
    TablaRef[Indice][Uno] := IndUno;
    TablaRef[Indice][Dos] := IndDos;
    Indice := Indice + 1;
    end;
end;
 
// Una vez que esta creada la tabla de referencia, es fácil conmutar entre fichas y su numero de referencia (1..28).
 
Function OrdinalAFicha(const NumOrd: TNumFicha): TFicha;
begin
  Result := TablaRef[NumOrd];
end;
 
// La funcion inversa FichaAOrdinal es un poco más complicada pero de momento no se necesita}
// Otra funcion que necesitaré más tarde:
function ValorOpuesto(DobleValor: TDobleValor; ExtActual: TExtremo): TValor;
begin
  if ExtActual = Uno then
    Result := DobleValor[Dos]
  else
    Result := DobleValor[Uno];
end;

Ahora solo queda:
- Repartir las fichas, o sea llenar los Sets del array Manos. Algo así como

1
2
3
4
begin
    for Jugador := 1 to NumJugador do
      for j := 1 to 7 do
        Include(Manos[Jugador], Random(MaxNumFicha + 1);

Esta instruccion, evidentemente NO VALE porque la funcion Random no garantiza que no va a dar valores repetidos, pero la dejo como punto de partida. Todo es cuestion de pulirlo un poco.
- Una vez repartidas las fichas, hay que ir jugandolas, o sea pasar de la mano de cada jugador a la partida. Para ello hay que usar una ficha que coincida con uno de los dos extremos de la partida que estan en ExtValor (puede ser que la ficha coincida con ambos).
Para encontrar los candidatos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  // Estamos con Jugador. Aplicarlo después al siguiente, etc y volver al primero hasta que termine el juego.
  // Y es una pena que dev-pascal no tenga la construcción for <valor> in <set> do que hace un barrido de los elementos del set.
    for Indice := 1 to MaxNumFicha do if Indice in Manos[Jugador] then
    begin
      Ficha := OrdinalAFicha(Indice);
                                       // Probar si esta ficha vale. Podemos usarla
                                       // sin mas o buscar mas candidatas y
                                       // decidirlo después. Pero esto ya es
                                       // cuestión de estrategia del juego y no
                                       // estamos resolviendo eso.
       JugarFicha(Jugador, Indice);
       if Manos[Jugador] = [] then     // Si se ha vaciado la mano...
         Jugador HA GANADO.            // Soy el campeón!
     end;
  end;

Y el procedimiento JugarFicha sería algo así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function JugarFicha(Jugador: TNumJugador; var Indice: TNumFicha): boolean;
  var ExtPartida, ExtFicha;            // Tantear los dos valores en Extremos y Ficha
  var Ficha: TFicha;
  begin
    Ficha := OrdinalToFicha(Indice);
    for ExtPartida := Uno to Dos do for ExtFicha := Uno to Dos do
      if Ficha[ExtFicha] = PartExtremo[ExtPartida] then
      begin
        Exclude(Manos[Jugador], Indice); // Quitar la ficha al jugador
        Include(Partida, Indice);        // y ponerla en la partida
                           // Cambiar el valor al extremo poniendo el valor del otro lado de la ficha
        PartExtremo[ExtPartida] := ValorOpuesto(Ficha, ExtFicha)];
        break;                           // Ya hemos jugado la ficha -->salir
      end;
    else
    begin
      // NO SE PUEDE PONER ESTA FICHA. Probar con otra y si no hay más, dar paso al siguente jugador
    end;
  end;

Falta ensamblar un programa inicializando las variables, crear la tabla de referencia y organizar un bucle de jugadas en que cada jugador vaya sacando las fichas que puede añadir a los extremos hasta que se quede sin fichas.
Como no he llegado a crear un programa completo no he podido comprobar el código, que supongo que tendrá bastantes errores. Paciencia.
Si tienes mas problemas, explicalos en un post o mandame un mensaje. Intentaremos aclararlo.
A seguir lo menos mal posible.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar