Random VB.NET

Iniciado por Jeezy, 5 Agosto 2018, 05:16 AM

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

Jeezy

Hola quiero hacer lo siguiente:
Quiero hacer que en un textbox se pongan numeros random pero no los que quiera sino una secuencia que yo ponga ejemplo
: que se ponga el 1 luego el 20 luego en 50...
y que no se ponga cualquier otro numero solo los que yo diga


Tengo una forma que es usando varios timers, pero quisiera saber si hay otra forma mas optimizada

Serapis

Creas un array, metes ahí todos los números personalizados que quieras...

Luego se trata de eleigr al azar un índice entre 0 y el último índice del array.
Si tienes 25 números en el array, entonces los índices van del 0 al 24.
Y Random debe elegir un valor entre 0 y 24...
Finalmente en tu textbox pones el valor que consta en el array en la posición obtenida al azar...

Para forzar una mayor entropía, con cada número obtenido intercambia el par de valores según indiceprevio e índiceactual.

Y si... si quieres que el número cambie por sí solo, usar un timer está bien, pero recuerda que habrá algún momento en que deba estar activo y alguno en que deba ser desactivado (salvo que solo tenga un propósito decorativo), y recuerda que el lapso de tiempo debe ser algo que mantenga el valor el tiempo suficiente para ser visualizado, o si se trata de simular un 'barajado' puede ser algo más rápido, pero que todavía dé tiempo a poder leer valores...

Código (vbnet) [Seleccionar]

    Dim miArrayRnd() As Int32 = New Int32() {2, 20, 50, 69, 13, 3, 72, 96, 44, 31, 58, 85, 22, 12, 94, 57, 36, 7, 5, 39, 92, 83, 64, 18, 74}

    Dim IndicePrevio As Int32 ' = 0
    Dim IndiceActual As Int32 ' = 0



    Private Sub form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Randomize()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Dim tmp As Int32

        IndiceActual = CInt(Int((miArrayRnd.Length - 1) * Rnd()))
        TextBox1.Text = miArrayRnd(IndiceActual).ToString

        ' intercambiar el par de valores:
        tmp = miArrayRnd(IndiceActual)
        miArrayRnd(IndiceActual) = miArrayRnd(IndicePrevio)
        miArrayRnd(IndicePrevio) = tmp

       ' Recordar el índice previo... en la siguiente llamada.
        IndicePrevio = IndiceActual
    End Sub

Eleкtro

#2
Aquí tienes otra forma de hacerlo...

Básicamente declaro un Array con los valores (la ordenación de los valores no importa) y se añaden desordenados a una pila. En cada tic del temporizador se comprueba si la pila está vacía, y si lo está entonces se vuelve a llenar con un una nueva desordenación de los valores. Dicho de otra forma, la secuencia se desordena una vez, se añaden los valores desordenados a una pila, y cuando la pila está vacía la secuencia se vuelve desordenar y se vuelve a llenar la pila con la nueva desordenación. No sé si esto es exactamente lo que quieres hacer, tampoco has dado suficientes detalles...

Código (vbnet) [Seleccionar]
Public NotInheritable Class Form1 : Inherits Form

   Private ReadOnly rng As Random

   ' Aquí se define el Array con la secuencia de valores que más tarde serán desordenados...
   Private ReadOnly sequence As Integer() = {1, 2, 3, 4, 5, 6, 7, 8, 9}
   Private stack As Stack(Of Integer)

   Public Sub New()
       ' This call is required by the designer.
       MyClass.InitializeComponent()

       ' Add any initialization after the InitializeComponent() call.
       Me.rng = New Random(Seed:=Environment.TickCount)
       Me.stack = New Stack(Of Integer)
   End Sub

   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
       Me.Timer1.Interval = CInt(TimeSpan.FromSeconds(1).TotalMilliseconds)
       Me.Timer1.Enabled = True
       Me.Timer1.Start()
   End Sub

   Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Timer1.Tick
       ' Si la pila está vacía, la llenamos con una nueva secuencia de valores desordenados.
       If (Me.stack.Count = 0) Then
           Me.FillStack(Me.stack, Me.sequence, shuffleValues:=True)
       End If

       ' Obtenemos el siguiente valor de la pila.
       Dim nextValue As Integer = Me.stack.Pop()

       ' Hacer aquí lo que sea que quieras hacer con el valor obtenido...
       Me.TextBox1.AppendText(CStr(nextValue))
   End Sub

   Private Sub FillStack(Of T)(ByRef refStack As Stack(Of T), ByVal values As IEnumerable(Of T), ByVal shuffleValues As Boolean)
       Dim newValues As IEnumerable(Of T) =
           If(shuffleValues, (From value As T In values Order By Me.rng.Next Select value), values)

       refStack.Clear()
       For Each value As T In newValues
           refStack.Push(value)
       Next value
   End Sub

End Class


La clase Random se basa en un algoritmo de pseudo-aleatoriedad, es más que suficiente para la gran mayoría de escenarios/aplicaciones no-científicas, pero si por lo que sea necesitas un algoritmo de aleatoriedad más sofisticado con mayor entropía, con una distribución de mayor singularidad sobre todos los posibles resultados, entonces usa la clase RNGCryptoServiceProvider.

Saludos.