I'm new to QBasic and coding in general and I'm making a guessing game that just wont work - qbasic

I'm new to QBasic and coding in general and I'm making a guessing game that just won't work.
I have to make a guessing game that does not use GOTO or Do statements, and gives the user 5 chances. Here's the code:
chances%=1
dim guess as integer
dim answer as string
randomize timer
rndnum=INT(RND*100+1)
'makinng a title
color 5
locate 12,32
print "welcome to My guessing game."
Print "think of a number between 1 and 100."
color 12
Input "enter you guess: ",guess
while chances%<4
if guess >rndnum then
print "wrong, too high"
elseif guess <rndnum then
print "wrong, too low"
elseif guess=rndnum then
print "your guessed the number!"
end if
wend
chances%=chances%+1
color 14
Print "you took "; chances%;"to guess the number"
color 3
Input would you like to play again (yes/no)?", answer
wend
if answer = "yes" then
?
else
print "have a good day"
end if
end

You are asking for input one time, then you have a closed loop that checks the answer until attempts are greater than four, but attempts does not ever increment because the Wend command tells it to start the loop again without asking the question again or incrementing the counter at all. This is what is called an "endless loop" because the conditions inside the loop will not change. I'll leave it at that and see if you can figure out how to correct both of these issues - note that fixing only one of them will not stop it from being an "endless loop" you must solve both.

You could use WHILE...WEND to run a loop until chances becomes 0.Here is what I mean:
....(rest of code)
chances = 5
WHILE chances > 0
....
if guess > rndnum then
print "wrong, too high"
chances = chances - 1
elseif guess < rndnum then
print "wrong, too low"
chances = chances -1
....
WEND

Your guess must be inside the while wend loop and when the correct answer is given chances% must be set equal to 4 otherwise you end up with an eternal loop.
It is also necessary to increment chances% directly after the first guess. See the slightly changed code. Please also see guesses and change your line saying you took x guess from chances% to guesses
chances%=0
while chances% < 4
Input "enter your guess: ",guess
chances% = chances% + 1
if guess > rndnum then
print "wrong, too high"
elseif guess < rndnum then
print "wrong, too low"
elseif guess = rndnum then
print "your guessed the number!"
guesses = Chances%
chances% = 4
end if
wend

if you're still having problems I found that here:
Input would you like to play again (yes/no)?", answer
...
if answer = "yes"
...
you would have to change answer to answer$ because you cannot save a string inside a number value.

This snip demonstrates a number guessing game in QB64:
REM guessing game.
Tries = 5
DO
PRINT "Guess a number between 1 and 100 in"; Tries; "guesses."
Number = INT(RND * 100 + 1)
Count = 1
DO
PRINT "Enter guess number"; Count; " ";
INPUT Guess
IF Guess = Number THEN
PRINT "Correct! You guessed it in"; Count; "tries."
EXIT DO
END IF
IF Guess > Number THEN
PRINT "Wrong. Too high."
ELSE
PRINT "Wrong. Too low."
END IF
Count = Count + 1
IF Count > Tries THEN
PRINT "The number was"; Number
PRINT "You didn't guess it in"; Tries; "tries."
EXIT DO
END IF
LOOP
DO
PRINT "Play again(yes/no)";
INPUT Answer$
IF LCASE$(Answer$) = "no" THEN
END
END IF
IF LCASE$(Answer$) = "yes" THEN
EXIT DO
END IF
LOOP
LOOP
END

Related

Syntax error with UCASE$?

Not sure what this means. It says it's a syntax error with UCASE$ but can I not put letter$ in there?
CLS
PRINT "Do you want lower case or upper case? (U/L)"
DO
CASED$ = INKEY$
LOOP UNTIL CASED$ = "U" OR CASED$ = "L"
IF CASED$ = "L" THEN
FOR char = 1 TO 26
READ letter$
PRINT letter$; " = "; ASC(letter$)
SLEEP 1
NEXT char
ELSE
FOR char = 1 TO 26
READ letter$
UCASE$(letter$)
PRINT letter$; " = "; ASC(letter$)
SLEEP 1
NEXT char
END IF
DATA a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
UCASE$ is a function that returns a string. You need to pass what it returns into a variable. A common behavior of most built-in functions in BASIC is that they can stand in place of a variable or expression.
letter$ = UCASE$(letter$)
To demonstrate why this is, try
a$ = "h"
PRINT a$, UCASE$(a$)
in a new program. As you can see, UCASE$ itself becomes the new string instead of manipulating the original string. If you want to preserve the result of the function, you must pass it into a variable.

how to search for a sub string within a string in QBasic

I am creating a simple chat programme in QBasic that will answer questions based on some specific key words present in the user input.therefore I need a way to search for a sub string (I.e. A specific word)within a string.
So, please help me.
To find out if a string contains a certain (sub-)string, you can do this:
text$ = "nonsense !"
IF INSTR( text$, "sense" ) >= 1 THEN
PRINT "This text makes sense !"
END IF
And no, I was not able to test this, as a no longer have QBasic on my PC ;-)
According to the link from the comment above >= 1 is ok
I think INSTR is usually used as follows:
sent$ = "This is a sentence"
PRINT INSTR(1, sent$, "is")
PRINT INSTR(4, sent$, "is")
PRINT INSTR(1, sent$, "word")
the first PRINT command will print a '3' since the first location of "is" within the sentence is at position 3. (The 'is' in 'This')
the second PRINT command starts searching at position 4 (the 's' in 'This'), and so finds the "is" at position 6. So it will print '6'.
the third PRINT command will print a '0' since there is no instance of "word" in the sentence.
Counts the occurrences of a substring within a string.
T$ = "text to be searched and to be displayed"
S$ = "to"
l = 1
DO
x = INSTR(l, T$, S$)
IF x THEN
n = n + 1
l = x + LEN(S$)
ELSE
EXIT DO
END IF
LOOP
PRINT "text '"; S$; "' matches"; n; "times."

Qbasic reading comport reply without newline

I'm working on reading device reply using QBasic. The problem is the qbasic wait for the newline or CHR$(13) before outputting the data but my device reply don't have CHR$(13) (example: "OK") so qbasic hang waiting for newline.
How can i get the reply or read comport even without newline? is this possible?
[EDIT]
CLS
OPEN "com2:9600,n,8,1,BIN,cs,ds,rs" FOR RANDOM AS #1
param$ ="Some data"
PRINT #1, param$
DO WHILE b$ <> "*CLOSE*"
INPUT #1, b$
PRINT b$
LOOP
That is my code but in that code it can't read *CLOSE* because no newline after *CLOSE*.
And another thing the device delay 5 sec before replying.
Could you give an example of your code? I suspect you are using INPUT#n , but maybe instead you should use INPUT$(x). I found an example here, see code below
a$ = ""
DO
IF LOC(1) THEN a$ = a$ + INPUT$(1, 1)
LOOP UNTIL INSTR(a$, "OK")
This code sample demonstrates accessing modem in Basic.
REM Reset modem source:
CLS
OPEN "COM2:9600,N,8,1,BIN,CS,DS,RS" FOR RANDOM AS #1
Reset$ = "ATZ" + CHR$(13) + CHR$(10)
PRINT #1, Reset$;
Inp$ = ""
DO
IF LOC(1) THEN
Inp$ = Inp$ + INPUT$(1, 1)
IF INSTR(Inp$, "OK") THEN
PRINT "Modem reset."
EXIT DO
END IF
END IF
LOOP
END

Get Paragraphs in specific Section of Word Document

I'm having problems finding a specific section in word. It was recommended I try looking through the VB Object Browser in Word for help. I know there are at least 5 heading "sets" (I.E. if you look in the Document Map, I see numbered 1,2,3,4,5...). I don't know how to navigate to that fifth heading, initially I thought it was sections, but when I viewed sections I realized that almost all of it is in one section, but in case anyone is looking for information on how to do sections, the below seems to work, since I already went through the trouble of writing it.
my($document) = $Word->Documents->Open($input) || die("Unable to open document ", Win32::OLE->LastError());
my $section = $document->{Sections}->Item(1); # put section number you're looking for in here
$section_five_paragraphs = $section->{Range}->Paragraphs();
$enumerate = new Win32::OLE::Enum($section_five_paragraphs);
while (defined($paragraph = $enumerate->Next()))
{
print $paragraph->{Range}->{Text} . "\n";
}
So does anyone know how to get to this 5th heading area, or can point me to something that might help?
Tell me if I didn't follow you correctly but you're trying to find the 5th Heading 1 in the a certain section? If that's the case, although Word clearly defines sections (which you note as $document->{Sections}->Item(1)), it does not clearly define Headings in specific or styles in general. For that you'll have to go through all the styles looking for those of interest. The following VBA code (and I apologize for not writing perl) does just that and looks only in a specific section.
Sub FindHeading1()
On Error GoTo MyErrorHandler
Dim currentDocument As Document
Set currentDocument = ActiveDocument
Dim findRange As Range
Set findRange = currentDocument.Sections(2).Range 'which section you want
Dim endRange As Long
endRange = findRange.end
findRange.Find.ClearFormatting
findRange.Find.Style = ActiveDocument.Styles("Heading 1")
Dim headingCountFound As Long
Do While findRange.Find.Execute(FindText:="")
If findRange.End > endRange Then Exit Sub
findRange.Select
headingCountFound = headingCountFound + 1
If headingCountFound = 3 Then 'which occurance you want
MsgBox "Found."
Exit Do
End If
DoEvents
Loop
Exit Sub
MyErrorHandler:
MsgBox "FindHeading1" & vbCrLf & vbCrLf & "Err = " & Err.Number & vbCrLf & "Description: " & Err.Description
End Sub

Trouble using 'while' loop to evaluate multiple lines, Perl

Thank you in advance for indulging an amateur Perl question. I'm extracting some data from a large, unformatted text file, and am having trouble combining the use of a 'while' loop and regular expression matching over multiple lines.
First, a sample of the data:
01-034575 18/12/2007 258,750.00 11,559.00 36 -2 0 6 -3 2 -2 0 2 1 -1 3 0 5 15
-13 -44 -74 -104 -134 -165 -196 -226 -257 -287 -318 -349 -377 -408 -438
-469 -510 -541 -572 -602 -633 -663
Atraso Promedio ---> 0.94
The first sequence, XX-XXXXXX is a loan ID number. The date and the following two numbers aren't important. '36' is the number of payments. The following sequence of positive and negative numbers represent how late/early this client was for this loan at each of the 36 payment periods. The '0.94' following 'Atraso Promedio' is the bank's calculation for average delay. The problem is it's wrong, since they substitute all negative (i.e. early) payments in the series with zeros, effectively over-stating how risky a client is. I need to write a program that extracts ID and number of payments, and then dynamically calculates a multi-line average delay.
Here's what I have so far:
#Create an output file
open(OUT, ">out.csv");
print OUT "Loan_ID,Atraso_promedio,Atraso_alt,N_payments,\n";
open(MYINPUTFILE, "<DATA.txt");
while(<MYINPUTFILE>){
chomp($_);
if($ID_select != 1 && m/(\d{2}\-\d{6})/){$Loan_ID = $1, $ID_select = 1}
if($ID_select == 1 && m/\d{1,2},\d{1,3}\.00\s+\d{1,2},\d{1,3}\.00\s+(\d{1,2})/) {$N_payments = $1, $Payment_find = 1};
if($Payment_find == 1 && $ID_select == 1){
while(m/\s{2,}(\-?\d{1,3})/g){
$N++;
$SUM = $SUM + $1;
print OUT "$Loan_ID,$1\n"; #THIS SHOWS ME WHAT NUMBERS THE CODE IS GRABBING. ACTUAL OUTPUT WILL BE WRITTEN BELOW
print $Loan_ID,"\n";
}
if(m/---> *(\d*.\d*)/){$Atraso = $1, $Atraso_select = 1}
if($ID_select == 1 && $Payment_find == 1 && $Atraso_select == 1){
...
There's more, but the while loop is where the program is breaking down. The problem is with the pattern modifier, 'g,' which performs a global search of the string. This makes the program grab numbers that I don't want, such as the '1' in loan ID and the '36' for the number of payments. I need the while loop to start from wherever the previous line in the code left off, which should be right after it has identified the number of loans. I've tried every pattern modifier that I've been able to look up, and only 'g' keeps me out of an infinite loop. I need the while loop to go to the end of the line, then start on the next one without combing over the parts of the string already fed through the program.
Thoughts? Does this make sense? Would be immensely grateful for any help you can offer. This work is pro-bono, unpaid: just trying to help out some friends in a micro-lending institution conduct a risk analysis.
Cheers,
Aaron
The problem is probably easier using split, for instance something like this:
use strict;
use warnings;
open DATA, "<DATA.txt" or die "$!";
my #payments;
my $numberOfPayments;
my $loanNumber;
while(<DATA>)
{
if(/\b\d{2}-\d{6}\b/)
{
($loanNumber, undef, undef, undef, $numberOfPayments, #payments) = split;
}
elsif(/Atraso Promedio/)
{
my (undef, undef, undef, $atrasoPromedio) = split;
# Calculate average of payments and print results
}
else
{
push(#payments, split);
}
}
If the data's clean enough, I might approach it by using split instead of regular expressions. The first line is identifiable if field[0] matches the form of a loan number and field[1] matches the format of a date; then the payment dates are an array slice of field[5..-1]. Similarly testing the first field of each line tells you where you are in the data.
Peter van her Heijden's answer is a nice simplification for a solution.
To answer the OP's question about getting the regexp to continue where it left off, see Perl operators - regexp-quote-like operators, specifically the section "Matching in list context" and the "\G assertion" section just after that.
Essentially, you can use m//gc along with the \G assertion to use regexps match where previous matches left off.
The example in the "\G assertion" section about lex-like scanners would seem to apply to this question.