Programming in (Q)BASIC
Perhaps you found your way here either because you're new to
programming and would like to start of by learning BASIC, or on
the other end you're an experienced programmer looking to hone
your skills. While this tutorial primarily focuses on the former,
I'll write separate sections for advanced techniques as well.
The thing I find most irritating about tutorials, especially on
the internet, is they usually assume previous knowledge of one
langauge or another. As well, they often throw things at you and
hardly explain what they mean, and why it's
like that. I hope to break that trend, or at least go against it
with this tutorial.
Therefore from here on in I'll write like you've never programmed
before in your life, and try to cover important points in detail
with sufficient explanation.
To start off, what is programming anyway?
1.1 - Introduction To Programming
A program is esentially something
you write that's easy for you to understand because it's written
in a form understandable to people. However, when you RUN or
COMPILE it (make the computer do something with it) it's first
changed into a form which can be run by the computer, and would
be very hard for the average person to understand without a great
deal of effort and training. How do you write a program.
Bascially, you write commands. These are special
keywords telling the computer to do something. For example, one
of the simplest commands in BASIC is the PRINT statment. It goes
like this:
Print "Hello!"
When you type this in (you'll need
a special program which can interperet BASIC, which i'll get to
in a minute) and RUN it, you'll see a blank screen come
up with the word Hello! in the corner. We can then conclude that
what the print statement does is print out text on the screen.
Then, why the "" around Hello! ? It will make sense
later as you learn about variables, subprograms and
other such more complex parts, but for now just accept that that
is the syntax it should be in. You should have quote marks around
the text to print.
Don't assume though that all commands are a command followed by
something in quote marks. That couldn't be further from the truth.
Now, I guess maybe you'll want to be able to actually write and run programs. The program we'll be making the programs with is called QBASIC. You might be able to dig it up on your windows CD, but if not, I recommend getting ahold of QB 4.5 somehow.
1.2 - A couple simple commands
We'll start with a few simple
commands. The first you already learned - PRINT. Here's a few
more, which we'll go over:
COLOR
LOCATE
CLS
To start, let's go over color.
Well, like it sounds, it has something to do with color (DUH!).
It's important to note that most of the time a command with
either be a descriptive word about what it does, or an acronym
for a descriptive word.
Color does one thing. It changes the current color. What do we
mean by current color? Well, when you use the print statement the
text will be printed in whatever the "current color" is.
This by default is grey. You use color to change this.
Unfortunately, color is just a little bit complicated because
instead of just saying:
COLOR Green
You have to use special numbers
which are assigned to each color. The code number for green is 2.
So let's see color in action by adding to our earlier example:
Color 2
Print "Hello!"
Our first program print Hello! in the default grey. Now that
we put Color 2 in front of it, it
will print that same text in green.
Notice that the number for the color is NOT
inside quotes like the text for print was. Commands that take
numbers generally don't need the number in quotes.
Here's a handy table which lists all the colors and their code
numbers:
0 = black | 4 = red | 8 = grey | 12 = light red |
1 = blue | 5 = magenta | 9 = light blue | 13 = light magenta |
2 = green | 6 = brown | 10 = light green | 14 = yellow |
3 = cyan | 7 = white | 11 = light cyan | 15 = bright white |
It's time to make another important point. What should this
program do?:
Color 6
Print "Hello!"
Color 1
Will it print the text in brown, or in blue? The answer is
brown. Why?
BASIC programs are in order, line by line. Even though color 1 changes the current color to blue,
it will have no effect because of when it happens. This
command comes after the print statement, so it doesn't effect it
- by this time, the print statement has already done it's job.
However, this program will print the text in both brown and blue:
Color 6
Print "Hello!"
Color 1
Print "Ahoy hoy"
It will print Hello! in brown, then on the next line down,
Ahoy hoy in blue.
So, a print statement not only takes into account what the
current color is, but also the current row number it should print
on. Print automatically prints on the next line unless you tell
it otherwise. You do this by using LOCATE.
LOCATE takes two things with it called parameters.
The number that color needs to work, or the text that print needs
are also called parameters. Basically, any information
you give to the command to make it go is called a parameter. For
locate, you give it two numbers. First the row number then the
column number. The screen has about 24 rows and 80 columns. Each
number can only be whole (because there's no in between) and must
be >0. For example, to move the text down to the 5th row:
LOCATE 5,1
Again, no quotes here. Perhaps you want to move it to the
middle of the screen:
LOCATE 12,40
Which is about the middle of the screen. Locate is pretty easy to understand. Just don't give it numbers too big, or less than zero, because you'll get error messages and your program won't work. Something even as minor as that is called a bug. Little things like that can mess up a whole program, so watch even for such minor details. It can be very irritating to find when your program is in the 100s or 1000s of lines.
That's simple enough. Here is a command even simpler: CLS. This is an acronym for CLear Screen. It does what it sounds: Clears the screen. The screen is not automatically cleared of text after you run the program, so you may notice junk text leftover if you run a program over and over. Usually you'll want to start a program with CLS, but as you go on you'll find less and less use for it.
1.3 - Interaction
Well, it's all fine and dandy to
be able to give the user some information, but to really do
anything interesting you'll need to get input from the user. To
start, we'll get input by asking questions and so on, or
prompting them to type something in. Later, we can make games by
using the keyboard as a control. And if you're really ambitous,
with a deep understanding of BASIC you can move on to using the
mouse (this is a rather technical procedure if you're into not
just doing, but understanding - which i advocate: it's for
advanced programmers only). So, here's what we'll be looking at:
INPUT
IF...THEN...ELSE
Again, it does like it sounds. It
gets some input. This one's a bit different though. The parameter
is a variable.
Variables are a BIG part of programming. Unlike in the math
sense, you use them to store things. There's different kinds of
variables to store the different types of data. For example,
there's numeric variables to store.... numbers, of
course. Then there's string variables to store strings
(one or more characters of text. the message in the earlier print
statement is a string). There's actually more than one type of
numeric variable, but don't worry about that as of yet.
So, let's make a simple program to ask the user their name.
Print "What's your
name?"
Input n$
Print n$ ; "? What a terrible name!"
So, what here does input n$ do? It tells the computer to
prompt the user to type something in, then it stores whatever
they type in in that variable. They'll probably unwittingly enter
their name, only to be told by the computer a second later that
it's a terrible name. But something's different about this print
statement. It has a semi-colon. It's very simple - in a print
statement, you can connect multiple things with a semicolon. You
need it if you want to print out both n$ and ? What a terrible
name!, on the same line. Notice that you can print out variables
as well as plain messages. Because n$ is not in quotes, it prints
out whatever's in that variable. If it was in quotes, it would
literally print out n$ on the screen, rather than whatever was
entered through INPUT.
Notice now that the variable is called n$. Why is it called this
specifically. Well, you can name a variable whatever you want! It
just has to only numbers and letters, and cannot start with a
number. But doesn't the $ at the end break this rule? NO. That $
tells the computer that this variable will hold a string.
If you drop the $, it signifies that it's holding numbers. It may
seem that a string is no different than a number, but that's not
true. Numbers and strings are treated differently, so properly
label your variables!!
Names of variables can be pretty long. I could have chosen name$,
username$, nameofthepersonusingthisprogram$, anything i want
pretty much. But i prefer short variables. However, name$ is
probably better because it makes your program easy to read,
something very important for long programs.
Another very important part of programming is making decisions
based on the input. A simple way to do this is the IF statement. This is throwing rather alot at
you at once, but I don't want to lose your interest.
With IF you basically give it something that could happen.
There's a word that goes with it; THEN. Whatever comes after THEN
is what it should do; But, it only does it if the IF thing
happens. For example, let's looking at a little number guessing
game:
num = 7
Print "I'm thinking of a number between 0 and 15. Try to
guess it in one try!"
input guess
IF guess = num THEN print "Yeah! You got it right" ELSE
print "Sorry! That's wrong!"
Wow, that if statement is long! Let's break it down. It says
first:
IF guess = num
so, it's going to check to see if guess
and num contain the same number.
THEN print "Yeah! You got it
right"
a THEN statement only happens if an IF
statement is true. so if they put in 6, 0, 1, 6.83451, -2, and on
the whole anything but 7, this wont happen. but there's still one
more part:
ELSE print "Sorry! That's wrong!"
if they get it wrong, the then doesn't happen. But, we want to give them a message anyway. That's where else comes in. Else happens if the IF turns out to be false - what it was looking for didn't happen.
1.4 - Eleminating redundant code: Loops
What if we wanted to give them more than 1 guess? Say, 6
guesses this time. Well, we could do it like this:
num = 7
Print "I'm thinking of a number between 0 and 15. Try to
guess it in one try!"
input guess
IF guess = num THEN print "Yeah! You got it right" ELSE
print "Sorry! That's wrong!"
input guess
IF guess = num THEN print "Yeah! You got it right" ELSE
print "Sorry! That's wrong!"
input guess
IF guess = num THEN print "Yeah! You got it right" ELSE
print "Sorry! That's wrong!"
input guess
IF guess = num THEN print "Yeah! You got it right" ELSE
print "Sorry! That's wrong!"
input guess
IF guess = num THEN print "Yeah! You got it right" ELSE
print "Sorry! That's wrong!"
input guess
IF guess = num THEN print "Yeah! You got it right" ELSE
print "Sorry! That's wrong!"
Well, that's very redundant. You typed (or
maybe copy+pasted) the same code 6 times! That's terrible
programming practice, and just flat out boring to do. So, let's
look at something at takes care of things that need to be done
many times: Loops. Here's a couple kinds of loops and loop-related
commands we'll look at:
For...Next
Do...Loop
Exit for
Exit do
Okay, let's use the first one to make
this program a few lines shorter. In a for loop, we give a
variable and a value it should start at. Then, we make it loop,
adding to this variable every time it runs through, until it gets
to a certain point. An example loop might look like this:
For a = 1 to 10
....
....
....
Next a
The dots in the middle are just my way of saying you'll put some
stuff between there, and it'll be whatever you want, as you'll
see in a second. So, this loop will take the variable A (remember
it will store a number because it doesn't have a $ after it - you
can't do number math with a string variable) and make it equal 1.
Then it will do whatever stuff you want it to. It will keep doing
things until it comes to the words Next A. This closes the loop.
It goes back to the beginning, adds 1 to a, and does it again and
again like this unless a is more than 10.
num = 7
print "I'm thinking of a number between 0 and 15. Try to
guess it in 3 tries"
For a = 1 to 3
input guess
if guess = num then
print "You got it!"
exit for
Else
print "No, sorry"
End if
next a
So, we now know this loops 3 times. First A is 1, then 2, then
3. So, it asks for a guess 3 times. Notice I did something
different with the IF...THEN...ELSE part. It's still the same
statement, but it's spread across multiple lines to allow it to
do more: It sees if guess = num. If it does, then it does 2
things. It prints a positive message, and it breaks out of the
loop. Obviously we don't want to ask them over and over after
they got it right like our first program did. So, we break out or
exit the loop. Exit for means exit the for loop, whether
a is 3 yet or not.
If they didn't guess right we go to the else statement and do
what comes after it. We give them a negative message. Obviously
we could have a gazillion lines after THEN if we wanted to, and
the same with ELSE, because this format lets us do more than one
thing per IF and more than one thing per ELSE. So, we have to
tell the computer to end the if statement somewhere, just like
the loop ends (and loops again) somewhere. That's what END IF
does. It ends the if statement.
When we stretch an IF...THEN on for multiple lines like this, and
end it with END IF, it's called an IF-END IF block
I realize this has been alot of information to digest at once. As you read my tutorial, make sure you understand it pretty well before you move on. Programming, like math or langauge, builds on itself, and the more you press on knowing less, the harder it gets. If you go to far without understanding very much, you'll eventually just break down and reteach yourself anyway.
Let's take a different approach to this program. Lets make it
so that the user keeps guessing until they get it right. For
this, we'll need a loop that doesn't just go for a set number of
times. This is where the DO LOOP is handy. A do loop may look
like this
DO
.....
.....
.....
Loop until num = guess
This loop theoretically could go forever, because num has to =
guess for the loop to end. If that never happens, the loop never
ends (another easy place for bugs....). So, here's yet another
version of the program, using a DO LOOP:
num = 7
print "I'm thinking of a number
between 0 and 15. Try to guess it in 3 tries"
Do
input guess
if guess <> num then print ":Sorry! NO!"
Loop until guess = num
Print "You finally found the number! Good job!"
So, what's happening here. Well, again the basic stuff. It asks for input every time the loop goes. Notice i made an if statement that was a little different though. I said if guess <> num. What's with that? Well, <> means "Greater than or less than". So, if they guess something that's greater the number, they get told it's wrong, and if they guess less than the number, they're told it's wrong. So, the only thing that wouldn't make it say no would be if it's equal. If they guess the right number then, they're not told it's wrong. And look at the part that says loop. It only loops is guess doesn't = num. So, it bascially loops again, giving them another chance, if they're wrong. If they are right, the loop ends and it says they're right. This program is much easier and cleaner than the two previous, and runs slightly faster (although not noticable, it does take milliseconds less to process because less stuff happens)
One last thing. Remember EXIT FOR to get out of a FOR LOOP? Well, there's a similar statement, EXIT DO, that you can use if you want to prematurely end a DO LOOP for one reason or another.
1.5 - Even more input
Commands/keywords for this section:
SCREEN()
INKEY$
AND
If you got all previously discussed, you've already mastered a
small chunk of the language. So far, i've given you some very
important commands in BASIC. But i tend to gear my tutorials to
eventually culminate in game design, so let's look some
very humble beginnings for a pac-man style game.
For simplicity, let's make a very tiny, basic maze. This is not a
maze we'd really want, but it's okay to learn from. Let's just
put it right on the screen with some print statements:
PRINT "0000000" PRINT " " PRINT "0 000 0" PRINT "0 0 0 0" PRINT "0 0" PRINT "0 000 0" PRINT " 0 " PRINT "0 0" PRINT "0000000"
Wow! It's craptacular! Anyhow... that'll do for now. Now, in
this maze, our character will be an asterik - we'll do more
asthetically pleasing games once we get into graphics, files, and
all that fun stuff. Again, for the sake of simplicity, you'll
control him with the number pad.
So, let's think a bit on how we'll accomplish this. We'll draw a
maze, with print, and draw the asterik character with print.
We'll need the help of locate to position him in the maze. The
user will hit keys - which we'll show you how to do in a second -
to move the guy around. Of course, if we LOCATE him, we're gonna
be using coordinates. So, let's plan that out:
The first empty space in the maze is at 2,1. We'll start him
there. If he moves up he'll go to 1,1 and if he moves down he'll
go to 3,1. So, we'll subtract to move him up, add to move him
down. The same logic applies to left and right. From 2,1 if he
goes right he'll be at 2,2 and if he goes left he'll be at 2,0 (yes,
that zero is not allowed with locate, but this
is purely hypothetical). So, we'll add to go right and subtract
to go left. Good, that's most of the work right there.
But, what about not running into walls? Well, i'll introduce you
to a seldom used command called the SCREEN
function. It can acutally get info straight off of the
screen, after it's been printed! Unfortunately, i also have to
introduce you to a hideous monster called ASCII.
Let's start with the really confusing part to get it out of the way. What is ASCII (pronounced ass-key). It's an acronym for American Standard Code for Information Interchange, or something like that. Essentially, it goes like this: It gives a special code to 256 different characters, letters, numbers, and symbols. Beleive me, it is helpful, but I hate to have to throw such things at you which are not easy to at first glance comprehend. You'll see as you program more that it is useful, and start to understand why it's around, but whether you do or not it's an important part of programming, and must unfortunately be covered. Well, here's the ASCII table:
The reason why i mentioned this is because the SCREEN function
will spit out what it's supposed to,
but instead of a simple character of text like you'd expect, it
gives you an ASCII code. For example, say we've printed our maze
and we do this:
Print SCREEN(1,1)
It will give you the number 48. Clearly, there's a 0 at (1,1), not a 48. Well, 48 is the ASCII code for 0. So, we'll only let our guy move onto something if there's not a 0. To do this, we'll look at where he's trying to move with SCREEN(). If it gives us a 48, he's not allowed to move there and he stays put.
Now for the other technicality: INKEY$.
We don't want input statements constantly prompting the user,
making them type something in, and hitting return. We want to be
able to move around easily. INKEY$ is a special variable.
Whenever you hit a key at any time (outside an input statement),
even if seemingly nothing else is happening, QBASIC takes that
key and puts it into INKEY$. So INKEY$ is very handy in a
situation like a video game, because you can let the enter single
keystrokes without any prompting.
Take this loop for example:
DO
Loop until inkey$ = "1"
Print "You broke out of the loop!"
There's nothing in it! That doesn't matter, because if the
user is hitting buttons while this empty loop runs, the key goes
into INKEY$. When they hit anything but 1, nothing happens. But
if they hit 1, the loop ends.
However, i usually write that kind of loop like this:
DO
a$ = inkey$
Loop until a$ = "1"
Print "You broke out of the loop!"
Why do that if you can just look at inkey itself? Isn't that extra pointless code? Well, inkey$ is constantly changing and very touchy, so this loop works better, because you have something more solid to look at. Inkey$ changes so frequently that hitting the right key might not break the loop. I am just in the habit of doing A$ = inkey$, then checking it. That is the style i'll use in this tutorial as well.
Let's start to write the code based on what we just discussed
CLS y = 2 x = 1 COLOR 15 PRINT "0000000" PRINT " " PRINT "0 000 0" PRINT "0 0 0 0" PRINT "0 0" PRINT "0 000 0" PRINT " 0 " PRINT "0 0" PRINT "0000000" DO a$ = INKEY$ checky = y: checkx = x LOCATE y, x: COLOR 0: PRINT "X" IF a$ = "8" AND y - 1 > 0 THEN checky = y - 1 IF a$ = "4" AND x - 1 > 0 THEN checkx = x - 1 IF a$ = "2" THEN checky = y + 1 IF a$ = "6" THEN checkx = x + 1 IF SCREEN(checky, checkx) <> 48 THEN y = checky x = checkx END IF IF X > 7 then x = 7 LOCATE y, x: COLOR 15: PRINT "X" LOCATE 10, 10: PRINT x, y, checkx, checky LOOP UNTIL a$ = "Q" OR a$ = "q"
A few new things here, but the rest isn't too complex.
Firstly, there's AND. It's a special word you can use in IF
statements, making them more specific. This line for example:
IF a$ = "8" AND y - 1 > 0 THEN
checky = y - 1
Recall that the thing after THEN won't happen if the IF didn't. We use AND to give it more conditions. A$ has to be 8 AND y - 1 has to be more than zero. If those are both true, then we'll give the variable checky a value that's one less than y. This thinking applies to the next line also.
The next new thing here is colons. They let you put more than
one command on a line. This is just a matter of style. This line:
LOCATE y, x: COLOR 0: PRINT "X"
Works the same as these lines:
LOCATE y, x
COLOR 0
PRINT "X"
There is absolutely no difference, i just felt like putting them on one line to make it look neater (to me anyway) Same with the indenting; i like to indent code that's between DO....LOOP, and indent code between IF...END IF. Although it's perfectly fine not to indent, you'll see most programmers do this indenting with ifs and loops, and other such blocks of code.
Now that that's out of the way, let's step through this
program.
First we clear whatever may be on the screen from before. Then we
set the variables that store where the 'character' is on the
screen. We draw the maze (using color 15 because i wanted a white
maze). Now we enter the main loop. Good programs have a main loop
(where necessary). Then, we put inkey$ into another variable to
make it easier to work with. Here it gets going:
checky = y: checkx = x
Since we're going to be checking to see if they try to run
over a wall, i chose to use different variables that remember
where they're 'trying to move'. Later the program looks at what
character is on the screen there. If it's character 48 according
to the ASCII table, which is a maze wall, then they don't
actually move there.
Just like locate, screen ( ) can't have zeros in its parameters.
So the ifs for moving up or moving left make sure that the
program doesn't even bother checking if they would be trying to
move off the screen [to (0, x) or (y, 0)]. Also, after all the
checks are done and stuff like that there's this line:
IF X > 7 then x = 7
There's no maze past 7 on the x axis, so we don't let them
move there!
We'll get back to finishing this game later as we learn more. It
would be big and difficult using only what we know now. A pac-man
like game has more things to it: pellets, power pellets, enemies,
multiple levels. We'll need more knowledge to work with before we
can accomplish these.
to PART
2
After, while, before reading, if you have any questions, comments, or suggestions, please e-mail
me: E-mail
Originally posted at http://www.doorknobsoft.com/