greenmachine Posted March 5, 2006 Share Posted March 5, 2006 I made a little UDF dealing with random numbers because I needed a file for a C++ project I'm working on in class. This UDF places random numbers in an array, checking each time if the number has already been placed (to prevent repeats), and returns the completed array. The function works in production or beta versions. The test script will run under production (if you comment out the correct lines), and work under beta as is. expandcollapse popup#include <array.au3> $Rands = _RandomExclusive (52, 1, 52, 1); Example: shuffle a deck of cards (numbered 1-52) Select Case @error = 1 MsgBox (0, "error " & @error, "Count is too high.") Case @error = 2 MsgBox (0, "error " & @error, "Min is greater than or equal to max.") Case @error = 3 MsgBox (0, "error " & @error, "One or more of the parameters is not a number.") Case Else ;~ ;use these with production version ;~ $msg = $Rands[1] ;~ For $i = 2 To $Rands[0] ;~ $msg = $msg & @CRLF & $Rands[$i] ;~ Next ;~ MsgBox (0, "rands", $msg) ;~ ;use these with beta or an array.au3 file that does not have "const" in the _ArrayDisplay() func _ArrayDisplay ($Rands, "Rands before sort") _ArraySort ($Rands, 0, 1) _ArrayDisplay ($Rands, "Rands after sort") EndSelect ;=============================================================================== ; ; Function Name : _RandomExclusive() ; Description : Returns a quantity of random numbers in an array - does not use the same number more than once ; Parameter(s) : $iCount - how many random numbers to get? ; : $iMin - [Optional] minimum number, default is 0 ; : $iMax - [Optional] maximum number, default is 1 ; : $iFlag - [Optional] flag for Random -> 0 is default (floats), set to 1 for ints ; Requirement : None. ; Return Value(s) : On Success - returns an array containing the random numbers ; : $Array[0] - quantity ; : $Array[1] through $Array[n] - random numbers ; : On Failure - returns -1 and sets @error to one of the following: ; : @error = 1 - Count is too high (only when flag is 1) ; : @error = 2 - Min is greater than or equal to Max ; : @error = 3 - One or more parameters is not a number ; Author(s) : Michael Guynn (greenmachine) ; Note(s) : A good way to shuffle numbers. ; ;=============================================================================== Func _RandomExclusive($iCount, $iMin = 0, $iMax = 1, $iFlag = 0) If $iCount > ($iMax - ($iMin - 1)) And $iFlag = 1 Then SetError (1) Return -1 EndIf If ($iMin >= $iMax) Then SetError (2) Return -1 EndIf If Not IsNumber ($iCount) Or Not IsNumber ($iMin) Or Not IsNumber ($iMax) Or Not IsNumber ($iFlag) Then SetError (3) Return -1 EndIf Local $a_randomArray[$iCount + 1], $Rand_found For $Rand_counter = 1 To $iCount $a_randomArray[0] = $Rand_counter Do $Rand_found = 0 $a_randomArray[$Rand_counter] = Random ($iMin, $iMax, $iFlag) For $Rand_subcounter = 1 To $Rand_counter - 1 If $a_randomArray[$Rand_counter] = $a_randomArray[$Rand_subcounter] Then $Rand_found = 1 ExitLoop EndIf Next Until $Rand_found = 0 Next Return $a_randomArray EndFunc Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted March 5, 2006 Moderators Share Posted March 5, 2006 (edited) Hey green... good job... I was toying around with this, because I had to do something similar with EnCodeIt a while back... the one without the For/Next loop seems to be a tad faster most of the time... thought I'd post it and let you test it out to see if it suited your needs for school$Timer = TimerInit() $TestRandomArray = _RandomExclusive(10, 1, 10, 1) Local $Display_Array = '' For $x = 1 To UBound($TestRandomArray) - 1 $Display_Array = $Display_Array & '[' & $x & '] = ' & $TestRandomArray[$x] & @LF Next MsgBox(0, 'Display Array and it took: ' & Round(TimerDiff($Timer) / 1000, 3) & ' seconds', $Display_Array) Func _RandomExclusive($iCount, $iMin = 0, $iMax = 1, $iFlag = 0) If $iCount > ($iMax - ($iMin - 1)) And $iFlag = 1 Then SetError(1) Return -1 EndIf If ($iMin >= $iMax) Then SetError(2) Return -1 EndIf If Not IsNumber($iCount) Or Not IsNumber($iMin) Or Not IsNumber($iMax) Or Not IsNumber($iFlag) Then SetError(3) Return -1 EndIf Local $a_randomArray[$iCount + 1], $Rand_found For $Rand_counter = 1 To $iCount $a_randomArray[0] = $Rand_counter Do $Rand_found = 0 $a_randomArray[$Rand_counter] = Random ($iMin, $iMax, $iFlag) For $Rand_subcounter = 1 To $Rand_counter - 1 If $a_randomArray[$Rand_counter] = $a_randomArray[$Rand_subcounter] Then $Rand_found = 1 ExitLoop EndIf Next Until $Rand_found = 0 Next Return $a_randomArray EndFunc $Timer = TimerInit() $TestRandomArray = _RandomNumDisplay(10, 1, 10, 1) Local $Display_Array = '' For $x = 1 To UBound($TestRandomArray) - 1 $Display_Array = $Display_Array & '[' & $x & '] = ' & $TestRandomArray[$x] & @LF Next MsgBox(0, 'Display Array and it took: ' & Round(TimerDiff($Timer) / 1000, 3) & ' seconds', $Display_Array) Func _RandomNumDisplay($iCount, $iMin = 0, $iMax = 1, $iFlag = 0) Local $Rand_Array = '' Local $StartCount = 0 If $iCount > ($iMax - ($iMin - 1)) And $iFlag = 1 Then SetError(1) Return -1 EndIf If ($iMin >= $iMax) Then SetError(2) Return -1 EndIf If Not IsNumber($iCount) Or Not IsNumber($iMin) Or Not IsNumber($iMax) Or Not IsNumber($iFlag) Then SetError(3) Return -1 EndIf Do $StartCount = $StartCount + 1 $Rand_Number = Random($iMin, $iMax, $iFlag) If Not StringInStr(Chr(01) & $Rand_Array, Chr(01) & $Rand_Number & Chr(01)) Then $Rand_Array = $Rand_Array & $Rand_Number & Chr(01) Else $StartCount = $StartCount - 1 EndIf Until $StartCount = $iCount Return StringSplit(StringTrimRight($Rand_Array, 1), Chr(01)) EndFuncEdit: Rounded the timer of 2 3 decimals. Edited March 5, 2006 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
greenmachine Posted March 5, 2006 Author Share Posted March 5, 2006 You're right, yours is much faster. I'm still trying to figure out what it's doing though.. the added chr(01)'s are throwing me off. Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted March 5, 2006 Moderators Share Posted March 5, 2006 The Chr(01) is simply the 'delimeter' that StringSplit() will use to create the array. I use Chr(01) alot because it's not a common delimeter that you'll see when parsing strings to create an array. Unlike @LF or other Delimters that you'd run into often. If your trying to keep the array unique, you want the type of delimter that is also unique. Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
greenmachine Posted March 5, 2006 Author Share Posted March 5, 2006 Yeah I figured out that you were using it as a delimeter, it was just weird because (like you said) it isn't used much. I didn't know what it was either, so I looked it up. According to www.lookuptables.com, it's a "start of heading". Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now