Ayuda juego Mastermind en C++

Iniciado por TheXiiscoZ, 10 Diciembre 2017, 17:13 PM

0 Miembros y 1 Visitante están viendo este tema.

TheXiiscoZ

Buenas, mi compañero y yo hemos empezado este año en TIC y nuestro primer trabajo es programar un juego sencillo, nada del otro mundo y que tenemos que entregar. Sí, somos muy novatos en la programación y apenas hace 1 mes que empezamos y necesitamos acabar el juego.

Nuestra idea es crear un mastermind, con diferentes dificultades desde el modo clásico (4 digitos) hasta añadirles mas niveles pero no damos con la tecla a la hora de introducir el código y el programa revise si en los números hay heridos, muertos etc.


#include <iostream>
#include <windows.h>
#include <sstream>
#include <string>
using namespace std;
int a,b,c,d,N;
int q,w,e,r;

void clasicresp(){
   N=N-1;
   cout<<"Intenta adivinar el codigo. Quedan" <<N<<"intentos" <<endl;
   cin>>q;
   cin>>w;
   cin>>e;
   cin>>r;
   
   if(a=q){
      cout<<"Excelente, todos los números son correctos";
         }
         else{
         clasicresp();   
         }
}

void cla(){
   N=12;
   cout<<"Introduce el codigo"<<endl;
   cin>>a;
   cin>>b;
   cin>>c;
   cin>>d;
   system("cls");
   clasicresp();
}


   
   
   



void jugar(){
        int d;
        system("cls");
      cout<<"****SELECCIONA EL NIVEL DE DIFICULTAD*****"<<endl;
      cout<<""<<endl;
      cout<<"[1] NOOB"<<endl;
      cout<<"[2] CLASICO"<<endl;
       cout<<"[3] DIFICIL"<<endl;
      cout<<"[4] HARDCORE"<<endl;
      cin>> d;
      
      switch(d){
      case 1:
      break;
      case 2: cla();
      break;
      case 3:
      break;
      case 4:
      break;
      default:
      cout<<"Valor no valido"<<endl;
      Sleep(1500);
      system("cls");
      jugar();
   }
      
      
}


void menu(){
   int n;
   cout<<"=============================="<<endl;
   cout<<"Bienvenido a Inspector Numbers"<<endl;
   cout<<"=============================="<<endl;
   cout<<""<<endl;
   cout<<"[1] Jugar"<<endl;
   cout<<"[2] Ayuda"<<endl;
   cin>> n;
   switch(n){
      case 1: jugar();
      break;
      case 2: system("cls");
               cout<<"NO PIERDAS ;)"<<endl;
      break;
      default:
      cout<<"Valor no valido"<<endl;
      Sleep(1500);
      system("cls");
      menu();
   }
   

}

int main(){
menu();
return 0;
}



_TTFH_3500

#1
Este es un codigo que hice hace varios años en Pascal, se puede pasar a C muy fácil.

"Regulares" es a lo que tu llamas heridos y "buenos" es muertos.
ObtenerNota haya dichos valores en el codigo, en este caso tiene un largo de seis letras que pueden ir de la A a la H

Código (pascal) [Seleccionar]
PROCEDURE ObtenerNota(propuesta, codigo: TipoCodigo; VAR buenos, regulares: RangoBR);

Código (cpp) [Seleccionar]
void ObtenerNota(TipoCodigo propuesta, TipoCodigo codigo, RangoBR &buenos, RangoBR &regulares) {

Código (pascal) [Seleccionar]
PROGRAM MasterMind (input, output);
CONST
MAXIMO_INTENTOS = 20;
LARGO_CODIGO = 6;
PRIMERA_LETRA = 'A';
ULTIMA_LETRA = 'H';
TYPE
RangoCodigo = 1..LARGO_CODIGO;
TipoCodigo = ARRAY [RangoCodigo] OF Char;

RangoBR = 0..LARGO_CODIGO;
TRegistroNota = RECORD
codigo: TipoCodigo;
buenos,
regulares: RangoBR
END;

   THistoria = RECORD
info: ARRAY [1..MAXIMO_INTENTOS] OF TRegistroNota;
tope: 0..MAXIMO_INTENTOS
END;

ListaNotas = ^CeldaNota;
CeldaNota = RECORD
codigo: TipoCodigo;
buenos,
regulares: RangoBR;
turno: 1..MAXIMO_INTENTOS;
siguiente: ListaNotas
END;
VAR
secreto, codigo: TipoCodigo;
historia: THistoria;
buenos, regulares: RangoBR;
i, intentos: Integer;
exito, fracaso: Boolean;
lista: ListaNotas;

FUNCTION EsValido(codigo: TipoCodigo): Boolean;
VAR
i: Integer;
BEGIN
i := 1;
WHILE (i <= LARGO_CODIGO) AND (codigo[i] >= PRIMERA_LETRA) AND (codigo[i] <= ULTIMA_LETRA) DO
i := i + 1;
EsValido :=  i > LARGO_CODIGO
END;

PROCEDURE ObtenerNota(propuesta, codigo: TipoCodigo; VAR buenos, regulares: RangoBR);
VAR
i, j, max: Integer;
propuestacopia: TipoCodigo;
BEGIN
buenos := 0;
FOR i := 1 TO LARGO_CODIGO DO
BEGIN
IF propuesta[i] = codigo[i] THEN
buenos := buenos + 1;
propuestacopia[i] := propuesta[i]
END;
max := 0;
FOR i := 1 TO LARGO_CODIGO DO
BEGIN
j := 1;
WHILE (j <= LARGO_CODIGO) AND (codigo[i] <> propuestacopia[j]) DO
j := j + 1;
IF j <= LARGO_CODIGO THEN
BEGIN
max := max + 1;
propuestacopia[j] := ' '
END
END;
regulares := max - buenos
END;

PROCEDURE IniciarHistoria(VAR historia: THistoria);
BEGIN
WITH historia DO
tope := 0
END;

PROCEDURE GuardarNota(VAR historia: THistoria;
codigo: TipoCodigo;
buenos, regulares: RangoBR);
VAR
i: Integer;
BEGIN
WITH historia DO
BEGIN
tope := tope + 1;
FOR i := 1 TO LARGO_CODIGO DO
info[tope].codigo[i] := codigo[i];
info[tope].buenos := buenos;
info[tope].regulares := regulares
END
END;

FUNCTION ListaOrdenada(historia: THistoria): ListaNotas;
VAR
i, j: Integer;
p, actual, anterior, lista: ListaNotas;
BEGIN
lista := NIL;
FOR i := 1 TO historia.tope DO
BEGIN
new(p);
FOR j := 1 TO LARGO_CODIGO DO
p^.codigo[j] := historia.info[i].codigo[j];
p^.buenos := historia.info[i].buenos;
p^.regulares := historia.info[i].regulares;
p^.turno := i;

actual := lista;
anterior := lista;
WHILE (actual <> NIL) AND (10 * actual^.buenos + actual^.regulares <= 10 * p^.buenos + p^.regulares) DO
BEGIN
anterior := actual;
actual := actual^.siguiente
END;
IF (anterior = NIL) OR (anterior = actual) THEN
BEGIN
p^.siguiente := anterior;
lista := p
END
ELSE
BEGIN
p^.siguiente := actual;
anterior^.siguiente := p
END
END;
ListaOrdenada := lista
END;

PROCEDURE GenerarCodigo(VAR codigo: TipoCodigo);
VAR
i: Integer;
ordprim, ordult: Integer;
BEGIN
ordprim := ord(PRIMERA_LETRA);
ordult  := ord(ULTIMA_LETRA);
FOR i := 1 TO LARGO_CODIGO DO
codigo[i] := chr(ordprim + random(ordult - ordprim + 1))
END;

PROCEDURE LeerCodigo(VAR codigo: TipoCodigo);
VAR
i: Integer;
BEGIN
FOR i := 1 TO LARGO_CODIGO DO
Read(codigo[i]);
ReadLn
END;

(* ------ Programa Principal ------ *)
BEGIN
Randomize;
IniciarHistoria(historia);
GenerarCodigo(secreto);
intentos := 0;
exito := false;
fracaso := false;
WriteLn('He pensado un codigo, intenta adivinarlo.');
WriteLn('*Pista: tiene ', LARGO_CODIGO, ' letras y estas estan entre la ', PRIMERA_LETRA, ' y la ', ULTIMA_LETRA);
WriteLn('Las letras pueden repetirse o no aparecer en mi codigo, y solo tienes ', MAXIMO_INTENTOS, ' intentos.');
WriteLn;
REPEAT
LeerCodigo(codigo);
WHILE NOT EsValido(codigo) DO
BEGIN
WriteLn('El codigo no es valido, intentalo de nuevo.');
LeerCodigo(codigo)
END;
intentos := intentos + 1;
ObtenerNota(codigo, secreto, buenos, regulares);
IF buenos = LARGO_CODIGO THEN
exito := true
ELSE IF intentos = MAXIMO_INTENTOS THEN
fracaso := true
ELSE
BEGIN
Write('B: ', buenos, '   R: ', regulares);
WriteLn('                      Te quedan ', MAXIMO_INTENTOS - intentos, ' intentos')
END;
GuardarNota(historia, codigo, buenos, regulares)
UNTIL exito OR fracaso;
WriteLn;
WriteLn;
IF exito THEN
WriteLn('***** FELICIDADES, has ganado. *****')
ELSE
BEGIN
WriteLn('--- Demasiados intentos, perdiste. ---');
Write  ('    El codigo secreto era: ');
FOR i := 1 TO LARGO_CODIGO DO
Write(secreto[i])
END;
WriteLn;
WriteLn;
lista := ListaOrdenada(historia);
WHILE lista <> NIL DO
BEGIN
FOR i := 1 TO LARGO_CODIGO DO
Write(lista^.codigo[i]);
Write(' -->  Bs = ', lista^.buenos, ',  Rs = ', lista^.regulares, ' (Turno: ', lista^.turno, ')');
WriteLn;
lista := lista^.siguiente
END;
ReadLn
END.

TheXiiscoZ

Cita de: _TTFH_3500 en 10 Diciembre 2017, 17:58 PM
Este es un codigo que hice hace varios años en Pascal, se puede pasar a C muy fácil.

"Regulares" es a lo que tu llamas heridos y "buenos" es muertos.
ObtenerNota haya dichos valores en el codigo, en este caso tiene un largo de seis letras que pueden ir de la A a la H

Código (pascal) [Seleccionar]
PROCEDURE ObtenerNota(propuesta, codigo: TipoCodigo; VAR buenos, regulares: RangoBR);

Código (cpp) [Seleccionar]
void ObtenerNota(TipoCodigo propuesta, TipoCodigo codigo, RangoBR &buenos, RangoBR &regulares) {

Código (pascal) [Seleccionar]
PROGRAM MasterMind (input, output);
CONST
MAXIMO_INTENTOS = 20;
LARGO_CODIGO = 6;
PRIMERA_LETRA = 'A';
ULTIMA_LETRA = 'H';
TYPE
RangoCodigo = 1..LARGO_CODIGO;
TipoCodigo = ARRAY [RangoCodigo] OF Char;

RangoBR = 0..LARGO_CODIGO;
TRegistroNota = RECORD
codigo: TipoCodigo;
buenos,
regulares: RangoBR
END;

   THistoria = RECORD
info: ARRAY [1..MAXIMO_INTENTOS] OF TRegistroNota;
tope: 0..MAXIMO_INTENTOS
END;

ListaNotas = ^CeldaNota;
CeldaNota = RECORD
codigo: TipoCodigo;
buenos,
regulares: RangoBR;
turno: 1..MAXIMO_INTENTOS;
siguiente: ListaNotas
END;
VAR
secreto, codigo: TipoCodigo;
historia: THistoria;
buenos, regulares: RangoBR;
i, intentos: Integer;
exito, fracaso: Boolean;
lista: ListaNotas;

FUNCTION EsValido(codigo: TipoCodigo): Boolean;
VAR
i: Integer;
BEGIN
i := 1;
WHILE (i <= LARGO_CODIGO) AND (codigo[i] >= PRIMERA_LETRA) AND (codigo[i] <= ULTIMA_LETRA) DO
i := i + 1;
EsValido :=  i > LARGO_CODIGO
END;

PROCEDURE ObtenerNota(propuesta, codigo: TipoCodigo; VAR buenos, regulares: RangoBR);
VAR
i, j, max: Integer;
propuestacopia: TipoCodigo;
BEGIN
buenos := 0;
FOR i := 1 TO LARGO_CODIGO DO
BEGIN
IF propuesta[i] = codigo[i] THEN
buenos := buenos + 1;
propuestacopia[i] := propuesta[i]
END;
max := 0;
FOR i := 1 TO LARGO_CODIGO DO
BEGIN
j := 1;
WHILE (j <= LARGO_CODIGO) AND (codigo[i] <> propuestacopia[j]) DO
j := j + 1;
IF j <= LARGO_CODIGO THEN
BEGIN
max := max + 1;
propuestacopia[j] := ' '
END
END;
regulares := max - buenos
END;

PROCEDURE IniciarHistoria(VAR historia: THistoria);
BEGIN
WITH historia DO
tope := 0
END;

PROCEDURE GuardarNota(VAR historia: THistoria;
codigo: TipoCodigo;
buenos, regulares: RangoBR);
VAR
i: Integer;
BEGIN
WITH historia DO
BEGIN
tope := tope + 1;
FOR i := 1 TO LARGO_CODIGO DO
info[tope].codigo[i] := codigo[i];
info[tope].buenos := buenos;
info[tope].regulares := regulares
END
END;

FUNCTION ListaOrdenada(historia: THistoria): ListaNotas;
VAR
i, j: Integer;
p, actual, anterior, lista: ListaNotas;
BEGIN
lista := NIL;
FOR i := 1 TO historia.tope DO
BEGIN
new(p);
FOR j := 1 TO LARGO_CODIGO DO
p^.codigo[j] := historia.info[i].codigo[j];
p^.buenos := historia.info[i].buenos;
p^.regulares := historia.info[i].regulares;
p^.turno := i;

actual := lista;
anterior := lista;
WHILE (actual <> NIL) AND (10 * actual^.buenos + actual^.regulares <= 10 * p^.buenos + p^.regulares) DO
BEGIN
anterior := actual;
actual := actual^.siguiente
END;
IF (anterior = NIL) OR (anterior = actual) THEN
BEGIN
p^.siguiente := anterior;
lista := p
END
ELSE
BEGIN
p^.siguiente := actual;
anterior^.siguiente := p
END
END;
ListaOrdenada := lista
END;

PROCEDURE GenerarCodigo(VAR codigo: TipoCodigo);
VAR
i: Integer;
ordprim, ordult: Integer;
BEGIN
ordprim := ord(PRIMERA_LETRA);
ordult  := ord(ULTIMA_LETRA);
FOR i := 1 TO LARGO_CODIGO DO
codigo[i] := chr(ordprim + random(ordult - ordprim + 1))
END;

PROCEDURE LeerCodigo(VAR codigo: TipoCodigo);
VAR
i: Integer;
BEGIN
FOR i := 1 TO LARGO_CODIGO DO
Read(codigo[i]);
ReadLn
END;

(* ------ Programa Principal ------ *)
BEGIN
Randomize;
IniciarHistoria(historia);
GenerarCodigo(secreto);
intentos := 0;
exito := false;
fracaso := false;
WriteLn('He pensado un codigo, intenta adivinarlo.');
WriteLn('*Pista: tiene ', LARGO_CODIGO, ' letras y estas estan entre la ', PRIMERA_LETRA, ' y la ', ULTIMA_LETRA);
WriteLn('Las letras pueden repetirse o no aparecer en mi codigo, y solo tienes ', MAXIMO_INTENTOS, ' intentos.');
WriteLn;
REPEAT
LeerCodigo(codigo);
WHILE NOT EsValido(codigo) DO
BEGIN
WriteLn('El codigo no es valido, intentalo de nuevo.');
LeerCodigo(codigo)
END;
intentos := intentos + 1;
ObtenerNota(codigo, secreto, buenos, regulares);
IF buenos = LARGO_CODIGO THEN
exito := true
ELSE IF intentos = MAXIMO_INTENTOS THEN
fracaso := true
ELSE
BEGIN
Write('B: ', buenos, '   R: ', regulares);
WriteLn('                      Te quedan ', MAXIMO_INTENTOS - intentos, ' intentos')
END;
GuardarNota(historia, codigo, buenos, regulares)
UNTIL exito OR fracaso;
WriteLn;
WriteLn;
IF exito THEN
WriteLn('***** FELICIDADES, has ganado. *****')
ELSE
BEGIN
WriteLn('--- Demasiados intentos, perdiste. ---');
Write  ('    El codigo secreto era: ');
FOR i := 1 TO LARGO_CODIGO DO
Write(secreto[i])
END;
WriteLn;
WriteLn;
lista := ListaOrdenada(historia);
WHILE lista <> NIL DO
BEGIN
FOR i := 1 TO LARGO_CODIGO DO
Write(lista^.codigo[i]);
Write(' -->  Bs = ', lista^.buenos, ',  Rs = ', lista^.regulares, ' (Turno: ', lista^.turno, ')');
WriteLn;
lista := lista^.siguiente
END;
ReadLn
END.


Me da error al compilar; me da el error de too many decimals on point en la linea 8

_TTFH_3500

Aquí lo tienes en C++ más reducido, este no muestra el historial de intentos.

También tengo una IA que busca las mejores combinaciones en base a los intentos anteriores.

Código (cpp) [Seleccionar]

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>

const int MAXIMO_INTENTOS = 20;
const int LARGO_CODIGO = 6;
const char PRIMERA_LETRA = 'A';
const char ULTIMA_LETRA = 'H';

typedef char TipoCodigo[LARGO_CODIGO + 1];

bool EsValido(TipoCodigo codigo) {
// Devuelve true si el codigo es valido.
int i = 1;
while (i <= LARGO_CODIGO && codigo[i] >= PRIMERA_LETRA && codigo[i] <= ULTIMA_LETRA)
i++;
// Es valido si todos los elementos del codigo estan en el rango.
return i > LARGO_CODIGO;
}

void ObtenerNota(TipoCodigo propuesta, TipoCodigo codigo, unsigned int &buenos, unsigned int &regulares) {
// Obtener cantidad de buenos y regulares entre dos codigos.
TipoCodigo propuestacopia;
buenos = 0;
for (int i = 1; i <= LARGO_CODIGO; i++) {
if (propuesta[i] == codigo[i]) buenos++;
propuestacopia[i] = propuesta[i];
}
int max = 0;
// Hallar la "maxima" cantidad de buenos.
for (int i = 1; i <= LARGO_CODIGO; i++) {
int j = 1;
while (j <= LARGO_CODIGO && codigo[i] != propuestacopia[j]) j++;
if (j <= LARGO_CODIGO) {
// Borrar la letra para no volver a usar la misma.
propuestacopia[j] = ' ';
max++;
}
}
regulares = max - buenos;
}

void GenerarCodigo(TipoCodigo &codigo) {
// Generar codigo aleatorio
int ord_prim = (int)PRIMERA_LETRA;
int ord_ult = (int)ULTIMA_LETRA;
for (int i = 1; i <= LARGO_CODIGO; i++)
codigo[i] = ord_prim + rand() % (ord_ult - ord_prim + 1);
}

void LeerCodigo(TipoCodigo &codigo) {
char c;
for (int i = 1; i <= LARGO_CODIGO; i++) {
scanf("%c", &c);
codigo[i] = toupper(c);
}
do {
c = getchar();
} while (c != '\n');
}

int main() {
srand(time(NULL));
TipoCodigo secreto;
GenerarCodigo(secreto);
int intentos = 0;
bool exito = false;
bool fracaso = false;
printf("He pensado un codigo, intenta adivinarlo.\n");
printf("*Pista: tiene %d letras y estas estan entre la %c y la %c\n", LARGO_CODIGO, PRIMERA_LETRA, ULTIMA_LETRA);
printf("Las letras pueden repetirse o no aparecer en el codigo, y solo tienes %d intentos.\n\n", MAXIMO_INTENTOS);
do {
TipoCodigo codigo;
LeerCodigo(codigo);
while (!EsValido(codigo)) {
printf("El codigo no es valido, intentalo de nuevo.\n");
LeerCodigo(codigo);
}
intentos++;
unsigned int buenos, regulares;
ObtenerNota(codigo, secreto, buenos, regulares);
if (buenos == LARGO_CODIGO) exito = true;
else if (intentos == MAXIMO_INTENTOS) fracaso = true;
else {
printf("B: %d   R: %d", buenos, regulares);
printf("                      Te quedan %d intentos\n", MAXIMO_INTENTOS - intentos);
}
} while (!(exito || fracaso));

printf("\n\n");
if (exito) printf("***** FELICIDADES, has ganado. *****\n");
else {
printf("--- Demasiados intentos, perdiste. ---\n");
printf("El codigo secreto era: ");
for (int i = 1; i <= LARGO_CODIGO; i++) printf("%c", secreto[i]);
}
printf("\n");
}

Serapis

#4
Darte un código, no me parece lo más adecuado.
Con copiar y pegar, no se aprende. Debes pensar por ti mismo, aunque tengas orientación.

Supongamos que las líneas contienen 4 bolas que el usuario debe resolver, elegibles sobre un total de 8 bolas

Quiere el jugador seguir jugando?

buleano = Funcion PedirPartida
   dato= PedirDatoAlUsuario("¿ DeseaJugar otra partida (S/N)? ")
   Si (dato="S") ó (dato="s") luego
       devolver TRUE
   Sino
       devolver FALSE
   Fin si
Fin funcion


Crear el array de bolas de la 'banca' y barajarlo...

Array de bytes =Funcion BarajarBolas(entero cantidad) //8 bolas
    Array bytes Bolas()
   entero i, j, k

   RedimensionarArray Bolas(0 a cantidad-1)

   // Meter en el "saco" todas las bolas que participan
   bucle para k desde 0 a cantidad-1
       Bolas(k) = k    
   Repetir

   //Barajar el array.
   // aunque se barajan todas, el usuario solo debe resolver las 4 primeras.
   bucle para k desde cantidad-1 a 1 regresivamente
       j= Random(entre 0 y k)
       i=bolas(k)
       bolas(k)= bolas(j)
       bolas(j)=i
   repetir
   
   devolver bolas //devuelve el array barajado.
Fin funcion


Cuando el jugador completa su apuesta (todas las bolas d euna línea), se verifica si es la 'respuesta' coincidente con la que almacena la banca.
cantidad es el tamaño del array bolas (8), y cantidadUser son 4, las que debe resolver el jugador.
Devuelve FALSE si la partida terminó.

buleano = funcion VerificarLinea(entero cantidad, entero cantidadUser, arraybytes bolasUser())
   entero h, i, j, k

   bucle para k desde 0 a cantidadUser-1
       j= EstaBolaUserEnBanca(bolasUser(k), cantidad)
       Si (j>=0) luego  //la bola que eligió el jugador está en la línea...
           i +=1
           si (j= bolas(k)) luego //además coincide en el sitio
               h +=1
           fin si
        fin si
   Fin bucle
   Pintar h bolas, de blanco //indicador de bolas correctas y en su sitio.
   Si (h=cantidadUser) luego
       mensaje "enhorabuena, juego resuelto"
       devolver FALSE
   Sino
       pintar i-h bolas, de gris // indicador de bolas correctas pero fuera de sitio.
       pintar cantidaduser - i bolas, de negro //indicador de bolas erróneas
       tiradas +=1  //intentos del jugador
       Si (tiradas = Maxtiradas) luego // por ejemplo 10, ó 12 tintentos
          mensaje "Lo sentimos, perdiste todas tus oportunidades de acertar. GAME OVER"
           devolver FALSE
       sino
           devolver TRUE //el jugador puede seguir jugando...
       Fin si
   Fin si
   // puede resumirse en (pintar) solo dos informaciones en vez de en 3... al gusto (omitiendo el 1º de los 3 puntosm, pintar h bolas de blanco), y/o cambiar colores para expresar una u otra cosa.
Fin funcion


Verifica si la bola apostada, consta en la línea de la banca...
Si está devuelve su posición, si no está devuelve -1

entero = Funcion EstaBolaUserEnBanca(entero Bola, entero cantidad) // esta cantidad es la de bolas totales que hay
    entero k

   bucle para k desde 0 a cantidad-1
       si bola = Bolas(k) luego
           devolver k
       fin si
   fin bucle

   devolver -1    
Fin funcion


Verifica si la bola y la posición donde el jugador la quiere depositar es válida.
Devuelve FALSE mientras al jugador le falte colocar alguna bola
No se verifica 'posición', se supone que si el jugador solo puede posicionarla en 4 posiciones no va a poder elegir un valor fuera del rango 0-3 (tampoco se verifica que la bola esté en el rango esperado (0-7)

buleano = Funcion BolaValida(entero bola, entero posicion, entero cantidadUser)
   entero j, k

   Si (bola=-1) luego  // equivale a eliminar una bola, ...para ubicarla en otra posición
       bolasUser(posicion) = -1 // -1 equivale a un hueco libre en el array de apuesta del jugador
       devolver FALSE  
   fin si
   
   // Comprobar que esa bola no haya sido ya elegida
   bucle para k desde 0 a cantidadUser-1
       Si (bola = bolasUser(k)) luego
           mensaje "Ya tienes esa bola elegida"
           devolver FALSE  //solo puede elegirse una vez una bola del mismo color.
       sino
           Si (bolasUser(k) >-1) luego
               Si (k=posicion) luego // pretende ubicarse la bola  en una posición ya ocupada...
                                                       // podria hacerse diferentes cosas, pero lo mejor es impedirlo e indicarlo.
                   mensaje "Ya hay una bola en esa posición, solo puede colocar bolas en huecos libres. si lo precisa retire una bola de la posición deseada antes de colocar otra.                                    
               fin si
           sino
               Si (k=posicion) luego
                   bolasUser(k)= bola //el jugador mete su bola en un hueco
               sino
                   j +=1  // queda un hueco más en el array para alojar una bola...
               fin si
           fin si
       fin si
   fin bucle

   Si (j=0)
       devolver TRUE //Si no hay huecos, si ya tiene todas las bolas devuelve TRUE
   sino
       devolver FALSE
   fin si
fin funcion



Función principal...

Funcion IniciarPartida
   array bytes bolas(), bolasUser()
   entero bola, posicion, tiradas, maxTiradas

   maxTiradas=10
   Hacer mientras PedirPartida = TRUE
       bolas = llamada a BarajarBolas(8)
       tiradas =0

       Hacer // nueva tirada del jugador
           bolasUser = llamada a BorrarBolasUser(4)
           Hacer // pedir bolas de una línea al jugador
               bola = PedirDatoBola al jugador (0-7) // volver a pedir mientras esté fuera del rango 0-7
               posicion = pedirDatoPosicion al jugador (0-3) // volver a pedir mientras quede fuera del rango 0-3
           Repetir mientras BolaValida(bola, posicion, 4) = FALSE    
           // al salir del bucle el jugador completo su apuesta y consta en el array bolasUser  

       Repetir mientras VerificarLinea(8, 4, bolasUser) = TRUE
   Repetir
fin funcion


Se resetea la apuesta del jugador (todo el array a valor -1)

arrayBytes = funcion BorrarBolasUser(entero cantidadUser)
   array bytes arr()
   entero k
 
   bucle para k desde 0 a cantidadUser-1
       arr(k) = -1
   fin bucle    
   
   devolver arr
fin funcion


Quizás me deje alguna pequeña funcionalidad en el tintero, pero ya tienes suficientes detalles para entenderlo y modificarlo a tu antojo... eso sí, pensando... que es de lo que trata la programación (para copiar y pegar están las impresoras, los escáneras, las cámaras de fotos... pero ellas no cran programas, se requiere pensar).

p.d.: Los niveles de dificultad, pueden crearse modificando el número de intentos que tiene el jugador así como el número de bolas que debe acertar y las bolas elegibles...
- Cuantos menos intentos, más difícil.
- Cuantas más bolas deba acertar (tenga la línea d ela banca a acertar), más difícil.
- Cuantas más bolas elegibles entre las que apostar, más difícil...