HTBasic Help
×
Menu
Index

Example: Rock/Paper/Scissors Game

 
10     ! *********************************************************************
20     ! Example: Rock/Paper/Scissors Game
30     !
40     ! This program is designed to show the operation of LABEL and
50     ! PUSHBUTTON widgets. It plays the game of "rock/paper/scissors"
60     ! in which each of two players guesses one of three items -
70     ! rock, paper, or scissors. The guesses are then compared
80     ! for the following outcomes:
90     !
100   !  - An identical guess is a tie
110   !  - Paper covers rock, paper wins
120   !  - Scissors cuts paper, scissors wins
130   !  - Rock breaks scissors, rock wins
140   !
150   ! The program sets up a panel with a large LABEL to prompt the user
160   ! for his or her guess, sets up a PUSHBUTTON for each guess, then
170   ! goes into a loop where it waits for PUSHBUTTON input.
180   !
190   ! Each one of the three PUSHBUTTON widgets causes an event that invokes
200   ! the appropriate handler routine. These three routines each contain
210   ! a SELECT statement that matches the PUSHBUTTON against a guess made
220   ! by the program -- rock, scissors, or paper.  On the basis of the
230   ! match, each routine then provides a dialog indicating the match and
240   ! calls the appropriate Win, Lose, or Tie routine.
250   !
260   ! ******************************************************************
270   !
280   RANDOMIZE INT(FRACT(TIMEDATE)*10^7)
290   !
300   ! Variables Used:
310   !
320   ! Me,You,Tie:                                                Store game outcomes
330   ! Rock,Paper,Scissors:                                Guess values
340   ! B$,S$:                                                                General purpose strings
350   !
360   INTEGER Me,You,Tie,Rock,Paper,Scissors
370   DATA 0,0,0,0,1,2
380   READ Me,You,Tie,Rock,Paper,Scissors
390   !
400   INTEGER Black,White,Red,Yellow,Green,Cyan,Blue,Magenta
410   DATA 0,1,2,3,4,5,6,7
420   READ Black,White,Red,Yellow,Green,Cyan,Blue,Magenta
430   !
440   DIM B$[50],S$[100]
450   INTEGER Nlines,D(1:4),Dw,Dh                                                ! Variables for display handling
460   INTEGER Pw,Ph,Px,Py,Iw,Ih                                                ! PANEL dimensions & coordinates
470   INTEGER Gapw,Gaph,W1,H1,W2,H2                                ! Widget scaling factors
480   INTEGER R1,R2,R3,R4,R5,R6,C1,C2,C3
490   !
500   ! Get display dimensions
510   !
520   STATUS CRT,13;Nlines
530   GESCAPE CRT,3;D(*)
540   Dw=D(3)-D(1)
550   Dh=(D(4)-D(2))*((Nlines-7)/Nlines)
560   !
570   Pw=Dw*.5
580   Ph=Dh*.8
590   Px=(Dw-Pw)/2
600   Py=(Dh-Ph)/2
610   !
620   CLEAR SCREEN
630   ASSIGN @Main TO WIDGET "PANEL";SET ("VISIBLE":0)
640   CONTROL @Main;SET ("MAXIMIZABLE":0,"RESIZABLE":0)
650   CONTROL @Main;SET ("X":Px,"Y":Py,"WIDTH":Pw,"HEIGHT":Ph)
660   CONTROL @Main;SET ("TITLE":" Example: Rock/Paper/Scissors Game")
670   CONTROL @Main;SET ("SYSTEM MENU":"Quit")
680   !
690   STATUS @Main;RETURN ("INSIDE WIDTH":Iw,"INSIDE HEIGHT":Ih)
700   !
710   Gapw=Iw*.03                                                ! Width gap
720   Gaph=Ih*.03                                                ! Height gap
730   W1=(Iw-Gapw*4)/3                                                ! Width of PUSHBUTTONs and most LABELS
740   H1=(Ih-Gaph*8)/4                                                ! Height of PUSHBUTTONs and all LABELS
750   W2=Iw-Gapw*2                                                ! Width of main LABEL and all SEPARATORs
760   H2=Gaph                                                                ! Height of SEPARATORs
770   !
780   C1=Gapw                                                                ! Column coordinates, based on PUSHBUTTON width
790   C2=C1+W1+Gapw
800   C3=C2+W1+Gapw
810   !
820   R1=Gaph                                                                ! Row coordinates:  row for main LABEL
830   R2=R1+H1+Gaph                                                ! Row for first SEPARATOR
840   R3=R2+H2+Gaph                                                ! Row for input PUSHBUTTONs
850   R4=R3+H1+Gaph                                                ! Row for second SEPARATOR
860   R5=R4+H2                                                ! Row for result-title LABELs
870   R6=R5+H1                                                ! Row for result-value LABELs
880   !
890   ! Now add child widgets: main LABEL
900   !
910   ASSIGN @Label TO WIDGET "LABEL";PARENT @Main
920   CONTROL @Label;SET ("X":C1,"Y":R1,"WIDTH":W2,"HEIGHT":H1)
930   CONTROL @Label;SET ("BORDER":0,"BACKGROUND":Black,"PEN":Red)
940   CONTROL @Label;SET ("PEN":White,"VALUE":"Make a guess!")
950   !
960   ! Create SEPARATOR widget
970   !
980   ASSIGN @S1 TO WIDGET "SEPARATOR";PARENT @Main
990   CONTROL @S1;SET ("X":C1,"Y":R2,"WIDTH":W2,"HEIGHT":H2)
1000  !
1010  ! User input keys
1020  !
1030  ASSIGN @Rock TO WIDGET "PUSHBUTTON";PARENT @Main
1040  CONTROL @Rock;SET ("X":C1,"Y":R3,"WIDTH":W1,"HEIGHT":H1)
1050  CONTROL @Rock;SET ("BACKGROUND":Blue,"PEN":White)
1060  CONTROL @Rock;SET ("LABEL":"ROCK")
1070  !
1080  ASSIGN @Scissors TO WIDGET "PUSHBUTTON";PARENT @Main
1090  CONTROL @Scissors;SET ("X":C2,"Y":R3,"WIDTH":W1,"HEIGHT":H1)
1100  CONTROL @Scissors;SET ("BACKGROUND":Blue,"PEN":White)
1110  CONTROL @Scissors;SET ("LABEL":"SCISSORS")
1120  !
1130  ASSIGN @Paper TO WIDGET "PUSHBUTTON";PARENT @Main
1140  CONTROL @Paper;SET ("X":C3,"Y":R3,"WIDTH":W1,"HEIGHT":H1)
1150  CONTROL @Paper;SET ("BACKGROUND":Blue,"PEN":White)
1160  CONTROL @Paper;SET ("LABEL":"PAPER")
1170  !
1180  ! Next SEPARATOR widget
1190  !
1200  ASSIGN @S2 TO WIDGET "SEPARATOR";PARENT @Main
1210  CONTROL @S2;SET ("X":C1,"Y":R4,"WIDTH":W2,"HEIGHT":H2)
1220  !
1230  ! Results titles and values. Note that none of these LABELS have
1240  ! borders; the titles also have backgrounds that have the same color
1250  ! as the PANEL background, so they appear to be written directly on
1260  ! the PANEL.
1270  !
1280  ASSIGN @Me_title TO WIDGET "LABEL";PARENT @Main
1290  CONTROL @Me_title;SET ("X":C1,"Y":R5,"WIDTH":W1,"HEIGHT":H1)
1300  CONTROL @Me_title;SET ("BORDER":0,"VALUE":"ME")
1310  !
1320  ASSIGN @Me_value TO WIDGET "LABEL";PARENT @Main
1330  CONTROL @Me_value;SET ("X":C1,"Y":R6,"WIDTH":W1,"HEIGHT":H1)
1340  CONTROL @Me_value;SET ("BORDER":0,"BACKGROUND":Black,"PEN":Red)
1350  CONTROL @Me_value;SET ("VALUE":Me)
1360  !
1370  ASSIGN @You_title TO WIDGET "LABEL";PARENT @Main
1380  CONTROL @You_title;SET ("X":C2,"Y":R5,"WIDTH":W1,"HEIGHT":H1)
1390  CONTROL @You_title;SET ("BORDER":0,"VALUE":"YOU")
1400  !
1410  ASSIGN @You_value TO WIDGET "LABEL";PARENT @Main
1420  CONTROL @You_value;SET ("X":C2,"Y":R6,"WIDTH":W1,"HEIGHT":H1)
1430  CONTROL @You_value;SET ("BORDER":0,"BACKGROUND":Black,"PEN":Green)
1440  CONTROL @You_value;SET ("VALUE":You)
1450  !
1460  ASSIGN @Tie_title TO WIDGET "LABEL";PARENT @Main
1470  CONTROL @Tie_title;SET ("X":C3,"Y":R5,"WIDTH":W1,"HEIGHT":H1)
1480  CONTROL @Tie_title;SET ("BORDER":0,"VALUE":"TIE")
1490  !
1500  ASSIGN @Tie_value TO WIDGET "LABEL";PARENT @Main
1510  CONTROL @Tie_value;SET ("X":C3,"Y":R6,"WIDTH":W1,"HEIGHT":H1)
1520  CONTROL @Tie_value;SET ("BORDER":0,"BACKGROUND":Black,"PEN":Yellow)
1530  CONTROL @Tie_value;SET ("VALUE":Tie)
1540  !
1550  ! PANEL completed, set up EVENTS
1560  !
1570  ON EVENT @Rock,"ACTIVATED" GOSUB Gotrock
1580  ON EVENT @Scissors,"ACTIVATED" GOSUB Gotscissors
1590  ON EVENT @Paper,"ACTIVATED" GOSUB Gotpaper
1600  ON EVENT @Main,"SYSTEM MENU" GOTO Finis
1610  !
1620  ! Turn on the PANEL, make everything visible, then loop
1630  !
1640  CONTROL @Main;SET ("VISIBLE":1)
1650  !
1660  ! Main loop, set random-number seed, then loop
1670  !
1680  LOOP
1690    WAIT FOR EVENT
1700  END LOOP
1710  STOP
1720  !
1730  ! ****************  End of Main Program **********************
1740  !
1750  ! The three following handler routines are all basically similar:
1760  ! each is invoked by one of the three PUSHBUTTONs and uses a SELECT
1770  ! statement to figure the appropriate outcome. For each outcome, it
1780  ! loads a string with the appropriate result and calls the appropriate
1790  ! Win, Lose, or Tie routine.
1800  !
1810 Gotrock: !
1820  SELECT INT(3*RND)
1830  CASE Rock
1840    B$="ROCK ON ROCK"
1850    GOSUB Tie
1860  CASE Scissors
1870    B$="ROCK BREAKS SCISSORS"
1880    GOSUB Win
1890  CASE Paper
1900    B$="PAPER COVERS ROCK"
1910    GOSUB Lose
1920  END SELECT
1930  RETURN
1940  !
1950 Gotscissors: !
1960  SELECT INT(3*RND)
1970  CASE Rock
1980    B$="ROCK BREAKS SCISSORS"
1990    GOSUB Lose
2000  CASE Scissors
2010    B$="SCISSORS ON SCISSORS"
2020    GOSUB Tie
2030  CASE Paper
2040    B$="SCISSORS CUTS PAPER"
2050    GOSUB Win
2060  END SELECT
2070  RETURN
2080  !
2090 Gotpaper: !
2100  SELECT INT(3*RND)
2110  CASE Rock
2120    B$="PAPER COVERS ROCK"
2130    GOSUB Win
2140  CASE Scissors
2150    B$="SCISSORS CUTS PAPER"
2160    GOSUB Lose
2170  CASE Paper
2180    B$="PAPER ON PAPER"
2190    GOSUB Tie
2200  END SELECT
2210  RETURN
2220  !
2230  ! The three results routines -- Win, Tie, Lose -- are also similar to
2240  ! each other. Each takes the result of the match from the calling
2250  ! routine, concatenates it with the appropriate conclusion, displays
2260  ! it with a dialog, then increments the appropriate tally and returns.
2270  !
2280 Win: !
2290  S$=B$&": You WIN!"
2300  DIALOG "INFORMATION",S$;SET ("TITLE":" Results","PEN":Green)
2310  You=You+1
2320  CONTROL @You_value;SET ("VALUE":You)
2330  RETURN
2340  !
2350 Tie: !
2360  S$=B$&": Tie!"
2370  DIALOG "INFORMATION",S$;SET ("TITLE":" Results","PEN":Yellow)
2380  Tie=Tie+1
2390  CONTROL @Tie_value;SET ("VALUE":Tie)
2400  RETURN
2410  !
2420 Lose: !
2430  S$=B$&": You LOSE!"
2440  DIALOG "INFORMATION",S$;SET ("TITLE":" Results","PEN":Red)
2450  Me=Me+1
2460  CONTROL @Me_value;SET ("VALUE":Me)
2470  RETURN
2480  !
2490 Finis: !
2500  ASSIGN @Main TO *                                ! Delete the PANEL widget
2510  END