Matching cards by using .tag - vb.net

In this game I am creating, I have a set of "cards" as pictureboxes set to a random lot of images. When the game starts, the images in the pictureboxes are hidden and the user has to guess which image was in each card. I am having trouble with finding if the user's guess matches what was in the actual card.
In the code below, I am using a listbox to score the names of images in which the user can guess from.
https://imgur.com/a/xCg8X
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
If ClickedCard Is Nothing Then 'Make sure that a card has been clicked, otherwise the below code will fail.
MsgBox("You must select a card.")
Return 'Do not continue execution of this code.
End If
btnSubmit.Visible = True
ClickedCard.Image = imglist1.Images(ListBox1.SelectedIndex)
If ClickedCard.Tag = ListBox1.SelectedIndex Then
roundscore += 1
If roundscore = Cards.Count Then
MsgBox("All right")
End If
End If
End Sub

Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
Static AlreadySelected As New List(Of Integer)
If AlreadySelected.Contains(ListBox1.SelectedIndex) Then
MessageBox.Show("Already select once")
Exit Sub
End If
AlreadySelected.Add(ListBox1.SelectedIndex)
'Your other code here
End Sub
The static list will persist between calls to this sub. You will have to clear this list when you go to a new round. I hope this helps with the problem you mentioned in your comments. :-)

Related

Infinite loop is causing the form to not show up vb

I have an infinite loop in this sub because I want the program to keep testing this process to see if the variable has changed. When I run the program in the debugger, nothing shows up, including the form however when I removed the infinite loop from the program, the form showed up again. Does anyone know why this is happening? I should also mention I've tried a DO LOOP as well. Can anyone help?
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim greenCount As Integer
Dim looptest As Boolean = True
While looptest = True
For Each control In Me.Controls.OfType(Of Button)
If control.BackColor = Color.Lime Then
greenCount += 1
End If
Next
txtFielder.Text = greenCount.ToString
End While
End Sub
You need to get rid of all that code regardless. Depending on how you're changing the BackColor of those Buttons in the first place, updating the lime count might be best done there. Otherwise, you should be handling the appropriate event, e.g.
Private limeButtonCount As Integer = 0
Private Sub Buttons_BackColorChanged(sender As Object, e As EventArgs) Handles Button3.BackColorChanged,
Button2.BackColorChanged,
Button1.BackColorChanged
If DirectCast(sender, Button).BackColor = Color.Lime Then
limeButtonCount += 1
Else
limeButtonCount -= 1
End If
TextBox1.Text = limeButtonCount.ToString()
End Sub
Note that this code assumes that there are only two possible BackColor values and that all Buttons are not lime by default. If your scenario is a bit more complex than that then you may need to change a code a little, e.g.
Private limeButtonCount As Integer = 0
Private Sub Buttons_BackColorChanged(sender As Object, e As EventArgs) Handles Button3.BackColorChanged,
Button2.BackColorChanged,
Button1.BackColorChanged
limeButtonCount = Controls.OfType(Of Button)().Count(Function(b) b.BackColor = Color.Lime)
TextBox1.Text = limeButtonCount.ToString()
End Sub
Form.Load occurs before a form is displayed for the first time.
This means that you'll never see your form as long as you loop in this event. You probably want to use the Shown event instead.

How to update a form based on a checkbox status

I'm currently trying to code some macros for a software (Revit), and I ran into an issue I do not know how to solve.
So I have a windows form with two checkboxes and a list of elements, and I would like that list of elements to be updated depending on what the status of the checkboxes is.
Here's my checkbox status' code:
If StructcheckBox.Checked = True Then
Select Case tmpView.ViewType
Case ViewType.EngineeringPlan
vpList.Add(tmpVP)
End Select
End If
If LegcheckBox.Checked = True Then
Select Case tmpView.ViewType
Case ViewType.Legend
vpList.Add(tmpVP)
End Select
End If
Now the problem with that code is that it only checks the initial status of the checkboxes, but do not update the list when the checkboxes are checked/unchecked.
How to make it so that the list VpList is updated everytime a checkbox status is changed?
Thanks!
The key here is to add a sub that does the checkboxes checking. You will need that sub because it will called multiple times depending on the user's actions.
Because you are not providing any insights about tmpView and vpList I will stick with your code, however you should note that depending on what exactly are you trying to do your code can be simplified or rewritten to be a bit more efficient. For example you don't specify if you want the tmpVP value to be unique in the list or to be more than one times, I assume that you want to be unique, so here is the sub's code (please read the comments in the code):
Private Sub CheckBoxesStatus(StructcheckBoxChecked As Boolean, LegcheckBoxChecked As Boolean)
If StructcheckBoxChecked Then
If tmpView.ViewType = ViewType.EngineeringPlan Then
'Add code here to check if the tmpVP element is already in the vpList
'and add it only if there isn't otherwise it will be added each time the
'StructcheckBox is checked by the user...
'An example code is as follows:
If Not vpList.Contains(tmpVP) Then vpList.Add(tmpVP)
End If
End If
If LegcheckBoxChecked Then
If tmpView.ViewType = ViewType.Legend Then
'Add code here to check if the tmpVP element is already in the vpList
'and add it only if there isn't otherwise it will be added each time the
'LegcheckBox is checked by the user...
'An example code is as follows:
If Not vpList.Contains(tmpVP) Then vpList.Add(tmpVP)
End If
End If
End Sub
Now that you have the sub you can call it whenever you want. "Whenever you want" means on various user's actions, like checking or un-checking a checkbox and in various other places like form's initialization (loading) these are events. According to your question you need to call it from 3 different events.
1.When the form is loading in order to get the initial status:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
CheckBoxesStatus(StructcheckBox.Checked, LegcheckBox.Checked)
End Sub
2.When the user changes the StructcheckBox status:
Private Sub StructcheckBox_CheckedChanged(sender As Object, e As EventArgs) Handles StructcheckBox.CheckedChanged
CheckBoxesStatus(StructcheckBox.Checked, LegcheckBox.Checked)
End Sub
3.When the user changes the LegcheckBox status:
Private Sub LegcheckBox_CheckedChanged(sender As Object, e As EventArgs) Handles LegcheckBox.CheckedChanged
CheckBoxesStatus(StructcheckBox.Checked, LegcheckBox.Checked)
End Sub
Here is the full form's code:
Public Class Form1
Private Sub CheckBoxesStatus(StructcheckBoxChecked As Boolean, LegcheckBoxChecked As Boolean)
If StructcheckBoxChecked Then
If tmpView.ViewType = ViewType.EngineeringPlan Then
'Add code here to check if the tmpVP element is already in the vpList
'and add it only if there isn't otherwise it will be added each time the
'StructcheckBox is checked by the user...
'An example code is as follows:
If Not vpList.Contains(tmpVP) Then vpList.Add(tmpVP)
End If
End If
If LegcheckBoxChecked Then
If tmpView.ViewType = ViewType.Legend Then
'Add code here to check if the tmpVP element is already in the vpList
'and add it only if there isn't otherwise it will be added each time the
'LegcheckBox is checked by the user...
'An example code is as follows:
If Not vpList.Contains(tmpVP) Then vpList.Add(tmpVP)
End If
End If
End Sub
Private Sub StructcheckBox_CheckedChanged(sender As Object, e As EventArgs) Handles StructcheckBox.CheckedChanged
CheckBoxesStatus(StructcheckBox.Checked, LegcheckBox.Checked)
End Sub
Private Sub LegcheckBox_CheckedChanged(sender As Object, e As EventArgs) Handles LegcheckBox.CheckedChanged
CheckBoxesStatus(StructcheckBox.Checked, LegcheckBox.Checked)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
CheckBoxesStatus(StructcheckBox.Checked, LegcheckBox.Checked)
End Sub
End Class
Hope this helps.

Barcode scanning to a listbox checking for duplicates

Good day!
I want to add some strings from a barcode scanner, captured in a text box, to a list box, and, before adding it, to check if the specific string hasn't been already added. So I have a text box called txtWO which captures what the reader scans and a list box called lstScanBOM to which I add the text box string if the item is not already added. The problem is, that whatever I do, only after the specific string is added twice the checking for duplicate entry starts to work. In other words I scan the same string twice, it added it, and then when I scan the third time only it throws the message with the error saying it is a duplicate. I don't understand why is doing this. The code is below:
Private Sub frmValidareFIP_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If txtWO.Focused = False Then
txtWO.Select()
End If
End Sub
Private Sub AddUnique(StringToAdd As String)
If lstScanBom.Items.Contains(StringToAdd) = True Then
MsgBox("Articol duplicat!", vbOKOnly)
Else
'it does not exist, so add it..
lstScanBom.Items.Add(StringToAdd)
End If
End Sub
Private Sub txtWO_KeyDown(ByVal sender As Object,ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtWO.KeyDown
If e.KeyCode = Keys.Enter Then
Dim barcode As String
barcode = txtWO.Text
AddUnique(barcode)
txtWO.Clear()
txtWO.Focus()
End If
End Sub
IMO Try listing the data outside of the ListBox. I can't see why it isn't working, maybe we need a third pair of eyes to see it!?
Try adding a list (of string) as a Private within the form, populate this as your user scans, and check the duplicate there..
This is definately not the best solution, but I'm sure it will help!
Private List_Barcodes As List(Of String)
Private Sub frmValidareFIP_Load(sender As Object, e As EventArgs) Handles MyBase.Load
List_Barcodes = New List(Of String)
'You can also populate this list on load, if you have a stored cahce of previous scanned barcodes?
'List_Barcodes.Add("0123456")
'List_Barcodes.Add("4567890")
'...etc
If txtWO.Focused = False Then
txtWO.Select()
End If
End Sub
Private Sub AddUnique(StringToAdd As String)
If List_Barcodes.Contains(StringToAdd) Then
MsgBox("Articol duplicat!", vbOKOnly)
Else
'Place into dynamic list
List_Barcodes.Add(StringToAdd)
'and Place into your listbox
lstScanBom.Items.Add(StringToAdd)
End If
End Sub
Private Sub txtWO_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtWO.KeyDown
If e.KeyCode = Keys.Enter Then
Dim barcode As String
barcode = txtWO.Text
AddUnique(barcode)
txtWO.Clear()
txtWO.Focus()
End If
End Sub
Your barcode reader is returning <carriage return><line feed> as enter. Your code catches the enter key (carriage return = 13), but leaves the line feed (10) character. So the next time you scan something it will start with a line feed. The two strings in your example are different because the first is "58335001" and the second is "<line feed>58335001". The third one is "<line feed>58335001", which is a duplicate of the second.
One way to fix this is to trim your string.
Private Sub txtWO_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtWO.KeyDown
If e.KeyCode = Keys.Enter Then
Dim barcode As String
'Add the .Trim() to remove the leading <line feed> character
barcode = txtWO.Text.Trim()
AddUnique(barcode)
txtWO.Clear()
txtWO.Focus()
End If
End Sub
The most simple decision is ONLY to make your textBox control txtWO NOT multiline
And that's enough! Your code will work correctly!

combox selected index didnt work on picturebox

Now what i was doing is when i click a button group box 1 and group box 2 will show out i want to select the combobox item than the picturebox item will load
and this can be used it multiple time like when button-5 clicked the combobox item name will change and the picture will change too.
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
GroupBox1.Show()
GroupBox2.Show()
comboboxselectdiffrent.Items.Add("pizza_ChickenSupreme")
comboboxselectdiffrent.Items.Add("pizza_CockadoodleBacon")
If comboboxselectdiffrent.SelectedIndex = 0 Then
PictureBox1.Image = PIZZA_HUT_SYSTEM_NEW_VER.My.Resources.Resources.pizza_ChickenSupreme
ElseIf comboboxselectdiffrent.SelectedIndex = 1 Then
PictureBox1.Image = PIZZA_HUT_SYSTEM_NEW_VER.My.Resources.Resources.pizza_CockadoodleBacon
End If
End Sub
Can anyone tell me what i was do wrong? i have no idea why it wont work
After looking at your code personality I would have the event trigger from the combobox click, that way it will save the user having to first click on the combo to select their pizza and then having to click on a button to load the picture & details. Nevertheless try this.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ComboBox1.Items.Add("pizza_ChickenSupreme")
ComboBox1.Items.Add("pizza_CockadoodleBacon")
ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
GroupBox1.Show()
GroupBox2.Show()
Select Case ComboBox1.SelectedItem
Case Is = "pizza_ChickenSupreme"
PictureBox1.ImageLocation = "Pictures/mypic.jpg"
Case Is = "pizza_CockadoodleBacon"
PictureBox1.ImageLocation = "Pictures/mypic1.jpg"
End Select
End Sub
End Class
Using a custom Folder within the solution explorer will be better than using a setting resource. Create a folder and drag your pictures into it and change the name of the image location to suit your needs.
Also i think using the items name is better than the items index because what happens if someone reason that indexed item is to change from 1 to 5, you would have to recode it all, but by using the items name, it has more detail as to what to look for.
If you have any problems, leave a comment and I will do my best to help you out.Happy Coding!

Parallel programming in VB.NET

I have a simple For Each loop in a Button's click even, which looks like so:
Protected Sub SelectAllButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles SelectAllButton.Click
RadGrid1.AllowPaging = False
RadGrid1.Rebind()
For Each item In RadGrid1.Items
TryCast(TryCast(item, GridDataItem)("template").FindControl("CheckBox1"), CheckBox).Checked = True
Next
SaveSelectedRFPs()
RadGrid1.AllowPaging = True
RadGrid1.Rebind()
End Sub
Now inside that for each loop there could be upwards of 100k records to loop through and I know there has to be a more efficient way to accomplish this, maybe parallel programming?
#Nico Schetler:
I tried that, here's how the code looks
Protected Sub SelectAllButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles SelectAllButton.Click
RadGrid1.AllowPaging = False
RadGrid1.Rebind()
Parallel.ForEach(RadGrid1.Items.AsQueryable.Cast(Of GridDataItem).ToList(), Sub(item)
TryCast(TryCast(item, GridDataItem)("template").FindControl("CheckBox1"), CheckBox).Checked = True
End Sub)
SaveSelectedRFPs()
RadGrid1.AllowPaging = True
RadGrid1.Rebind()
End Sub
But that gives me a Source is not IEnumerable<> error when I try to run it.
Correct me if I'm wrong... (no, seriously)
Don't you want to select every term in the array?
Currently, as far as I can tell, when you perform actions on your selected set, you check which one is checked. Maybe add a parameter to SaveSelectedRFPs() that determines whether to save selected RFPs or unselected ones. That saves you the entire loop process. Of course, you lose the visual effect, but it may be worth it to the customer for a massive performance advantage.
Public Sub SaveRFPs(SelectedOrUnselected As Boolean)
If selectedRFP.Checked = SelectedOrUnselected Then
selectedRFP.save()
End If
End Sub