Begging for help with simple loop.
BlitzMax Forums/BlitzMax Programming/Begging for help with simple loop.| 
 | ||
| Please help me. I am so frustrated that I could shout at my screen. I am simply trying to produce a list of unique resolutions with no duplicates whatsoever. I have been playing around with this the entire night and I still end up with duplicates. I don't understand why!!! The second loop is entirely redundant. However, I am getting so desperate that I tried to break it down into two separate loops to isolate the issue. Your help would be greatly appreciated. The function to look at specifically is: Function PopulateRes() Local m:Res Local check:String[CountList(resolution.resolutionlist)] Local i:Int = 0 Local j:Int = 0 Local found:Int For m = EachIn Resolution.Resolutionlist check[i] = m.resolution i=i+1 Next For j=0 To check.length-1 found = 0 For m = EachIn Resolution.Resolutionlist If m.resolution = check[j] If found > 1 Then check[j]="" found = found + 1 End If Next Next For i=0 To check.length-1 If check[i]<>"" AddGadgetItem rescombobox, check[i] Print check[i] 'Testing EndIf Next End Function Here is the full code 
' <HEADER>
	SuperStrict
	Import maxgui.drivers
	Import brl.Graphics	
	Global APP_WIDTH:Int = 640
	Global APP_HEIGHT:Int = 240
' </HEADER>
' <OBJECTS>
	Type Resolution
		Global ResolutionList:TList = New TList
		Method New()
			ResolutionList.AddLast(Self)
		End Method
	End Type
	Type Res Extends Resolution
		Field Resolution:String
		Field Depth:String
		Field Hz:String	
		
		Function Create:Res(r:String,d:Int,h:Int)
			Local ent:Res = New Res
			ent.Resolution = r
			ent.Depth = d
			ent.Hz = h
			Return ent
		End Function
	End Type
' </OBJECTS>
' <FUNCTIONS>
	Function PopulateRes()
		Local m:Res
		Local check:String[CountList(resolution.resolutionlist)]
		Local i:Int = 0
		Local j:Int = 0
	      Local found:Int	
		For m = EachIn Resolution.Resolutionlist
			check[i] = m.resolution
			i=i+1
		Next
		
		For j=0 To check.length-1
			found = 0
			For m = EachIn Resolution.Resolutionlist		
				If m.resolution = check[j]										      			
					If found > 1 Then check[j]=""						
					found = found + 1 
				End If				
			Next			
		Next
		For i=0 To check.length-1
		  If check[i]<>"" 
			AddGadgetItem rescombobox, check[i]
			Print check[i]
		  EndIf
		Next	
	End Function
' </FUNCTION>
' <GUI>
	Local wx:Int = (GadgetWidth(Desktop()) - APP_WIDTH) / 2
	Local wy:Int = (GadgetHeight(Desktop()) - APP_HEIGHT) / 2
	Global window:TGadget = CreateWindow("Launcher", wx, wy, APP_WIDTH, APP_HEIGHT, Null, WINDOW_TITLEBAR | WINDOW_CLIENTCOORDS)
	Global rescombobox:TGadget = CreateComboBox(4, 50, 200, 22, window)
	Global depthcombobox:TGadget = CreateComboBox(4, 80, 200, 22, window)
	Global refreshcombobox:TGadget = CreateComboBox(4, 110, 200, 22, window)
' </GUI>
' <LISTS>
	Local mode:TGraphicsMode
	For mode:TGraphicsMode = EachIn GraphicsModes()
	    Local r:Res = res.Create(mode.width + " X " + mode.height,mode.depth,mode.hertz)
	Next
' </LISTS>
	
' <TEST>
	PopulateRes()
	'Local m:Res
	'For m = EachIn Resolution.Resolutionlist
      '   Print m.resolution
	'Next
' </TEST>
' <BODY>
	While WaitEvent()
	   Select EventID()
	
	   	Case EVENT_WINDOWCLOSE
	   		End
	
	   	Case EVENT_APPTERMINATE
	   		End
	   End Select
	Wend
' </BODY>
 | 
| 
 | ||
| If found > 1This should be >=1 | 
| 
 | ||
| Unless my compiler is buggy, this doesn't work for me. Does it work for you? | 
| 
 | ||
| I dont have Max yet so excuse me if I'm daft... Where do you eliminate duplicates? Local mode:TGraphicsMode For mode:TGraphicsMode = EachIn GraphicsModes() Local r:Res = res.Create(mode.width + " X " + mode.height,mode.depth,mode.hertz) Next In that loop you should put something like Local mode:TGraphicsMode For mode:TGraphicsMode = EachIn GraphicsModes() if ResNotRegistered(r:Res) Local r:Res = res.Create(mode.width + " X " + mode.height,mode.depth,mode.hertz) end if Next of course you would need to create the ResNotRegistered function that just checks the current list of Resolutions against the incoming resolution | 
| 
 | ||
| For j=0 To check.length-1 found = 0 For Local jj:Int = j To check.length-1 If check[jj] = check[j] found = found + 1 If found > 1 Then check[jj]="" End If Next Next | 
| 
 | ||
| Oops.. Local mode:TGraphicsMode For mode:TGraphicsMode = EachIn GraphicsModes() local rmode=mode.width + " X " + mode.height if ResNotRegistered(rmode) Local r:Res = res.Create(rmode,mode.depth,mode.hertz) end if Next | 
| 
 | ||
| Skully: Thanks for your help. I also can't get that to work. I still get duplicates on a couple of resolutions. Whatever and whichever way I try to write a function that returns True or False, I always end up with a few false negative. (Especially with the resolution 320 x 200) Zeke: I can't wait to try your version out. I cannot see in which way it is different to what I currently have. I tried it using two arrays the first time around and removing items from the first list. I will give it a go as soon as I am back in front of my screen. (Did you test it yourself?) | 
| 
 | ||
| Here's how I get a de-duplicated list of available graphics modes in the retroremakes framework: 	' Find graphics modes for all available drivers, de-duplicate
	' and exclude modes that don't appear on both drivers (where
	' available)
	Method FindGraphicsModes()
		'Get the OpenGL Modes first	
		SetGraphicsDriver(GLMax2DDriver())
		graphicsModes_ = ListFromArray(GraphicsModes())
		
		TGameEngine.GetInstance().LogInfo("OpenGL Graphics Modes Found: " + graphicsModes_.Count())
		'DirectX modes if on Windows
		?win32
			SetGraphicsDriver(D3D7Max2DDriver())
			Local dxModes:TList = ListFromArray(GraphicsModes())
			SetGraphicsDriver(D3D9Max2DDriver())
			Local dx9Modes:TList = ListFromArray(GraphicsModes())
			
			For Local mode:TGraphicsMode = EachIn dx9Modes
				dxModes.AddLast(mode)
			Next
			
			TGameEngine.GetInstance().LogInfo("DirectX Graphics Modes Found: " + dxModes.Count())
			'Remove DirectX Modes that aren't available under OpenGL
			
			For Local findMode:TGraphicsMode = EachIn dxModes
				Local found:Int = False
				For Local mode:TGraphicsMode = EachIn graphicsModes_
					If findMode.width = mode.width And ..
						findMode.height = mode.height And ..
						findMode.depth = mode.depth And ..
						findMode.hertz = mode.hertz
							found = True
							Exit
					End If
				Next
				
				If Not found
					dxModes.Remove(findMode)
				End If
			Next
			
			'Remove OpenGL Modes that aren't available under DirectX
			For Local findMode:TGraphicsMode = EachIn graphicsModes_
				Local found:Int = False
				For Local mode:TGraphicsMode = EachIn dxModes
					If findMode.width = mode.width And ..
						findMode.height = mode.height And ..
						findMode.depth = mode.depth And ..
						findMode.hertz = mode.hertz
							found = True
							Exit
					End If
				Next
				
				If Not found
					graphicsModes_.Remove(findMode)
				End If
			Next
			
			'Merge the lists
			For Local mode:TGraphicsMode = EachIn dxModes
				graphicsModes_.AddLast(mode)
			Next
		?
		
		' Now sort and deduplicate
		graphicsModes_.Sort(True, TGraphicsService.GraphicsModeSort)
		TGameEngine.GetInstance().LogInfo("Total Graphics Modes Found: " + graphicsModes_.Count())
		graphicsModes_ = DeDuplicateGraphicsModes(graphicsModes_)
		TGameEngine.GetInstance().LogInfo("Final De-Duplicated Graphics Modes Found: " + graphicsModes_.Count())
	End Method
	
	Function GraphicsModeSort:Int(o1:Object, o2:Object)
		Local o1mode:TGraphicsMode = TGraphicsMode(o1)
		Local o2mode:TGraphicsMode = TGraphicsMode(o2)
		Local compare:Int
		If o1mode.width < o2mode.width
			compare = -1
		ElseIf o1mode.width > o2mode.width
			compare = 1
		Else
			If o1mode.height < o2mode.height
				compare = -1
			ElseIf o1mode.height > o2mode.height
				compare = 1
			Else
				If o1mode.depth < o2mode.depth
					compare = -1
				ElseIf o1mode.depth > o2mode.depth
					compare = 1
				Else
					If o1mode.hertz < o2mode.hertz
						compare = -1
					ElseIf o1mode.hertz > o2mode.hertz
						compare = 1
					Else
						compare = 0
					End If
				End If
			End If
		End If
		
		Return compare
	End Function
	
	
	Method DeDuplicateGraphicsModes:TList(modes:TList)
		Local deDupedModes:TList = New TList
		Local first:Int = True
		For Local mode:TGraphicsMode = EachIn modes
			If first
				deDupedModes.AddLast(mode)
				first = False
			Else
				If GraphicsModeSort(deDupedModes.Last(), mode) <> 0
					deDupedModes.AddLast(mode)
				End If
			End If
		Next
		Return deDupedModes
	End MethodThere's a link to the framework in my sig if you want to check out the code in-situ. It's contained in the TGraphicsService.bmx file which is one of the core services of the framework. Muttley | 
| 
 | ||
| How about using a TMap? it sorts at insertion time and does not allow duplicates. Throw in a decent compare method, or just use strings... | 
| 
 | ||
| Dear grable, That looks really useful. Thanks. I would still like to figure out what is wrong with my code. I cannot get my head around what is causing the issue. It should be so simple! | 
| 
 | ||
| The reason it's not working is because you have your loops round the wrong way. You should iterate through the ResolutionList first and then the array. Each time it found a dupe, "j" had not increased in value so it was nulling the same string in the array each time it found one. Also, I think it should increment found before the if statement, not after. It should look like this: For m = EachIn Resolution.Resolutionlist found=0 For j=0 To check.length-1 If m.resolution = check[j] found = found + 1 If found > 1 check[j]="" End If End If Next Next Like Grable says, Tmap would be a good approach to this. Hope that helps! | 
| 
 | ||
| Awesome!! Can't wait to try it out and also learn about Tmap. Thanks. | 
| 
 | ||
| Thank you very much. I learned something new today. 
   local i:int
   for i=0 to 10
      print i 'result is 1 to 10
   next
   print i 'result is 11 !! (Now that is interesting)
If I print "i" after the loop, the value is 11. | 
| 
 | ||
| I'll recommend this idiom (used in Java/BlitzMax etc) to correctly modularize code: SuperStrict For Local i:Int = 0 To 10 Next print i ' will not work! (undefined variable) You can use another variable defined in a broader scope than the loop to save any loop-index values you might be interested in. It's (imho) a very good practice to use index variables (such as i in the example above) only within the loop, and since BMX supports isolating the variable to the loop this is really preferred. |