.Net C# Tragamonedas

Iniciado por 01munrra, 3 Agosto 2016, 05:09 AM

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

01munrra

saludos!!!

estoy haciendo mi proyecto final que es un tragamonedas, y estoy en el cambio de imagen del juego, El Profesor me pidio que no Usara un Timer que usara un BackGroundWorker,  entonces programe lo siguiente para el cambio de imagen del juego:

Código (csharp) [Seleccionar]

   private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            int i = 1;

            while ( i > 0 )
            {
                imagen1 = objeto.Next(0, 3);
                n1 = Convert.ToString(imagen1);
                if (imagen1 == 0)
                {
                    pictureBox1.Image = Traga_monedas_frutas.Properties.Resources.Banana;
                }
                else
                    if (imagen1 == 1)
                    {
                        pictureBox1.Image = Traga_monedas_frutas.Properties.Resources.Manzana;
                    }
                    else
                        if (imagen1 == 2)
                        {
                            pictureBox1.Image = Traga_monedas_frutas.Properties.Resources.Pina;
                        }
                        else
                            if (imagen1 == 3)
                            {
                                pictureBox1.Image = Traga_monedas_frutas.Properties.Resources.Cereza;
                            }
                i++;
            }
        }


inicio el subproceso con:

Código (csharp) [Seleccionar]

  private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }


lo detengo dando clic en un boton, ahora la logica del juego es que este cambiando constantemente la imagen de los picturebox, son 4 picture box que estoy usando, y por supuesto tengo 4 BackGroundWorker, uno para cada imagen.

el error que me esta generando es el siguiente:
Código (csharp) [Seleccionar]

El Codigo de usuario no encontro InvalidOperationException


da en la linea:

Código (csharp) [Seleccionar]

pictureBox1.Image = Traga_monedas_frutas.Properties.Resources.Banana;


que estoy haciendo mal?

gracias por su atencion.




Eleкtro

#1
Cita de: 01munrra en  3 Agosto 2016, 05:09 AM

Código (csharp) [Seleccionar]
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
       {
           int i = 1;

           while ( i > 0 )
           {
                      ...
               i++;
           }
       }

Hola

Primeramente, ¿eso exactamente con que intención lo haces?. No es necesario tener una variable-contador intermediaria para llevar a cabo las iteraciones, puedes simplificarlo de la siguiente manera:

Código (csharp) [Seleccionar]
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
   while (true) {
       // Insertar código aquí.
   }
}





Segundo, esto ya depende de gustos, puedes hacerlo como prefieras, pero yo considero que así te quedaría un código más legible e intuitivo: podrías reemplazar toda esa colmena de condicionales lo por un switch:

Código (csharp) [Seleccionar]
private static readonly Random rnd = new Random();
private static Image img;
private static Int32 imgId;


Código (csharp) [Seleccionar]
imgId = rnd.Next(minValue: 0, maxValue: 3);

switch (imgId) {

   case 0:
       img = Traga_monedas_frutas.Properties.Resources.Banana;
       break;

   case 1:
       img = Traga_monedas_frutas.Properties.Resources.Manzana;
       break;

   case 2:
       img = Traga_monedas_frutas.Properties.Resources.Pina;
       break;

   default:
       img = Traga_monedas_frutas.Properties.Resources.Cereza;
       break;
}





Tercero y último, el mensaje de error que has mencionado parece ficticio, tiene faltas de ortografia de principio a fín, y no parece tener ningún sentido razonable entre eso del user-code y la mención a la excepción. Por favor, muestra el mensaje de error real, tal y como te lo muestra Visual Studio (preferiblemente en Inglés si te fuese posible,,puesto que las traducciones de los mensajes de error por parte de Microsoft al Castellano ... son lo peor)

De todas formas, intuyo que posiblemente tengas un conflicto por intentar manipular un control que no fue creado desde el mismo hilo en donde estás ejecutando el BackgroundWorker.

Prueba a intentar utilizar un delegado, de la siguiente manera:

Código (csharp) [Seleccionar]
private static readonly Random rnd = new Random();
private static Image img;
private static Int32 imgId;

public delegate void SetPictureBoxImage(PictureBox pcb, Image img);
public static SetPictureBoxImage PictureBoxDelegate = new SetPictureBoxImage(SetPictureBoxImageMethod);


Código (csharp) [Seleccionar]
public static void SetPictureBoxImageMethod(PictureBox pcb, Image img) {
   pcb.Image = img;
}


Código (csharp) [Seleccionar]
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {

   imgId = rnd.Next(minValue: 0, maxValue: 3);

   switch (imgId) {

       case 0:
           img = Traga_monedas_frutas.Properties.Resources.Manzana;
           break;

       case 1:
           img = Traga_monedas_frutas.Properties.Resources.Pina;
           break;

       case 2:
           img = Traga_monedas_frutas.Properties.Resources.Cereza;
           break;

       default:
           img = Traga_monedas_frutas.Properties.Resources.Banana;
           break;
   }

   form1.Invoke(PictureBoxDelegate, new object[] { pictureBox1, img });

}


Saludos








01munrra

#2
Aplique tu forma y funciono!.. (Y) interesante la logica que le aplicastes, se lo aplique a los 4 PictureBox que tiene el juego, aqui una imagen para que tengas una idea:



lo añadi en un ciclo:
Código (csharp) [Seleccionar]

While(true)
{
  .................
}


e hice esto para ver si se detiene los  backgroundWorker:
Código (csharp) [Seleccionar]

       private void button2_Click(object sender, EventArgs e)
       {
           backgroundWorker1.CancelAsync();
           backgroundWorker2.CancelAsync();
           backgroundWorker3.CancelAsync();
           backgroundWorker4.CancelAsync();


pero no se esta deteniendo, como se hace ps????

Saludos!! Gracias!

Eleкtro

#3
Cita de: 01munrra en  3 Agosto 2016, 14:10 PMpero no se esta deteniendo, como se hace ps????

( hasta que has mostrado la imagen no habia entendido del todo bien tu duda por que no sabía que era eso de tragamonedas, aquí lo llamamos tragaperras xD )

Piensa en lo siguiente: lo único que tienes hecho hasta ahora es un thread que ejecuta un búcle infinito, ¿cómo esperas poder cancelarlo por arte de mágia sin añadir nada más, si de ese búcle nunca sales?

Para que tu thread/backgroundworker se pueda cancelar, debes modificar el código actual (el bloque de código del evento BackgroundWorker.DoWork) para añadir una comprobación que determine si existe una petición/señal de cancelación, y en caso afirmativo, terminar la ejecución de ese bloque de código.

Cuando llamas al método BackgroundWorker.CancelAsync(), se activa el valor de la propiedad booleana BackgroundWorker.CancellationPending, ese es el valor que debes controlar dentro de tu búcle infinito para modificar el comportamiento o flujo de tu BackgroundWorker.

Es algo muy sencillo, pero lo mejor es que leas y estudies la siguiente documentación (sobre todo el primer enlace, y el ejemplo de código que verás ahí) para que aprendas a hacerlo por ti mismo:

PD: ¿realmente el profesor os ha mandado implementar algoritmos de programación asincrónica sin haberos enseñado antes?

Saludos!








01munrra

Cita de: Eleкtro en  3 Agosto 2016, 15:58 PM
PD: ¿realmente el profesor os ha mandado implementar algoritmos de programación asincrónica sin haberos enseñado antes?

el dio una clase, y ps primero se enredo explicando el tema(no lo explico bien) y segundo dio un ejercicio que cargaba unos datos que estaban en un .TXT y mostraba en el form, pero no tan complejo como un juego como este.

Gracias por tu ayuda, me leere esa documentación.

Saludos!

01munrra

Amigo añadi esto al DOWork:
Código (csharp) [Seleccionar]

                    if (backgroundWorker1.CancellationPending == true)
                    {
                        e.Cancel = true;
                        return;
                    }


quedando asi:

Código (csharp) [Seleccionar]

      private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            while (true)
                {
                    imgId = rnd.Next(minValue: 0, maxValue: 3);
                    switch (imgId)
                    {

                        case 0:
                            img = Traga_monedas_frutas.Properties.Resources.Manzana;
                            break;

                        case 1:
                            img = Traga_monedas_frutas.Properties.Resources.Pina;
                            break;

                        case 2:
                            img = Traga_monedas_frutas.Properties.Resources.Cereza;
                            break;

                        default:
                            img = Traga_monedas_frutas.Properties.Resources.Banana;
                            break;
                    }

                    if (backgroundWorker1.CancellationPending == true)
                    {
                        e.Cancel = true;
                        return;
                    }

                    Invoke(PictureBoxDelegate, new object[] { pictureBox1, img });
                }           
        }


y si funciona!....

gracias por tu ayuda me ha servido de mucho   ;-)