========= Spaghetti Version =========
This version is a program called "Tunes" taken from
http://www2.corvallis.k12.or.us/chs/students/2005/Anh_Tran/Pages/Qbasic/
I don't know what the SUB Tunes is for. I bet the teacher said "Put all your tunes in a SUB" so he did. But the teacher didn't say "And don't put them anywhere else".
I like guys that can follow specs!
========= Modular Version ============
It works exactly the same except
1) The randomizer is modified to ensure that a given tune is not played again until all other tunes have been played.
2) The answer evaluation logic is expanded to allow simple spelling mistakes. If the user enters MACKARANA instead of MACARENA that should count.
======== Spartan Version ============
Same as modular version except SCREEN 13 and COLOR type crap removed. Who needs all that which stands in the way of debugging?
I am hoping someone can modify this to allow data entry while the tune is playing and to stop the playing when data entry is finished (or even as soon as it is started - who want's to keep listening until the bitter end).
' **** NAME THAT TUNE ****
' LAB 3 SECTION 3
' ANH TRAN
'SELECT SONG
SCREEN 13
5 CLS
INTRODUCTION
COLOR 11
r = INT(RND * 7) + 2
IF r = 2 THEN GOTO 20
IF r = 3 THEN GOTO 30
IF r = 4 THEN GOTO 40
IF r = 5 THEN GOTO 50
IF r = 6 THEN GOTO 60
IF r = 7 THEN GOTO 70
20 PLAY "MNT100L4O1AL8A.L16AL4AL8>C.L16<BL8"
INPUT "Name That Tune"; C$: C$ = UCASE$(C$)
IF C$ = "FUNERAL MARCH" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF C$ <> "FUNERAL MARCH" THEN PRINT "**Sorry Try Again**": PRINT
PLAY "MNT100L4O1AL8A.L16AL4AL8>C.L16<BL8B.L16AL8A.L16AL2AL4>CL8C.L16CL4CL8E.L16DL8D.L16CL8C.L16CL2C"
INPUT "Name That Tune"; D$: D$ = UCASE$(D$)
IF D$ = "FUNERAL MARCH" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF D$ <> "FUNERAL MARCH" THEN PRINT "**You Are Incorrect**": PRINT : GOTO 100
30 PLAY "t100o2mnl4g> l8cp16l16c l2c<l4g> l8d<p16l16b> "
INPUT "Name That Tune"; E$: E$ = UCASE$(E$)
IF E$ = "WEDDING MARCH" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF E$ <> "WEDDING MARCH" THEN PRINT "**Sorry Try Again**": PRINT
PLAY "t100o2mnl4g> l8cp16l16c l2c<l4g> l8d<p16l16b> l2c <l4g> l8cp16l16f l4fl8ep16l16d l4c<l8bp16l16>cl2d<l4g>l8cp16l16cl2c<l4g>l8dp16l16<b>l2c<l4g>l8cp16l16e l4gl8ep16l16c<l4a> l8dp16l16el2c"
INPUT "Name That Tune"; F$: F$ = UCASE$(F$)
IF F$ = "WEDDING MARCH" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF F$ <> "WEDDING MARCH" THEN PRINT "**You Are Incorrect**": PRINT : GOTO 100
40 PLAY "MNT255L4O2GGABGBAD"
INPUT "Name That Tune"; G$: G$ = UCASE$(G$)
IF G$ = "YANKEE DOODLE" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF G$ <> "YANKEE DOODLE" THEN PRINT "**Sorry Try Again**": PRINT
PLAY "MNT255L4O2GGABGBADGGABL2GF+L4GGAB>C<BAGF+DEF+L2GL4G P4L4EF+EDEF+L2GL4DEDC<L2B>L2DL4EF+EDEF+GEDGF+AL2GL4G"
INPUT "Name That Tune"; H$: H$ = UCASE$(H$)
IF H$ = "WEDDING MARCH" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF H$ <> "WEDDING MARCH" THEN PRINT "**You Are Incorrect**": PRINT : GOTO 100
50 PLAY "t200l4o2mn eel2el4eel2el4eg"
INPUT "Name That Tune"; I$: I$ = UCASE$(I$)
IF I$ = "JINGLE BELLS" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF I$ <> "JINGLE BELLS" THEN PRINT "**Sorry Try Again**": PRINT
PLAY "t200l4o2mn eel2el4eel2el4eg l3cl8dl1e l4ffl3fl8fl4fel2el8eel4eddel2dgl4eel2el4eel2el4egl3cl8dl1el4ffl3fl8fl4fel2el8efl4ggfdl2c"
INPUT "Name That Tune"; J$: J$ = UCASE$(J$)
IF J$ = "JINGLE BELLS" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF J$ <> "JINGLE BELLS" THEN PRINT "**You Are Incorrect**": PRINT : GOTO 100
60 PLAY "MNT180L4O2CL8CCL4CL8CCCCCCCE<GGL4>C"
INPUT "Name That Tune"; K$: K$ = UCASE$(K$)
IF K$ = "MACARENA" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF K$ <> "MACARENA" THEN PRINT "**Sorry Try Again**": PRINT
PLAY "MNT180L4O2CL8CCL4CL8CCCCCCCE<GGL4>CL8CCL4CL8CCCCCCL4<A G>CL8CCL4CL8CCCCCCL4EGL2GL8EP8GEP4L2C"
INPUT "Name That Tune"; L$: L$ = UCASE$(L$)
IF L$ = "MACARENA" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF L$ <> "MACARENA" THEN PRINT "**You Are Incorrect**": PRINT : GOTO 100
70 PLAY "mnt200l4o1cp4>c<agemll2gl4gmnmll2dl4d"
INPUT "Name That Tune"; M$: M$ = UCASE$(M$)
IF M$ = "TAKE ME OUT TO THE BALL GAME" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF M$ <> "TAKE ME OUT TO THE BALL GAME" THEN PRINT "**Sorry Try Again**": PRINT
PLAY "mnt200l4o1cp4>c<agemll2gl4gmnmll2dl4dmnl4cp4>c<agemll2gggmnl4ag+aefgl2al4fmll2dl4dmnl2al4aab>cd<bagedcp4>c<agemll2gl4gmnl2dl4dl2cl4defgmll2aamnl4ab>cp4p4cp4p4c<bagf+gmll2al4al2bl4b>l2cc"
INPUT "Name That Tune"; N$: N$ = UCASE$(N$)
IF N$ = "TAKE ME OUT TO THE BALL GAME" THEN COLOR 13: PRINT "**You Are Correct**": PRINT : GOTO 100
IF N$ <> "TAKE ME OUT TO THE BALL GAME" THEN PRINT "**You Are Incorrect**": PRINT : GOTO 100
100
COLOR 14
INPUT "Would you like to try again"; Z$
Z$ = UCASE$(Z$)
IF LEFT$(Z$, 1) = "Y" THEN GOTO 5
IF LEFT$(Z$, 1) = "N" THEN GOTO 999
999 END
SUB INTRODUCTION
COLOR 12
PRINT " ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»"
PRINT " º NAME THAT TUNE º"
PRINT " ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ"
PRINT
PRINT
COLOR 2
PRINT " TRY GUESSING THE TUNE THAT IS PLAYING."
PRINT "YOU GET ONLY 2 GUESSES. GOOD LUCK!"
PRINT
END SUB
SUB TUNES
'Funeral March
'play "MNT100L4O1AL8A.L16AL4AL8>C.L16<BL8B.L16AL8A.L16AL2AL4>CL8C.L16CL4CL8E.L16DL8D.L16CL8C.L16CL2C"
'Take Me Out To The Ball Game
'PLAY "mnt200l4o1cp4>c<agemll2gl4gmnmll2dl4dmnl4cp4>c<agemll2gggmnl4ag+aefgl2al4fmll2dl4dmnl2al4aab>cd<bagedcp4>c<agemll2gl4gmnl2dl4dl2cl4defgmll2aamnl4ab>cp4p4cp4p4c<bagf+gmll2al4al2bl4b>l2cc"
DECLARE FUNCTION GotIt% (w$, s$)
DECLARE SUB INTRODUCTION ()
SCREEN 13
DIM i AS INTEGER, j AS INTEGER, k AS INTEGER
DIM d(6, 3) AS STRING: GOSUB BuildD
DIM q(6) AS INTEGER
DIM Song AS INTEGER
DO
GOSUB BuildQ
FOR Song = 1 TO 6
CALL INTRODUCTION
GOSUB PlaySong
PRINT R$: PRINT
COLOR 14
INPUT "Would you like to try again"; z$
IF NOT LEFT$(UCASE$(z$), 1) = "Y" THEN EXIT DO
NEXT Song
LOOP
END
PlaySong:
COLOR 11
R$ = "**You Are Correct**"
IF GotIt(d(q(Song), 1), d(q(Song), 2)) THEN RETURN
PRINT "**Sorry Try Again**": PRINT
IF GotIt(d(q(Song), 1), d(q(Song), 2) + d(q(Song), 3)) THEN RETURN
R$ = "**You Are Incorrect**"
RETURN
BuildQ:
FOR i = 1 TO 6: q(i) = i: NEXT i
RANDOMIZE TIMER
DO
FOR i = 1 TO 6
j = 1 + INT(RND * 6)
IF i <> j THEN SWAP q(i), q(j): k = k + 1
NEXT i
LOOP WHILE k < 20
RETURN
FUNCTION GotIt% (w$, s$)
PLAY s$
LINE INPUT "Name That Tune:"; c$: c$ = UCASE$(c$)
FOR i = 1 TO LEN(c$)
j = INSTR(w$, MID$(c$, i, 1))
IF j = 0 THEN
cntb = cntb + 1
ELSE
MID$(c$, i, 1) = CHR$(0)
cntg = cntg + 1
END IF
NEXT i
IF cntb > 2 OR cntg + 3 < LEN(w$) THEN EXIT FUNCTION
COLOR 13: GotIt% = -1
END FUNCTION
SUB INTRODUCTION
COLOR 12
CLS
PRINT " ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»"
PRINT " º NAME THAT TUNE º"
PRINT " ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ"
PRINT
PRINT
COLOR 2
PRINT " TRY GUESSING THE TUNE THAT IS PLAYING."
PRINT "YOU GET ONLY 2 GUESSES. GOOD LUCK!"
PRINT
END SUB
DECLARE FUNCTION GotIt% (w$, s$)
DECLARE SUB INTRODUCTION ()
DIM i AS INTEGER, j AS INTEGER, k AS INTEGER
DIM d(6, 3) AS STRING: GOSUB BuildD
DIM q(6) AS INTEGER
DIM Song AS INTEGER
DO
GOSUB BuildQ
FOR Song = 1 TO 6
CALL INTRODUCTION
GOSUB PlaySong
PRINT R$: PRINT
INPUT "Will now play a different song. Proceed"; z$
IF NOT LEFT$(UCASE$(z$), 1) = "Y" THEN EXIT DO
NEXT Song
LOOP
END
PlaySong:
R$ = "**You Are Correct**"
IF GotIt(d(q(Song), 1), d(q(Song), 2)) THEN RETURN
PRINT "**Sorry Try Again**": PRINT
IF GotIt(d(q(Song), 1), d(q(Song), 2) + d(q(Song), 3)) THEN RETURN
R$ = "**You Are Incorrect**"
RETURN
BuildQ:
FOR i = 1 TO 6: q(i) = i: NEXT i
RANDOMIZE TIMER
DO
FOR i = 1 TO 6
j = 1 + INT(RND * 6)
IF i <> j THEN SWAP q(i), q(j): k = k + 1
NEXT i
LOOP WHILE k < 20
RETURN
FUNCTION GotIt% (w$, s$)
PLAY s$
LINE INPUT "Name That Tune:"; c$: c$ = UCASE$(c$)
FOR i = 1 TO LEN(c$)
j = INSTR(w$, MID$(c$, i, 1))
IF j = 0 THEN
cntb = cntb + 1
ELSE
MID$(c$, i, 1) = CHR$(0)
cntg = cntg + 1
END IF
NEXT i
IF cntb > 2 OR cntg + 3 < LEN(w$) THEN EXIT FUNCTION
GotIt% = -1
END FUNCTION
SUB INTRODUCTION
CLS
PRINT " ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»"
PRINT " º NAME THAT TUNE º"
PRINT " ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ"
PRINT
PRINT
PRINT "TRY GUESSING THE TUNE THAT IS PLAYING."
PRINT "YOU GET ONLY 2 GUESSES. GOOD LUCK!"
PRINT
END SUB
DECLARE FUNCTION GotIt% (w$)
DECLARE SUB INTRODUCTION ()
DIM i AS INTEGER, j AS INTEGER, k AS INTEGER
DIM d(6, 3) AS STRING: GOSUB BuildD
DIM q(6) AS INTEGER
ON ERROR GOTO Ignore
ON PLAY(1) GOSUB MusicBOX
DIM SHARED Music AS STRING
DIM SHARED Interrupt AS STRING
DIM SHARED Work1 AS STRING
DIM Song AS INTEGER
DO
GOSUB BuildQ
FOR Song = 1 TO 6
CALL INTRODUCTION
GOSUB PlaySong
PRINT R$: PRINT
INPUT "Will now play a different song. Proceed"; z$
IF NOT LEFT$(UCASE$(z$), 1) = "Y" THEN EXIT DO
NEXT Song
LOOP
SYSTEM
Ignore:
Interrupt = CHR$(0)
RESUME NEXT
MusicBOX:
Interrupt = INKEY$: IF Interrupt <> "" THEN RETURN
GOSUB GetP: IF p$ = "" THEN Interrupt = CHR$(0): RETURN
Work1 = p$
DO WHILE INSTR(p$, "L") = 0
GOSUB GetP
Work1 = Work1 + p$
IF p$ = "" THEN p$ = "L"
LOOP
PLAY Work1
RETURN
GetP:
SELECT CASE LEN(Music)
CASE IS < 15: p$ = Music: Music = ""
CASE ELSE:
y = INSTR(5, Music, "L")
IF y = 0 THEN
p$ = Music: Music = ""
ELSE
p$ = LEFT$(Music, y - 1)
Music = RIGHT$(Music, LEN(Music) - y + 1)
END IF
END SELECT
RETURN
PlaySong:
R$ = "**You Are Correct**"
Music = d(q(Song), 2): GOSUB DoIt
IF GotIt(d(q(Song), 1)) THEN RETURN
PRINT "**Sorry Try Again**": PRINT
Music = d(q(Song), 2) + d(q(Song), 3): GOSUB DoIt
IF GotIt(d(q(Song), 1)) THEN RETURN
R$ = "**You Are Incorrect**"
RETURN
DoIt:
Music = UCASE$(Music)
y = INSTR(Music, "LL")
WHILE y > 0: MID$(Music, y, 1) = "lL": y = INSTR(Music, "LL"): WEND
PLAY ON
LOCATE , , 1: PRINT "Press key when ready to answer: ";
Interrupt = "": GOSUB MusicBOX: WHILE Interrupt = "": WEND
PLAY OFF
RETURN
BuildQ:
FOR i = 1 TO 6: q(i) = i: NEXT i
RANDOMIZE TIMER
DO
FOR i = 1 TO 6
j = 1 + INT(RND * 6)
IF i <> j THEN SWAP q(i), q(j): k = k + 1
NEXT i
LOOP WHILE k < 20
RETURN
FUNCTION GotIt% (w$)
LOCATE , , 1: PRINT SPACE$(70);
WHILE INKEY$ <> "": WEND
PRINT : LINE INPUT "Name That Tune: "; c$: c$ = UCASE$(c$)
FOR i = 1 TO LEN(c$)
j = INSTR(w$, MID$(c$, i, 1))
IF j = 0 THEN
cntb = cntb + 1
ELSE
MID$(c$, i, 1) = CHR$(0)
cntg = cntg + 1
END IF
NEXT i
IF cntb > 2 OR cntg + 3 < LEN(w$) THEN EXIT FUNCTION
GotIt% = -1
END FUNCTION
SUB INTRODUCTION
CLS
PRINT " ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»"
PRINT " º NAME THAT TUNE º"
PRINT " ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ"
PRINT
PRINT
PRINT "TRY GUESSING THE TUNE THAT IS PLAYING."
PRINT "YOU GET ONLY 2 GUESSES. GOOD LUCK!"
PRINT
END SUB
DECLARE SUB ZPlay (m$)
DECLARE FUNCTION GotIt% (NameOfMelody$, Melody$)
DIM i AS INTEGER, j AS INTEGER, k AS INTEGER
DIM D(6, 3) AS STRING: GOSUB BuildD: ' Load songs
DIM Q(6) AS INTEGER: ' Pointer to song to be played
RANDOMIZE TIMER
DIM Song AS INTEGER
DO
GOSUB BuildQ
FOR Song = 1 TO 6
GOSUB Introduction
GOSUB PlaySong: PRINT R$: PRINT
INPUT "Will now play a different song. Proceed"; z$
IF NOT LEFT$(UCASE$(z$), 1) = "Y" THEN EXIT DO
NEXT Song
LOOP
SYSTEM
PlaySong:
R$ = "**You Are Correct**"
N$ = D(Q(Song), 1): ' Name of the melody
m$ = D(Q(Song), 2): 'Melody (beginning)
IF GotIt(N$, m$) THEN RETURN
PRINT "**Sorry Try Again**": PRINT
m$ = m$ + D(Q(Song), 3): 'Melody (entire)
IF GotIt(N$, m$) THEN RETURN
R$ = "**You Are Incorrect**"
RETURN
BuildQ:
FOR i = 1 TO 6: Q(i) = i: NEXT i
DO
FOR i = 1 TO 6
j = 1 + INT(RND * 6)
IF i <> j THEN SWAP Q(i), Q(j): k = k + 1
NEXT i
LOOP WHILE k < 20
RETURN
FUNCTION GotIt% (NameOfMelody$, Melody$)
' ### Play melody until user presses a key
DIM m AS STRING: m = Melody$
DIM y AS INTEGER, t AS STRING * 1
LOCATE , , 1: PRINT "Press key when ready to answer: ";
DO
IF INKEY$ <> "" THEN EXIT DO
IF m <> "" THEN
Notes = 0
FOR i = 1 TO LEN(m)
t = LCASE$(MID$(m, i, 1))
IF INSTR("abcdefg", t) > 0 THEN
Notes = Notes + 1
IF Notes > 1 THEN EXIT FOR
END IF
NEXT i
IF i < LEN(m) THEN
p$ = LEFT$(m, i - 1)
m = RIGHT$(m, LEN(m) - i + 1)
ELSE
p$ = m
m = ""
END IF
PLAY p$
END IF
LOOP
LOCATE , 1: PRINT SPACE$(70); : LOCATE , 1
WHILE INKEY$ <> "": WEND
' ### Evaluate user guess at name of melody
DIM N AS STRING: N = NameOfMelody$
DIM G AS STRING: 'G is the user guess of N
DIM cntB AS INTEGER: 'Count of bad characters in guess
DIM cntG AS INTEGER: 'Count of good ones
LINE INPUT "Name That Tune: "; G: G = UCASE$(G)
FOR i = 1 TO LEN(G)
j = INSTR(N, MID$(G, i, 1))
IF j = 0 THEN
cntB = cntB + 1
ELSE
MID$(G, i, 1) = CHR$(0)
cntG = cntG + 1
END IF
NEXT i
IF cntB > 2 OR cntG + 3 < LEN(N) THEN EXIT FUNCTION
GotIt% = -1
END FUNCTION
The ON PLAY version of Ahn's program was complicated to no advantage.
The cleaner version uses the technique promoted by Solitaire, TheBob and mercury0x000d; namely, PLAY short segments at a time. See
http://www.network54.com/Forum/202193/message/1177079294
But I wanted to compute these short segments, not have them pre-set in an array. Given a long PLAY statement, divide it into small segments.
The cleaner version shows one way to do that. It works like this, given N is a note (A-G) and x is other stuff.
xxxxNxxxxNNxxxxNxNNNNxNNNxxxxxNxxxN
becomes
xxxxNxxxx
N
Nxxxx
Nx
N
N
N
Nx
N
N
Nxxxxx
Nxxx
N
I was going to mention that there were more non-notes than just "L#" but it worked fine for this particular program, so what the hell. The INSTR("abcdefg", t) > 0 method definitely covers all of them.