Monday, September 17, 2012

Petit Computer Journal #7


Petit Computer Journal #7
Character and String

So far we have dealt with numbers. It's time to deal with the other data type: String. What is a string? It's a string of characters. What is a character? That's a good question. It goes back to the beginning. What are computer made of? A bunch of numbers. Therefore a character is a number. It's a special number, however. What's the difference between this character number and ordinary number? An ordinary number can go to 524287. A character number is from 0 to 255. You can see what they are by going to Help Menu#12 "Text and Display" - Character Code List.

Please note that character 0 (NULL) and character 32 (SPACE) are two different characters!

Basic Character ASC() CHR$() VAL() STR$() HEX$()

You already know how to get a character given a number. Use CHR$() as given by this program from Petit Computer Journal#5:

'ASCII TABLE
S=0
@MAINLOOP
CLS
FOR I=S TO S+15
R=I%16
LOCATE 0,R:?I;:LOCATE 5,R:?CHR$(I) :'<--Right here!
NEXT

GOSUB @SETB3

IF INBUTTON$=="U" THEN S=S+16
IF INBUTTON$=="D" THEN S=S+256-16
S=S%256
?:?"S=";S;"   ";INBUTTON$:WAIT 60:'OPTIONAL FOR DEBUGGING
GOTO @MAINLOOP

Given a number, CHR$() will show a character. What is the reverse function of it? The ASC(). Given a character, it will return a number. How about regular number? Let's say we have a number 1043, and we want a string "1043". How do we do it? We use STR$(). And the reverse? VAL(). Go to RUN Mode, and try these out:

?CHR$(31) 'Prints "!"
?CHR$(65) 'Prints "A"
?ASC("A") 'Prints 65
?ASC("a") 'Prints 97
?HEX$(80) 'Prints 50
?HEX$(80,4) 'Prints 0050 Note leading zeros.

?"ABC"+"DEF" 'Prints ABCDEF
?"ABC"*3 'Prints ABCABCABC


Let's do a couple quick functions. UCASE and LCASE, which returns Upper Case string and Lower case strings respectively.

@MAINLOOP
LINPUT "string",A$
?"Upper Case: ";:GOSUB @UCASE:?A$
?"Lower case: ";:GOSUB @LCASE:?A$
?:?
GOTO @MAINLOOP

@UCASE
T$=""
FOR I=0 TO LEN(A$)-1
C$=MID$(A$,I,1):'SINGLE CHARACTER AT LOCATION I
IF ASC(C$)>=97 AND 122>=ASC(C$) THEN C$=CHR$(ASC(C$)-32)
T$=T$+C$:'APPEND C$ TO T$
NEXT
A$=T$
RETURN


@LCASE
T$=""
FOR I=0 TO LEN(A$)-1
C$=MID$(A$,I,1):'SINGLE CHARACTER AT LOCATION I
IF ASC(C$)>=65 AND 90>=ASC(C$) THEN C$=CHR$(ASC(C$)+32)
T$=T$+C$:'APPEND C$ TO T$
NEXT
A$=T$
RETURN


Search and Replace LEN() MID$() RIGHT$() LEFT$() INSTR SUBST$

You have seen a few more string functions: LEN(A$). This is the number of character in A$. In other words, string LENgth of A$. We subtract 1 from LEN(A$) because strings are zero-based, while the LEN() is 1-based.


MID$(A$,I,1). You'll probably see this construct a lot. What it does is basically returns the character at position I (zero based). We can return more than 1 character. If we want 4 characters starting at position I, we'll do this: MID$(A$,I,4). It's that simple!

LEFT$() and RIGHT$() are just like MID$, except they don't start in the middle. They start at left and right respectively. Try this out in RUN Mode:

A$="Hello World"
?LEFT$(A$,5)  'Prints "Hello"
?RIGHT$(A$,5)  'Prints "World"

Type NEW. Start a new program. Type this program in Edit Mode and run it:

INPUT A$
CLS
@LOOP
LOCATE 0,0:?A$
WAIT 15
A$=RIGHT$(A$,LEN(A$)-1)+LEFT$(A$,1)
GOTO @LOOP

Did you see a rotating banner? Good! All this does is take the rest of A$ except the first character and add the first character. In other words, put the first character at the end. You can change the number '1' with any number to rotate that many characters.

Let's do a stack and queue real quick. Stacks puts in data (PUSH) and pull out data (POP) at the same place. We'll do it at the end. Queue in (ENQ) also at the end. but Queue Out (DEQ) is at the opposing end. We'll see it in action. Start a new program.

CLS:CLEAR
A$="A":GOSUB @PUSH
A$="B":GOSUB @PUSH
A$="C":GOSUB @PUSH
A$="D":GOSUB @PUSH
GOSUB @POP
GOSUB @POP
GOSUB @POP
A$="E":GOSUB @PUSH
A$="F":GOSUB @PUSH

CLEAR
A$="A":GOSUB @ENQ
A$="B":GOSUB @ENQ
A$="C":GOSUB @ENQ
A$="D":GOSUB @ENQ
GOSUB @DEQ
GOSUB @DEQ
GOSUB @DEQ
A$="E":GOSUB @ENQ
A$="F":GOSUB @ENQ

END

@PUSH
?"PUSH ";
S$=S$+A$
?"A$=";A$;" S$=";S$
RETURN

@POP
?"POP  ";
A$=RIGHT$(S$,1)
S$=LEFT$(S$,LEN(S$)-1) 
?"A$=";A$;" S$=";S$
RETURN

@ENQ :'Enqueue (same as PUSH!)
?"ENQ ";
S$=S$+A$
?"A$=";A$;" S$=";S$
RETURN

@DEQ :'Dequeue
?"DEQ ";
A$=RIGHT$(S$,1)
S$=LEFT$(S$,LEN(S$)-1) 
?"A$=";A$;" S$=";S$
RETURN

Compare the two. Do you see the difference between stack and queue?
Push enters data from the right side. Pops it from the right side.
Enqueue enters data from the right side. Takes it from the left side.
That's it,really. Simple. BTW, PUSHing from Left is S$=A$+S$.

I use INSTR function quite a lot. I use it as indexing function. Basically, If I want to know whether something is a vowel. I can use this:

L=INSTR("AEIOU",C$) :'Where C$ is a character to check for vowel. L=-1 means not a vowel.

SUBSTR$() is handy if you don't want to do a lot of shifting with LEFT$ AND RIGHT$. Let's say you want to replace <> with the player's name. You can do this:

CLS:CLEAR
T$="HELLO <>! TODAY IS <>. THE TIME IS <

INPUT "NAME";N$
S$=T$ :'COPIES T$ TO S$
L=INSTR(S$,"<>"):LLEN=LEN("<>")
S$=SUBST$(S$,L,LLEN,N$)
L=INSTR(S$,"<>"):LLEN=LEN("<>")
S$=SUBST$(S$,L,LLEN,DATE$)
L=INSTR(S$,"<
S$=SUBST$(S$,L,LLEN,TIME$)

?:?S$

Now you have the skeleton program for MadLibs. Add this to the program to see how you can replace the same string multiple times. This is also the way Mail Merge program works, BTW. Simple Template applications.

T$="HELLO <>! GOODBYE <>!"
S$=T$ :'COPIES T$ TO S$
L=INSTR(S$,"<>"):LLEN=LEN("<>")
S$=SUBST$(S$,L,LLEN,N$)
?:?S$ :'SUB THE FIRST <>
L=INSTR(S$,"<>"):LLEN=LEN("<>")
S$=SUBST$(S$,L,LLEN,N$)
?:?S$ :'SUB THE SECOND <>

And that's all there is to it! Wow, we have written a lot of programs today, and we're still not done! I know I'm bucking the convention here, but I like to just go through the steps all at once. It's not that hard to go through the different commands. It's hard to understand the purpose of such commands, which is why I'm giving you all the different examples to use. You probably don't know why I choose these kind of programs. Trust me when I say that these programs are the basic building blocks of computer programming.

You may take a break here if you're tired. Come back later and we'll do one final program: a game that uses our newfound knowledge, and something that is doable in one hour, and fun, and something worthwhile that you can show off to other people. Wow, is that a tall order or what?

Haha, joking aside, I do have such program. And, no, it's not Mad Libs. That one is 15 minutes! Try to guess what it is before you proceed. who knows? Maybe you have a better suggestion than mine!




A Simple Game: Hangman

Let's do a Hangman program real quick. What is it? Show and Tell! what is Hangman? It's a game where you have to guess the secret sentence. Each wrong guess nets you a mark. Once 10 marks or whatever number decided is reach, you lose! It's simple enough to be done in one hour.

What do we need?
1. T$: The secret sentence.
2. G$: Guessed letters
3. W$: Wrong guesses
4. K$: Available characters to guess.

What are the steps?
1. Display all 4 strings. If T$ char not in G$ then show Square
2. Ask for input (set to UPPERCASE)
3. If the character is in K$, then proceed, else GOTO step 1.
4. if the character is in T$, then add to G$, else add to W$.
5. If LEN(w$)>=10 then LOSE
6. If all char in T$ is in G$ then WIN
7. GOTO 1


CLS:CLEAR

@INIT
T$="":G$=" ":W$=" "
K$="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
C$="abcdefghijklmnopqrstuvwxyz"

T$="THIS IS THE SECRET WORD"

@MAIN
CLS:?"HANGMAN"
?:?
FOR I=0 TO LEN(T$):A$=MID$(T$,I,1)
IF INSTR(G$,A$)< 0 THEN ?"#"; ELSE ?A$;
NEXT
?:?:?"GUESSED LETTERS"
?G$
?:?:?"WRONG LETTERS"
?W$
?:?:?"AVAILABLE LETTERS"
FOR I=0 TO LEN(K$):A$=MID$(K$,I,1)
IF INSTR(G$,A$)< 0 AND INSTR(W$,A$)< 0 THEN ?A$;
NEXT
?:?:?:LINPUT "LETTER?";S$

First stage: 18 minutes. Now to complete the rest of the program.

CLS:CLEAR

@INIT
T$="":G$=" ":W$=" "
K$="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
C$="abcdefghijklmnopqrstuvwxyz"

T$="THIS IS THE SECRET WORD"

@MAIN
CLS:?"HANGMAN"
?:?
FOR I=0 TO LEN(T$):A$=MID$(T$,I,1)
IF INSTR(G$,A$)< 0 THEN ?"#"; ELSE ?A$;
NEXT
?:?:?"GUESSED LETTERS"
?G$
?:?:?"WRONG LETTERS"
?W$
?:?:?"AVAILABLE LETTERS"
FOR I=0 TO LEN(K$):A$=MID$(K$,I,1)
IF INSTR(G$,A$)< 0 AND INSTR(W$,A$)< 0 THEN ?A$;
NEXT

@STEP2
?:?:?:LINPUT "LETTER?";S$
S$=LEFT$(S$,1):IF S$=="" GOTO @MAIN
IF INSTR(C$,S$)>=0 THEN S$=CHR$(ASC(S$)-32)
?"YOUR GUESS IS: ";S$

@STEP3
IF INSTR(G$,S$)>=0 GOTO @MAIN
IF INSTR(W$,S$)>=0 GOTO @MAIN

@STEP4
IF INSTR(T$,S$)>=0 THEN G$=G$+S$ ELSE W$=W$+S$

@STEP5
IF LEN(W$)>9 GOTO @LOSE

@STEP6
WIN=1
FOR I=0 TO LEN(T$)
C1=INSTR(K$,MID$(T$,I,1))
C2=INSTR(G$,MID$(T$,I,1))
IF C1< 0 GOTO @STEP6A
IF C2< 0 THEN WIN=0
@STEP6A
NEXT
IF WIN GOTO @WIN
GOTO @MAIN

@LOSE
?"YOU LOSE!"
GOTO @ANYKEY

@WIN
?"YOU WIN!"
GOTO @ANYKEY

@ANYKEY
WAIT 60
FOR I=0 TO 1:I=TCHST OR BUTTON(3):NEXT
GOTO @INIT


Second stage:  18 minutes



We have a complete program in about 36 minutes. That's typing it from scratch using stylus on the device. We'll add one more thing: READ and DATA

CLS:CLEAR

@INIT
T$="":G$=" ":W$=" "
K$="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
C$="abcdefghijklmnopqrstuvwxyz"

'T$="THIS IS THE SECRET WORD"
I=1:RESTORE @TEXTDATA
@SETT
READ D$
IF D$=="" GOTO @MAIN
IF !RND(I) THEN T$=D$
I=I+1
GOTO @SETT

@MAIN
CLS:?"HANGMAN"
?:?
FOR I=0 TO LEN(T$):A$=MID$(T$,I,1)
IF INSTR(G$,A$)< 0 THEN ?"#"; ELSE ?A$;
NEXT
?:?:?"GUESSED LETTERS"
?G$
?:?:?"WRONG LETTERS"
?W$
?:?:?"AVAILABLE LETTERS"
FOR I=0 TO LEN(K$):A$=MID$(K$,I,1)
IF INSTR(G$,A$)< 0 AND INSTR(W$,A$)< 0 THEN ?A$;
NEXT

@STEP2
?:?:?:LINPUT "LETTER?";S$
S$=LEFT$(S$,1):IF S$=="" GOTO @MAIN
IF INSTR(C$,S$)>=0 THEN S$=CHR$(ASC(S$)-32)
?"YOUR GUESS IS: ";S$

@STEP3
IF INSTR(G$,S$)>=0 GOTO @MAIN
IF INSTR(W$,S$)>=0 GOTO @MAIN

@STEP4
IF INSTR(T$,S$)>=0 THEN G$=G$+S$ ELSE W$=W$+S$

@STEP5
IF LEN(W$)>9 GOTO @LOSE

@STEP6
WIN=1
FOR I=0 TO LEN(T$)
C1=INSTR(K$,MID$(T$,I,1))
C2=INSTR(G$,MID$(T$,I,1))
IF C1< 0 GOTO @STEP6A
IF C2< 0 THEN WIN=0
@STEP6A
NEXT
IF WIN GOTO @WIN
GOTO @MAIN

@LOSE
?"YOU LOSE!"
GOTO @ANYKEY

@WIN
?"YOU WIN!"
GOTO @ANYKEY

@ANYKEY
WAIT 60
FOR I=0 TO 1:I=TCHST OR BUTTON(3):NEXT
GOTO @INIT

@TEXTDATA
DATA "THIS IS THE SECRET WORD"
DATA "THIS IS A VERY LONG PHRASE THAT WILL WRAP AROUND"
DATA "I WOULD TYPE A LITTLE FASTER"
DATA "TO BOLDLY GO WHERE NO MAN HAS   GONE BEFORE"
DATA "THE QUICK BROWN FOX JUMPS OVER  THE LAZY DOG"
DATA ""

And that's the complete program. Obviously, if you have more time, you can add more data. That's the beauty of it. You can add as many as you like! Be careful about punctuation marks, since the program cannot handle them. Or put some punctuation marks on G$!

The program we have now is just a simple quick and dirty program. We don't draw the Hangman character, for one. Also, it would be nice to show the completed solution. But that's enough for now. Not bad for one hour computer programming using stylus pecking!

No comments: