21 game

From Rosetta Code
Revision as of 06:44, 25 August 2018 by rosettacode>Gerard Schildberger (→‎{{header|REXX}}: added a word to the REXX section header.)


21 game is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

21   is a two player game,   the game is played by choosing a number   (1,   2,   or   3)   to be added to the   running total.

The game is won when the   running total   reaches   exactly   21.
The   running total   starts at zero.

One player will be the computer.   Players alternate supplying a number to be added to the   running total.


Task

Write a computer program that will:

  •   do the prompting   (or provide a button menu),
  •   check for errors and display appropriate error messages,
  •   do the additions   (add a number to the   running total),
  •   display the   running total,
  •   provide a mechanism for the player to   quit/exit/halt/stop/close   the program,
  •   issue a notification when there is a winner,   and
  •   determine who goes first   (possibly a random choice, or it can be specified when the game begins).



Phix

If the computer goes first you cannot win.
Once the computer stops displaying "no clear strategy" you cannot win.
The computer_first flag only applies to the first game. After winning, losing, or conceding, you go first. <lang Phix>bool computer_first = false bool show_spoiler = false

integer total = 0

procedure computer_play()

   integer move = 0
   for i=1 to 3 do
       if mod(total+i,4)=1 then
           move = i
           exit
       end if
   end for
   if move=0 then
       puts(1,"no clear strategy\n")
       move = rand(min(3,21-total))
   end if
   printf(1,"Total is %d. I play %d.\n",{total,move})
   total += move
   if total=21 then
       puts(1,"21! I win!\n")
   end if

end procedure

puts(1,"\n21 game\n\n") puts(1,"Press escape or q to quit the game, c to concede and start a new game from 0\n\n")

if computer_first then

   printf(1,"Total is %d.\n",{total})  
   computer_play()

elsif show_spoiler then

   -- The secret to winning!
   puts(1,sq_sub("Uif!pomz!xbz!up!xjo!jt!qmbz!2!gjstu-!uifo!5.=dpnqvufs!npwf?!fwfsz!ujnf",1)&"\n\n")

end if

while 1 do

   printf(1,"Total is %d. enter 1, 2, or 3: ",{total})
   integer ch = wait_key()
   puts(1,iff(ch=#1B?"esc":ch)&"\n")
   if ch>='1' and ch<='3' then
       ch -= '0'
       if total+ch>21 then
           puts(1,"Too big\n")
       else
           total += ch
           if total=21 then
               puts(1,"21! You win!\n")
           else
               computer_play()
           end if
       end if
   elsif ch=#1B or lower(ch)='q' then
       puts(1,"Quitting\n")
       exit
   end if
   if lower(ch)='c' or total=21 then
       total = 0
   end if

end while</lang>

Output:
21 game

Press escape or q to quit the game, c to concede and start a new game from 0

Total is 0. enter 1, 2, or 3: 1
no clear strategy
Total is 1. I play 3.
Total is 4. enter 1, 2, or 3: 1
no clear strategy
Total is 5. I play 1.
Total is 6. enter 1, 2, or 3: 3
no clear strategy
Total is 9. I play 1.
Total is 10. enter 1, 2, or 3: 1
Total is 11. I play 2.
Total is 13. enter 1, 2, or 3: 3
Total is 16. I play 1.
Total is 17. enter 1, 2, or 3: 2
Total is 19. I play 2.
21! I win!
Total is 0. enter 1, 2, or 3: q
Quitting

REXX

Around half of the REXX program deals with incorrect or missing input   (of the required integer). <lang rexx>/*REXX program plays the 21 game with a human, each player chooses 1, 2, or 3 which */ /*──────────── is added to the current sum, the first player to reach exactly 21 wins.*/ sep= copies('─', 8); sep2= " "copies('═', 8)" " /*construct an eye─catching msg fences.*/ say sep 'Playing the 21 game.' /*tell what's happening here at the zoo*/ high= 3 /*the highest integer that can be used.*/ g= 21 /*the game target (winning total/sum.*/ $= 0 /*the sum (so far). */

   do j=1  while $<g;    ok= 1                  /*obtain optional move from ARG or ask.*/
   low = (j \== 1)                              /*allow user to choose computer go 1st.*/
   say;     say sep  'Please enter a number from ' low " ───► 3               (or Quit):"
   if j==1  then say sep '[A value of 0 (zero) means you want the computer to go first.]'
   pull x _ . 1 ax                              /*obtain an answer;   so far, so good. */
   if x=               then call ser "Nothing entered."
   if _\==             then call ser "Too many arguments entered: "       ax
   if abbrev('QUIT', x, 1)  then do;   say;       say sep  "quitting.";    exit;      end
   if \datatype(x, 'N')  then call ser "Argument isn't numeric: "           x
   if \datatype(x, 'W')  then call ser "Number isn't an integer: "          x
   if x<0                then call ser "Number can't be negative: "         x
   if x=0  &  j \== 1    then call ser "Number can't be zero: "             x
   if x>high             then call ser "Number is too large  (>"high'): '   x
   if \ok  then iterate                         /*Had an error? Then get another number*/
   x= x/1                                       /*normalize the  X  number;  +2 001 3. */
   if $+x > g            then call ser "Number will cause the sum to exceed " g': '   x
   if x\==0   then call tot x, 1                /*0?   User wants computer to go first.*/
   if $==g    then leave                        /*the user won the game with the last #*/
   if $>=g-3  then y= g - $                     /*choose a winning number to add to $. */
              else y= 1                         /*   "   " minimum    "    "  "   " "  */
   say sep 'The computer chooses '     y     " as it's choice."
   call tot y, 0
   end   /*j*/

say if who then say sep 'Congratulations! You have won the 21 game.'

       else say sep  'The computer has won the  21  game.'

exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ ser: if \ok then return; ok=0; er= sep '***error***'; say /*set some literals. */

    say;    say er  arg(1);    say;     ok=0;      return        /*say errMsg; set ¬OK.*/

/*──────────────────────────────────────────────────────────────────────────────────────*/ tot: arg q,who; $=$+q; say sep 'The game total is now' sep2 $ sep2; return /*add; show $*/</lang>

output:
──────── Playing the  21  game.

──────── Please enter a number from  1 ───► 3               (or Quit):
──────── [A value of 0 (zero) means you want the computer to go first.]
3                                                                         ◄■■■■■■■■■■ user input
──────── The game total is now  ════════  3  ════════
──────── The computer chooses  1  as it's choice.
──────── The game total is now  ════════  4  ════════

──────── Please enter a number from  1 ───► 3               (or Quit):
3                                                                          ◄■■■■■■■■■■ user input
──────── The game total is now  ════════  7  ════════
──────── The computer chooses  1  as it's choice.
──────── The game total is now  ════════  8  ════════

──────── Please enter a number from  1 ───► 3               (or Quit):
3                                                                          ◄■■■■■■■■■■ user input
──────── The game total is now  ════════  11  ════════
──────── The computer chooses  1  as it's choice.
──────── The game total is now  ════════  12  ════════

──────── Please enter a number from  1 ───► 3               (or Quit):
3                                                                          ◄■■■■■■■■■■ user input
──────── The game total is now  ════════  15  ════════
──────── The computer chooses  1  as it's choice.
──────── The game total is now  ════════  16  ════════

──────── Please enter a number from  1 ───► 3               (or Quit):
1                                                                          ◄■■■■■■■■■■ user input
──────── The game total is now  ════════  17  ════════
──────── The computer chooses  1  as it's choice.
──────── The game total is now  ════════  18  ════════

──────── Please enter a number from  1 ───► 3               (or Quit):
3                                                                          ◄■■■■■■■■■■ user input 
──────── The game total is now  ════════  21  ════════

──────── Congratulations!   You have won the  21  game.

Ring

<lang ring>

  1. Project : 21 Game

load "guilib.ring"

limit = 21 posold = 0 button = list(limit) mynum = list(3) yournum = list(3)

new qapp

       {
       win1 = new qwidget() {
                 setwindowtitle("21 Game")
                 setgeometry(100,100,1000,600)
                 label1 = new qlabel(win1) {
                             setgeometry(10,10,1000,600)
                             settext("")
                 }
                 label2 = new qlabel(win1) {
                             setgeometry(240,50,120,40)
                             setAlignment(Qt_AlignHCenter)
                             setFont(new qFont("Verdana",12,100,0))
                             settext("my number:")
                 }
                 label3 = new qlabel(win1) {
                             setgeometry(640,50,120,40)
                             setAlignment(Qt_AlignHCenter)
                             setFont(new qFont("Verdana",12,100,0))
                             settext("your number:")
                 }
                 for p = 1 to 3
                      mynum[p] = new qpushbutton(win1) {
                                         setgeometry(200+p*40,100,40,40)
                                         setstylesheet("background-color:orange")
                                         settext(string(p))
                                         setclickevent("choose(" + string(p) + ",1)")
                                         }
                  next
                  for p = 1 to 3
                       yournum[p] = new qpushbutton(win1) {
                                            setgeometry(600+p*40,100,40,40)
                                            setstylesheet("background-color:white")
                                            settext(string(p))
                                            setclickevent("choose(" + string(p) + ",2)")
                                            }
                  next
                  for n = 1 to limit
                       button[n] = new qpushbutton(win1) {
                                         setgeometry(40+n*40,190,40,40)
                                         settext(string(n))
                                         }
                   next
                   show()
       }
       exec()
       }

func choose(ch,ym)

       pos = posold + ch
       if pos > limit
          msg = "You must choose number from 1 to " + string(limit - posold)
          msgBox(msg)
          for n = 1 to 3
               mynum[n].setenabled(false)
               yournum[n].setenabled(false)
          next
          return
       ok
       for n = posold+1 to pos
            if ym = 1
               button[n] { setstylesheet("background-color:orange") }
            else
               button[n] { setstylesheet("background-color:white") }
            ok
       next
       posold = pos
       if ym = 1
          for n = 1 to 3
               mynum[n].setenabled(false)
               yournum[n].setenabled(true)
          next
        else
          for n = 1 to 3
               mynum[n].setenabled(true)
               yournum[n].setenabled(false)
          next
        ok
        if pos = 21
           if ym = 1
              msgBox("I won!")
           else
              msgBox("You won!")
           ok
        ok

func msgBox(text) { m = new qMessageBox(win1) { setWindowTitle("21 Game") setText(text) show() }

       }

</lang> Output:
21 Game