If condition being ignored - vb.net

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

Related

I want to save a file in VB.net from the amount of tries a user has

I'm a student trying to learn Console App .Net Framework and I want to code a random number between 0000 and 9999 (as a pin that you need to guess). Thus far I've had to set it as a random number from 1000 to 9999 as the system wont let me do 0000. Furthermore, I want to save the amount of tries the user has as a text file e.g. if the user tries 50 times, I'd like it to say
Username Tries
I've tried Randomise() Rnd(*9999) and X = EasyNum.Next(1000, 9999) but then I can't compare unless I convert that to an integer.
Module Module1
Dim Tries As String = 0
Dim EasyNum As New Random
Dim HardNum As New Random
Dim Attempt As String
Sub Main()
Dim Difficulty As String
Console.WriteLine("Welcome to MasterMind")
Console.WriteLine("Choose between Easy and Hard difficulty")
Difficulty = Strings.LCase(Console.ReadLine)
While Difficulty <> "easy" And Difficulty <> "hard"
Console.WriteLine("That's not a correct mode")
Difficulty = Strings.LCase(Console.ReadLine)
End While
If Difficulty = "easy" Then
Easy()
ElseIf Difficulty = "hard" Then
Hard()
End If
End Sub
Dim EasyGuess1 As Integer
Dim EasyGuess2 As Integer
Dim X As String
Dim Y As Integer
Sub Easy()
Console.WriteLine("You have chosen the easy difficulty")
Console.WriteLine("You have to guess a 4 Digit number between 1000 and 9999")
Console.WriteLine("Enter your guess")
X = EasyNum.Next(1000, 9999)
Console.WriteLine(X)
EasyGuess1 = Console.ReadLine
Tries = +1
If Mid(CStr(EasyGuess1), 1, 1) = Mid(CStr(X), 1, 1) Then
Console.WriteLine("You have 1 number correct, try again?")
Attempt = Strings.LCase(Console.ReadLine)
While Attempt <> "yes" And Attempt <> "no"
Console.WriteLine("Enter either yes or no")
Attempt = Strings.LCase(Console.ReadLine)
End While
ElseIf Mid(CStr(EasyGuess1), 2, 1) = Mid(CStr(X), 2, 1) Then
Console.WriteLine("You have 1 number correct, try again?")
Attempt = Strings.LCase(Console.ReadLine)
While Attempt <> "yes" And Attempt <> "no"
Console.WriteLine("Enter either yes or no")
Attempt = Strings.LCase(Console.ReadLine)
End While
End If
If Attempt = "yes" Then
EasyYes()
ElseIf Attempt = "no" Then
EasyNo()
End If
Console.WriteLine("incorrect")
Console.ReadKey()
End Sub
Sub EasyYes()
Console.WriteLine("Enter a new guess")
EasyGuess1 = Console.ReadLine
End Sub
Sub EasyNo()
Dim Save As String
Dim File As System.IO.File
Console.WriteLine("Do you want to save your tries? Enter Yes or no")
Save = Strings.LCase(Console.ReadLine)
If Save = "yes" Then
System.IO.File.Create(Tries, "C:\X\Code\VB\Challenges\Challenge 1\MasterMind Test")
End If
End Sub
Sub Hard()
Console.WriteLine("You have chosen the hard difficulty")
End Sub
Sub HardYes()
End Sub
Sub HardNo()
End Sub
End Module
When I try to save the tries, I get this:
System.InvalidCastException: 'Conversion from string "C:\X\Code\VB\Challenges\Cha" to type 'Integer' is not valid.'
InnerException
FormatException: Input string was not in a correct format.
Which I don't understand myself.
Comments in line. Please read all comments. This program is still not working too well but I will leave it to you to tidy up.
Module Module1
Dim Tries As Integer = 0
'Use only a single instance of Random
Dim EasyNum As New Random
'Dim HardNum As New Random
Dim Attempt As String
Sub Main()
Dim Difficulty As String
Console.WriteLine("Welcome to MasterMind")
Console.WriteLine("Choose between Easy and Hard difficulty")
Difficulty = Strings.LCase(Console.ReadLine)
'AndAlso prevents the second condition from executing if the first condition is true
While Difficulty <> "easy" AndAlso Difficulty <> "hard"
Console.WriteLine("That's not a correct mode")
Difficulty = Strings.LCase(Console.ReadLine)
End While
If Difficulty = "easy" Then
Easy()
'ElseIf Difficulty = "hard" Then
' Hard() 'Not implemented
End If
End Sub
'Dim EasyGuess2 As Integer
'Dim X As String
'Dim Y As Integer
Sub Easy()
Dim EasyGuess1 As Integer
Console.WriteLine("You have chosen the easy difficulty")
Console.WriteLine("You have to guess a 4 Digit number between 1000 and 9999")
Console.WriteLine("Enter your guess")
'X = EasyNum.Next(1000, 9999)
'The next method returns a non-negative integer not a string
'To get 0 to 9999 with leading zeros do the following
'Returns a non-negative random integer that is less than the specified maximum.
Dim X = EasyNum.Next(10000).ToString("0000")
Console.WriteLine(X)
'Console.ReadLine returns a String. You should Not assign a String to an Integer
'EasyGuess1 = Console.ReadLine
'Never trust a user :-) Use .TryParse to set the variable
Integer.TryParse(Console.ReadLine, EasyGuess1)
'This just assigns the value of 1 to Tries
'Tries = +1
'If you want to increment Tries
Tries += 1
'Let's compare apples and apples
'If you just convert EasyGuess1 To a string and EasyGuess1 is 54
'the string is "54" You want a 4 character string
'If Mid(EasyGuess1.ToString("0000"), 1, 1) = Mid(CStr(X), 1, 1) Then
' 'but you only compared the first character, what about the rest?
' 'Mid is aroung for backward compatibility. It should not be used for new code.
' 'The position Integer is one based which is not at all sympatico with .net
' Console.WriteLine("You have 1 number correct, try again?")
' Attempt = Strings.LCase(Console.ReadLine)
' While Attempt <> "yes" And Attempt <> "no"
' Console.WriteLine("Enter either yes or no")
' Attempt = Strings.LCase(Console.ReadLine)
' End While
'ElseIf Mid(CStr(EasyGuess1), 2, 1) = Mid(CStr(X), 2, 1) Then
' Console.WriteLine("You have 1 number correct, try again?")
' Attempt = Strings.LCase(Console.ReadLine)
' While Attempt <> "yes" And Attempt <> "no"
' Console.WriteLine("Enter either yes or no")
' Attempt = Strings.LCase(Console.ReadLine)
' End While
'End If
Dim CorrectCharacters = TestInput(EasyGuess1, X)
Console.WriteLine($"You have guessed {CorrectCharacters} correctly. Try again?")
'Use the .net way. The framework is available to all languages in .net
'so it will be easier to learn other languages.
Attempt = (Console.ReadLine).ToLower
If Attempt = "yes" Then
EasyYes()
ElseIf Attempt = "no" Then
EasyNo()
End If
Console.WriteLine("incorrect")
Console.ReadKey()
End Sub
Sub EasyYes()
Dim guess As Integer
Console.WriteLine("Enter a new guess")
'You are doing this twice ???
'EasyGuess1 = Console.ReadLine
Integer.TryParse(Console.ReadLine, guess)
'EasyGuess1 will be 0 if the entry is other than an integer
'Very nice bu this Sub doesn't do anything
End Sub
Sub EasyNo()
Dim Save As String
'Unused local variable and if you needed this it is a poor choice for a variable name
'Dim File As System.IO.File
Console.WriteLine("Do you want to save your tries? Enter Yes or no")
Save = Console.ReadLine.ToLower
If Save = "yes" Then
'Give the file name an extension.
'When you pass (String, Integer) to the Create method, the Integer is the number of bytes
'buffered for reads And writes to the file.
'Not exactly what you were expecting.
'System.IO.File.Create("C:\X\Code\VB\Challenges\Challenge 1\MasterMind Test.txt", Tries)
'Imports System.IO at top of file
File.WriteAllText("C:\X\Code\VB\Challenges\Challenge 1\MasterMind Test.txt", Tries.ToString)
End If
End Sub
Sub Hard()
Console.WriteLine("You have chosen the hard difficulty")
End Sub
Private Function TestInput(Guessed As Integer, RandString As String) As Integer
Dim Correct As Integer
Dim Guess As String = Guessed.ToString("0000")
'A String can be a Char array
'Here we check each character in the 2 strings for equality
'and if true then increment Correct
For i = 0 To 3
If Guess(i) = RandString(i) Then
Correct += 1
End If
Next
Return Correct
End Function
End Module
There are a lot of issues, but I don't want to spoil it for you.
I definitely recommend to put "Option Strict On" in the project settings, so you immediately see where there are conversion errors (a string assigned to a integer etc).
To save the file, it should be something like
If Save = "yes" Then
File.WriteAllText("C:\X\Code\VB\Challenges\Challenge 1\MasterMind Test", Tries.ToString())
End If
(there are also File.Append... functions).
The Random class is a bit tricky, this is an object that provides random values and is not yet the random value itself. Always use the same random object for all different numbers, otherwise you might get the same number:
Private Randomizer As New Random(Environment.TickCount)
Private EasyNum As Int32 = Randomizer.Next(0, 10000) '0 to 9999
Private HardNum As Int32 = Randomizer.Next(0, 100000) '0 to 99999
The "from" value of the randomizer's Next method is always inclusive, the "to" value exclusive, for whatever reasons.
To increment a variable, the syntax is
Tries += 1
instead of "Tries = +1"
To write a number with leading digits, use might use
Console.Out.WriteLine($"The correct solution would have been: {EasyNum:0000}")
or
EasyNum.ToString("0000")

Code iterating through whole string in hangman

How can I stop my code from iterating through a whole string stating whether the input from the user matches that of the random string bearing in mind this is for a hangman game, I want the code to just display once if the user's chosen letter is either correct or incorrect rather than displaying up too eight times.
Sub letterInput()
For i As Integer = 0 To randomWord.Length - 1
If userInput = randomWord(i) Then
MessageBox.Show("correct")
ElseIf userInput <> randomWord(i) Then
MessageBox.Show("incorrect")
Label4.Text = counter
Exit for
End If
Next
End Sub
Sub wordGeneration()
Dim wordUsed As Array = {"pizza", "noodle", "zombie", "object", "rowin", "running", "elephant", "lion"}
Dim random As New Random
randomWord = wordUsed(random.Next(0, 9))
Label2.Text = randomWord
End Sub
What I meant in the comments was that you just need to replace your for loop with a simple if/else. String.Contains checks the whole string already, so there is no need to iterate through each letter anymore:
Sub letterInput()
If randomWord.Contains(userInput) Then
MessageBox.Show("correct")
Else
MessageBox.Show("incorrect")
Label4.Text = counter
End If
End Sub

How to stop message box repeating because of array?

I'm trying to make a hangman game and to input "incorrect" if the user picks the wrong letter but it will keep repeating because of the randomWord which chooses the word from an array how do I stop this?
Sub wordGeneration()
Dim wordUsed As Array = {"pizza", "noodle", "zombie", "object", "rowin", "running", "elephant", "lion"}
Dim random As New Random
randomWord = wordUsed(random.Next(0, 8))
Label2.Text = randomWord
End Sub
Sub letterInput()
For i As Integer = 0 To randomWord.Length - 1
If userInput = randomWord(i) Then
MessageBox.Show("correct")
ElseIf userInput <> randomWord(i) Then
MessageBox.Show("incorrect")
Label4.Text = counter
End If
Next
End Sub
Simpler and faster to let VB do the search for you.
Sub letterInput()
if InStr(randomWord.Length, userInput) > 0
MessageBox.Show("correct")
Else
MessageBox.Show("incorrect")
Label4.Text = counter
End If
End Sub
Note: I am assuming userInput is a single character.

how to validate input data in access form by vba

I try to not allow users to enter fractional values example .238 or 0.123 or 1.4,.
My code So far.
to Validate <= 8 , If Not IsNumeric, <> 12
Private Sub txt_xampleqty_BeforeUpdate(Cancel As Integer)
On Error GoTo errormsg
If Len(Me.txttxt_xampleqty) <= 8 Then
Cancel = True
Resume Next
Else
If Len(Trim(Me.txt_xampleqty)) <> 12 Then
MsgBox ("Enter Correct QTY.")
Cancel = True
End If
End If
If Not IsNumeric(Trim(txt_xampleqty)) Then
MsgBox "the entry must be a 12 number QTY "
Cancel = True
End If
Exit Sub
Just check each position in the string and see if it is numeric
Public Function ValidNumericValue() As Boolean
Dim s As String
Dim i As Integer
Dim bValid as Boolean
bValid = True
'get Text value
s = txt_xampleqty
'loop through the entire string
For i = 1 To Len(s)
'check to see if the character is a numeric one
If IsNumeric(Mid(s, i, 1)) = False Then
'set the return value
bValid = False
Exit For
End If
Next i
ValidNumericValue = bValid
End Function
Cast the number to an integer and see if has the same value:
If IsNumeric(Trim(txt_xampleqty)) Then
if CLng(txt_xampleqty)<>CCurr(txt_xampleqty)
MsgBox "You are not allowd users to entry fractional values example .238 or 0.123 or 1.4"
Cancel = True
End If
End If
Use TextSearch Function to search for deciml point:
If IsNumeric(Trim(txt_xampleqty)) Then
if InStr(txt_xampleqty,".")<Len(txt_xampleqty) Then
MsgBox "You are not allowd users to entry fractional values example .238 or 0.123 or 1.4"
Cancel = True
End If
End If

Hangman VB Not Working

I am making a hangman game on VB. An help is appreciated
All I have is that player 1 enters a word. The program then puts it into an array, which sorts it into letters. The player 2 (on the same computer) tries to guess the word, one letter at the time. They type in a letter and the program will go trough the array to check if there are any letter in the word. If there are it will show the letter (leaving the others blank) and leave the scoring system at 10 (I still need to put this in) If they guess wrong the letters will remain covered and it will minus 1 of the scoring system.
Module Module1
Sub Main()
Dim myword, guess As String
Dim mywordlen As Integer
Dim flag As Boolean
Console.WriteLine("Player 1, please enter a word to guess")
myword = Console.ReadLine()
mywordlen = myword.Length
Dim answer(mywordlen) As Char
For x = 0 To mywordlen - 1
answer(x) = "_"
While answer > 0 Then
Console.WriteLine("Please guess a letter")
guess = Console.ReadLine()
flag = False
For x = 0 To mywordlen - 1
If guess = myword Then {0}
answer(x) = guess
flag = True
Console.WriteLine("The answer is, {0}")
Next
Next
End Sub
Dim myword, guess As String
Dim mywordlen, x As Integer
Dim flag As Boolean
Console.WriteLine("Player 1, please enter a word to guess")
myword = Console.ReadLine()
mywordlen = myword.Length - 1
Dim answer(mywordlen), displayword(mywordlen) As Char
Dim score As Integer = 10
For x = 0 To mywordlen
answer(x) = Mid(myword, x + 1, 1)
displayword(x) = "_"
Next
While score > 0
Console.WriteLine("Please guess a letter")
guess = Console.ReadLine() 'Assumes user only types one letter
flag = False
For x = 0 To mywordlen
If guess = answer(x) Then
displayword(x) = guess
flag = True
End If
Next
If flag Then
If New String(displayword) = myword Then
Console.WriteLine("Congratulations! You won!")
Exit While
Else
Console.WriteLine("Correct! {0}", New String(displayword))
End If
Else
Console.WriteLine("Incorrect. {0}", New String(displayword))
score -= 1
End If
End While
Console.WriteLine("Game over. The word was {0}", myword)