My if loop is taking effect even when it should not - powershell

I am making a random number guessing program where users try to guess a number between 1 and 100 while receiving whether they were higher or lower. one of the stipulations was that there must be a function to quit the program upon the user entering Q or q so I formatted my loop as such:
$RandomNumber = Get-Random -Minimum 1 -Maximum 101
write-output $RandomNumber
$GuessNumber = 0
While ($RandomNumber -ne $Guess)
{
$Guess = Read-Host -Prompt 'Guess a number between 1 and 100 Or enter Q to quit'
if ($Guess -eq 'q' -or 'Q')
{
Write-output "Thank you for playing"
BREAK
}
if ($Guess -gt 100 -or $Guess -le 1)
{
Write-Output 'Invalid Input please enter a number between 1 and 100'
}
if ($Guess -le $RandomNumber)
{
Write-output 'Your number is lower than the hidden number please guess again'
$GuessNumber = $GuessNumber +1
}
if ($Guess -gt $RandomNumber)
{
Write-output 'Your number is higher than the hidden number please guess again'
$GuessNumber = $GuessNumber +1
}
if ($Guess -eq $RandomNumber)
{
$GuessNumber = $GuessNumber +1
Write-output 'Congratulations you guessed the number in' $GuessNumber 'tries'
}
}
the issue I run into is even when the input is equal to 10 for example it still outputs "Thank you for playing" meaning that if loop has taken effect. I am not sure why this occurs as I'm new to powershell and a reasoning for this happening would be helpful

Replace
if ($Guess -eq 'q' -or 'Q')
with
if ($Guess -eq 'q' -or $Guess -eq 'Q')

Your error partially comes from -or 'Q' which evaluates to $true always:
$false -or 'somestring' # => True
And it's also worth noting, -eq is case insensitive ('q' -eq 'Q' is $true).The other error comes from comparing a string with an integer. The output from Read-Host is System.String in this case:
'50' -gt 100 # => True
'50' -lt 100 # => False
On the other hand, you could make your code more readable using a switch statement. For input validation you could use a recursive script block to make sure its always right (between 1 and 100 or Q). To break the outer while loop you can use a labeled break.
$RandomNumber = Get-Random -Minimum 1 -Maximum 101
$validation = {
$choice = Read-Host 'Guess a number between 1 and 100 Or enter Q to quit'
if($choice -notmatch '^([1-9][0-9]?|100|q)$') {
Write-Warning 'Invalid Input, try again.'
return & $validation
}
$choice
}
$attempts = 0
:outer while($true) {
$choice = & $validation
if($choice -eq 'q') {
# End the Game
'Thanks for Playing'
break
}
$attempts++
switch([int]$choice) {
{$_ -gt $RandomNumber} {
"$_ was greater than hidden number"
break
}
{$_ -lt $RandomNumber} {
"$_ was lower than hidden number"
break
}
default {
"You guessed right after $attempts tries, Congratulations!"
break outer
}
}
}

The condition is wrong. $Guess -eq 'q' -or 'Q' returns true always, it should be $Guess -eq 'q' -or $Guess -eq 'Q'.

Related

Build an interactive menu using powershell

Below script will display the menu and prompt for a selection.However this doesn't give the option to reselect if the selection is made wrong.
I would like to re write in such a way that , it should give the option to confirm the selection and if the selection is made wrong, should give an option to re select from the menu. Is it possible using "do until" loop? Any help is high appreciated
write-host ""
Write-host -ForegroundColor yellow "Choose which Cluster you want to gather ratios on:"
write-host "(it may take a few seconds to build the list)"
write-host ""
$ICLUSTER = get-cluster -server $VIServer | Select-Object Name | Sort-object Name
if ($null -eq $ICLUSTER)
{
Update-log "Unable to find Cluster Information.Please verify the cluster status before proceed `n"
break
}
else
{
$i = 1
$ICLUSTER | %{Write-Host $i":" $_.Name; $i++}
$HCLUSTER = Read-host "Choose the name of cluster you want to select on by entering corresponding number:"
$SCLUSTER = $ICLUSTER[$HCLUSTER -1].Name
Update-log "You have selected $($SCLUSTER). `n"
start-sleep -s 3
}
A loop & couple additional if statements should get you there:
# break the loop by setting $x not equal to 1
$x = 1
While ($x -eq 1){
$ICLUSTER = get-cluster -server $VIServer | Select-Object Name | Sort-object Name
if ($null -eq $ICLUSTER){
Update-log "Unable to find Cluster Information. Please verify the cluster status before proceed `n"
$x = 2
}
else{
$i = 1
$ICLUSTER | %{Write-Host $i":" $_.Name; $i++}
$HCLUSTER = Read-host "Choose the name of cluster you want to select on by entering corresponding number:"
$SCLUSTER = $ICLUSTER[$HCLUSTER -1].Name
if ($SCLUSTER -in $ICLUSTER.Name){
Write-Host "You have selected $($SCLUSTER), do you want to continue?"
$yesno = Read-host "Please type 'Y' to continue or 'N' to quit"
if ($yesno -eq "Y"){
$x = 1
}
else {Write-Host "Quitting"
$x = 2
}
Write-Host "Performing commands"
# Add commands here, to do the work & complete the task
$x = 2
}
elseif (-not($SCLUSTER -in $ICLUSTER.Name)){
Write-Host "Your selection was not found, Would you like to try again?"
$yesno = Read-host "Please type 'Y' to try again or 'N' to quit"
if ($yesno -eq "Y"){
Write-Host "Trying this again"
$x = 1
}
else {Write-Host "Quitting"
$x = 2
}
}
start-sleep -s 3
}
}

Finding Middle Number in PowerShell

I am practicing in PowerShell and am making a user response input where one of the options is to input 3 numbers, and the program will return the middle number. I have done this a million times and it seems I cannot get it to return the middle number consistently.
For example when my numbers are 1, 23452342 and 3, it says that 3 is the middle number.
Here is my code:
if ($response -eq 1) {
$a = Read-Host "Enter a number "
$b = Read-Host "Enter a second number "
$c = Read-Host "Enter a third number "
if (($a -gt $b -and $a -lt $c) -or ($a -lt $b -and $a -gt $c)) {
Write-Host "$a is the middle number"
}
if (($b -gt $a -and $b -lt $c) -or ($b -gt $c -and $b -lt $a)) {
Write-Host "$b is the middle number"
}
if (($c -gt $a -and $c -lt $b) -or ($c -gt $b -and $c -lt $a)) {
Write-Host "$c is the middle number"
}
}
Instead of doing a number of individual comparisons simply sorting the three values and picking the second element will give you the median right away. But I suspect what's actually messing up the results for you is that Read-Host returns strings when you need them to be numeric values. Sort order of strings ("1" < "20" < "3") is different from numeric sort order (1 < 3 < 20), because characters at corresponding positions are compared rather than the whole number.
Casting the entered values to integers (or doubles if you expect floating point numbers) should resolve the issue:
if ($response -eq 1) {
[int]$a = Read-Host 'Enter a number'
[int]$b = Read-Host 'Enter a second number'
[int]$c = Read-Host 'Enter a third number'
$n = ($a, $b, $c | Sort-Object)[1]
Write-Host "$n is the median."
}
As an additional solution that would work on any array where u need the middle item you could just solve it like this:
$arr = 1..50
($arr | Sort-Object)[[int](($arr.count -1) /2)]
If your array comes in a format that does not need the sorting, just leave this part out.
edit: Obviously you would have to insert the data into an array on the first step.
Best regards

PowerShell guessing game max number of guesses

Hi I have made a number guessing game, but I struggle to make the game stop after a x guesses.
$Number = (Get-Random 100) + 1
$Guess = 0
$count = 1
Write-Host "I'm thinking of a number between 1 and 100."
While ($Number -ne $Guess) {
Write-Host -NoNewline "What is the number? "
$Guess = [int] (Read-Host)
If ($Guess -gt $Number) { Write-Host "$Guess is too high." }
If ($Guess -lt $Number) { Write-Host "$Guess is too low." }
If ($count -eq 7) {break}
}
Write-Host "Correct! $Number is the number I was thinking!"
I've added a variable into your while loop, named $Tries it increments itself by one everytime someone guesses a number, until it equals 10, then the loop breaks.
Next to that, I've included the line that tells you that the number is correct within the loop and tell it to display the correct message and break the loop when the number is correct.
I had to include this in the loop because if I would just let it break the loop when $Tries was bigger than 10 it would still display the message stating that the number was correct.
$Number = (Get-Random 100) + 1
$Guess = 0
$Tries = 0
Write-Host "I'm thinking of a number between 1 and 100."
While ($Number -ne $Guess) {
Write-Host -NoNewline "What is the number? "
$Guess = [int] (Read-Host)
$Tries = $Tries + 1
If ($Tries -gt 10) { Write-Host "You have used all of your guesses, try again." ; break }
If ($Guess -gt $Number) { Write-Host "$Guess is too high." }
If ($Guess -lt $Number) { Write-Host "$Guess is too low." }
If ($Guess -eq $Number) { Write-Host "Correct! $Number is the number I was thinking!" ; break}
}

Powershell - Check number for several ranges

Hi I am new to Powershell and need some help:
My Script gets a number by userinput. I want to check this number if it´s between these ranges. So far so easy, but the input from 1-9 is with a leading zero.
With google, I got this working without the special case "leading zero".
do {
try {
$numOk = $true
$input = Read-host "Write a number between 1-12"
} # end try
catch {$numOK = $false }
} # end do
# check numbers
until (
($input -ge 1 -and $input -lt 13) -or
($input -ge 21 -and $input -lt 25) -or
($input -ge 41 -and $input -lt 49) -or
($input -ge 61 -and $input -lt 67) -and $numOK)
Write-Host $input
For example:
Input "5" Output "5"
Input "05" stucks in loop, should be "05"
AddOn: Is it possible to block inputs like 1-9 and just accept inputs like 01-09?
you can use the -f operator to format the string here is to get a 2 digits number
PS>"{0:00}" -f 5
05
some readings : http://ss64.com/ps/syntax-f-operator.html

Dynamic input array Powershell

once again I contact you because I am once again having problems with a Powershell script assignment.
My current assignement is to make a script that lets a user put in 1-10 values. The values have to be positive numbers. After that I have to calculate an average of an array.
My idea in this was the following:
clear-host
$averageArray = #()
Write-Host "How many numbers do you want to put in?" -for yellow
Write-Warning "Maximum is 10!"
Write-Host "Press the Enter key to continue."
$amountValues = Read-host
while($amountVAlues -notmatch "^([1-9]|[1][0])$") {
$amountValues = Read-Host "Please enter a number between 1 and 10"
if($amountVAlues -notmatch "^([1-9]|[1][0])$") {Write-host "Error! Please enter a number between 1 and 10!"}
}
$value1 = read-host "Enter number one"
while($value1 -notmatch '^\d+$') {
$value1 = Read-Host
if($value1 -notmatch '^\d+$') {Write-host "Error! Please enter a positive number!"}
}
$value2 = read-host "Enter number two"
while($value2 -notmatch '^\d+$') {
$value2 = Read-Host
if($value2 -notmatch '^\d+$') {Write-host "Error! Please enter a positive number!"}
}
$averageArray = $averageArray + $value1
write-host "$averageArray"
read-host
I created an array, and made the user input a number between 1-10 for the amount of total $values they want in the array. After that I wanted to loop the input of a $value, and input it in the array. I wanted to loop it as many times as the $amountValues variable.
Problem with doing this is that if I would loop it, $variable1 would get overwritten an 'x' amount of times.
Is there any way to input the values via a loop into the array?
I'ld do it like this:
while ( (1..10) -notcontains $g)
{
$g = read-host "How many numbers do you want to put in? (value from 1 to 10) "
}
$ar=#()
for ($i=0; $i -lt $g; $i++)
{
$ar += read-host "Enter value $($i+1)"
}
$averageArray = ($ar | Measure-Object -Average).average
write-host "Average is : $averageArray"