Do Until Loop checking for duplicates wont stop looping - vb.net

I'm trying to do a Do Until Loop to check for duplicates in my combo box. It runs the loop but it never stops looping.
Dim i As Integer = 0
Dim flavors As Integer = flavorsComboBox.Items.Count
Do Until (i < flavors - 1)
If flavors = flavorsComboBox.Items.Count Then
MessageBox.Show("Flavor Already Exists!", "Error")
Else
flavorsComboBox.Items.Add(flavorsComboBox.Text)
End If
Loop

The condition of the loop looks at the i variable and the flavors variable:
Do Until (i < flavors - 1)
But those variables don't ever change at any point in the body of the loop:
If flavors = flavorsComboBox.Items.Count Then
MessageBox.Show("Flavor Already Exists!", "Error")
Else
flavorsComboBox.Items.Add(flavorsComboBox.Text)
End If
You need to add code to change one or both of those variables. But that's still the hard way to do this. Just use the Distinct() method:
Dim items = flavorsComboBox.Items.Distinct().ToArray()
flavorsComboBox.Items.Clear()
flavorsComboBox.Items.AddRange(items)

Here is a simple do until loop
Dim i as integer = 0
Dim flavors as Integer = 10
do until (i > flavors -1)
Console.WriteLine(i.ToString())
i = i +1
loop
Output
0
1
2
3
4
5
6
7
8
9
In your code:
do until (i < flavors - 1)
if i = 0 and flavors is the Count -1 when is 0 greater than count, to enter the condition of the loop.
The next omission is that you never change the value of condition variable of looping, to have an accurate evaluation of the condition to stop the loop.

Try this:
Option Strict On
Option Explicit On
Option Infer Off
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If AddDistinct(flavorsComboBox, "test") Then
MsgBox("Item did not exist, so it was added.")
Else
MsgBox("Item already existed, so it was not added.")
End If
End Sub
Public Function AddDistinct(cboBox As ComboBox, value As Object) As Boolean
If cboBox.Items.IndexOf(value) = -1 Then cboBox.Items.Add(value) : Return True
Return False
End Function
End Class

You are not resetting the value of flavors
Try this:
Dim i As Integer = 0
Dim flavors As Integer = flavorsComboBox.Items.Count
Do Until (i < flavors - 1)
If flavors = flavorsComboBox.Items.Count Then
MessageBox.Show("Flavor Already Exists!", "Error")
Else
flavorsComboBox.Items.Add(flavorsComboBox.Text)
flavors = flavorsComboBox.Items.Count
End If
Loop

Related

If condition being ignored

I'm currently writing code for a game called Caladont.
The game is about first player saying the word and the next one has to say the word that starts with last two letters of previous word.
The problem comes when I want to check if word contains less than 3 letters or if it's empty.
In the first cycle when list for filling is still empty, everything is fine.
However, after I type for example 5 or more words and type a single letter or leave it empty, it prints two "You've lost!" messages, which means that code from if statement is being ignored since it changes bool variable to false and is supposed to exit the While loop.
I've tried replacing ok = false with Exit While in condition which checks if words contains less than 3 letters and it worked, but I want to understand what is the problem.
The code can also be found here [Caladont game
GitHub](https://github.com/whistleblower91/VB.net/blob/master/Caladont%20game):
Module Module1
Sub Main()
Kaladont()
End Sub
Sub Kaladont()
Const msg As String = "You've lost!"
Dim list As New List(Of String)
Dim word As String
Dim i As Integer
Dim ok As Boolean
ok = True
While ok
Console.Write("Insert word:")
word = Console.ReadLine()
list.Add(word)
If word.Length < 3 Or word = "" Then
Console.WriteLine(msg)
ok = False
End If
If list.Count > 1 Then 'Skip checking first word
For i = 0 To list.Count - 2
If word.ToLower = lista(i).ToLower Then
Console.WriteLine(msg)
ok = False
End If
Next
If LastTwo(word) = "ka" Or LastTwo(word)="nt" Then
Console.WriteLine("KALADONT! You won!")
ok = False
End If
If FirstTwo(list.Last) <> LastTwo(list(list.Count - 2)) Then
Console.WriteLine(msg)
ok = False
End If
End If
End While
Check()
End Sub
Function FirstTwo(ByVal s1 As String) As String
Return Left(s1.ToLower, 2)
End Function
Function LastTwo(ByVal s2 As String) As String
Return Right(s2.ToLower, 2)
End Function
Sub Check()
Dim sign As Char
Console.WriteLine("Do you want to start new game? y\n")
sign = Console.ReadLine()
If sign = CChar("y") Then
Console.Clear()
Kaladont()
ElseIf sign = CChar("n") Then
Exit Sub
End If
End Sub
End Module
Any solutions?
Even if you set ok to false, it will still go inside the other loop, you'll need to use Else
If word.Length < 3 Or word = "" Then
Console.WriteLine(msg)
ok = False
Else If list.Count > 1 Then 'Skip checking first word
An other way would be to exit the while with End while.
If word.Length < 3 Or word = "" Then
Console.WriteLine(msg)
ok = False
Exit While
End If

Visual Basic: How can i display the prime numbers between 1 and the inputted number

Hello everyone so i'm trying to find the prime numbers of any input. I want them to be in a listbox and the input in a text box. I would like to use two arguments but i don't know how to. this is the code i have i need dire help. I am not the best at visual basic i just need some guidance. My code isn't working but display a drop down box when i press display.
Public Class Form1
Private Sub Button3_Click_1(sender As Object, e As EventArgs) Handles Button3.Click
Dim prim As Integer
Dim test As Integer
Dim imPrime As Boolean = False
prim = CInt(txtNum.Text)
test = prim
If prim = 1 Then
imPrime = False
MessageBox.Show("Enter a number greater than one please")
Else
Do While prim >= 2
For i As Integer = 2 To prim
If prim Mod i = 0 Then
imPrime = False
Exit For
Else
imPrime = True
lstPrime.Items.Add(prim)
End If
Next
Loop
End If
If imPrime = True Then
lstPrime.Items.Add(prim)
End If
End Sub
End Class
This is my fastest VBA code to generate prime numbers between two numbers.
The generated prime numbers are put in clipboard. You will need to open
your ms office word and type Ctrl+V to view all the generated prime numbers.
Sub generateprimenumbersbetween()
Dim starting_number As Long
Dim last_number As Long
Dim primenumbers As Variant
Dim a As Long
Dim b As Long
Dim c As Long
starting_number = 1 'input value here
last_number = 1000000 'input value here
primenumbers = ""
For a = starting_number To last_number
c = Round(Sqr(a)) + 1
For b = 2 To c
If a = 1 Or (a Mod b = 0 And c <> b) Then
Exit For
Else
If b = c Then
primenumbers = primenumbers & " " & a
Exit For
End If
End If
Next b
Next a
Dim answer As DataObject
Set answer = New DataObject
answer.SetText primenumbers
answer.PutInClipboard
End Sub
I think the while loop is not working as you intend. You need two loops, the first one counting up to the possible prime, and an inner one counting up to the counter in the outer loop.
You can find examples everywhere... here's one implemented in C#, but since your question was specifically about a listbox, I've translated it to VB.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
calculatePrimes()
End Sub
Private Sub calculatePrimes()
Dim prim As Integer
Dim count As Integer = 0
prim = CInt(Me.TextBox1.Text)
If prim < 3 Then
MsgBox("Please enter a bigger number")
Return
End If
Me.ListBox1.Items.Clear()
For i As Integer = 1 To prim
Dim isPrime As Boolean = True
For j As Integer = 2 To i
If (i Mod j <> 0) Then count = count + 1
Next
If count = (i - 2) Then Me.ListBox1.Items.Add(i)
count = 0
Next
End Sub
End Class
(This assumes you have a textbox for input called TextBox1 and a listbox for display called ListBox1)

Collection was modified; enumeration operation may not execute. VB thearding

Here is my code,
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
For Each kthread As Thread In _threads
If kthread.Name = "123" Then
_threads.Remove(kthread)
kthread.Abort()
killedthreads += 1 'a integer
End If
Next
End Sub
I added the killedthreads integer at last as a check, vb executes the whole function good but at the last line it always throw the error said in title.
Not sure why, if killedthreads += 1 is not there then the error goes to kthread.Abort()
I had the same problem with C# with a different app earlier this year.
Edit,
Public Sub KillThread(kThread As Thread)
For i As Integer = (_threads.Count - 1) To 0 Step -1
If _threads.Item(i).Name = kThread.Name Then
_threads.Item(i).Abort()
_threads.RemoveAt(i)
End If
Next
End Sub
I did this code as Eminem said it. This gets in kThread from the running threads if something is not good or it has finished all its functions. But my problem is that, only the first thread that sends it gets abort and removed from list, others seem to get stuck once the first thread is aborted.
I create threads using,
Public Sub multiThreader(int As Integer, link As String)
Dim tCount As Integer = _threads.Count
If tCount >= Form1.ListView1.Items.Count Then
Else
Dim dy As Integer = DateTime.Now.Day
Dim mo As Integer = DateTime.Now.Month
Dim fileNum As String = dy.ToString() + "-" + mo.ToString() + "_" + int.ToString
botThread = New Thread(Sub() MainThread(fileNum, link, botThread, int.ToString()))
botThread.IsBackground = True
botThread.Name = String.Format("AutoBotThread{0}", fileNum)
_threads.Add(botThread)
botThread.Start()
End If
End Sub
and _threads is publicly, Public _threads As New List(Of Thread)
MainThread is a Public Sub which runs functions and gets return and send KillThread under certain conditions.
The problem is that you remove an item from an enumeration, before you finished iterating through it.
It's like trying to iterate from 0 to list.count, when the count changes from an iteration to another. As Bjørn-Roger Kringsjå said, you should do something like this:
For i As Integer = (_threads.count - 1) to 0 Step -1
If _threads.Item(i).Name = "123" Then
_threads.Item(i).Abort
_threads.RemoveAt(i)
killedthreads += 1 'a integer
End If
Next
By using Step -1 you make sure that an Index was out of range error will not occur, and make sure that your operations are fitted, and execute on the right order/item.

If an INDEX exist in Listbox in vb.net

I am running a Do Until Loop and its giving the error Index out of range. I am using this code:
If Not imgList.Item(i).ToString = Nothing Then
but its not working..
Actually this loop (in a private sub) is called before addition of any value in the Listbox..
here is the complete loop..
Dim i As Integer = 0
Do Until i = pagesRange
If Not imgList.Item(i).ToString = Nothing Then
'other code
i += 1
Else
End If
Loop
for the given code to avoid Index out of range exception try below
If imgList.Count < i AndAlso Not (imgList.Item(i).ToString Is Nothing) Then
End If
Remember about Zero Based ..
Dim i As Integer = 0
Do Until i = pagesRange -1
If Not imgList.Item(i).ToString = Nothing Then
'other code
i += 1
Else
End If
'why i += 1 not here ?
Loop

My program is assigning a value to ALL objects in an array. What's happening and how do I prevent it ? (VB 2008)

I have exhausted all of my options and am very desperate for help since I cannot figure out where the bug in my code is, or if there is something I don't understand.
I'm trying to create a "methinks it is a weasel!" mimmick from Richard Dawkins' late 80s documentary about evolution. The goal is to progress through a genetic algorithm until the algorithm guesses the correct answer through mutation and fitness tournaments.
Now, here's the problem:
Private Function fitnessTourney(ByVal editGuess() As Guess, ByVal popIndex As Integer, ByVal tourneySize As Integer, ByVal popNum As Integer)
Dim randInt(tourneySize - 1) As Integer
Dim loopCount1 As Integer = 0
Dim fitnessWinner As New Guess
fitnessWinner.setFitness(-50)
...
And, this loop is where I am experiencing the critical error
...
For i = 0 To tourneySize - 1
Randomize()
randInt(i) = Int(Rnd() * popNum)
While editGuess(randInt(i)).Used = True
If loopCount1 > tourneySize Then
loopCount1 = 0
For i2 = 0 To popNum - 1
editGuess(i2).setUsed(False)
Next
i = -1
Continue For
End If
loopCount1 += 1
randInt(i) = Int(Rnd() * popNum)
End While
editGuess(randInt(i)).determineFitness(correctPhrase)
editGuess(randInt(i)).setUsed(True)
Next
For i = 0 To popNum - 1
editGuess(i).setUsed(False)
Next
What this loop is trying to do is pick out four random instances of the editGuess array of objects. This loop tries to prevent one from being used multiple times, as the population is competing to one of the 10 members (highest fitness of the 4 chosen candidates is supposed to win).
The critical error is that I mysteriously get an endless loop where any instances of editGuess(randInt(i)).Used will always evaluate to true. I have tried to fix this by resetting all instances to False if it loops too many times.
The stumper is that I'll have all instances evaluate to False in the debugger. Then, when I reach "editGuess(randInt(i)).setUsed(True)" (the exact same thing as "editGuess(randInt(i)).Used = True"), it sets this value for EVERY member of the array.
Is there anyone who can see what is happening? I am so close to completing this!
Here's the Guess class:
Public Class Guess
Dim Fitness As Integer
Dim strLength As Integer
Dim strArray(30) As String
Dim guessStr As String
Dim Used As Boolean
Public Sub New()
Fitness = 0
guessStr = ""
strLength = 0
Used = 0
End Sub
Public Sub determineFitness(ByVal correctPhrase As String)
Dim lowerVal
If guessStr.Length <= correctPhrase.Length Then
lowerVal = guessStr.Length
Else
lowerVal = correctPhrase.Length
End If
strArray = guessStr.Split("")
Fitness = 0 - Math.Abs(correctPhrase.Length - guessStr.Length)
For i = 0 To lowerVal - 1
If correctPhrase(i) = guessStr(i) Then
Fitness = Fitness + 1
End If
Next
End Sub
Public Sub Mutate(ByVal mutatepercentage As Decimal, ByVal goodLetters As String)
If mutatepercentage > 100 Then
mutatepercentage = 100
End If
If mutatepercentage < 0 Then
mutatepercentage = 0
End If
mutatepercentage = mutatepercentage / 100
If Rnd() < mutatepercentage Then
strLength = Int(Rnd() * 25) + 5
If strLength < guessStr.Length Then
guessStr = guessStr.Remove(strLength - 1)
End If
End If
For i = 0 To strLength - 1
If Rnd() < mutatepercentage Then
If i < guessStr.Length Then
guessStr = guessStr.Remove(i, 1).Insert(i, goodLetters(Int(Rnd() * goodLetters.Length)))
Else
guessStr = guessStr & goodLetters(Int(Rnd() * goodLetters.Length))
End If
End If
Next
End Sub
Public Sub setFitness(ByVal num As Integer)
Fitness = num
End Sub
Public Sub setStrLength(ByVal num As Integer)
strLength = num
End Sub
Public Sub initializeText()
End Sub
Public Sub setUsed(ByVal bVal As Boolean)
Used = bVal
End Sub
End Class
And, finally, here's where and how the function is called
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
population1(counter) = fitnessTourney(population1, counter, 4, 10)
population2(counter) = fitnessTourney(population2, counter, 4, 10)
population1(counter).Mutate(2, goodLetters)
population2(counter).Mutate(20, goodLetters)
Label1.Text = population1(counter).guessStr
Label2.Text = population2(counter).guessStr
counter += 1
If counter > 9 Then
counter = 0
End If
End Sub
End Class
EDIT 1:
Thank you guys for your comments.
Here is the custom constructor I use to the form. This is used to populate the population arrays that are passed to the fitnessTourney function with editGuess.
Public Sub New()
InitializeComponent()
Randomize()
For i = 0 To 9
population1(i) = New Guess
population2(i) = New Guess
Next
counter = 0
correctPhrase = "Methinks it is a weasel!"
goodLetters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ !##$%^&*()_+-=?></.,;\|`'~"
goodLettersArr = goodLetters.Split("")
For i = 0 To 9
population1(i).setStrLength(Int(Rnd() * 25) + 5)
population2(i).setStrLength(Int(Rnd() * 25) + 5)
For i2 = 0 To population1(i).strLength
population1(i).guessStr = population1(i).guessStr & goodLetters(Int(Rnd() * goodLetters.Length))
Next
For i2 = 0 To population2(i).strLength
population2(i).guessStr = population2(i).guessStr & goodLetters(Int(Rnd() * goodLetters.Length))
Next
Label1.Text = population1(i).guessStr
Label2.Text = population2(i).guessStr
Next
population1(0).guessStr = correctPhrase
population1(0).determineFitness(correctPhrase)
End Sub
I haven't studied all of your code thoroughly, but one big problem is that you are calling Randomize from within the loop. Every time you call Randomize, it re-seeds the random numbers with the current time. Therefore, if you call it multiple times before the clock changes, you will keep getting the first "random" number in the sequence using that time which will always evaluate to the same number. When generating "random" numbers, you want to re-seed your random number generator as few times as possible. Preferably, you'd only seed it once when the application starts.
As a side note, you shouldn't be using the old VB6 style Randomize and Rnd methods. Those are only provided in VB.NET for backwards compatibility. You should instead be using the Random class. It's easier to use too. With the Random class, you don't even need to call a randomize-like method, since it automatically seeds itself at the point in time when you instantiate the object. So, in the case of the Random class, the thing to be careful is to make sure that you only instantiate the object once before entering any loop where you might be using it. If you create a new Random object inside a loop, it will similarly keep generating the same numbers.