|
-
May 27th, 2014, 01:13 PM
#1
Thread Starter
Lively Member
Sorting Listview by comparing values
I am having a little trouble figuring out a method of doing this. Basically, I have a listview that contains a bunch of poker hands. I have written a function to convert a text string into a hand. (Example: AS-2S-3S-4S-5S results in a straight flush.) I have also wrote a function to compare two hands to see which one wins. Now I need to cycle through my listview and sort the hands using my compare function. Since it is hard to reorder a listview, I thought maybe would be better to add a new column with a rank. The hand with 1 in the rank column would be the highest hand.
Right now, I'm just trying to wrap my head around the logic. Any help would be appreciated.
-
May 27th, 2014, 02:17 PM
#2
Re: Sorting Listview by comparing values
Yep adding a rank and then sort by rank, should be simple
http://www.vbforums.com/showthread.p...s-numbers-text
-
May 27th, 2014, 03:29 PM
#3
Thread Starter
Lively Member
Re: Sorting Listview by comparing values
Thanks for the response, but it's not quite what I'm looking for. That project basically shows how to sort a listview by clicking on a column. I could use that to sort the rank column numerically, but what I need is to assign a rank to each hand first. I hope that makes sense.
-
May 27th, 2014, 03:36 PM
#4
Re: Sorting Listview by comparing values
So what are you asking?
I would imagine that there are lots of samples online related to poker hands.
Why are you using a listview at all? I would probably just use arrays
-
May 27th, 2014, 04:02 PM
#5
Thread Starter
Lively Member
Re: Sorting Listview by comparing values
The listview is displaying the results. Basically, I will have 50-300 people submitting a poker hand. The listview displays each poker hand and who it belongs to. Once everyone submits their hands, I need to find out who has the highest and lowest hands. I suppose it would be a little easier to just get the high and low hands, but I would just like to sort the whole list. The listview looks like this:
Name Cards Hand Rank?
Chad AS-2S-3C-4D-5H Straight ?
John 2S-3S-4S-5S-6S Straight Flush ?
etc.
I wrote a function that will take 2 hands and find out which one wins. Now I just need to sort the list. I only added the Rank column for sorting purposes. It could go away if it is not needed, but I figured it would be easier to fill in a rank than to sort the listview. Once the Rank column is filled, it could easily be sorted by that column.
-
May 27th, 2014, 04:30 PM
#6
Re: Sorting Listview by comparing values
If you are already using a function that compares two hands, then you already have the basis of a sorting mechanism in place, surely? Ranking 50-300 hands is simply a matter of bubble-sorting your 300 hands using your existing function to move items toward the top as you compare them. Lots of bubble sort examples here...
If you don't know where you're going, any road will take you there...
My VB6 love-children: Vee-Hive and Vee-Launcher
-
May 28th, 2014, 01:25 AM
#7
Re: Sorting Listview by comparing values
The standard API sort would work well in this situation if I understand it correctly, since it sorts by comparing 2 items. The only particularly burdensome part is you need to set the lParam to identify items.
But if you did that... you would send LVM_SORTITEMS, with the address of the compare proc. The compare proc compares 2 items and sorts based on the results. So you could look up each item from the lparam, then pass their hands to your function that determines which wins. So it doesn't sort by the value in the column (although you could), it takes the info from the columns - the two player hands - and sorts based on which one you say wins.
Using an API sort has the additional benefit, I believe, of being much faster than non-API sort methods, which may be significant if you're frequently sorting 300 items. (and if it's not faster, it would be if it was an pure API listview, so shh).
Here's basically what you would need. I haven't ran this code, so it might have errors, and cutting out just the definitions needed from my def files which have every listview api def ever would take a good 20-30minutes... I'll leave at least that part to you. Everything is the standard ANSI api definition (lvitem with psztext as string, etc.. no unicode).
Code:
Public Sub SortListView()
Call ListView_SortItems(ListView1.hWnd, 0, AddressOf ListViewSortProc)
End Sub
Public Function SetLVItemlParam(hWnd As Long, iItem As Long, lParam As Long) As Long
'you'd have to call this function each time you added an item with a unique value
'for lparam. the index would be fine.
Dim lvi As LVITEM
lvi.mask = LVIF_PARAM
lvi.iItem = iItem
lvi.lParam = lParam
SetLVItemlParam = SendMessage(hWnd, LVM_SETITEM, 0, lvi)
End Function
Public Function ListView_SortItems(hWndLV As Long, pfnCompare As Long, lParamSort As Long) As Boolean
ListView_SortItems = SendMessage(hWndLV, LVM_SORTITEMS, ByVal lParamSort, ByVal pfnCompare)
End Function
Public Function ListViewSortProc(ByVal lParam1 As Long, _
ByVal lParam2 As Long, _
ByVal lParamSort As Long) As Long
Dim sHand1 As String
Dim sHand2 As String
Dim lResult As Long
sHand1 = GetLVHand(lParam1)
sHand2 = GetLVHand(lParam2)
ListViewSortProc = CompareHands(sHand1, sHand2)
'your CompareHands procedure would have to return 0, 1, or 2
'where 1 means the hands are the same.
'Alternatively, If you did have a rank column, you could just
'get those values and compare them directly like a standard sort
'lHand1,2 = GetHandRank(...just get a different subitem than GetLVHand)
'If lHand1 <, =, > then return 0,1,2
End Function
Public Function GetLVHand(lParam As Long) As String
Dim hIndex As Long
Dim r As Long
Dim lvf As LVFINDINFO
Dim lvi As LVITEM
lvf.Flags = LVFI_PARAM
lvf.lParam = lParam
hIndex = SendMessage(hWnd, LVM_FINDITEM, -1, lvf)
lvi.mask = LVIF_TEXT
lvi.iSubItem = 1 'or whichever subitem contains the players hands
lvi.pszText = Space$(32)
lvi.cchTextMax = Len(lvi.pszText)
r = SendMessage(hWnd, LVM_GETITEMTEXT, hIndex, lvi)
If r > 0 Then
GetLVHand = Left$(lvi.pszText, r)
End If
End Function
Last edited by fafalone; May 28th, 2014 at 02:15 PM.
-
May 28th, 2014, 05:01 PM
#8
Thread Starter
Lively Member
Re: Sorting Listview by comparing values
That last code is a little above my head. I don't really see what is going on there.
I have been playing with the Collection method that I mentioned above, but I can't get it quite right. It seems to be close. The order is just a bit off. Maybe someone can see what is wrong with it. Keep in mind, I am not a real programmer. I just do this as a hobby occasionally.
Code:
Public Sub RankHands(lvw As ListView)
Dim colHands As New Collection
Dim LI As ListItem
Dim Hand1 As Hand
Dim Hand2 As Hand
Dim iWinner As Integer
Dim TempIndex As Integer
Dim x As Integer
Dim y As Integer
'Add first list item to collection
colHands.Add lvw.ListItems(1)
'Insert remaining listitems into collection
For x = 2 To lvw.ListItems.Count
Set LI = lvw.ListItems(x)
Hand1 = StringToHand(LI.SubItems(1))
For y = 1 To colHands.Count
Hand2 = StringToHand(colHands(y).SubItems(1))
iWinner = CompareHands(Hand1, Hand2)
Select Case iWinner
Case 0
'Tie
If y = colHands.Count Then colHands.Add LI, LI, , y
Case 1
'Hand1 wins
colHands.Add LI, LI, y
If y < colHands.Count Then Exit For
Case 2
'Hand2 wins
If y = colHands.Count Then colHands.Add LI, LI, , y
Case Else
MsgBox "Error"
End Select
Next y
Next x
'Write collection back to listview
For y = 1 To lvw.ListItems.Count
lvw.ListItems(y).SubItems(3) = colHands(y).index
Next y
End Sub
-
May 28th, 2014, 06:37 PM
#9
Re: Sorting Listview by comparing values
I can't follow your code either so...
My code would work like:
1) When you add an item to the list, you also call SetLVItemlParam(listview.hwnd, item number, item number again since that is unique)
2) Call the SortListView function
And the only changes youd make,
-In ListviewSortProc, just convert the string that's returned from subitem 1 (A-Q-9 whatever) to your hand object
-Your CompareHands should return 1 as a tie, and 0 or 2 for a winner
It was magic to me at first too, fortunately you don't need to worry about how exactly it works, just have to change a couple details. It really is the best way to do this; trying to do it another way is going to be just as complicated. Sorting isn't easy to get your head around if you're not using it frequently.
-
May 29th, 2014, 09:24 AM
#10
Thread Starter
Lively Member
Re: Sorting Listview by comparing values
Thanks for the help, but I think I'm going to give up on this. I can sort it by hand type (Straight, Flush, etc.) since each hand type is just an integer anyway. Then I will just have to manually compare hands of the same type.
-
May 29th, 2014, 10:44 PM
#11
Re: Sorting Listview by comparing values
 Originally Posted by littlewing1977
Thanks for the help, but I think I'm going to give up on this. I can sort it by hand type (Straight, Flush, etc.) since each hand type is just an integer anyway. Then I will just have to manually compare hands of the same type.
Well your *principle* sorting approach may be right (I havent tested what you posted in #8) -
but the errors creep in IMO, because you don't store "hard values" in your collection,
but the reference-values to the ListItem-Objects themselves.
I'd deal with your Hand-Strings directly instead (avoiding Object-Refs).
As I see it - what you attempt is an enumeration of "Hands" which exist in a ListView -
entering them whilst doing so into a collection - then refilling the listview from the
(now sorted) collection, after the enumeration-loop is through.
Below is an example which demonstrates that with simplified strings (and not
using a ListView, but a ListBox) - but that's what should be easy to adapt.
Code:
Option Explicit
Private Sub Form_Load() 'Demo-Data
List1.AddItem "456"
List1.AddItem "xyz"
List1.AddItem "abc"
List1.AddItem "123"
End Sub
Private Sub Form_Click()
Dim i As Long, Col As New Collection
For i = 0 To List1.ListCount - 1 'sorted adding to the Col
AddSortedTo Col, List1.List(i)
Next i
List1.Clear 'clear the List-Content
For i = 1 To Col.Count 're-add the List-Content
List1.AddItem Col(i)
Next i
End Sub
Private Sub AddSortedTo(Col As Collection, ByVal Item As String)
Dim i As Long
'exit early, as soon as the the current ColItem becomes > than our new one (the Item-Parameter of this Sub)
For i = 1 To Col.Count
If CompareHandStrings(Col(i), Item) = 1 Then Exit For
Next
If i > Col.Count Then Col.Add Item Else Col.Add Item, , i
End Sub
Private Function CompareHandStrings(ByVal strH1 As String, ByVal strH2 As String) As Long
CompareHandStrings = StrComp(strH1, strH2)
End Function
The above function: CompareHandStrings
needs to be adjusted by you appropriately - currently it hands out
the result of the StrComp-function - just mimic that behaviour in your
Hand-comparison:
-1 when smaller
0 when equal
1 when larger
It's just a principle-demo I was trying to keep as understandable as possible.
Olaf
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|