DavidFC3S Posted January 20, 2011 Posted January 20, 2011 I'm trying to work out how I can write a script that will pick a random item from an array full of strings. Then pick another random item etc without ever picking one twice. I'm sorry for such a vague question I admit I'm very new to programing of any kind. Even just some psuedo code to steer me in the right direction would be helpfull
nitekram Posted January 20, 2011 Posted January 20, 2011 take an array and put the string values into each index, then use the random function to pick an index, then check if the index has been used and if so skip that index, continue skipping each index that has been used until you have used all the indexs hope this helps as it is late 2¢ All by me:"Sometimes you have to go back to where you started, to get to where you want to go." "Everybody catches up with everyone, eventually" "As you teach others, you are really teaching yourself." From my dad "Do not worry about yesterday, as the only thing that you can control is tomorrow." WIKI | Tabs; | Arrays; | Strings | Wiki Arrays | How to ask a Question | Forum Search | FAQ | Tutorials | Original FAQ | ONLINE HELP | UDF's Wiki | AutoIt PDF AutoIt Snippets | Multple Guis | Interrupting a running function | Another Send StringRegExp | StringRegExp Help | RegEXTester | REG TUTOR | Reg TUTOT 2 AutoItSetOption | Macros | AutoIt Snippets | Wrapper | Autoit Docs SCITE | SciteJump | BB | MyTopics | Programming | UDFs | AutoIt 123 | UDFs Form | UDF Learning to script | Tutorials | Documentation | IE.AU3 | Games? | FreeSoftware | Path_Online | Core Language Programming Tips Excel Changes ControlHover.UDF GDI_Plus Draw_On_Screen GDI Basics GDI_More_Basics GDI Rotate GDI Graph GDI CheckExistingItems GDI Trajectory Replace $ghGDIPDll with $__g_hGDIPDll DLL 101? Array via Object GDI Swimlane GDI Plus French 101 Site GDI Examples UEZ GDI Basic Clock GDI Detection Ternary operator
DavidFC3S Posted January 20, 2011 Author Posted January 20, 2011 When you say index, does that mean one of the entries in the array or do you just mean declare a variable as a future point of reference. I think the reason I have so much difficulty asking for help is I don't know the correct terminology. Could you show some example code of what you mean?
Varian Posted January 20, 2011 Posted January 20, 2011 Here's a simple example with a zero based array #include <Array.au3> Local $Array[5] = ['Jim', 'Paul', 'Sharon', 'Candice', 'Mr. Peanut'] Local $String While 1 If UBound($Array) > 1 Then $Index = Random(0, UBound($Array), 1) If $Index > UBound($Array) - 1 Then $Index = UBound($Array) - 1 MsgBox(262208, '', 'Current (Random) Index = ' & $Index & @LF & 'Array Elements Left = ' & UBound($Array)) $String &= $Array[$Index] $String &= ' - ' _ArrayDelete($Array, $Index) Else $String &= $Array[0] ExitLoop EndIf WEnd MsgBox(262208, 'Final String', $String)
DavidFC3S Posted January 20, 2011 Author Posted January 20, 2011 Perhaps giving some more information would be helpfull. I recently started teaching myself to code and have no background in any other languages for reference. I've written a few basic scripts for work that just use mousemove and mouseclick to automate some of my work. I've written a visual timer that countsdown to my breaks haha and the most advanced thing I've written so far is a client/server type program that allows you to send text messages to each other via a socket. Currently what I'm working on is a simple card game just to further my coding knowledge. There's 52 cards in a deck and it has to randomly generate a card without ever repeating it. What I started out doing was declaring 52 individual variables for each of the cards $1 = 2c $2 = 2h $3 = 2s $4 = 2d etc etc etc. this is of course psuedo code and not the syntax I used. I was then just randomly generating a number between 1 and 52 and displaying the corresponding variable. Since starting this project though I have learned about arrays and can see that makes the system I did have planned ridiculously inefficient.
DavidFC3S Posted January 20, 2011 Author Posted January 20, 2011 Thanks Varian, I had already made my second post before I noticed your reply, I'll give that a try tonight and let you know how it goes
JoHanatCent Posted January 20, 2011 Posted January 20, 2011 Could you show some example code of what you mean? #include <Array.au3>; enable showing the array Local $Textinside[7] = ["Sun", "Mon", "Tue", "Wen", "Thu", "Fry", "Sat"];Add text to array Dim $ArrayVar Dim $avArray[1] Rand_O() Func Rand_O() Do $RandNum = Random(0, UBound($Textinside) - 1, 1) $Pos = _ArraySearch($avArray, $Textinside[$RandNum], 0, 0, 0) If $Pos = -1 Then _ArrayAdd($avArray, $Textinside[$RandNum]) EndIf Until UBound($avArray) = UBound($Textinside) + 1 EndFunc ;==>Rand_O $avArray[0] = UBound($avArray) - 1 _ArrayDisplay($avArray, "Text array"); Check there is NO duplicates
GEOSoft Posted January 20, 2011 Posted January 20, 2011 I'm not working out the code right now, I'm on the wrong machine for that but I think this ahould be fairly simple using 2 randoms 1-4 (representing suits) and 1-13 representing face values and using some conditionals and either a switch or a select to get the proper return value. I did something similar for a lottery game I did a few years ago but it only required a single random and a conditional check. George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!"
Varian Posted January 20, 2011 Posted January 20, 2011 Here is one way to shuffle the cards #include <Array.au3> Local $Cards[52], $Count = 0 Local $Suits[4] = ['Clubs', 'Spades', 'Diamonds', 'Hearts'] Local $Faces[13] = ['Ace', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'Jack', 'Queen', 'King'] For $Element2 In $Suits For $Element1 In $Faces $Cards[$Count] = $Element1 & ' of ' & $Element2 ;Combine the Face and Suit to make one card $Count += 1 Next Next _ArrayDisplay($Cards, '"Brand New" Deck of Cards') Local $String While 1 If UBound($Cards) > 1 Then $Index = Random(0, UBound($Cards), 1) If $Index > UBound($Cards) - 1 Then $Index = UBound($Cards) - 1 $String &= $Cards[$Index] & @LF _ArrayDelete($Cards, $Index) Else $String &= $Cards[0] ExitLoop EndIf WEnd MsgBox(262208, 'Your Shuffled Deck', $String)
jchd Posted January 20, 2011 Posted January 20, 2011 The technical term is random permutation. about it. This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)
GEOSoft Posted January 20, 2011 Posted January 20, 2011 expandcollapse popup#Include<array.au3>;For display purposes only $aCards = _DrawCards() If NOT @Error Then _ArrayDisplay($aCards) Else MsgBox(4096, "Error", $aCards) EndIf Func _DrawCards($iMax_Cards = 5) Local $sFace, $iSuit, $sDrawn = "", $iCards = 0, $sVal, $sSuit, $aRtn Do $iSuit = Random(1, 4, 1) $sFace = Random(1, 13, 1) $sSuit = "" Switch $iSuit Case 1 $sSuit = " of Hearts" Case 2 $sSuit = " of Diamonds" Case 3 $sSuit = " of Spades" Case Else $sSuit = " of Clubs" EndSwitch Switch $sFace Case 1 $sFace = "Ace" Case 11 $sFace = "Jack" Case 12 $sFace = "Queen" Case 13 $sFace = "King" EndSwitch If StringInStr($sDrawn, "|" & $sFace & $sSuit) Then ContinueLoop $sDrawn &= "|" & $sFace & $sSuit $iCards += 1 Until $iCards = $iMax_Cards $aRtn = StringRegExp($sDrawn, "\|([\w\s]+)", 3) If NOT @Error Then Return ($aRtn) Return (SetError(1, 1, "Houston; We have a problem!")) EndFunc ;==>_DrawCards George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!"
GEOSoft Posted January 20, 2011 Posted January 20, 2011 This one is a bit more flexible and gives a better example of the results. of course there is always room for improvement. expandcollapse popup#Include<array.au3>;For array display purposes only Local $iDeal = 5, $iPlayrs[4] = ["", "", "", ""];; Adjust these according to the number of cards each player gets and the number of players $aCards = _DrawCards(UBound($iPlayrs) * $iDeal) If NOT @Error Then _ArrayDisplay($aCards) FOR $i = 0 To UBound($aCards) - UBound($iPlayrs) Step UBound($iPlayrs) FOR $x = 0 To UBound($iPlayrs) - 1 $iPlayrs[$x] &= $aCards[$i + $x] & "|" Next Next FOR $i = 0 To UBound($iPlayrs) - 1 $iPlayrs[$i] = StringSplit(StringTrimRight($iPlayrs[$i], 1), "|", 2) _ArrayDisplay($iPlayrs[$i], "Player " & $i + 1) Next Else MsgBox(4096, "Error", $aCards) EndIf Func _DrawCards($iMax_Cards = 20) Local $sFace, $iSuit, $sDrawn = "", $iCards = 0, $sVal, $sSuit, $aRtn Do $iSuit = Random(1, 4, 1) $sFace = Random(1, 13, 1) $sSuit = "" Switch $iSuit Case 1 $sSuit = " of Hearts" Case 2 $sSuit = " of Diamonds" Case 3 $sSuit = " of Spades" Case Else $sSuit = " of Clubs" EndSwitch Switch $sFace Case 1 $sFace = "Ace" Case 11 $sFace = "Jack" Case 12 $sFace = "Queen" Case 13 $sFace = "King" EndSwitch If StringInStr($sDrawn, "|" & $sFace & $sSuit) Then ContinueLoop $sDrawn &= "|" & $sFace & $sSuit $iCards += 1 Until $iCards = $iMax_Cards $aRtn = StringRegExp($sDrawn, "\|([\w\s]+)", 3) If NOT @Error Then Return ($aRtn) Return (SetError(1, 1, "Houston; We have a problem!")) EndFunc ;==>_DrawCards George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!"
Newb Posted January 20, 2011 Posted January 20, 2011 To make it simple so you can understand: $Array[3] Is made by: $Array[0] $Array[1] $Array[2] As the count of an array starts from 0 everytime. So if I want to put A, B, C in an array i must declare it like this $Array[3]=[A,B,C] OR $Array[0]="A",$Array[1]="B",$Array[2]="C" Those 0, 1, 2 are called "indexes", so that's what is an Index. To call an element randomly you can do this $x=$Array[Random(0,2,1)] and it will call a random value included from 0 to 2. By the way, this can call more than once the same value, as a random number cal can draw numbers like this: 1,0,2,2,2,0,0,1,2,2,1,0 and so on. To extract one element only once look at the useful "Deck Shuffle" function that is listed above. I used it and it was very useful. Hope to have made it clear. Servant 1 I'm a compulsive poster. When I post something, come to read it at least 5 minutes later after the posting, because I will edit it. I edited even this signature a few minutes later after I wrote it.
GEOSoft Posted January 20, 2011 Posted January 20, 2011 $Array[3]=[A,B,C]Don't forget to quote string values when you do that. $Array[3]=["A","B","C"] Yes you can draw the same value more than once with Random and that's precisely why I put it into a string then check to see if the card has already been drawn. George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!"
DavidFC3S Posted January 21, 2011 Author Posted January 21, 2011 Wow, thanks for so many answers guys. Looks like I have some studying to do because most of this is chinese to me at the moment. I didn't know what an array was a few days ago haha
DavidFC3S Posted January 21, 2011 Author Posted January 21, 2011 Is there a specific reason I should have 2 seperate arrays for face value and suit instead of just having an array with 52 entries ['2c','2h','2s','2d'] etc etc? Is it just to do with efficiency and making handling the indexes faster? or are their some rules about storing integers and characters in the same array?
GEOSoft Posted January 21, 2011 Posted January 21, 2011 (edited) Why try to randomize 52 elements when you can randomize 17? It's faster with 17 and if you look at it It's random for 13 cards and another random for 4 suits. I should have added that doing it with just random numbers you don't have to prefill the arrays. Edited January 21, 2011 by GEOSoft George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!"
Dana Posted January 21, 2011 Posted January 21, 2011 (edited) Oddly enough, I just finished doing much the same thing, but to pick files up to a maximum aggregate file size or a user specified number ($desired): expandcollapse popupDo If GUIGetMsg() = $cancelbutton Then Exit If $i = $array[0] + 1 Then $replacemode = 0 ;MsgBox(0, "debug", "no more than " & $array[0] & " files to pick") ExitLoop EndIf $unique = 1 $randidx[$i] = Random(1, $array[0], 1) ; pick a random integer between 1 and $array[0] (number of files in array) ;MsgBox(4096, "debug", $i & " " & $randidx[$i]) For $a = 1 To $i - 1 If ($randidx[$i] = $randidx[$a]) And ($i > 1) Then ;MsgBox(4096, "debug", "duplicate found") $i = $i - 1 ; decrement $i so the same $i value runs again $unique = 0 ExitLoop EndIf Next If $unique Then ;$msg = $msg & @CRLF & $i & " " & $randidx[$i] & ":" & @TAB & $array[$randidx[$i]] ; message for debug box $totsize = $totsize + (FileGetSize($array[$randidx[$i]]) / 1048576) EndIf If (($totsize) > $maxsize) Then ;MsgBox(4096, "debug", "max size " & $totsize & " reached at file no. " & $i) $totsize = $totsize - (FileGetSize($array[$randidx[$i]]) / 1048576) $i = $i - 1 ;$desired = $i-1 ExitLoop EndIf $i = $i + 1 Until $i = $desired + 1 In the above example $array[0] is the available number of files and the remaining elements in $array are the file names; the loop stops when either that number or $desired is reached, or the total size ($totsize) reaches the limit ($maxsize). As somebody pointed out, yours could be made faster by checking suits and numbers separately in two arrays rather than one array containing all 52 cards, but I suspect you wouldn't see the difference... even with over 8000 files my above routine is reasonably fast, and with fewer elements (say a hundred or two) it's so fast you hardly even see it happening. Edited January 21, 2011 by Dana
GEOSoft Posted January 21, 2011 Posted January 21, 2011 Dana that's true, I have one project that has to handle an array of almost 89 thousand elements and there is no way to split it down to less. It appears to run slow however considering the number of elements it really isn't too bad. In the OPs case I would still go with 2 arrays. One of the upsides is better randomization and I'm sure that one of the math wizards will come along and calculate the difference in odds. I remember doing one (a lottery) where I had to return 20 numbers out of 80 and in order to get the odds to where I needed them to be the function first randomly drew 40 numbers at random and then from that 40 element array it drew the final 20 at random. With a bit more manipulation, the odds of winning are within .01% of the government version and it displays pretty much the same as the governments version. The same thing applied to a second where I need 7 numbers out of 49 (6/49 plus a bonus number), level of randomness can be important at times and I think this would apply in a card game. George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!"
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