@Psyke1
Mas que una matriz quedaría precioso en una clase... al rato lo traslado a una clase para aumentar la velocidad de procesamiento, ya que de este modo se le aumenta el peformance ( en relación procesador/tiempo, pero no memoria ) con una clase.
Mas que una matriz quedaría precioso en una clase... al rato lo traslado a una clase para aumentar la velocidad de procesamiento, ya que de este modo se le aumenta el peformance ( en relación procesador/tiempo, pero no memoria ) con una clase.
Este código es una mera actualización directa de este otro, se puede decir que es la version 2.0
[source] Números Aleatorio desde X a Y con excepciones.
Vaya solo le falta una opción a mi punto de vista y es meterle una lista de números antes de generar alguno tal cual se le hace en la función solo que ahora seria una propiedad, y podría modificarse en cualquier instante, pero eso se los dejo a ustedes, yo ya hice mi labor.
* El ordenamiento QuickSort se sustituyo por una heuristica mas eficiente.
En un modulo de clase:
cRndNumbersNR.cls
Código
' ' //////////////////////////////////////////////////////////////// ' // Autor: BlackZeroX ( Ortega Avila Miguel Angel ) // ' // // ' // Web: http://InfrAngeluX.Sytes.Net/ // ' // // ' // |-> Pueden Distribuir Este Codigo siempre y cuando // ' // no se eliminen los creditos originales de este codigo // ' // No importando que sea modificado/editado o engrandesido // ' // o achicado, si es en base a este codigo // ' //////////////////////////////////////////////////////////////// Option Explicit Private Declare Function VarPtrA Lib "msvbvm60.dll" Alias "VarPtr" (ByRef Ptr() As Any) As Long Private Declare Sub lCopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long) Private Type stRangos lValIni As Long lValEnd As Long End Type Private lcvalmax As Long Private lcvalmin As Long Private lvcsplit() As stRangos Private lacexcep() As Long Private bChange As Long Private Sub Swapnumbers(ByRef lvalone As Long, ByRef lvaltwo As Long) ' // Intercambia el contenido de las variables. Dim lvaltmp As Long lvaltmp = lvalone lvalone = lvaltwo lvaltwo = lvaltmp End Sub Private Function Fixnumbers(ByRef lvalmin As Long, lvalmax As Long) As Boolean ' // Corrige los valores dados. If lvalmax < lvalmin Then Call Swapnumbers(lvalmin, lvalmax) Fixnumbers = True End If End Function Private Function NumRandom(lvalmin As Long, lvalmax As Long) As Long ' // Genera un Numero aleatorio de acuerdo a un rango dado. Call Fixnumbers(lvalmin, lvalmax) Call Randomize NumRandom = (lvalmin - lvalmax) * Rnd + lvalmax End Function Public Sub Reset() ' // Reinicia y permite nuevamente generar los números aleatorios desde el principio, si no aplica este al generar todos los numeros, entonces no generara mas números y devolverá únicamente 0.. Erase lvcsplit() Erase lacexcep() ReDim lvcsplit(0 To 0) lvcsplit(0).lValIni = lcvalmin lvcsplit(0).lValEnd = lcvalmax bChange = False End Sub Public Property Get GetMore() As Boolean ' // Hay mas ocurrencias? cuando ya no hay se elimina el array de ocurrencias. GetMore = Itsarrayini(VarPtrA(lvcsplit)) Or bChange = True End Property Private Function Itsarrayini(ByVal lpszv As Long, Optional llen As Long = 4) As Boolean ' // Obtiene el limite superior de los numeros a generar de manera aleatoria sin repetir. Dim lpsz As Long If lpszv <> 0 And llen > 0 Then Call lCopyMemory(ByVal VarPtr(lpsz), ByVal lpszv, llen) Itsarrayini = Not lpsz = 0 End If End Function Private Sub SeparateRange(ByVal lDivVal As Long, ByVal lindex As Long, ByRef vArray() As stRangos) ' // Es un proceso para aplicar el dicho "Divide y Venceras", esto aumenta mucho la velocidad para no repetir numeros dentro de un rango dado y generados de manera aleatoria. ' // Repeti un poco de codigo lo siento xP... Dim lu As Long Dim lpsz As Long If (vArray(lindex).lValIni <= lDivVal And lDivVal <= vArray(lindex).lValEnd) Then lu = UBound(vArray) lpsz = VarPtr(vArray(lindex)) If (vArray(lindex).lValIni = lDivVal) Then vArray(lindex).lValIni = vArray(lindex).lValIni + 1 If (vArray(lindex).lValIni > vArray(lindex).lValEnd) Then If (lu > 0) Then lCopyMemory lpsz, lpsz + &H8, ((lu - lindex) * &H8) lu = lu - 1 ReDim Preserve vArray(0 To lu) Else Erase vArray() End If End If ElseIf (vArray(lindex).lValEnd = lDivVal) Then vArray(lindex).lValEnd = vArray(lindex).lValEnd - 1 If (vArray(lindex).lValIni > vArray(lindex).lValEnd) Then If (lu > 0) Then lCopyMemory lpsz, lpsz + &H8, ((lu - lindex) * &H8) lu = lu - 1 ReDim Preserve vArray(0 To lu) Else Erase vArray() End If End If Else lu = lu + 1 ReDim Preserve vArray(0 To lu) lpsz = VarPtr(vArray(lindex)) lCopyMemory lpsz + &H10, (lpsz + &H8), (((lu - 1) - lindex) * &H8) vArray(lindex + 1).lValEnd = vArray(lindex).lValEnd vArray(lindex + 1).lValIni = (lDivVal + 1) vArray(lindex).lValEnd = (lDivVal - 1) End If End If End Sub Public Property Get GetNumRandom() As Long ' // Genera un numero aleatorio sin repetir de acuerdo a un rango de valores dados. Dim lindex As Long Dim lu As Long Dim lret As Long If (bChange = True) Then Call Fixnumbers(lcvalmin, lcvalmax) Call Reset End If If (GetMore = True) Then lindex = NumRandom(0, UBound(lvcsplit)) lret = NumRandom(lvcsplit(lindex).lValIni, lvcsplit(lindex).lValEnd) SeparateRange lret, lindex, lvcsplit If (Itsarrayini(VarPtrA(lacexcep)) = True) Then lu = UBound(lacexcep) + 1 Else lu = 0 End If ReDim Preserve lacexcep(0 To lu) lacexcep(lu) = lret GetNumRandom = lret End If End Property Public Property Let minval(ByVal ldata As Long) ' // Establece el limite inferior de los numeros a generar de manera aleatoria sin repetir. lcvalmin = ldata bChange = True End Property Public Property Get minval() As Long ' // Obtiene el limite inferior de los numeros a generar de manera aleatoria sin repetir. minval = lcvalmin End Property Public Property Let maxval(ByVal ldata As Long) ' // Establece el limite superior de los numeros a generar de manera aleatoria sin repetir. lcvalmax = ldata bChange = True End Property Public Property Get maxval() As Long ' // Obtiene el limite superior de los numeros a generar de manera aleatoria sin repetir. maxval = lcvalmax End Property Public Property Get GetNumbers() As Long() ' // Devueve una coleccion de los numeros generados. GetNumbers() = lacexcep() End Property Public Function RegenerateThis(ByVal lVal As Long) As Boolean Dim ii As Long Dim lub As Long If (lcvalmin <= lVal) And (lcvalmax >= lVal) Then If (breglist = True) Then If (Itsarrayini(VarPtrA(lacexcep)) = True) Then For ii = 0 To UBound(lacexcep) If (lacexcep(ii) = lVal) Then RemoveInArrayLong ii, lacexcep() Exit For End If Next ii End If End If If (Itsarrayini(VarPtrA(lvcsplit)) = True) Then lub = UBound(lvcsplit) For ii = 0 To (lub - 1) If (lvcsplit(ii).lValEnd > lVal) And (lvcsplit(ii + 1).lValIni < lVal) Then If ((lvcsplit(ii).lValEnd + 1) = lVal) Then lvcsplit(ii).lValEnd = lVal ElseIf ((lvcsplit(ii + 1).lValIni) = lVal) Then lvcsplit(ii + 1).lValIni = lVal End If Select Case (lvcsplit(ii).lValEnd = lvcsplit(ii + 1).lValIni) Case 0, 1 lub = (lub - 1) lvcsplit(ii).lValEnd = lvcsplit(ii + 1).lValEnd ReDim Preserve lvcsplit(0 To lub) Case Else If Not ((lvcsplit(ii).lValEnd + 1) = lvcsplit(ii + 1).lValIni) Then lub = (lub + 1) ReDim Preserve lvcsplit(0 To lub) SwapBlockMemoryInCicle VarPtr(lvcsplit(ii)), (VarPtr(lvcsplit(lub)) + LenB(lvcsplit(0))), LenB(lvcsplit(0)) lvcsplit(ii + 1).lValIni = lVal lvcsplit(ii + 1).lValEnd = lVal End If End Select RegenerateThis = True Else Exit For End If Next ii Else ReDim lvcsplit(0 To 0) lvcsplit(0).lValIni = lVal lvcsplit(0).lValEnd = lVal End If End If End Function Private Sub Class_Initialize() ' // Constructor de la clase, no tengo por que hacer lo siguiente pero como me estoy adaptando a un standart lo hare. bChange = False End Sub
uso simple:
Código
Option Explicit Private Sub Form_Load() Dim cls As cRndNumber Dim lc As Long Set cls = New cRndNumber With cls ' // Este simple codigo probara la velocidad, que de hecho ya es rapido a consideracion de otros que conozco. .minval = 0 .maxval = 99999 Do While (.GetMore = True) DoEvents lc = .GetNumRandom Loop MsgBox "Se recorrieron todos los numeros sin repetir alguno xD" ' // Si se cambian los valores menor y mayor entonces es como si se le aplicara call .Reset ' // Este codigo hara un test de repeticion .minval = 0 .maxval = 99 Do While (.GetMore = True) DoEvents Debug.Print .GetNumRandom Loop MsgBox "Se recorrieron todos los numeros sin repetir alguno xD" End With End Sub
Temibles Lunas!¡.