(21) Ejemplo de aplicación de subprocesos múltiples: bola de dos colores (6 rojas + 1 azul)

    


1. Demanda


    1. Bola de doble color: Los números de apuesta constan de 6 números de bola roja y 1 número de bola azul.
    
    2. Seleccione el número de bola roja del 01 al 33 y la bola roja no se podrá repetir.
    
    3. Elija el número de bola azul del 01 al 16.
        
    4. El resultado final son 7 números : 6 + 1, es decir, elija 6 de 33 (rojo) + elija 1 de 16 (azul)
        
    5. Producto: 
        puede usarse, los usuarios pueden usarlo con confianza,
        principio: confiar en suerte, sin operaciones secretas y números de lotería. Aleatoriedad.
        
    6. Cómo hacerlo:
        (1) De izquierda a derecha---cambios ordenados
        (2) De derecha a izquierda---cambios ordenados
        (3) Al mismo tiempo, los números de bolas cambian~~
        (4) Puede por hacer Todas las bolas cambian, y todas son independientes entre sí, aleatorias (recomendado)


2. Procedimiento


    1. Interfaz: 6 etiquetas de bolas rojas muestran LblRedNum1-LblRedNum6 y una bola azul LblBlue.
        Dos botones, BtnStart y BtnStop. un cuadro de lista1.


        
    2. Código:

        private string[] redNums = Enumerable.Range(1, 33).Select(i => i.ToString("00")).ToArray();
        private string[] blueNums = Enumerable.Range(1, 16).Select(i => i.ToString("00")).ToArray();
        private object lockObj = new object();
        private List<Task> tasks = new List<Task>();
        private CancellationTokenSource cts;

        private async void BtnStart_Click(object sender, EventArgs e)
        {
            BtnStart.Enabled = false;
            BtnStop.Enabled = true;
            cts = new CancellationTokenSource();
            CancellationToken ct = cts.Token;

            //初始化,置00
            foreach (Label lbl in Controls.OfType<Label>().Where(b => b.Name.Contains("Red")))
            { lbl.Text = "00"; }

            //开7个线程
            foreach (Label lbl in Controls.OfType<Label>())
            {
                if (lbl.Name.Contains("Blue"))
                {
                    tasks.Add(Task.Run(async () =>//蓝球显示
                    {
                        while (!ct.IsCancellationRequested)
                        {
                            await Task.Delay(200);
                            string strBlue = blueNums[GetRandom(0, 16)];
                            lbl.Invoke(new Action(() =>
                            {
                                lbl.Text = strBlue;
                            }));
                        }
                    }));
                }
                else
                {
                    tasks.Add(Task.Run(async () =>//红球显示
                     {
                         while (!ct.IsCancellationRequested)
                         {
                             await Task.Delay(200);
                             int idx = GetRandom(0, 33);
                             string strRed = redNums[idx];
                             lock (lockObj)
                             {
                                 List<string> list = GetCurNumList();
                                 if (!list.Contains(strRed))
                                 {
                                     lbl.Invoke(new Action(() => { lbl.Text = strRed; }));
                                     redNums[idx] = strRed;
                                 }
                             }
                         }
                     }));
                }
            }

            await Task.Run(() =>//任务取消时显示
                 {
                     Task.WaitAll(tasks.ToArray());
                     Invoke(new Action(() =>
                     {
                         List<string> list = new List<string>();
                         foreach (Label lbl in this.Controls.OfType<Label>().Where(b => b.Name.Contains("Red")))
                         {
                             list.Add(lbl.Text);
                         }
                         list.Sort();
                         list.Add(LblBlue.Text);
                         listBox1.Items.Add(string.Join(",", list.ToArray()));
                     })
                     );
                 });
        }

        private List<string> GetCurNumList()//返回当前红球列表
        {
            List<string> list = new List<string>();
            foreach (Label lbl in this.Controls.OfType<Label>().Where(b => b.Name.Contains("Red")))
            { Invoke(new Action(() => { list.Add(lbl.Text); })); }

            return list;
        }

        private int GetRandom(int min, int max)//产生强随机数
        {
            byte[] bytes = new byte[4];
            using (var rng = RandomNumberGenerator.Create())
            { rng.GetBytes(bytes); }

            int seed = BitConverter.ToInt32(bytes, 0);
            return new Random(seed).Next(min, max);
        }

        private void BtnStop_Click(object sender, EventArgs e)
        {
            cts.Cancel();
            BtnStart.Enabled = true;
            BtnStop.Enabled = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        { BtnStop.Enabled = false; }


3. Detalles


    1. Cree dos matrices y obtenga números aleatorios basados ​​en índices generados aleatoriamente.
        Por ejemplo, si el índice 3 se genera aleatoriamente, entonces para la bola roja redNum[3] es un número generado aleatoriamente
        
        utilizando un número aleatorio fuerte. Devuelve los bytes correspondientes según la personalización. Debido a que la semilla debe ser un int, solo necesita 4 bytes y luego use la función estática BitConvert para convertir la semilla y generar un número aleatorio más realista.
        
    2. La bola azul usa un hilo y la bola roja usa 6 hilos para funcionar simultáneamente.
        No te preocupes por las bolas azules.
        Las bolas rojas del 01 al 33 no se pueden repetir, por lo que cada vez tendrás que comparar las 6 bolas rojas para ver si son iguales, si son iguales se regenerarán nuevamente hasta obtener 6 números diferentes.
        Seis subprocesos funcionan de la misma manera, pero es fácil competir. Por ejemplo, si todos comparan los números de las seis etiquetas actuales, pero ambos subprocesos producen el mismo número, como 5, al final habrá duplicación. . , establezca un bloqueo mutex para este propósito. Al generar números, solo se permite la entrada de un subproceso. Después de cambiar la lista de etiquetas actual, sale. El segundo subproceso ingresa y compara. Después de encontrar la diferencia, actualiza la lista y sale de nuevo. Este ciclo puede hacer que el número de etiqueta actual sea siempre diferente.
        
    3. Visualización de resultados.
        Para evitar un punto muerto, abra un subproceso para esperar el final de los 7 subprocesos anteriores y utilice await para evitar la animación suspendida.
        
        Además, después de ordenar las 6 bolas rojas, coloque la bola azul al final y agregue listbox1 para mostrar. (No se pueden ordenar todos, el rojo y el azul son dos partes)
    
  

Supongo que te gusta

Origin blog.csdn.net/dzweather/article/details/132903847
Recomendado
Clasificación