I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# 21 game

21 game
You are encouraged to solve this task according to the task description, using any language you may know.

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 by the player whose chosen number causes the running total to reach 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.

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 chosen 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 (maybe a random or user choice, or can be specified when the game begins).

## 11l

`F select_count(game_count)   ‘selects a random number if the game_count is less than 18. otherwise chooses the winning number’   Int t   I game_count < 18      t = random:(1..3)   E      t = 21 - game_count   print(‘The computer chooses #.’.format(t))   R t F request_count()   ‘request user input between 1,2 and 3. It will continue till either quit(q) or one of those numbers is requested.’   V t = ‘’   L      X.try         t = input(‘Your choice 1 to 3 :’)         I Int(t) C [1, 2, 3]            R Int(t)         E            print(‘Out of range, try again’)      X.catch         I t == ‘q’            R 0         E            print(‘Invalid Entry, try again’) F start()   V game_count = 0   print("Enter q to quit at any time.\nThe computer will choose first.\nRunning total is now #.".format(game_count))   V roundno = 1   L      print("\nROUND #.: \n".format(roundno))      V t = select_count(game_count)      game_count = game_count + t      print("Running total is now #.\n".format(game_count))      I game_count >= 21         print(‘So, commiserations, the computer has won!’)         R 0      t = request_count()      I t == 0         print(‘OK,quitting the game’)         R -1      game_count = game_count + t      print("Running total is now #.\n".format(game_count))      I game_count >= 21         print(‘So, congratulations, you've won!’)         R 1      roundno++ V c = 0V m = 0L   V o = start()   I o == -1      L.break   E      c += I o == 0 {1} E 0      m += I o == 1 {1} E 0   print(‘Computer wins #. game, human wins #. games’.format(c, m))   V t = input(‘Another game?(press y to continue):’)   I t != ‘y’      L.break`
Output:

The same as in Python.

## AArch64 Assembly

Works with: as version Raspberry Pi 3B version Buster 64 bits
` /* ARM assembly AARCH64 Raspberry PI 3B *//*  program game21_64.s   */  /*******************************************//* Constantes file                         *//*******************************************//* for this file see task include a file in language AArch64 assembly*/.include "../includeConstantesARM64.inc" .equ HITTOTAL,   21.equ BUFFERSIZE, 10  /*********************************//* Initialized data              *//*********************************/.dataszMessRules:         .ascii "21 Game\n"                    .ascii "21 is a two player game, the game is played by choosing a number \n"                    .ascii "(1, 2, or 3) to be added to the running total. The game is won by\n"                    .ascii "the player whose chosen number causes the running total to reach \n"                    .asciz "exactly 21. The running total starts at zero.\n\n\n" szMessHumanChoice:  .asciz "Enter your choice (1,2, 3 or type (q)uit to exit): "szMessErrChoise:    .asciz "invalid choice.\n  "szMessHumanBegin:   .asciz "The first move is human move.\n"szMessPiBegin:      .asciz "The first move is Raspberry pi. \n"szMessHumanWon:     .asciz "You won. \n"szMessHumanLost:    .asciz "You lost. \n"szMessTotal:        .asciz "The running total is @ \n"szMessPiChoice:     .asciz "Raspberry choice is  @ \n" szMessNewGame:      .asciz "New game (y/n) ? \n"szCarriageReturn:   .asciz "\n".align 4qGraine:  .quad 123456/*********************************//* UnInitialized data            *//*********************************/.bsssZoneConv:        .skip 24sBuffer:          .skip BUFFERSIZE/*********************************//*  code section                 *//*********************************/.text.global main main:                                 // entry of program      ldr x0,qAdrszMessRules    bl affichageMess1:    mov x10,#0                         // total = 0    mov x0,#100    bl genereraleas     cmp x0,#50    blt 2f    ldr x0,qAdrszMessHumanBegin        // human begin    bl affichageMess    b 4f2:                                     // Rasp begin    ldr x0,qAdrszMessPiBegin    bl affichageMess    mov x0,#13:                                    // rasp turn    add x10,x10,x0    ldr x1,qAdrsZoneConv    bl conversion10                   // call decimal conversion    ldr x0,qAdrszMessPiChoice    ldr x1,qAdrsZoneConv              // insert conversion in message    bl strInsertAtCharInc    bl affichageMess    cmp x10,#HITTOTAL    bne 4f    ldr x0,qAdrszMessHumanLost    bl affichageMess    b 12f4:                                    // display current total    mov x0,x10    ldr x1,qAdrsZoneConv    bl conversion10                   // call decimal conversion    ldr x0,qAdrszMessTotal    ldr x1,qAdrsZoneConv              // insert conversion in message    bl strInsertAtCharInc    bl affichageMess 5:                                    // human turn    ldr x0,qAdrszMessHumanChoice    bl affichageMess    bl saisie    cmp x0,#'q'                       // quit ?    beq 100f    cmp x0,#'Q'    beq 100f    cmp x0,#'1'    add x9,x10,1    csel x10,x9,x10,eq    beq 6f    cmp x0,#'2'    add x9,x10,2    csel x10,x9,x10,eq    beq 6f    cmp x0,#'3'    add x9,x10,3    csel x10,x9,x10,eq    beq 6f    ldr x0,qAdrszMessErrChoise    bl affichageMess    b 5b6:    cmp x10,#HITTOTAL                // total = maxi ?    beq 11f                           // yes -> human won    cmp x10,#5                       // else compute rasp number    mov x9,5                         // compare total and optimun7:    cmp x10,x9    ble 8f    add x9,x9,4    b 7b8:    sub x0,x9,x10                   // compute number rasp9:                                  // control number rasp    cmp x0,#0    ble 10f    cmp x0,#3    ble 3b10:                                  // if not ok, generate random number    mov x0,#2    bl genereraleas    add x0,x0,#1    b 3b                            // and loop 11:                                  // display human won    ldr x0,qAdrszMessHumanWon    bl affichageMess12:                                 // display new game ?    ldr x0,qAdrszCarriageReturn    bl affichageMess    ldr x0,qAdrszMessNewGame    bl affichageMess    bl saisie    cmp x0,#'y'    beq 1b    cmp x0,#'Y'    beq 1b 100:                                  // standard end of the program     mov x0, #0                        // return code    mov x8, #EXIT                     // request to exit program    svc #0                            // perform the system call qAdrszCarriageReturn:     .quad szCarriageReturnqAdrszMessRules:          .quad szMessRulesqAdrszMessHumanBegin:     .quad szMessHumanBeginqAdrszMessPiBegin:        .quad szMessPiBeginqAdrszMessPiChoice:       .quad szMessPiChoiceqAdrszMessTotal:          .quad szMessTotalqAdrszMessHumanChoice:    .quad szMessHumanChoiceqAdrszMessHumanLost:      .quad szMessHumanLostqAdrszMessHumanWon:       .quad szMessHumanWonqAdrszMessNewGame:        .quad szMessNewGameqAdrszMessErrChoise:      .quad szMessErrChoiseqAdrsZoneConv:            .quad sZoneConv/******************************************************************//*            string saisie                                       */ /******************************************************************//* x0 return the first character of human entry */saisie:    stp x1,lr,[sp,-16]!    // save  registers    stp x2,x8,[sp,-16]!    // save  registers    mov x0,#STDIN          // Linux input console    ldr x1,qAdrsBuffer     // buffer address     mov x2,#BUFFERSIZE     // buffer size     mov x8,#READ           // request to read datas    svc 0                  // call system    ldr x1,qAdrsBuffer     // buffer address     ldrb w0,[x1]           // load first character100:    ldp x2,x8,[sp],16      // restaur  2 registers    ldp x1,lr,[sp],16      // restaur  2 registers    ret                    // return to address lr x30 qAdrsBuffer:         .quad sBuffer/***************************************************//*   Generation random number                  *//***************************************************//* x0 contains limit  */genereraleas:    stp x1,lr,[sp,-16]!        // save  registers    stp x2,x3,[sp,-16]!        // save  registers    stp x4,x5,[sp,-16]!        // save  registers    ldr x4,qAdrqGraine    ldr x2,[x4]    ldr x3,qNbDep1    mul x2,x3,x2    ldr x3,qNbDep2    add x2,x2,x3    str x2,[x4]                // maj de la graine pour l appel suivant     cmp x0,#0    beq 100f    udiv x3,x2,x0    msub x0,x3,x0,x2           // résult = remainder 100:                           // end function    ldp x4,x5,[sp],16          // restaur  2 registers    ldp x2,x3,[sp],16          // restaur  2 registers    ldp x1,lr,[sp],16          // restaur  2 registers    ret                        // return to address lr x30/*****************************************************/qAdrqGraine: .quad qGraineqNbDep1:     .quad 0x0019660dqNbDep2:     .quad 0x3c6ef35f /********************************************************//*        File Include fonctions                        *//********************************************************//* for this file see task include a file in language AArch64 assembly */.include "../includeARM64.inc" `

## ARM Assembly

Works with: as version Raspberry Pi
` /* ARM assembly Raspberry PI  *//*  program game21.s   */  /* REMARK 1 : this program use routines in a include file    see task Include a file language arm assembly    for the routine affichageMess conversion10    see at end of this program the instruction include *//* for constantes see task include a file in arm assembly *//************************************//* Constantes                       *//************************************/.include "../constantes.inc".equ STDIN,  0       @ Linux input console.equ READ,   3       @ Linux syscall.equ HITTOTAL,   21.equ BUFFERSIZE, 10  /*********************************//* Initialized data              *//*********************************/.dataszMessRules:         .ascii "21 Game\n"                    .ascii "21 is a two player game, the game is played by choosing a number \n"                    .ascii "(1, 2, or 3) to be added to the running total. The game is won by\n"                    .ascii "the player whose chosen number causes the running total to reach \n"                    .asciz "exactly 21. The running total starts at zero.\n\n\n" szMessHumanChoice:  .asciz "Enter your choice (1,2, 3 or type (q)uit to exit): "szMessErrChoise:    .asciz "invalid choice.\n "szMessHumanBegin:   .asciz "The first move is human move.\n"szMessPiBegin:      .asciz "The first move is Raspberry pi. \n"szMessHumanWon:     .asciz "You won. \n"szMessHumanLost:    .asciz "You lost. \n"szMessTotal:        .asciz "The running total is @ \n"szMessPiChoice:     .asciz "Raspberry choice if  @ \n" szMessNewGame:      .asciz "New game (y/n) ? \n"szCarriageReturn:   .asciz "\n".align 4iGraine:  .int 123456/*********************************//* UnInitialized data            *//*********************************/.bsssZoneConv:        .skip 24sBuffer:          .skip BUFFERSIZE/*********************************//*  code section                 *//*********************************/.text.global main main:                                 @ entry of program      ldr r0,iAdrszMessRules    bl affichageMess1:    mov r10,#0                         @ total = 0    mov r0,#100    bl genereraleas     cmp r0,#50    blt 2f    ldr r0,iAdrszMessHumanBegin        @ human begin    bl affichageMess    b 4f2:                                     @ Rasp begin    ldr r0,iAdrszMessPiBegin    bl affichageMess    mov r0,#13:                                    @ rasp turn    add r10,r10,r0    ldr r1,iAdrsZoneConv    bl conversion10                   @ call decimal conversion    ldr r0,iAdrszMessPiChoice    ldr r1,iAdrsZoneConv              @ insert conversion in message    bl strInsertAtCharInc    bl affichageMess    cmp r10,#HITTOTAL    bne 4f    ldr r0,iAdrszMessHumanLost    bl affichageMess    b 10f4:                                    @ display current total    mov r0,r10    ldr r1,iAdrsZoneConv    bl conversion10                   @ call decimal conversion    ldr r0,iAdrszMessTotal    ldr r1,iAdrsZoneConv              @ insert conversion in message    bl strInsertAtCharInc    bl affichageMess 5:                                    @ human turn    ldr r0,iAdrszMessHumanChoice    bl affichageMess    bl saisie    cmp r0,#'q'                       @ quit ?    beq 100f    cmp r0,#'Q'    beq 100f    cmp r0,#'1'    addeq r10,r10,#1    beq 6f    cmp r0,#'2'    addeq r10,r10,#2    beq 6f    cmp r0,#'3'    addeq r10,r10,#3    beq 6f    ldr r0,iAdrszMessErrChoise    bl affichageMess    b 5b6:    cmp r10,#HITTOTAL                @ total = maxi ?    beq 9f                           @ yes -> human won    cmp r10,#5                       @ else compute rasp number    rsble r0,r10,#5    ble 7f    cmp r10,#9    rsble r0,r10,#9    ble 7f    cmp r10,#13    rsble r0,r10,#13    ble 7f    cmp r10,#17    rsble r0,r10,#17    ble 7f    cmp r10,#21    rsble r0,r10,#21    ble 7f7:                                  @ control number rasp    cmp r0,#0    ble 8f    cmp r0,#3    ble 3b8:                                  @ if not ok, generate random number    mov r0,#2    bl genereraleas    add r0,r0,#1    b 3b                            @ and loop 9:                                  @ display human won    ldr r0,iAdrszMessHumanWon    bl affichageMess10:                                 @ display new game ?    ldr r0,iAdrszCarriageReturn    bl affichageMess    ldr r0,iAdrszMessNewGame    bl affichageMess    bl saisie    cmp r0,#'y'    beq 1b    cmp r0,#'Y'    beq 1b 100:                                  @ standard end of the program     mov r0, #0                        @ return code    mov r7, #EXIT                     @ request to exit program    svc #0                            @ perform the system call iAdrszCarriageReturn:     .int szCarriageReturniAdrszMessRules:          .int szMessRulesiAdrszMessHumanBegin:     .int szMessHumanBeginiAdrszMessPiBegin:        .int szMessPiBeginiAdrszMessPiChoice:       .int szMessPiChoiceiAdrszMessTotal:          .int szMessTotaliAdrszMessHumanChoice:    .int szMessHumanChoiceiAdrszMessHumanLost:      .int szMessHumanLostiAdrszMessHumanWon:       .int szMessHumanWoniAdrszMessNewGame:        .int szMessNewGameiAdrszMessErrChoise:      .int szMessErrChoiseiAdrsZoneConv:            .int sZoneConv/******************************************************************//*            string saisie                                       */ /******************************************************************//* r0 return the first character of human entry */saisie:    push {r1-r7,lr}        @ save registers    mov r0,#STDIN          @ Linux input console    ldr r1,iAdrsBuffer     @ buffer address     mov r2,#BUFFERSIZE     @ buffer size     mov r7,#READ           @ request to read datas    svc 0                  @ call system    ldr r1,iAdrsBuffer     @ buffer address     ldrb r0,[r1]           @ load first character100:    pop {r1-r7,lr}    bx lr                   @ return iAdrsBuffer:         .int sBuffer/***************************************************//*   Generation random number                  *//***************************************************//* r0 contains limit  */genereraleas:    push {r1-r4,lr}                   @ save registers     ldr r4,iAdriGraine    ldr r2,[r4]    ldr r3,iNbDep1    mul r2,r3,r2    ldr r3,iNbDep1    add r2,r2,r3    str r2,[r4]                       @ maj de la graine pour l appel suivant     cmp r0,#0    beq 100f    mov r1,r0                         @ divisor    mov r0,r2                         @ dividende    bl division    mov r0,r3                         @ résult = remainder 100:                                  @ end function    pop {r1-r4,lr}                    @ restaur registers    bx lr                             @ return/*****************************************************/iAdriGraine: .int iGraineiNbDep1:     .int 0x343FDiNbDep2:     .int 0x269EC3 /***************************************************//*      ROUTINES INCLUDE                           *//***************************************************/.include "../affichage.inc" `
```The first move is human move.
The running total is 0
Enter your choice (1,2, 3 or type (q)uit to exit): 4
invalid choice.
Enter your choice (1,2, 3 or type (q)uit to exit): 1
Raspberry choice if  1
The running total is 2
Enter your choice (1,2, 3 or type (q)uit to exit): 3
Raspberry choice if  2
The running total is 7
Enter your choice (1,2, 3 or type (q)uit to exit): 1
Raspberry choice if  1
The running total is 9
Enter your choice (1,2, 3 or type (q)uit to exit): 2
Raspberry choice if  2
The running total is 13
Enter your choice (1,2, 3 or type (q)uit to exit): 3
Raspberry choice if  1
The running total is 17
Enter your choice (1,2, 3 or type (q)uit to exit): 1
Raspberry choice if  3
You lost.

New game (y/n) ?
y
The first move is Raspberry pi.
```

## AutoHotkey

`Gui, font, S16Gui, add, Radio, vRadioC , CakeGui, add, Radio, vRadioE x+0 Checked, EasyGui, add, Radio, vRadioH x+0, HardGui, add, text, xs vT, Total : 00Gui, add, text, xs vComputer, Computer Dealt 00Gui, add, text, xs Section, Player 1loop, 3	Gui, add, button, x+5 vPlayer1_%A_Index% gTotal, % A_Index Gui, add, button, xs vReset gReset, resetGui show,, 21 GameWinners := [1,5,9,13,17,21]gosub, resetreturn;-----------------------------------reset:total := 0GuiControl,, T, % "Total : " SubStr("00" Total, -1)GuiControl,, Computer, % "Computer Waiting"Loop 3	GuiControl, Enable, % "Player1_" A_IndexRandom, rnd, 0, 1if rnd{	Loop 3		GuiControl, Disable, % "Player1_" A_Index	gosub ComputerTurn}return;-----------------------------------Total:Added := SubStr(A_GuiControl, 9,1)Total += AddedGuiControl,, T, % "Total : " SubStr("00" Total, -1)if (total >= 21){	MsgBox % "Player 1 Wins"	gosub reset	return}Loop 3	GuiControl, Disable, % "Player1_" A_Indexgosub, ComputerTurnreturn;-----------------------------------ComputerTurn:Gui, Submit, NoHideSleep 500if RadioE{	if (total < 13)		RadioC := true	else		RadioH := true		}if RadioC{	Random, Deal, 1, 3	total += Deal}if RadioH{	for i, v in Winners		if (total >= v)			continue		else		{			Deal := v - total			if Deal > 3				Random, Deal, 1, 3			total += Deal			break		}}GuiControl,, T, % "Total : " SubStr("00" Total, -1)GuiControl,, Computer, % "Computer Dealt " Dealif (total=21){	MsgBox Computer Wins	gosub, reset}else	Loop 3		GuiControl, Enable, % "Player1_" A_Indexreturn`

## AWK

`#  Game 21 - an example in AWK language for Rosseta Code. BEGIN {    srand();    GOAL = 21;    best = 1; best = 1; best = 3; best = 2;     print\        "21 Game                                                          \n"\        "                                                                 \n"\        "21 is a two player game, the game is played by choosing a number \n"\        "(1, 2, or 3) to be added to the running total. The game is won by\n"\        "the player whose chosen number causes the running total to reach \n"\        "exactly 21. The running total starts at zero.                    \n\n";     newgame();    prompt(); } // {    move = strtonum(\$0);    if (move + total <= GOAL) {        update("human", strtonum(\$0));        update("ai", best[total % 4]);    }    else        invalid();    prompt();}/[^123]/ {    if (\$0 == "quit") {        print "goodbye";        exit;    }    else {        invalid();        prompt();    }} function prompt(){    print "enter your choice (or type quit to exit): ";} function invalid(){    print "invalid move";} function newgame() {    print "\n---- NEW GAME ----\n";    print "\nThe running total is currently zero.\n";    total = 0;    if (rand() < 0.5) {        print "The first move is AI move.\n";        update("ai", best[total % 4]);    }    else        print "The first move is human move.\n";} function update(player, move) {    printf "%8s:  %d = %d + %d\n\n", player, total + move, total, move;    total += move;    if (total == GOAL) {        printf "The winner is %s.\n\n", player;        newgame();    }}`
Output:
```gawk -f Game21.awk
21 Game

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 by
the player whose chosen number causes the running total to reach
exactly 21. The running total starts at zero.

---- NEW GAME ----

The running total is currently zero.

The first move is human move.

enter your choice (or type quit to exit):
1
human:  1 = 0 + 1

ai:  2 = 1 + 1

enter your choice (or type quit to exit):
2
human:  4 = 2 + 2

ai:  5 = 4 + 1

enter your choice (or type quit to exit):
3
human:  8 = 5 + 3

ai:  9 = 8 + 1

enter your choice (or type quit to exit):
1
human:  10 = 9 + 1

ai:  13 = 10 + 3

enter your choice (or type quit to exit):
2
human:  15 = 13 + 2

ai:  17 = 15 + 2

enter your choice (or type quit to exit):
1
human:  18 = 17 + 1

ai:  21 = 18 + 3

The winner is ai.

---- NEW GAME ----

The running total is currently zero.

The first move is human move.

enter your choice (or type quit to exit):
wow
invalid move
222
invalid move
enter your choice (or type quit to exit):
1
human:  1 = 0 + 1

ai:  2 = 1 + 1

enter your choice (or type quit to exit):
quit
goodbye```

## bash

`shopt -s expand_aliasesalias bind_variables='{  local -ri goal_count=21  local -ri player_human=0  local -ri player_computer=1  local -i turn=1  local -i total_count=0  local -i input_number=0  local -i choose_turn=0}'whose_turn() {  case \$(( ( turn + choose_turn ) % 2 )) in   \${player_human}) echo "player";;   \${player_computer}) echo "computer";;  esac}next_turn() {  let turn++}validate_number() {  ! test \${input_number} -ge 1 -a \${input_number} -le \$( max_guess )}prompt_number() {  local prompt_str  test \$( max_guess ) -eq 1 && {    prompt_str="enter the number 1 to win"  true  } || {    prompt_str="enter a number between 1 and \$( max_guess )"  }  while [ ! ]  do   read -p "\${prompt_str} (or quit): "   input_number=\${REPLY}   case \${REPLY} in    "quit") {      false      return    } ;;   esac   validate_number || break   echo "try again"  done}update_count() {  let total_count+=input_number}remaining_count() {  echo \$(( goal_count - total_count ))}max_guess() {  local -i remaining_count  remaining_count=\$( remaining_count )  case \$( remaining_count ) in    1|2|3) echo \${remaining_count} ;;    *) echo 3 ;;  esac}iter() {  update_count  next_turn}on_game_over() {  test ! \${input_number} -eq \$( remaining_count ) || {    test ! "\$( whose_turn )" = "player" && {      echo -ne "\nYou won!\n\n"    true    } || {      echo -ne "\nThe computer won!\nGAME OVER\n\n"    }    false  }}on_game_start() {  echo 21 Game  read -p "Press enter key to start"}choose_turn() {  let choose_turn=\${RANDOM}%2}choose_number() {  local -i remaining_count  remaining_count=\$( remaining_count )  case \${remaining_count} in   1|2|3) {       input_number=\${remaining_count}   } ;;   5|6|7) {       let input_number=remaining_count-4   } ;;   *) {       let input_number=\${RANDOM}%\$(( \$( max_guess ) - 1 ))+1   }  esac}game_play() {  choose_turn  while [ ! ]  do    echo "Total now \${total_count} (remaining: \$( remaining_count ))"    echo -ne "Turn: \${turn} ("    test ! "\$( whose_turn )" = "player" && {      echo -n "Your"    true    } || {      echo -n "Computer"    }    echo " turn)"    test ! "\$( whose_turn )" = "player" && {      prompt_number || break    true    } || {      choose_number      sleep 2      echo "Computer chose \${input_number}"    }    on_game_over || break    sleep 1    iter  done}21_Game() {  bind_variables  on_game_start  game_play}if [ \${#} -eq 0 ] then trueelse exit 1fi21_Game `

## C

`/** * Game 21 - an example in C language for Rosseta Code. * * A simple game program whose rules are described below * - see DESCRIPTION string. * * This program should be compatible with C89 and up. */  /* * Turn off MS Visual Studio panic warnings which disable to use old gold * library functions like printf, scanf etc. This definition should be harmless * for non-MS compilers. */#define _CRT_SECURE_NO_WARNINGS #include <stdio.h>#include <stdlib.h>#include <time.h> /* * Define bool, true and false as needed. The stdbool.h is a standard header * in C99, therefore for older compilers we need DIY booleans. BTW, there is * no __STDC__VERSION__ predefined macro in MS Visual C, therefore we need * check also _MSC_VER. */#if __STDC_VERSION__ >= 199901L || _MSC_VER >= 1800#include <stdbool.h>#else#define bool int#define true  1#define false 0#endif #define GOAL               21#define NUMBER_OF_PLAYERS   2#define MIN_MOVE            1#define MAX_MOVE            3#define BUFFER_SIZE       256 #define _(STRING) STRING  /* * Spaces are meaningful: on some systems they can be visible. */static char DESCRIPTION[] =     "21 Game                                                          \n"    "                                                                 \n"    "21 is a two player game, the game is played by choosing a number \n"    "(1, 2, or 3) to be added to the running total. The game is won by\n"    "the player whose chosen number causes the running total to reach \n"    "exactly 21. The running total starts at zero.                    \n\n"; static int total;  void update(char* player, int move){    printf("%8s:  %d = %d + %d\n\n", player, total + move, total, move);    total += move;    if (total == GOAL)        printf(_("The winner is %s.\n\n"), player);}  int ai(){/* * There is a winning strategy for the first player. The second player can win * then and only then the frist player does not use the winning strategy. *  * The winning strategy may be defined as best move for the given running total. * The running total is a number from 0 to GOAL. Therefore, for given GOAL, best * moves may be precomputed (and stored in a lookup table). Actually (when legal * moves are 1 or 2 or 3) the table may be truncated to four first elements. */#if GOAL < 32 && MIN_MOVE == 1 && MAX_MOVE == 3    static const int precomputed[] = { 1, 1, 3, 2, 1, 1, 3, 2, 1, 1, 3, 2, 1, 1,        3, 2, 1, 1, 3, 2, 1, 1, 3, 2, 1, 1, 3, 2, 1, 1, 3 };    update(_("ai"), precomputed[total]);#elif MIN_MOVE == 1 && MAX_MOVE == 3    static const int precomputed[] = { 1, 1, 3, 2};    update(_("ai"), precomputed[total % (MAX_MOVE + 1)]);#else    int i;    int move = 1;    for (i = MIN_MOVE; i <= MAX_MOVE; i++)        if ((total + i - 1) % (MAX_MOVE + 1) == 0)            move = i;    for (i = MIN_MOVE; i <= MAX_MOVE; i++)        if (total + i == GOAL)            move = i;    update(_("ai"), move);#endif}  void human(void){    char buffer[BUFFER_SIZE];    int move;     while ( printf(_("enter your move to play (or enter 0 to exit game): ")),            fgets(buffer, BUFFER_SIZE, stdin),             sscanf(buffer, "%d", &move) != 1 ||            (move && (move < MIN_MOVE || move > MAX_MOVE || total+move > GOAL)))        puts(_("\nYour answer is not a valid choice.\n"));    putchar('\n');    if (!move) exit(EXIT_SUCCESS);    update(_("human"), move);}  int main(int argc, char* argv[]){    srand(time(NULL));    puts(_(DESCRIPTION));    while (true)    {        puts(_("\n---- NEW GAME ----\n"));        puts(_("\nThe running total is currently zero.\n"));        total = 0;         if (rand() % NUMBER_OF_PLAYERS)        {            puts(_("The first move is AI move.\n"));            ai();        }        else            puts(_("The first move is human move.\n"));         while (total < GOAL)        {            human();            ai();        }    }}`
Output:
```21 Game

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 by
the player whose chosen number causes the running total to reach
exactly 21. The running total starts at zero.

---- NEW GAME ----

The running total is currently zero.

The first move is AI move.

AI:  1 = 0 + 1

enter your move to play (or enter 0 to exit game): 1

human:  2 = 1 + 1

AI:  5 = 2 + 3

enter your move to play (or enter 0 to exit game): 3

human:  6 = 5 + 1

AI:  9 = 6 + 3

enter your move to play (or enter 0 to exit game): asd ?

enter your move to play (or enter 0 to exit game): -1

enter your move to play (or enter 0 to exit game): 4

enter your move to play (or enter 0 to exit game): 2

human:  10 = 9 + 1

AI:  13 = 10 + 3

enter your move to play (or enter 0 to exit game): 3

human:  14 = 13 + 1

AI:  17 = 14 + 3

enter your move to play (or enter 0 to exit game): 2

human:  18 = 17 + 1

AI:  21 = 18 + 3

The winner is AI.

---- NEW GAME ----

The running total is currently zero.

The first move is AI move.

AI:  1 = 0 + 1

enter your move to play (or enter 0 to exit game): 1

human:  2 = 1 + 1

AI:  5 = 2 + 3

enter your move to play (or enter 0 to exit game): 2

human:  6 = 5 + 1

AI:  9 = 6 + 3

enter your move to play (or enter 0 to exit game): 3

human:  10 = 9 + 1

AI:  13 = 10 + 3

enter your move to play (or enter 0 to exit game): 0```

## C++

### Model View Controller

`/** *  Game 21 - an example in C++ language for Rosseta Code. * *  This version is an example of MVC architecture. It seems be a little cleaner *  than MVP. The friendship has broken encapsulations to avoid getters. */ #include <cstdlib>#include <ctime>#include <iostream>#include <iomanip>#include <limits> using namespace std;#define _(STR) STR  class Model{public:    static const int GOAL = 21;    static const int NUMBER_OF_PLAYERS = 2;    static const int MIN_MOVE = 1;    static const int MAX_MOVE = 3;    int bestMove();    bool update(const char* player, int move);    bool isGameBegin();    bool isGameOver();protected:    friend class View;    View* view = nullptr;    const char* player = nullptr;    int oldTotal = 0;    int newTotal = 0;    int lastMove = 0;};  class View{protected:    Model* model;public:    View(Model* model);    void init(const char* player);    void update();};  class Controller{protected:    Model* model;    View* view;public:    Controller(Model* model, View* view);    int input();    void clear();    void run();};  int Model::bestMove(){    // This is not the fastest algorithm. There is possible to precompute    // and memorize all answers before game begin or even hard code them.     int move = MIN_MOVE;    for (int i = MIN_MOVE; i <= MAX_MOVE; i++)        if ((newTotal + i - 1) % (MAX_MOVE + 1) == 0)            move = i;    for (int i = MIN_MOVE; i <= MAX_MOVE; i++)        if (newTotal + i == GOAL)            move = i;    return move;} bool Model::update(const char* player, int move){    if (move >= MIN_MOVE && move <= MAX_MOVE && newTotal + move <= GOAL)    {        this->player = player;        oldTotal = newTotal;        newTotal = oldTotal + move;        lastMove = move;        view->update();        return true;    }    else        return false;} bool Model::isGameBegin(){    return oldTotal == 0;} bool Model::isGameOver(){    return newTotal == GOAL;}  View::View(Model* model){    this->model = model;    model->view = this;} void View::init(const char* player){    if (model->newTotal == 0)        cout << _("----NEW GAME----\n\n")             << _("The running total is currently zero.\n")             << _("The first move is ") << player << _(" move.\n\n");} void View::update(){    cout << setw(8) << model->player << ": " << model->newTotal << " = "         << model->oldTotal << " + " << model->lastMove << endl << endl;    if (model->isGameOver())        cout << endl << _("The winner is ") << model->player << _(".\n\n\n");}  Controller::Controller(Model* model, View* view){    this->model = model;    this->view = view;} void Controller::run(){    if (rand() % Model::NUMBER_OF_PLAYERS == 0)    {        view->init("AI");        model->update("AI", model->bestMove());    }    else        view->init("human");     while (!model->isGameOver())    {        while (!model->update("human", input()))            clear();        model->update("AI", model->bestMove());    }} int Controller::input(){    int value;    cout << _("enter a valid number to play (or enter 0 to exit game): ");    cin >> value;    cout << endl;    if (!cin.fail())    {        if (value == 0)            exit(EXIT_SUCCESS);        else            return value;    }    else        return model->MIN_MOVE - 1;} void Controller::clear(){    cout << _("Your answer is not a valid choice.") << endl;    cin.clear();    cin.ignore((streamsize)numeric_limits<int>::max, '\n');}  int main(int argc, char* argv){    srand(time(NULL));     cout << _(        "21 Game                                                          \n"        "                                                                 \n"        "21 is a two player game, the game is played by choosing a number \n"        "(1, 2, or 3) to be added to the running total. The game is won by\n"        "the player whose chosen number causes the running total to reach \n"        "exactly 21. The running total starts at zero.                    \n\n");     while (true)    {        Model* model = new Model();        View* view = new View(model);        Controller* controler = new  Controller(model, view);         controler->run();         delete controler;        delete model;        delete view;    }    return EXIT_SUCCESS; // dead code}`

### Model View Presenter

`/** *  Game 21 - an example in C++ language for Rosseta Code. * *  This version is an example of MVP architecture. The user input, as well as *  the AI opponent, is handled by separate passive subclasses of abstract class *  named Controller. It can be noticed that the architecture support OCP, *  for an example the AI module can be "easily" replaced by another AI etc. * *  BTW, it would be better to place each class in its own file. But it would *  be less convinient for Rosseta Code, where "one solution" mean "one file". */ #include <cstdlib>#include <ctime>#include <iostream>#include <iomanip>#include <limits>  using namespace std; #define _(STR) STR  class Model{protected:     int oldTotal;    int newTotal;    int lastMove; public:     static const int GOAL = 21;    static const int NUMBER_OF_PLAYERS = 2;     Model()    {        newTotal = 0;        oldTotal = 0;        lastMove = 0;    }     void update(int move)    {        oldTotal = newTotal;        newTotal = oldTotal + move;        lastMove = move;    }     int getOldTotal()    {        return oldTotal;    }     int getNewTotal()    {        return newTotal;    }     int getLastMove()    {        return lastMove;    }     bool isEndGame()    {        return newTotal == GOAL;    }};  class View{public:     void update(string comment, Model* model)    {        cout << setw(8) << comment << ": "            << model->getNewTotal()            << " = "            << model->getOldTotal()            << " + "            << model->getLastMove() << endl            << endl;    }     void newGame(string player)    {        cout << _("----NEW GAME----") << endl            << endl            << _("The running total is currently zero.") << endl            << endl            << _("The first move is ") << player << _(" move.") << endl            << endl;    }     void endGame(string name)    {        cout << endl << _("The winner is ") << name << _(".") << endl            << endl            << endl;    }};  class Controller{public:     virtual string getName() = 0;    virtual int getMove(Model* model) = 0;};  class AI : public Controller{public:     string getName()    {        return _("AI");    }     int getMove(Model* model)    {        int n = model->getNewTotal();        for (int i = 1; i <= 3; i++)            if (n + i == Model::GOAL)                return i;        for (int i = 1; i <= 3; i++)            if ((n + i - 1) % 4 == 0)                return i;        return 1 + rand() % 3;    }};  class Human : public Controller{public:     string getName()    {        return _("human");    }     int getMove(Model* model)    {        int n = model->getNewTotal();        int value;        while (true) {            if (n == Model::GOAL - 1)                cout << _("enter 1 to play (or enter 0 to exit game): ");            else if (n == Model::GOAL - 2)                cout << _("enter 1 or 2 to play (or enter 0 to exit game): ");            else                cout << _("enter 1 or 2 or 3 to play (or enter 0 to exit game): ");            cin >> value;            if (!cin.fail()) {                if (value == 0)                    exit(0);                else if (value >= 1 && value <= 3 && n + value <= Model::GOAL)                {                    cout << endl;                    return value;                }            }            cout << _("Your answer is not a valid choice.") << endl;            cin.clear();            cin.ignore((streamsize)numeric_limits<int>::max, '\n');        }    }};  class Presenter{protected:     Model* model;    View* view;    Controller** controllers; public:     Presenter(Model* model, View* view, Controller** controllers)    {        this->model = model;        this->view = view;        this->controllers = controllers;    }     void run()    {        int player = rand() % Model::NUMBER_OF_PLAYERS;        view->newGame(controllers[player]->getName());         while (true)        {            Controller* controller = controllers[player];            model->update(controller->getMove(model));            view->update(controller->getName(), model);            if (model->isEndGame())            {                view->endGame(controllers[player]->getName());                break;            }            player = (player + 1) % Model::NUMBER_OF_PLAYERS;        }    }};  int main(int argc, char* argv){    srand(time(NULL));     while (true)    {        Model* model = new Model();        View* view = new View();        Controller* controllers[Model::NUMBER_OF_PLAYERS];        controllers = new Human();        for (int i = 1; i < Model::NUMBER_OF_PLAYERS; i++)            controllers[i] = new AI();        Presenter* presenter = new Presenter(model, view, controllers);         presenter->run();         delete model;        delete view;        delete controllers;        delete controllers;        delete presenter;    }    return EXIT_SUCCESS; // dead code} `
Output:
```----NEW GAME----

The running total is currently zero.

The first move is human move.

enter 1 or 2 or 3 to play (or enter 0 to exit game): 1

human: 1 = 0 + 1

AI: 4 = 1 + 3

enter 1 or 2 or 3 to play (or enter 0 to exit game): 2

human: 6 = 4 + 2

AI: 9 = 6 + 3

enter 1 or 2 or 3 to play (or enter 0 to exit game): nope
enter 1 or 2 or 3 to play (or enter 0 to exit game): 8
enter 1 or 2 or 3 to play (or enter 0 to exit game): 3

human: 12 = 9 + 3

AI: 13 = 12 + 1

enter 1 or 2 or 3 to play (or enter 0 to exit game): 2

human: 15 = 13 + 2

AI: 17 = 15 + 2

enter 1 or 2 or 3 to play (or enter 0 to exit game): 3

human: 20 = 17 + 3

AI: 21 = 20 + 1

The winner is AI.

----NEW GAME----

The running total is currently zero.

The first move is human move.

enter 1 or 2 or 3 to play (or enter 0 to exit game): 1

human: 1 = 0 + 1

AI: 4 = 1 + 3

enter 1 or 2 or 3 to play (or enter 0 to exit game): 2

human: 6 = 4 + 2

AI: 9 = 6 + 3

enter 1 or 2 or 3 to play (or enter 0 to exit game): 3

human: 12 = 9 + 3

AI: 13 = 12 + 1

enter 1 or 2 or 3 to play (or enter 0 to exit game): 0
```

## C#

`// 21 Game  using System; namespace _21Game{    public class Program    {        private const string computerPlayer = "Computer";        private const string humanPlayer = "Player 1";         public static string SwapPlayer(string currentPlayer)        {            if (currentPlayer == computerPlayer)            {                currentPlayer = humanPlayer;            }            else            {                currentPlayer = computerPlayer;            }             return currentPlayer;        }         public static void PlayGame()        {            bool playAnother = true;            int total = 0;            int final = 21;            int roundChoice = 0;            string currentPlayer = RandomPLayerSelect();            int compWins = 0;            int humanWins = 0;             while (playAnother)            {                Console.WriteLine(\$"Now playing: {currentPlayer}");                try                {                    if (currentPlayer == computerPlayer)                    {                       roundChoice =  CompMove(total);                    }                    else                    {                        roundChoice = int.Parse(Console.ReadLine());                    }                      if (roundChoice != 1 && roundChoice != 2 && roundChoice != 3)                    {                        throw new Exception();                    }                     total += roundChoice;                }                catch (Exception)                {                    Console.WriteLine("Invalid choice! Choose from numbers: 1, 2, 3.");                    continue;                }                 Console.WriteLine(total);                 if (total == final)                {                    if (currentPlayer == computerPlayer)                    {                        compWins++;                    }                    if (currentPlayer == humanPlayer)                    {                        humanWins++;                    }                    Console.WriteLine(\$"Winner: {currentPlayer}");                    Console.WriteLine(\$"Comp wins: {compWins}. Human wins: {humanWins}");                    Console.WriteLine(\$"do you wan to play another round? y/n");                    var choice = Console.ReadLine();                    if (choice == "y")                    {                        total = 0;                    }                    else if (choice == "n")                    {                        break;                    }                    else                    {                        Console.WriteLine("Invalid choice! Choose from y or n");                        continue;                    }                }                 else if (total > 21)                {                    Console.WriteLine("Not the right time to play this game :)");                    break;                }                 currentPlayer = SwapPlayer(currentPlayer);            }        }         public static bool CheckIfCanWin(int total)        {            bool result = false;            if (total == 18)            {                result = true;            }            return result;        }         public static int CompMove(int total)        {            int choice = 0;             if (CheckIfCanWin(total))            {                choice = 21 - total;            }            else            {                choice = new Random().Next(1,4);            }             return choice;        }         public static string RandomPLayerSelect()        {            string[] players = new string[] { computerPlayer, humanPlayer };            var random = new Random().Next(0,2);            return players[random];        }         public static void Main(string[] args)        {            // welcome message and rules            Console.WriteLine("Welcome to 21 game \n");            Console.WriteLine(@"21 is a two player game. The game is played by choosing a number.1, 2, or 3 to be added a total sum. \nThe game is won by the player reaches exactly 21. \n" );                        Console.WriteLine("Choose your number: (1, 2 or 3)");             PlayGame();        }    }}   `

## Commodore BASIC

Written for BASIC v2 on the Commodore 64, this should be mostly compatible with all Commodore machines running any version of BASIC v2 and above. This implementation allows for one or both players to be either human or computer players. Also note that the computer player's "Thinking..." routine is a purely random delay meant to allow any human user time to process the flow of the game.

`1 rem 21 game2 rem for rosetta code 3 rem initialization4 l\$=chr\$(157):rem left cursor5 dim p\$(2),hc(2),ca(4):hc(1)=0:hc(2)=0:rem players6 ca(0)=1:ca(1)=1:ca(2)=3:ca(3)=2:rem computer answers7 dim cn\$(6):for i=1 to 6:read cn\$(i):next:rem computer names8 def fn m(x)=(x-(int(x/4))*4):rem modulo function 10 rem optionally set screen colors here20 print chr\$(147);chr\$(14):print spc(16);"21 GAME"25 print:print " The goal of this game is to take turns"26 print " adding the value of either 1, 2, or 3"27 print " to a running total. The first player"28 print " to bring the total to 21..."29 print:print spc(10);"... WINS THE GAME!"30 print:gosub 100035 print chr\$(147):for p=1 to 2 40 rem game setup and get players42 for p=1 to 244 print:print "Player";p;l\$;", [H]uman or [C]omputer? ";45 get k\$:if k\$<>"c" and k\$<>"h" then 4546 print k\$:hc(p)=(k\$="c")50 print:print"Player";p;l\$",":print"Enter your name";:if hc(p)then goto5452 input p\$(p):next p:goto 6054 gosub 1500:print "? ";p\$(p):next p60 print:for p=1 to 2:print p;l\$;". ";p\$(p):next65 print:print "Is this correct (y/n)? ";70 get k\$:if k\$<>"y" and k\$<>"n" then 7075 print k\$:if k\$="n" then goto 3580 print:print "Who will play first (1 or 2)? ";85 get k\$:if k\$<"1" or k\$>"2" then 8590 fp=asc(k\$)-48:print k\$:print95 print "Okay, ";p\$(fp);" will play first.":print:gosub 1000 100 rem start main game loop105 pi=fp:rt=0110 print chr\$(147);"Total so far:";rt115 print:print p\$(pi);"'s turn."120 if hc(pi) then gosub 1200125 if not hc(pi) then gosub 1100130 rt=rt+ad135 if rt=21 then goto 200140 if rt>21 then print:print p\$(pi);" loses by going over 21!!":goto 210145 pi=pi+1:if pi>2 then pi=1150 goto 110 200 rem winner winner chicken dinner205 print:print "21! ";p\$(pi);" wins the game!!!"210 print:print "Would you like to play again? ";215 get k\$:if k\$<>"n" and k\$<>"y" then 215220 print k\$225 if k\$="n" then print:print "Okay, maybe another time. Bye!":end230 goto 10 1000 rem pause for keypress1010 z\$=" Press a key to continue. "1015 print spc(20-int(len(z\$)/2));1016 print chr\$(18);z\$;chr\$(146)1020 get k\$:if k\$="" then 10201025 return 1100 rem human player move1105 print:print "How much to add,"1110 print "1, 2, or 3 (0 to quit)";:input ad1115 if ad<0 or ad>3 then print:print"Illegal amount. Try again.":goto11051120 if ad=0 then print:print "Game was ended by ";p\$(pi);".":end1125 return 1200 rem computer player move1205 print:print "Thinking...";1210 tt=int(rnd(1)*10)1215 for t=1 to tt:print ".";:for i=1 to 250:next i,t:print1220 rm=fn m(rt)1225 ad=ca(rm)1230 print:print p\$(pi);" adds";ca(rm);l\$;"."1235 for t=1 to 1000:next t1240 return 1500 rem pick a computer name1505 pn=int(rnd(1)*6)+1:t\$=cn\$(pn)1510 if t\$=p\$(p-1) then goto 15051515 p\$(p)=t\$1520 return 2000 rem some computer names to pick from2010 data "Commodore 64","VIC-20","Commodore 128","PET"2020 data "Plus/4","Commodore 16"`
Output:
```                21 GAME

The goal of this game is to take turns
adding the value of either 1, 2, or 3
to a running total. The first player
to bring the total to 21...

... WINS THE GAME!

Press a key to continue.

Player 1, [H]uman or [C]omputer? h

Player 1,

Player 2, [H]uman or [C]omputer? c

Player 2,

1. Mike
2. Commodore 64

Is this correct (y/n)? y

Who will play first (1 or 2)? 1

Okay, Mike will play first.

Press a key to continue.

Total so far: 0

Mike's turn.

1, 2, or 3 (0 to quit)? 1

Total so far: 1

Commodore 64's turn.

Thinking..........

Total so far: 2

Mike's turn.

1, 2, or 3 (0 to quit)? 3

Total so far: 5

Commodore 64's turn.

Thinking..........

...[LATER IN THE GAME]...

Total so far: 17

Commodore 64's turn.

Thinking.........

Total so far: 18

Mike's turn.

1, 2, or 3 (0 to quit)? 3

21! Mike wins the game!!!

Would you like to play again? n

Okay, maybe another time. Bye!

█
```

See Pascal

## EasyLang

The computer plays optimally

`print "Who reaches 21, wins"print "Do you want to begin (y/n)"if input = "n"  who = 1.who\$[] = [ "Human" "Computer" ]repeat  if who = 0    repeat      print ""      print "Choose 1,2 or 3 (q for quit)"      a\$ = input      n = number a\$      until a\$ = "q" or (n >= 1 and n <= 3)    .  else    sleep 1    if sum mod 4 = 1      n = random 3 + 1    else      n = 4 - (sum + 3) mod 4    .  .  sum += n  print who\$[who] & ": " & n & " --> " & sum  until sum >= 21 or a\$ = "q"  who = (who + 1) mod 2.if a\$ <> "q"  print ""  if who = 0    print "Congratulation, you won"  else    print "Sorry, you lost"  ..`

## Factor

A difficulty system has been implemented. The player chooses a difficulty from 1-10. There is a `difficulty in 10` chance that the computer opponent gets to move first. There is a `difficulty in 10` chance each turn that the computer opponent will make the optimal move (i.e. setting the total to a number of the form `4n+1`) as opposed to a random move. At difficulty level 10, it is impossible for the human player to win the game.

Works with: Factor version 0.99 2020-07-03
`USING: accessors combinators.random continuations formatting iokernel math math.functions math.parser multiline qw randomsequences ;IN: rosetta-code.21-game STRING: welcome21 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 by the player whose chosen number causes therunning total to reach 21. One player will be the computer. Players alternate supplying anumber to be added to the running total.; : .welcome ( -- ) welcome print ; SYMBOLS: +computer+ +human+ ; TUPLE: game total difficulty who ; ! Instead of saying something dry like 'invalid input,' spice! it up a little.: insult ( -- )    {        "No." "Er..." "Learn to read." "I think not."        "Come on, is it really this difficult?"    } random print ; : get-input ( options-seq prompt-str -- str )    dup "%s: " printf flush readln dup reach member?    [ 2nip ] [ drop insult get-input ] if ; : get-integer ( options-seq prompt-str -- n )    get-input string>number ; : get-difficulty ( -- x )    qw{ 1 2 3 4 5 6 7 8 9 10 }    "Difficulty (1-10)" get-integer 10 / ; : human-move ( game -- n )    drop qw{ q 1 2 3 } "Your move (1-3) or q to quit" get-input    dup "q" = [ drop return ] when string>number ; : choose-first-player ( difficulty -- player )    [ +computer+ ] [ +human+ ] ifp ; : <game> ( -- game )    0 get-difficulty dup choose-first-player game boa ; : swap-player ( game -- )    [ +human+ = +computer+ +human+ ? ] change-who drop ; : .total ( game -- ) total>> "Running total: %d\n" printf ; : random-move ( game -- n ) drop 3 random 1 + ; : boundary? ( n -- ? ) 1 - 4 divisor? ; : (optimal-move) ( m -- n ) dup 4 / ceiling 4 * 1 + swap - ; : optimal-move ( game -- n )    total>> dup boundary? [ random-move ] [ (optimal-move) ] if ; : computer-move ( game -- n )    dup difficulty>> [ optimal-move ] [ random-move ] ifp    dup "Computer chose %d.\n" printf ; : do-turn ( game -- )    dup dup who>> +human+ = [ human-move ] [ computer-move ] if    [ + ] curry change-total dup .total swap-player ; : do-turns ( game -- )    [ dup total>> 20 > ] [ dup do-turn ] until    dup swap-player who>> "%u wins!\n" printf ; : play-21-game ( -- )    .welcome nl [ <game> do-turns ] with-return ; MAIN: play-21-game`
Output:
```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 by the player whose chosen number causes the
running total to reach 21.

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

Difficulty (1-10): 3
Your move (1-3) or q to quit: 3
Running total: 3
Computer chose 2.
Running total: 5
Your move (1-3) or q to quit: 2
Running total: 7
Computer chose 2.
Running total: 9
Your move (1-3) or q to quit: 1
Running total: 10
Computer chose 3.
Running total: 13
Your move (1-3) or q to quit: apple
Er...
Your move (1-3) or q to quit: 3
Running total: 16
Computer chose 1.
Running total: 17
Your move (1-3) or q to quit: 1
Running total: 18
Computer chose 1.
Running total: 19
Your move (1-3) or q to quit: 2
Running total: 21
+human+ wins!
```

## Fortran

`! game 21 - an example in modern fortran language for rosseta code. subroutine ai  common itotal, igoal  if (itotal .lt. igoal) then    move = 1    do i = 1, 3      if (mod(itotal + i - 1 , 4) .eq. 0) then        move = i      end if    end do    do i = 1, 3      if (itotal + i .eq. igoal) then        move = i      end if    end do    print *, "      ai  ", itotal + move, " = ", itotal, " + ", move    itotal = itotal + move    if (itotal .eq. igoal) then      print *, ""      print *, "the winner is ai"      print *, ""    end if  end ifend subroutine ai subroutine human  common itotal, igoal  print *, ""  do while (.true.)    if (itotal + 1 .eq. igoal) then      print *, "enter 1 (or 0 to exit): "    else if (itotal + 2 .eq. igoal) then      print *, "enter 1 or 2 (or 0 to exit): "    else      print *, "enter 1 or 2 or 3 (or 0 to exit)"    end if    read(*,*) move    if (move .eq. 0) then      stop    else if (move .ge. 1 .and. move .le. 3 .and. move + itotal .le. igoal) then      print *, "   human  ", itotal + move, " = ", itotal, " + ", move      itotal = itotal + move      if (itotal .eq. igoal) then        print *, ""        print *, "the winner is human"        print *, ""      end if      return    else      print *, "a bad choice"    end if  end doend subroutine human program main  common itotal, igoal  print *,"game 21 - an example in fortran iv language for rosseta code."  print *,""  print *,"21 is a two player game, the game is played by choosing a number"  print *,"(1, 2, or 3) to be added to the running total. the game is won"  print *,"by the player whose chosen number causes the running total to reach"  print *,"exactly 21. the running total starts at zero."  print *,""  i = irand(1)  igoal = 21  do while(.true.)    print *, "---- new game ----"    print *, ""    print *, "the running total is currently zero."    print *, ""    itotal = 0    if (mod(irand(0), 2) .eq. 0) then      print *, "the first move is ai move."      call ai    else      print *, "the first move is human move."    end if    print *, ""    do while(itotal .lt. igoal)      call human      call ai    end doend doend program main`
Output:
```game 21 - an example in fortran language for rosseta code.

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
by the player whose chosen number causes the running total to reach
exactly 21. the running total starts at zero.

---- new game ----

the running total is currently zero.

the first move is human move.

enter 1 or 2 or 3 (or 0 to exit)
1
human             1  =            0  +            1
ai             2  =            1  +            1

enter 1 or 2 or 3 (or 0 to exit)
3
human             5  =            2  +            3
ai             6  =            5  +            1

enter 1 or 2 or 3 (or 0 to exit)
4
enter 1 or 2 or 3 (or 0 to exit)
3
human             9  =            6  +            3
ai            10  =            9  +            1

enter 1 or 2 or 3 (or 0 to exit)
2
human            12  =           10  +            2
ai            13  =           12  +            1

enter 1 or 2 or 3 (or 0 to exit)
3
human            16  =           13  +            3
ai            17  =           16  +            1

enter 1 or 2 or 3 (or 0 to exit)
2
human            19  =           17  +            2
ai            21  =           19  +            2

the winner is ai

---- new game ----

the running total is currently zero.

the first move is human move.

enter 1 or 2 or 3 (or 0 to exit)
0```

## FreeBASIC

`#define PLAYER 1#define COMP   0randomize timer dim as uinteger sum, add = 0dim as uinteger turn = int(rnd+0.5)dim as uinteger precomp(0 to 3) = { 1, 1, 3, 2 }  while sum < 21:    turn = 1 - turn    print using "The sum is ##"; sum    if turn = PLAYER then        print "It is your turn."        while add < 1 orelse add > 3 orelse add+sum > 21            input "How many would you like to add? ", add        wend    else        print "It is the computer's turn."        add = precomp(sum mod 4)        print using "The computer adds #."; add    end if    print    sum = sum + add    add = 0wend if turn = PLAYER then    print "Congratulations. You win."else    print "Bad luck. The computer wins."end if`

## Gambas

` ' Gambas module file Private gameConunt As Integer = 0Private numRound As Integer = 1Private winPlayer As Integer = 0Private winComputer As Integer = 0  Public Sub Main()   Dim entra As String   Print "Enter q to quit at any time\nThe computer will choose first"   While gameConunt < 21    Print "ROUND: " & numRound & "\n"    gameConunt += selectCount(gameConunt)    Print Subst("Running total is now &1 \n ", gameConunt)    If gameConunt = 21 Then      Inc winComputer      Print "The computer has won !\n"      endGame()    Endif    gameConunt += humanCount(gameConunt)    Print Subst("Running total is now &1", gameConunt)    If gameConunt = 21 Then      Inc winPlayer      Print "Congratulations! You've won!\n"      endGame()    Endif    Inc numRound  Wend End Private Function selectCount(cou As Integer) As Integer   Dim a As Integer   Randomize   If cou < 18 Then    a = Int(Rnd(1, 4))  Else    a = 21 - cou  Endif   Print "The computer choose " & a   Return a End Private Function humanCount(cou As Integer) As Integer   Dim entra As String  Dim a As Integer   While True    Print "Your choice 1 to 3"    Input entra    If entra = "q" Then      Print "Good Bye!"      Quit    Endif    Try a = CInt(entra)    If Error Then      Print "Invalid entry, try again"      Continue    Endif    If a < 1 Or a > 3 Then      Print "Out of range, try again"      Continue    Endif    If a + cou > 21 Then      Print "The sum is greater than 21, try again"      Continue    Endif        Return a  Wend End  Private Sub endGame()   Dim entra As String   Print Subst("Computer wins &1 games, human wins &2 games", winComputer, winPlayer)  Print "\nPlay again? (y/n)"  Input entra  If entra = "y" Or entra = "Y" Then    numRound = 1    gameConunt = 0    Print "Enter q to quit at any time\nThe computer will choose first"  Else    Print "Good Bye!"    Quit  Endif End`
```Enter q to quit at any time
The computer will choose first
ROUND: 1

The computer choose 2
Running total is now 2

4
Out of range, try again
0
Out of range, try again
g
Invalid entry, try again
1
Running total is now 3
ROUND: 2

The computer choose 2
Running total is now 5

3
Running total is now 8
ROUND: 3

The computer choose 2
Running total is now 10

3
Running total is now 13
ROUND: 4

The computer choose 2
Running total is now 15

3
Running total is now 18
ROUND: 5

The computer choose 3
Running total is now 21

The computer has won !

computer wins 1 games, human wins 0 games

Play again? (y/n)

Good Bye!
```

## Go

To give the human player a reasonable chance whoever goes first, the computer always chooses randomly when the running total is below 18 but otherwise chooses the exact number needed to win the game.

`package main import (    "bufio"    "fmt"    "log"    "math/rand"    "os"    "strconv"    "time") var scanner = bufio.NewScanner(os.Stdin) var (    total = 0    quit  = false) func itob(i int) bool {    if i == 0 {        return false    }    return true} func getChoice() {    for {        fmt.Print("Your choice 1 to 3 : ")        scanner.Scan()        if scerr := scanner.Err(); scerr != nil {            log.Fatalln(scerr, "when choosing number")        }        text := scanner.Text()        if text == "q" || text == "Q" {            quit = true            return        }        input, err := strconv.Atoi(text)        if err != nil {            fmt.Println("Invalid number, try again")            continue        }        newTotal := total + input        switch {        case input < 1 || input > 3:            fmt.Println("Out of range, try again")        case newTotal > 21:            fmt.Println("Too big, try again")        default:            total = newTotal            fmt.Println("Running total is now", total)            return        }    }} func main() {    rand.Seed(time.Now().UnixNano())    computer := itob(rand.Intn(2))    fmt.Println("Enter q to quit at any time\n")    if computer {        fmt.Println("The computer will choose first")    } else {        fmt.Println("You will choose first")    }    fmt.Println("\nRunning total is now 0\n")    var choice int    for round := 1; ; round++ {        fmt.Printf("ROUND %d:\n\n", round)        for i := 0; i < 2; i++ {            if computer {                if total < 18 {                    choice = 1 + rand.Intn(3)                } else {                    choice = 21 - total                }                total += choice                fmt.Println("The computer chooses", choice)                fmt.Println("Running total is now", total)                if total == 21 {                    fmt.Println("\nSo, commiserations, the computer has won!")                    return                }            } else {                getChoice()                if quit {                    fmt.Println("OK, quitting the game")                    return                }                if total == 21 {                    fmt.Println("\nSo, congratulations, you've won!")                    return                }            }            fmt.Println()            computer = !computer        }    }}`
Output:

A sample game where the human player manages to win even though the computer (chosen randomly) goes first.

```Enter q to quit at any time

The computer will choose first

Running total is now 0

ROUND 1:

The computer chooses 1
Running total is now 1

Your choice 1 to 3 : 3
Running total is now 4

ROUND 2:

The computer chooses 2
Running total is now 6

Your choice 1 to 3 : 4
Out of range, try again
Your choice 1 to 3 : 3
Running total is now 9

ROUND 3:

The computer chooses 2
Running total is now 11

Your choice 1 to 3 : 2
Running total is now 13

ROUND 4:

The computer chooses 2
Running total is now 15

Your choice 1 to 3 : 2
Running total is now 17

ROUND 5:

The computer chooses 1
Running total is now 18

Your choice 1 to 3 : 3
Running total is now 21

So, congratulations, you've won!
```

A sample game where the human player plays sensibly but still loses when the computer goes first.

```Enter q to quit at any time

The computer will choose first

Running total is now 0

ROUND 1:

The computer chooses 3
Running total is now 3

Your choice 1 to 3 : 3
Running total is now 6

ROUND 2:

The computer chooses 3
Running total is now 9

Your choice 1 to 3 : 3
Running total is now 12

ROUND 3:

The computer chooses 1
Running total is now 13

Your choice 1 to 3 : 3
Running total is now 16

ROUND 4:

The computer chooses 1
Running total is now 17

Your choice 1 to 3 : 1
Running total is now 18

ROUND 5:

The computer chooses 3
Running total is now 21

So, commiserations, the computer has won!
```

The computer chooses values randomly.

`import System.Randomimport System.IOimport System.Exitimport Control.Monadimport Text.Readimport Data.Maybe promptAgain :: IO IntpromptAgain = do  putStrLn "Invalid input - must be a number among 1,2 or 3. Try again."  playerMove playerMove :: IO IntplayerMove = do  putStr "Your choice(1 to 3):"  number <- getLine  when (number == "q") \$ do    exitWith ExitSuccess  let n = readMaybe number :: Maybe Int  x <- if isNothing n             then promptAgain             else let val = read number                   in if (val > 3 || val < 1)                      then promptAgain                      else return val  return x computerMove :: IO IntcomputerMove = do  x <- randomRIO (1, 3)  putStrLn \$ "Computer move:" ++ (show x)  return x gameLoop :: (IO Int, IO Int) -> IO IntgameLoop moveorder = loop moveorder 0  where loop moveorder total = do        number <- fst moveorder        let total1 = number + total        putStrLn \$ "Running total:" ++ (show total1)        if total1 >= 21           then return 0           else do             number <- snd moveorder             let total2 = number + total1             putStrLn \$ "Running total:" ++ (show total2)             if total2 >= 21                then return 1                else loop moveorder total2 main :: IO ()main = do  hSetBuffering stdout \$ BlockBuffering \$ Just 1  putStrLn "Enter q to quit at any time"  x <- randomRIO (0, 1) :: IO Int  let (moveorder, names) = if x == 0                 then ((playerMove, computerMove), ("Player", "Computer"))                 else ((computerMove, playerMove), ("Computer", "Player"))  when (x == 1) \$ do    putStrLn "Computer will start the game"  y <- gameLoop moveorder  when (y == 0) \$ do    putStrLn \$ (fst names) ++ " has won the game"  when (y == 1) \$ do    putStrLn \$ (snd names) ++ " has won the game"`

## J

The main definition g21 starts the game. J doesn't support niladic verbs. Although the y argument has no effect, it must be given. The empty literal vector '' types quickly, hence often used to trigger niladic verbs. g21 does not superfluously penalize final sums exceeding 21.

` g21=: [email protected]@setup ::('g21: error termination'"_) NB. non-verb must be defined before use, otherwise are assumed verbs.Until=: 2 :'u^:(0-:v)^:_' t=: 'score turn choice'(t)=: i. # ;: tempty erase't' Fetch=: &{Alter=: } play=: move Until donedone=: 21 <: score Fetchmove=: [: update you`[email protected](turn Fetch) update=: [email protected]@addadd=: score Alter~ (score Fetch + choice Fetch)display=: [ ([: echo 'sum: {}' format~ score Fetch)swap=: turn Alter~ ([: -. turn Fetch) it=: ([ [: echo 'It chose {}.' format~ choice Fetch)@(choice Alter~ cb)cb=: (1:`r`3:`2:)@.(4 | score Fetch)     NB. computer brainr=: 3 :'>:?3' you=: [email protected]@[email protected]prompt=: [ ([: echo 'your choice?'"_)acquire=: choice Alter~ ('123' i. 0 { ' ' ,~ read)check=: (choice Alter~ (665 - score Fetch))@([ ([: echo 'g21: early termination'"_))^:(3 = choice Fetch)qio1=: choice Alter~ ([: >: choice Fetch) setup=: ([ [: echo 'On your turn enter 1 2 or 3, other entries exit'"_)@((3 :'?2') turn Alter ])@0 0 0"_  NB. choose first player randomlysummarize=: ' won' ,~  (];._2 'it you ') {~ turn Fetch read=: 1!:1@:1:write=: 1!:2 4: NB. unusedformat=: ''&\$: :([: ; (a: , [: ":&.> [) ,. '{}' ([ (E. <@}.;._1 ]) ,) ]) `
```   g21''
On your turn enter 1 2 or 3, other entries exit
It chose 1.
sum: 1
q
g21: early termination
sum: 666
you won

g21''
On your turn enter 1 2 or 3, other entries exit
2
sum: 2
It chose 3.
sum: 5
1
sum: 6
It chose 3.
sum: 9
2
sum: 11
It chose 2.
sum: 13
3
sum: 16
It chose 1.
sum: 17
1
sum: 18
It chose 3.
sum: 21
it  won
```

## Java

Options for creating a game:

1. Who goes first on the first game. Thereafter, the winner of the current game goes first on the next game.
2. The value needed to win the game.
3. Valid values allowed to select on each turn.

Sample output provided for options as follows:

1. Computer goes first on the first game.
2. Value needed to win game is 21.
3. Valid values to select is 1, 2, or 3.

The computer strategy is to see if a valid value will win the game. If so, that value is selected. Otherwise, a random value among the valid values is selected.

` import java.util.Random;import java.util.Scanner; public class TwentyOneGame {     public static void main(String[] args) {        new TwentyOneGame().run(true, 21, new int[] {1, 2, 3});    }     public void run(boolean computerPlay, int max, int[] valid) {        String comma = "";        for ( int i = 0 ; i < valid.length ; i++ ) {            comma += valid[i];            if ( i < valid.length - 2 && valid.length >= 3 ) {                comma += ", ";            }            if ( i == valid.length - 2 ) {                comma += " or ";            }        }        System.out.printf("The %d game.%nEach player chooses to add %s to a running total.%n" +                 "The player whose turn it is when the total reaches %d will win the game.%n" +                 "Winner of the game starts the next game.  Enter q to quit.%n%n", max, comma, max);        int cGames = 0;        int hGames = 0;        boolean anotherGame = true;        try (Scanner scanner = new Scanner(System.in);) {            while ( anotherGame ) {                Random r = new Random();                int round = 0;                int total = 0;                System.out.printf("Start game %d%n", hGames + cGames + 1);                DONE:                    while ( true ) {                        round++;                        System.out.printf("ROUND %d:%n%n", round);                        for ( int play = 0 ; play < 2 ; play++ ) {                            if ( computerPlay ) {                                int guess = 0;                                //  try find one equal                                for ( int test : valid ) {                                    if ( total + test == max ) {                                        guess = test;                                        break;                                    }                                }                                //  try find one greater than                                if ( guess == 0 ) {                                    for ( int test : valid ) {                                        if ( total + test >= max ) {                                            guess = test;                                            break;                                        }                                    }                                }                                if ( guess == 0 ) {                                    guess = valid[r.nextInt(valid.length)];                                }                                total += guess;                                System.out.printf("The computer chooses %d%n", guess);                                System.out.printf("Running total is now %d%n%n", total);                                if ( total >= max ) {                                    break DONE;                                }                            }                            else {                                while ( true ) {                                    System.out.printf("Your choice among %s: ", comma);                                    String line = scanner.nextLine();                                    if ( line.matches("^[qQ].*") ) {                                        System.out.printf("Computer wins %d game%s, human wins %d game%s.  One game incomplete.%nQuitting.%n", cGames, cGames == 1 ? "" : "s", hGames, hGames == 1 ? "" : "s");                                        return;                                    }                                    try {                                        int input = Integer.parseInt(line);                                        boolean inputOk = false;                                        for ( int test : valid ) {                                            if ( input == test ) {                                                inputOk = true;                                                break;                                            }                                        }                                        if ( inputOk ) {                                            total += input;                                            System.out.printf("Running total is now %d%n%n", total);                                            if ( total >= max ) {                                                break DONE;                                            }                                            break;                                        }                                        else {                                            System.out.printf("Invalid input - must be a number among %s.  Try again.%n", comma);                                        }                                    }                                    catch (NumberFormatException e) {                                        System.out.printf("Invalid input - must be a number among %s.  Try again.%n", comma);                                    }                                }                            }                            computerPlay = !computerPlay;                        }                    }                String win;                if ( computerPlay ) {                    win = "Computer wins!!";                    cGames++;                }                else {                    win = "You win and probably had help from another computer!!";                    hGames++;                }                System.out.printf("%s%n", win);                System.out.printf("Computer wins %d game%s, human wins %d game%s%n%n", cGames, cGames == 1 ? "" : "s", hGames, hGames == 1 ? "" : "s");                while ( true ) {                    System.out.printf("Another game (y/n)? ");                    String line = scanner.nextLine();                    if ( line.matches("^[yY]\$") ) {                        //  OK                        System.out.printf("%n");                        break;                    }                    else if ( line.matches("^[nN]\$") ) {                        anotherGame = false;                        System.out.printf("Quitting.%n");                        break;                    }                    else {                        System.out.printf("Invalid input - must be a y or n.  Try again.%n");                    }                }            }        }    } } `
Output:

A sample of 3 games.

```The 21 game.
Each player chooses to add 1, 2 or 3 to a running total.
The player whose turn it is when the total reaches 21 will win the game.
Winner of the game starts the next game.  Enter q to quit.

Start game 1
ROUND 1:

The computer chooses 3
Running total is now 3

Your choice among 1, 2 or 3: 4
Invalid input - must be a number among 1, 2 or 3.  Try again.
Your choice among 1, 2 or 3: r
Invalid input - must be a number among 1, 2 or 3.  Try again.
Your choice among 1, 2 or 3: 1
Running total is now 4

ROUND 2:

The computer chooses 1
Running total is now 5

Your choice among 1, 2 or 3: 3
Running total is now 8

ROUND 3:

The computer chooses 1
Running total is now 9

Your choice among 1, 2 or 3: 3
Running total is now 12

ROUND 4:

The computer chooses 3
Running total is now 15

Your choice among 1, 2 or 3: 2
Running total is now 17

ROUND 5:

The computer chooses 3
Running total is now 20

Your choice among 1, 2 or 3: 1
Running total is now 21

You win and probably had help from another computer!!
Computer wins 0 games, human wins 1 game

Another game (y/n)? y

Start game 2
ROUND 1:

Your choice among 1, 2 or 3: 3
Running total is now 3

The computer chooses 1
Running total is now 4

ROUND 2:

Your choice among 1, 2 or 3: 3
Running total is now 7

The computer chooses 3
Running total is now 10

ROUND 3:

Your choice among 1, 2 or 3: 3
Running total is now 13

The computer chooses 2
Running total is now 15

ROUND 4:

Your choice among 1, 2 or 3: 2
Running total is now 17

The computer chooses 1
Running total is now 18

ROUND 5:

Your choice among 1, 2 or 3: 3
Running total is now 21

You win and probably had help from another computer!!
Computer wins 0 games, human wins 2 games

Another game (y/n)? y

Start game 3
ROUND 1:

Your choice among 1, 2 or 3: 3
Running total is now 3

The computer chooses 3
Running total is now 6

ROUND 2:

Your choice among 1, 2 or 3: 3
Running total is now 9

The computer chooses 2
Running total is now 11

ROUND 3:

Your choice among 1, 2 or 3: 3
Running total is now 14

The computer chooses 2
Running total is now 16

ROUND 4:

Your choice among 1, 2 or 3: 3
Running total is now 19

The computer chooses 2
Running total is now 21

Computer wins!!
Computer wins 1 game, human wins 2 games

Another game (y/n)? n
Quitting.
```

## JavaScript

The solution as a Javascript script inside a page written in HTML5. It should work with all modern browsers.

`<!DOCTYPE html><html lang="en"> <head>    <meta charset="UTF-8">    <meta name="keywords"    content="Game 21">    <meta name="description" content="      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 by      the player whose chosen number causes the running total to reach      exactly 21. The running total starts at zero.    ">    <!--DCMI metadata (Dublin Core Metadata Initiative)-->    <meta name="dc.publisher" content="Rosseta Code">    <meta name="dc.date"      content="2020-07-23">    <meta name="dc.created"   content="2020-07-23">    <meta name="dc.modified"  content="2020-07-30">    <title>        21 Game    </title>    <!-- Remove the line below in the final/production version. -->    <meta http-equiv="cache-control" content="no-cache">     <style>      .ui div   { width: 50%; display: inline-flex; justify-content: flex-end; }      div.total { margin-bottom: 1ch; }      label     { padding-right: 1ch; }      button + button { margin-left: 1em; }    </style></head> <body>  <h1>    21 Game in ECMA Script (Java Script)  </h1>   <p>    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 by    the player whose chosen number causes the running total to reach    exactly 21. The running total starts at zero.  </p>   <p><span id="first"></span> Use buttons to play.</p>   <div class="ui">    <div class="total">      <label for="human">human last choice:</label>      <input type="text" id="human" readonly>    </div>    <div class="total">      <label for="AI">AI last choice:</label>      <input type="text" id="AI" readonly>    </div>    <div class="total">      <label for="runningTotalText">running total:</label>      <input type="text" id="runningTotalText" readonly>    </div>    <div class="buttons">      <button onclick="choice(1);" id="choice1"> one   </button>      <button onclick="choice(2);" id="choice2"> two   </button>      <button onclick="choice(3);" id="choice3"> three </button>      <button onclick="restart();"> restart </button>    </div>  </div>   <p id="message"></p>   <noscript>    No script, no fun. Turn on Javascript on.  </noscript>   <script>    // I really dislike global variables, but in any (?) WWW browser the global    // variables are in the window (separately for each tab) context space.    //    var runningTotal = 0;    const human = document.getElementById('human');    const AI = document.getElementById('AI');    const runningTotalText = document.getElementById('runningTotalText');    const first = document.getElementById('first')    const message = document.getElementById('message');    const choiceButtons = new Array(3);     // An function to restart game in any time, should be called as a callback    // from the WWW page, see above for an example.    //    function restart()    {      runningTotal = 0;      runningTotalText.value = runningTotal;      human.value = '';      AI.value = '';      for (let i = 1; i <= 3; i++)      {        let button = document.getElementById('choice' + i);        button.disabled = false;        choiceButtons[i] = button;      }      message.innerText = '';      if (Math.random() > 0.5)      {        update(AI, ai());        first.innerText = 'The first move is AI move.'      }      else        first.innerText = 'The first move is human move.'    }     // This function update an (read-only for a user) two text boxes    // as well as runningTotal. It should be called only once per a move/turn.    //    function update(textBox, n)    {      textBox.value = n;      runningTotal = runningTotal + n;      runningTotalText.value = runningTotal;      for (let i = 1; i <= 3; i++)        if (runningTotal + i > 21)          choiceButtons[i].disabled = true;    }     // An callback function called when the human player click the button.    //    function choice(n)    {      update(human, n);      if (runningTotal == 21)        message.innerText = 'The winner is human.';      else      {        update(AI, ai());        if (runningTotal == 21)          message.innerText = 'The winner is AI.';      }    }     // A rather simple function to calculate a computer move for the given total.    //    function ai()    {      for (let i = 1; i <= 3; i++)        if (runningTotal + i == 21)          return i;       for (let i = 1; i <= 3; i++)        if ((runningTotal + i - 1) % 4 == 0)          return i;       return 1;    }     // Run the script - actually this part do only some initialization, because    // the game is interactively driven by events from an UI written in HTML.    //    restart();  </script> </body></html>`

## Julia

The computer or player can always win if they go first and choose a number that brings the total to one of the following: 1, 5, 9, 13, or 17. To make things vary more, there is a choice of computer play level at the start. The computer will randomly respond with level 1 and choose a random response 1/4 of the time at level 2.

` function trytowin(n)    if 21 - n < 4        println("Computer chooses \$(21 - n) and wins. GG!")        exit(0)    endend function choosewisely(n)    trytowin(n)    targets = [1, 5, 9, 13, 17, 21]    pos = findfirst(x -> x > n, targets)    bestmove = targets[pos] - n    if bestmove > 3        println("Looks like I could lose. Choosing a 1, total now \$(n + 1).")        return n + 1    end    println("On a roll, choosing a \$bestmove, total now \$(n + bestmove).")    n + bestmoveend function choosefoolishly(n)    trytowin(n)    move = rand([1, 2, 3])    println("Here goes, choosing \$move, total now \$(n + move).")    n + moveend function choosesemiwisely(n)    trytowin(n)    if rand() > 0.75        choosefoolishly(n)    else        choosewisely(n)    endend prompt(s) = (println(s, ": => "); return readline()) function playermove(n)    rang = (n > 19) ? "1 is all" : ((n > 18) ? "1 or 2" : "1, 2 or 3")    choice = 0    while true        nstr = prompt("Your choice (\$rang), 0 to exit")        if nstr == "0"            exit(0)        elseif nstr == "1"            return n + 1        elseif nstr == "2" && n < 20            return n + 2        elseif nstr == "3" && n < 19            return n + 3        end    endend  function play21game()    n = 0    level = prompt("Level of play (1=dumb, 3=smart)")    algo = choosewisely    if level == "1"        algo = choosefoolishly    elseif level == "2"        algo = choosesemiwisely    elseif level != "3"        println("Bad choice syntax--default to smart choice")    end    whofirst = prompt("Does computer go first? (y or n)")    if whofirst == 'y' || whofirst == 'Y'        n = algo(n)    end    while n < 21        n = playermove(n)        if n == 21            println("Player wins! Game over, gg!")            break        end        n = algo(n)    endend play21game() `

## Lua

` gamewon = falserunning_total = 0player = 1opponent = 2 while not gamewon do  num = 0   if player == 1 then    opponent = 2    repeat      print("Enter a number between 1 and 3 (0 to quit):")      num = io.read("*n")      if num == 0 then          os.exit()      end    until (num > 0) and (num <=3)  end   if player == 2 and not (gamewon) then      opponent = 1      if (21 - running_total <= 3) then        num = 21 - running_total      else        num = math.random(1,3)      end      print("Player 2 picks number "..num)  end   running_total = running_total + num  print("Total: "..running_total)   if running_total == 21 then    print("Player "..player.." wins!")    gamewon = true  end   if running_total > 21 then    print("Player "..player.." lost...")    print("Player "..opponent.." wins!")    gamewon = true  end   if player == 1 then    player = 2  else player = 1   end end `

## Mathematica / Wolfram Language

`SeedRandom;ClearAll[ComputerChoose, HumanChoose]ComputerChoose[n_] := If[n < 18, RandomChoice[{1, 2, 3}], 21 - n]HumanChoose[] := ChoiceDialog["How many?", {1 -> 1, 2 -> 2, 3 -> 3, "Quit" -> -1}]runningtotal = 0;whofirst = ChoiceDialog["Who goes first?", {"You" -> 1, "Computer" -> 2}];While[runningtotal < 21, If[whofirst == 1,   choice = HumanChoose[];   If[choice == -1, Break[]];   Print["You choose = ", choice];   runningtotal += choice;   Print["Running total = ", runningtotal];   If[runningtotal == 21, Print["You won!"]; Break[]];   choice = ComputerChoose[runningtotal];   Print["Computer choose = ", choice];   runningtotal += choice;   Print["Running total = ", runningtotal];   If[runningtotal == 21, Print["Computer won!"]; Break[]];   ,   choice = ComputerChoose[runningtotal];   Print["Computer choose = ", choice];   runningtotal += choice;   Print["Running total = ", runningtotal];   If[runningtotal == 21, Print["Computer won!"]; Break[]];   choice = HumanChoose[];   If[choice == -1, Break[]];   Print["You choose = ", choice];   runningtotal += choice;   Print["Running total = ", runningtotal];   If[runningtotal == 21, Print["You won!"]; Break[]];   ]; ]`
Output:
```You choose = 2
Running total = 2
Computer choose = 3
Running total = 5
You choose = 3
Running total = 8
Computer choose = 1
Running total = 9
You choose = 3
Running total = 12
Computer choose = 1
Running total = 13
You choose = 1
Running total = 14
Computer choose = 2
Running total = 16
You choose = 1
Running total = 17
Computer choose = 3
Running total = 20
You choose = 1
Running total = 21
You won!```

## Nim

There is a simple strategy which allows the first player to win in any case. It consists to choose a value which gives a running total equal to 1, 5, 9, 13 or 17. So never let the computer starts as the program uses this strategy.

` # 21 game. import randomimport strformatimport strutils const  Target = 21  PossibleChoices: array[18..20, seq[string]] = [@["1", "2", "3"], @["1", "2"], @["1"]]  Targets = [1, 5, 9, 13, 17, 21]     # Totals that a player must obtain to win. #--------------------------------------------------------------------------------------------------- proc printTotal(total: int) =  ## Print the running total.  echo fmt"Running total is now {total}." #--------------------------------------------------------------------------------------------------- proc computerPlays(total: var int) =  ## Make the computer play.  var choice: int  if total in Targets:    # No winning choice. Choose a random value.    choice = rand(1..3)  else:    # Find the running total to get.    for val in Targets:      if val > total:        choice = val - total        break  inc total, choice  echo fmt"I choose {choice}."  printTotal(total) #--------------------------------------------------------------------------------------------------- proc prompt(message: string; answers: openArray[string]): int =  ## Prompt a message and get an answer checking its validity against possible answers.   while true:    stdout.write(message & ' ')    try:      result = answers.find(stdin.readLine())      if result >= 0:        break      echo fmt"Please answer one of: {answers.join("", "")}."    except EOFError:      echo ""      return  # Quit. #--------------------------------------------------------------------------------------------------- randomize() echo "21 is a two player game. The game is played by choosing a number (1, 2, 3) to\n" &     "be added to the running total. The game is won by the player whose chosen number\n" &     "causes the running total to reach exactly 21. The running total starts at zero.\n"echo "You can quit the game at any time by typing 'q'." block mainLoop:   while true:    var total = 0     # Choose the player who will play first.    var answer = prompt("Who will play first ('you', 'me')?", ["q", "you", "me"])    if answer == 0:      echo "Quitting game."      break    elif answer == 1:      computerPlays(total)     # Internal game loop.    while true:       # Ask player its choice.      let choices = if total > 18: PossibleChoices[total] else: PossibleChoices      let choice = prompt(fmt"Your choice ({choices.join("", "")})?", "q" & choices)      if choice == 0:        echo "Quitting game."        break mainLoop       # Update running total and check if player win.      inc total, choice      printTotal(total)      if total == Target:        echo "Congratulations, you win."        break       # Make computer play.      computerPlays(total)      if total == Target:        echo "Sorry, I win."        break     # Ask player for another game.    answer = prompt("Do you want to play another game (y, n)", ["q", "y", "n"])    if answer != 1:      echo "Quitting game."      break `
Output:
```21 is a two player game. The game is played by choosing a number (1, 2, 3) to
be added to the running total. The game is won by the player whose chosen number
causes the running total to reach exactly 21. The running total starts at zero.

You can quit the game at any time by typing 'q'.
Who will play first (you, me)? x
Who will play first ('you', 'me')? you
I choose 1.
Running total is now 1.
Your choice (1, 2, 3)? 4
Your choice (1, 2, 3)? 3
Running total is now 4.
I choose 1.
Running total is now 5.
Your choice (1, 2, 3)? 3
Running total is now 8.
I choose 1.
Running total is now 9.
Your choice (1, 2, 3)? 3
Running total is now 12.
I choose 1.
Running total is now 13.
Your choice (1, 2, 3)? 3
Running total is now 16.
I choose 1.
Running total is now 17.
Your choice (1, 2, 3)? 3
Running total is now 20.
I choose 1.
Running total is now 21.
Sorry, I win.
Do you want to play another game (y, n) y
Who will play first (you, me)? me
Your choice (1, 2, 3)? 1
Running total is now 1.
I choose 2.
Running total is now 3.
Your choice (1, 2, 3)? 2
Running total is now 5.
I choose 2.
Running total is now 7.
Your choice (1, 2, 3)? 2
Running total is now 9.
I choose 1.
Running total is now 10.
Your choice (1, 2, 3)? 3
Running total is now 13.
I choose 3.
Running total is now 16.
Your choice (1, 2, 3)? 1
Running total is now 17.
I choose 2.
Running total is now 19.
Running total is now 21.
Congratulations, you win.
Do you want to play another game (y, n) n
Quitting game.
```

## Objeck

`class TwentyOne {  @quit : Bool;  @player_total : Int;  @computer_total : Int;   function : Main(args : String[]) ~ Nil {    TwentyOne->New()->Play();  }   New() {  }   method : Play() ~ Nil {    player_first := Int->Random(1) = 1;     "Enter 'q' to quit\n==="->PrintLine();    do {      if(player_first) {        PlayerTurn();        if(<>@quit) {          "---"->PrintLine();          ComputerTurn();        };      }      else {        ComputerTurn();        "---"->PrintLine();        PlayerTurn();      };      "==="->PrintLine();    }    while(<>@quit);  }   method : ComputerTurn() ~ Nil {    input := Int->Random(1, 3);     "Computer choose: {\$input}"->PrintLine();    @computer_total += input;     if(@computer_total = 21) {      "Computer Wins!"->PrintLine();      @quit := true;    }    else if(@computer_total > 21) {      "Computer Loses."->PrintLine();      @quit := true;    }    else {      "Computer total is {[email protected]_total}."->PrintLine();    };  }   method : PlayerTurn() ~ Nil {    input := GetInput();     if(input = -1) {      "Quit"->PrintLine();      @quit := true;    }    else if(input = 0) {      "Invalid Input!"->PrintLine();    }    else {      @player_total += input;    };     if(@player_total = 21) {      "Player Wins!"->PrintLine();      @quit := true;    }    else if(@player_total > 21) {      "Player Loses."->PrintLine();      @quit := true;    }    else {      "Player total is {[email protected]_total}."->PrintLine();    };  }   function : GetInput() ~ Int {    "Choosing a number beween 1-3: "->Print();     input := System.IO.Console->ReadString();    if(input->Size() = 1) {      if(input->Get(0) = 'q') {        return -1;      };       return input->ToInt();    };     return 0;  }}`

## Pascal

` program Game21; {\$APPTYPE CONSOLE} {\$R *.res} uses  System.SysUtils,  System.StrUtils, // for IfThen  Winapi.Windows;  // for ClearScreen const  HARD_MODE = True; var  computerPlayer: string = 'Computer';  humanPlayer: string = 'Player 1';   // for change color  ConOut: THandle;  BufInfo: TConsoleScreenBufferInfo; procedure ClearScreen;var  stdout: THandle;  csbi: TConsoleScreenBufferInfo;  ConsoleSize: DWORD;  NumWritten: DWORD;  Origin: TCoord;begin  stdout := GetStdHandle(STD_OUTPUT_HANDLE);  Win32Check(stdout <> INVALID_HANDLE_VALUE);  Win32Check(GetConsoleScreenBufferInfo(stdout, csbi));  ConsoleSize := csbi.dwSize.X * csbi.dwSize.Y;  Origin.X := 0;  Origin.Y := 0;  Win32Check(FillConsoleOutputCharacter(stdout, ' ', ConsoleSize, Origin, NumWritten));  Win32Check(FillConsoleOutputAttribute(stdout, csbi.wAttributes, ConsoleSize,    Origin, NumWritten));  Win32Check(SetConsoleCursorPosition(stdout, Origin));end; procedure ResetColor;begin  SetConsoleTextAttribute(ConOut, BufInfo.wAttributes);end; procedure ChangeColor(color: Word);begin  ConOut := TTextRec(Output).Handle;  GetConsoleScreenBufferInfo(ConOut, BufInfo);  SetConsoleTextAttribute(TTextRec(Output).Handle, color);end; function SwapPlayer(currentPlayer: string): string;begin  Result := IfThen(currentPlayer = humanPlayer, computerPlayer, humanPlayer);end; function RandomPlayerSelect(): string;begin  Result := IfThen(Random() < 0.5, computerPlayer, humanPlayer);end; function CheckIfCanWin(total: Integer): Boolean;begin  result := (total >= 18);end; function CheckIfCanLose(total: Integer; var choose: Integer; hardMode: Boolean =  False): Boolean;var  range: Integer;begin  range := 17 - total;  Result := false;  if (range > 0) and (range < 4) then  begin    Result := true;    if hardMode then      choose := range    else      choose := Random(range - 1) + 1;  end;end; function CompMove(total: Integer): Integer;begin  if (CheckIfCanWin(total)) then  begin    exit(21 - total);  end;   if CheckIfCanLose(total, Result, HARD_MODE) then    exit;   Result := Random(3) + 1;end; function HumanMove: Integer;var  choice: string;begin  repeat    Writeln('Choose from numbers: 1, 2, 3');    Readln(choice);  until TryStrToInt(choice, Result) and (Result in [1..3]);end; procedure PlayGame();var  playAnother: Boolean;  total, final_, roundChoice, compWins, humanWins: Integer;  choice, currentPlayer: string;begin  playAnother := True;  total := 0;  final_ := 21;  roundChoice := 0;  Randomize;  currentPlayer := RandomPLayerSelect();  compWins := 0;  humanWins := 0;   while (playAnother) do  begin    ClearScreen;    ChangeColor(FOREGROUND_INTENSITY or FOREGROUND_GREEN);    Writeln(total);    ResetColor;    Writeln('');     Writeln('Now playing: ' + currentPlayer);    if currentPlayer = computerPlayer then      roundChoice := CompMove(total)    else      roundChoice := HumanMove;    inc(total, roundChoice);     if (total = final_) then    begin      if (currentPlayer = computerPlayer) then      begin        inc(compWins);      end      else      begin        inc(humanWins);      end;       ClearScreen;      Writeln('Winner: ' + currentPlayer);      Writeln('Comp wins: ', compWins, '. Human wins: ', humanWins, #10);      Writeln('Do you wan to play another round? y/n');       readln(choice);       if choice = 'y' then      begin        total := 0;        ClearScreen;      end      else if choice = 'n' then        playAnother := false      else      begin        Writeln('Invalid choice! Choose from y or n');        Continue;      end;    end    else if total > 21 then    begin      Writeln('Not the right time to play this game :)');      break;    end;     currentPlayer := SwapPlayer(currentPlayer);  end; end; const  WELLCOME_MSG: array[0..5] of string = ('Welcome to 21 game'#10,    '21 is a two player game.', 'The game is played by choosing a number.',    '1, 2, or 3 to be added a total sum.'#10,    'The game is won by the player reaches exactly 21.'#10, 'Press ENTER to start!'#10); var  i: Integer; begin  try    for i := 0 to High(WELLCOME_MSG) do      Writeln(WELLCOME_MSG[i]);    ResetColor;    Readln; // Wait press enter     PlayGame();  except    on E: Exception do      Writeln(E.ClassName, ': ', E.Message);  end;end. `

## Perl

Translation of: Raku
`print <<'HERE';The 21 game. Each player chooses to add 1, 2, or 3 to a running total.The player whose turn it is when the total reaches 21 wins. Enter q to quit.HERE my \$total = 0; while () {    print "Running total is: \$total\n";    my (\$me,\$comp);    while () {        print 'What number do you play> ';        \$me = <>; chomp \$me;        last if \$me =~ /^\$/;        insult(\$me);    }    \$total += \$me;    win('Human') if \$total >= 21;    print "Computer plays: " . (\$comp = 1+int(rand(3))) . "\n";    \$total += \$comp;    win('Computer') if \$total >= 21;} sub win {    my(\$player) = @_;    print "\$player wins.\n";    exit;} sub insult {    my(\$g) = @_;    exit if \$g =~ /q/i;    my @insults = ('Yo mama', 'Jeez', 'Ummmm', 'Grow up');    my \$i = \$insults[1+int rand(\$#insults)];    print "\$i, \$g is not an integer between 1 and 3...\n"}`
Output:
```The 21 game. Each player chooses to add 1, 2, or 3 to a running total.
The player whose turn it is when the total reaches 21 wins. Enter q to quit.
Running total is: 0
What number do you play> 3
Computer plays: 3
Running total is: 6
What number do you play> 3
Computer plays: 3
Running total is: 12
What number do you play> 3
Computer plays: 2
Running total is: 17
What number do you play> 1
Computer plays: 1
Running total is: 19
What number do you play> 2
Human wins.```

## 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.

```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
```
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
```

## PHP

The solution as a server-side PHP7 script and HTML5.

`<!DOCTYPE html><html lang="en"> <head>    <meta charset="UTF-8">    <meta name="keywords"    content="Game 21">    <meta name="description" content="      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 by      the player whose chosen number causes the running total to reach      exactly 21. The running total starts at zero.    ">    <!--DCMI metadata (Dublin Core Metadata Initiative)-->    <meta name="dc.publisher" content="Rosseta Code">    <meta name="dc.date"      content="2020-07-31">    <meta name="dc.created"   content="2020-07-31">    <meta name="dc.modified"  content="2020-08-01">    <title>        21 Game    </title>    <!-- Remove the line below in the final/production version. -->    <meta http-equiv="cache-control" content="no-cache">     <style>      .ui div   { width: 50%; display: inline-flex; justify-content: flex-end; }      div.total { margin-bottom: 1ch; }      label     { padding-right: 1ch; }      button + button { margin-left: 1em; }    </style></head> <body>   <h1>    21 Game in PHP 7  </h1>   <p>    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 by    the player whose chosen number causes the running total to reach    exactly 21. The running total starts at zero.  </p>    <?php     const GOAL = 21;    const PLAYERS = array('AI', 'human');     function best_move(\$n)    {      for (\$i = 1; \$i <= 3; \$i++)        if (\$n + \$i == GOAL)          return \$i;      for (\$i = 1; \$i <= 3; \$i++)        if ((\$n + \$i - 1) % 4 == 0)          return \$i;      return 1;    }     if (isset(\$_GET['reset']) || !isset(\$_GET['total']))    {      \$first = PLAYERS[rand(0, 1)];      \$total = 0;      \$human = 0;      \$ai = 0;      \$message = '';      if (\$first == 'AI')      {        \$move = best_move(\$total);        \$ai = \$move;        \$total = \$total + \$move;      }    }    else    {      \$first   = \$_GET['first'];      \$total   = \$_GET['total'];      \$human   = \$_GET['human'];      \$ai      = \$_GET['ai'];      \$message = \$_GET['message'];    }     if (isset(\$_GET['move']))    {      \$move = (int)\$_GET['move'];      \$human = \$move;      \$total = \$total + \$move;      if (\$total == GOAL)        \$message = 'The winner is human.';      else      {        \$move = best_move(\$total);        \$ai = \$move;        \$total = \$total + \$move;        if (\$total == GOAL)          \$message = 'The winner is AI.';      }    }     \$state = array();    for (\$i = 1; \$i <= 3; \$i++)      \$state[\$i] = \$total + \$i > GOAL ? 'disabled' : '';     echo <<< END      <p>        The first player is \$first.        Use buttons to play.      </p>      <form class="ui">        <div>          <input type='hidden' id='first' name='first' value='\$first'>          <input type='hidden' name='message' value='\$message'>        </div>        <div class='total'>          <label for='human'>human last choice:</label>          <input type='text' name='human' readonly value='\$human'>        </div>        <div class='total'>          <label for='AI'>AI last choice:</label>          <input type='text' name='ai' readonly value='\$ai'>        </div>        <div class='total'>          <label for='runningTotalText'>running total:</label>          <input type='text' name='total' readonly value='\$total'>        </div>        <div class='buttons'>          <button type='submit' name='move' value='1' {\$state}> one   </button>          <button type='submit' name='move' value='2' {\$state}> two   </button>          <button type='submit' name='move' value='3' {\$state}> three </button>          <button type='submit' name='reset' value='reset'> reset </button>        </div>      </form>      <p>        \$message      </p>    END  ?> </body>`

## Python

### Python: Original, with output

Works with: Python 2.X and 3.X
` from random import randintdef start():	game_count=0	print("Enter q to quit at any time.\nThe computer will choose first.\nRunning total is now {}".format(game_count))	roundno=1	while game_count<21:		print("\nROUND {}: \n".format(roundno))		t = select_count(game_count)		game_count = game_count+t		print("Running total is now {}\n".format(game_count))		if game_count>=21:			print("So, commiserations, the computer has won!")			return 0		t = request_count()		if not t:			print('OK,quitting the game')			return -1		game_count = game_count+t		print("Running total is now {}\n".format(game_count))		if game_count>=21:			print("So, congratulations, you've won!")			return 1		roundno+=1 def select_count(game_count):	'''selects a random number if the game_count is less than 18. otherwise chooses the winning number'''	if game_count<18:		t= randint(1,3)	else:		t = 21-game_count	print("The computer chooses {}".format(t))	return t def request_count():	'''request user input between 1,2 and 3. It will continue till either quit(q) or one of those numbers is requested.'''	t=""	while True:		try:			t = raw_input('Your choice 1 to 3 :')			if int(t) in [1,2,3]:				return int(t)			else:				print("Out of range, try again")		except:			if t=="q":				return None			else:				print("Invalid Entry, try again") c=0m=0r=Truewhile r:	o = start()	if o==-1:		break	else:		c+=1 if o==0 else 0		m+=1 if o==1 else 0	print("Computer wins {0} game, human wins {1} games".format(c,m))	t = raw_input("Another game?(press y to continue):")	r = (t=="y")`
Output:
```Enter q to quit at any time.
The computer will choose first.
Running total is now 0

ROUND 1:

The computer chooses 1
Running total is now 1

Your choice 1 to 3 :4
Out of range, try again
Your choice 1 to 3 :w
Invalid Entry, try again
Your choice 1 to 3 :3
Running total is now 4

ROUND 2:

The computer chooses 1
Running total is now 5

Your choice 1 to 3 :2
Running total is now 7

ROUND 3:

The computer chooses 3
Running total is now 10

Your choice 1 to 3 :3
Running total is now 13

ROUND 4:

The computer chooses 1
Running total is now 14

Your choice 1 to 3 :2
Running total is now 16

ROUND 5:

The computer chooses 1
Running total is now 17

Your choice 1 to 3 :1
Running total is now 18

ROUND 6:

The computer chooses 3
Running total is now 21

So, commiserations, the computer has won!
Computer wins 1 game, human wins 0 games
Another game?(press y to continue):y
Enter q to quit at any time.
The computer will choose first.
Running total is now 0

ROUND 1:

The computer chooses 1
Running total is now 1

Your choice 1 to 3 :3
Running total is now 4

ROUND 2:

The computer chooses 3
Running total is now 7

Your choice 1 to 3 :3
Running total is now 10

ROUND 3:

The computer chooses 3
Running total is now 13

Your choice 1 to 3 :5
Out of range, try again
Your choice 1 to 3 :3
Running total is now 16

ROUND 4:

The computer chooses 2
Running total is now 18

Your choice 1 to 3 :3
Running total is now 21

So, congratulations, you've won!
Computer wins 1 game, human wins 1 games
Another game?(press y to continue):y
Enter q to quit at any time.
The computer will choose first.
Running total is now 0

ROUND 1:

The computer chooses 3
Running total is now 3

Your choice 1 to 3 :4
Out of range, try again
Your choice 1 to 3 :3
Running total is now 6

ROUND 2:

The computer chooses 3
Running total is now 9

Your choice 1 to 3 :q
OK,quitting the game
```

### Python: using tkinter

` ''' Python 3.6.5 code using Tkinter graphical user interface.    Starting player chosen randomly. ''' from tkinter import *from tkinter import messageboximport random # ************************************************ class Game:    def __init__(self, gw):        self.window = gw        self.won = 0        self.lost = 0        self.score = 0        self.puter_turn = None        self.var123 = IntVar()        self.varsub = IntVar()         # top frame:        self.top_fr = Frame(gw,                            width=600,                            height=100,                            bg='dodger blue')        self.top_fr.pack(fill=X)         self.hdg = Label(self.top_fr,                         text='  21 Game  ',                         font='arial 22 bold',                         fg='navy',                         bg='lemon chiffon')        self.hdg.place(relx=0.5, rely=0.5,                       anchor=CENTER)         self.play_btn = Button(self.top_fr,                               text='Play\nGame',                               bd=5,                               bg='navy',                               fg='lemon chiffon',                               font='arial 12 bold',                               command=self.play_game)        self.play_btn.place(relx=0.92, rely=0.5,                            anchor=E)         self.quit_btn = Button(self.top_fr,                               text='Quit\nGame',                               bd=5,                               bg='navy',                               fg='lemon chiffon',                               font='arial 12 bold',                               command=self.quit_game)        self.quit_btn.place(relx=0.07, rely=0.5,                            anchor=W)         # bottom frame:        self.btm_fr = Frame(gw,                            width=600,                            height=500,                            bg='lemon chiffon')        self.btm_fr.pack(fill=X)         self.msg = Label(self.btm_fr,                         text="(Click 'Play' or 'Quit')",                         font='arial 16 bold',                         fg='navy',                         bg='lemon chiffon')        self.msg.place(relx=0.5, rely=0.1,                       anchor=CENTER)         self.hdg = Label(self.btm_fr,                         text="Scoreboard",                         font='arial 16 bold',                         fg='navy',                         bg='lemon chiffon')        self.hdg.place(relx=0.5, rely=0.2,                       anchor=CENTER)         self.score_msg = Label(self.btm_fr,                               text="0",                               font='arial 16 bold',                               fg='navy',                               bg='dodger blue',                               width=8)         self.score_msg.place(relx=0.5, rely=0.27,                             anchor=CENTER)         self.ch_fr = LabelFrame(self.btm_fr,                                text='Choose a number',                                bg='dodger blue',                                fg='navy',                                bd=8,                                relief=RIDGE,                                font='arial 16 bold')        self.ch_fr.place(relx=0.5, rely=0.5,                         anchor=CENTER)         self.radio1 = Radiobutton(self.ch_fr,                                  text='1',                                  state='disabled',                                  font='arial 16 bold',                                  fg='navy',                                  bg='dodger blue',                                  variable=self.var123,                                  value=1)        self.radio1.pack()         self.radio2 = Radiobutton(self.ch_fr,                                  text='2',                                  state='disabled',                                  font='arial 16 bold',                                  fg='navy',                                   bg='dodger blue',                                  variable=self.var123,                                  value=2)        self.radio2.pack()         self.radio3 = Radiobutton(self.ch_fr,                                  text='3',                                  state='disabled',                                  font='arial 16 bold ',                                  fg='navy',                                   bg='dodger blue',                                  variable=self.var123,                                  value=3)        self.radio3.pack()         self.submit_btn = Button(self.btm_fr,                                 text='SUBMIT',                                 state='disabled',                                 bd=5,                                 bg='navy',                                 fg='lemon chiffon',                                 font='arial 12 bold',                                 command=self.submit)        self.submit_btn.place(relx=0.5, rely=0.75,                              anchor=CENTER)         self.won_lbl = Label(self.btm_fr,                             text="Won: 0",                             font='arial 16 bold',                             fg='navy',                             bg='lemon chiffon')        self.won_lbl.place(relx=0.85, rely=0.88,                           anchor=W)         self.lost_lbl = Label(self.btm_fr,                              text="Lost: 0",                              font='arial 16 bold',                              fg='navy',                              bg='lemon chiffon')        self.lost_lbl.place(relx=0.85, rely=0.93,                            anchor=W)     # play one game:        def play_game(self):        self.play_btn.config(state='disabled')        # pick who goes first randomly:        self.puter_turn = random.choice([True, False])        self.score = 0        self.score_msg.config(text=self.score)        if not self.puter_turn:            m = 'your turn'            self.msg.config(text=m)        # alternate turns until 21 is reached:        while self.score != 21:            if self.puter_turn:                self.puter_plays()            else:                self.user_plays()            self.puter_turn = not self.puter_turn        self.play_btn.config(state='normal')        return     # computer picks a number:    def puter_plays(self):        if self.score == 20:            x = 1        elif self.score == 19:                x = random.choice([1, 2])        else:            x = random.choice([1, 2, 3])        self.score += x        self.score_msg.config(text=self.score)        if self.score == 21:            m = 'Computer won!'            self.lost += 1            self.lost_lbl.config(text='Lost: ' + str(self.lost))        else:            m = 'Computer chose ' + str(x) + ', your turn'        self.msg.config(text=m)        return     # user picks a number:    def user_plays(self):        self.set_user_state('normal')        while True:            # wait for submit button to be pressed:            self.submit_btn.wait_variable(self.varsub)            x = self.var123.get()            if x + self.score > 21:                m = 'Score cannot exceed 21, try again'                messagebox.showerror('Error', m)            elif x not in (1,2,3):                m = 'No selection made'                messagebox.showerror('Error', m)            else:                break        self.score += x        if self.score == 21:            m = 'You won!'            self.msg.config(text=m)            self.score_msg.config(text=self.score)            self.won += 1            self.won_lbl.config(text='Won: ' + str(self.won))        # reset and disable radio buttons:           self.var123.set(0)          self.set_user_state('disabled')                             return     # set radio buttons to 'disabled' or 'normal':    def set_user_state(self, state):        self.radio1.config(state=state)        self.radio2.config(state=state)        self.radio3.config(state=state)        self.submit_btn.config(state=state)        return      def quit_game(self):        self.window.destroy()     # indicate that submit button was pressed:    def submit(self):        self.varsub.set(0) # ************************************************ root = Tk()root.title('21 Game')root.geometry('600x600+100+50')root.resizable(False, False)g = Game(root)root.mainloop() `

## R

`game21<-function(first = c("player","ai","random"),sleep=.5){  state = 0  finished = F  turn = 1  if(length(first)==1 && startsWith(tolower(first),"r")){    first = rbinom(1,1,.5)  }else{    first = (length(first)>1 || startsWith(tolower(first),"p"))  }  while(!finished){    if(turn>1 || first){      cat("The total is now",state,"\n");Sys.sleep(sleep)      while(T){        player.move = readline(prompt = "Enter move: ")        if((player.move=="1"||player.move=="2"||player.move=="3") && state+as.numeric(player.move)<=21){          player.move = as.numeric(player.move)          state = state + player.move          break        }else if(tolower(player.move)=="exit"|tolower(player.move)=="quit"|tolower(player.move)=="end"){          cat("Goodbye.\n")          finished = T          break        }else{          cat("Error: invaid entry.\n")        }      }    }    if(state == 21){      cat("You win!\n")      finished = T    }    if(!finished){      cat("The total is now",state,"\n");Sys.sleep(sleep)      while(T){        ai.move = sample(1:3,1)        if(state+ai.move<=21){          break        }      }      state = state + ai.move      cat("The AI chooses",ai.move,"\n");Sys.sleep(sleep)      if(state == 21){        cat("The AI wins!\n")        finished = T      }    }    turn = turn + 1  }}`
`game21()`
Output:
```The total is now 0
Enter move: 3
The total is now 3
The AI chooses 2
The total is now 5
Enter move: 3
The total is now 8
The AI chooses 3
The total is now 11
Enter move: 3
The total is now 14
The AI chooses 2
The total is now 16
Enter move: 1
The total is now 17
The AI chooses 3
The total is now 20
Enter move: 1
The total is now 21
You win!```
`game21(first = "ai")`
Output:
```The total is now 0
The AI chooses 2
The total is now 2
Enter move: quit
Goodbye.
```

## Racket

`#lang racket (define limit 21)(define max-resp 3) (define (get-resp)  (let loop ()    (match (read-line)      [(app (conjoin string? string->number) n)       #:when (and (exact-integer? n) (<= 1 n max-resp))       n]      ["q" (exit)]      [n (printf "~a is not in range 1 and ~a\n" n max-resp)         (loop)]))) (define (win human?) (printf "~a wins\n" (if human? "Human" "Computer"))) (printf "The ~a game. Each player chooses to add a numberin range 1 and ~a to a running total.The player whose turn it is when the total reaches exactly ~a wins.Enter q to quit.\n\n" limit max-resp limit) (let loop ([total 0] [human-turn? (= 0 (random 2))])  (define new-total    (+ total       (cond         [human-turn? (printf "Running total is: ~a\n" total)                      (printf "Your turn:\n")                      (get-resp)]         [else (define resp (random 1 (add1 max-resp)))               (printf "Computer plays: ~a\n" resp)               resp])))  (cond    [(= new-total limit) (win human-turn?)]    [(> new-total limit) (win (not human-turn?))]    [else (loop new-total (not human-turn?))]))`
Output:
```The 21 game. Each player chooses to add an integer
in range 1 and 3 to a running total.
The player whose turn it is when the total reaches exactly 21 wins.
Enter q to quit.

Running total is: 0
1
Computer plays: 3
Running total is: 4
foo
foo is not an integer in range 1 and 3
bar
bar is not an integer in range 1 and 3
3
Computer plays: 1
Running total is: 8
1
Computer plays: 1
Running total is: 10
1
Computer plays: 2
Running total is: 13
1
Computer plays: 3
Running total is: 17
1
Computer plays: 2
Running total is: 20
1
Human wins
```

## Raku

(formerly Perl 6)

Works with: Rakudo version 2018.09

Since there is no requirement that the computer play sensibly, it always plays a random guess so the player has some chance to win.

`say qq :to 'HERE';    The 21 game. Each player chooses to add 1, 2, or 3 to a running total.    The player whose turn it is when the total reaches 21 wins. Enter q to quit.    HERE my \$total = 0;loop {    say "Running total is: \$total";    my (\$me,\$comp);    loop {        \$me = prompt 'What number do you play> ';        last if \$me ~~ /^<>\$/;        insult \$me;    }    \$total += \$me;    win('Human') if \$total >= 21;    say "Computer plays: { \$comp = (1,2,3).roll }\n";    \$total += \$comp;    win('Computer') if \$total >= 21;} sub win (\$player) {    say "\$player wins.";    exit;} sub insult (\$g) {    exit if \$g eq 'q';    print ('Yo mama,', 'Jeez,', 'Ummmm,', 'Grow up,', 'Did you even READ the instructions?').roll;    say " \$g is not an integer between 1 & 3..."}`
Sample game:
```The 21 game. Each player chooses to add 1, 2, or 3 to a running total.
The player whose turn it is when the total reaches 21 wins. Enter q to quit.

Running total is: 0
What number do you play> 5
Did you even READ the instructions? 5 is not an integer between 1 & 3...
What number do you play> g
Yo mama, g is not an integer between 1 & 3...
What number do you play> 12
Jeez, 12 is not an integer between 1 & 3...
What number do you play> 3
Computer plays: 2

Running total is: 5
What number do you play> 3
Computer plays: 3

Running total is: 11
What number do you play> 1
Computer plays: 1

Running total is: 13
What number do you play> 3
Computer plays: 2

Running total is: 18
What number do you play> 3
Human wins.```

## REXX

Around half of the REXX program deals with incorrect or missing input   (of the required integer).

This REXX version allows the user to choose if the computer should go first.

`/*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  21  exactly 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*/\$=0;                       goal= 21              /*the sum [or running total]  (so far).*/    do j=1  while \$<goal;  call g                /*obtain the user's number via a prompt*/    if x\==0    then call tot x, 1               /*Not 0?   The user wants to go first. */    if \$==goal  then leave                       /*the user won the game with the last #*/    call ?;     if y==.  then y= random(1, 3)    /*get computer's choice  or  a random #*/    say sep 'The computer chooses '     y     " as its choice."         /*inform player.*/    call tot y, 0                                /*call subroutine to show the total.   */    end   /*j*/sayif who  then say sep  'Congratulations!   You have won the  21  game.'        else say sep  'The computer has won the  21  game.'exit 0                                           /*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/?:   y=.;   do c=1  for 3  until y\==.;  if (c+\$) // 4 == 1  then y= c;    end;     returnser: if bad  then return;  bad=1;  say;  say;  say sep '***error***' arg(1);  say;  returntot: arg q,who; \$=\$+q; say sep 'The game total is now' sep2 \$ sep2; /*add; show \$*/ return/*──────────────────────────────────────────────────────────────────────────────────────*/g: low = (j \== 1)                               /*allow user to have computer go first.*/     do until \bad;   bad= 0;     say            /*prompt 'til user gives a good number.*/     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.]'     parse pull x _ . 1 ox;   upper x            /*obtain user's lowercase response(s). */     if   x=''             then call ser "Nothing entered."     if _\==''             then call ser "Too many arguments entered: "       ox     if abbrev('QUIT', x, 1)  then do;   say;      say sep  "quitting.";      exit 1;  end     if \datatype(x, 'N')  then call ser "Argument isn't numeric: "           ox     if \datatype(x, 'W')  then call ser "Number isn't an integer: "          ox     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>3                then call ser "Number is too large  (>3): "         x     if bad                then iterate          /*Had an error? Then get another number*/     x= x/1; if \$+x>goal   then call ser "Number will cause the sum to exceed " goal': ' x     end   /*until*/;           return`
output :
```──────── Playing the  21  game.

──────── Please enter a number from  0  ───► 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  2  as its choice.
──────── The game total is now  ════════  5  ════════

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

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

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

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

──────── The computer has won the  21  game.
```

## Ring

` # Project : 21 Game load "guilib.ring" limit = 21posold = 0button = 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()	       }        } `

Output:
21 Game

## Ruby

` # 21 Game - an example in Ruby for Rosetta Code. GOAL = 21MIN_MOVE = 1MAX_MOVE = 3 DESCRIPTION = "*** Welcome to the 21 Game! ***21 is a two player game.Each player chooses to add 1, 2 or 3 to a running total.The player whose turn it is when the total reaches 21 will win the game.The running total starts at zero. The players start the game in turn.Enter q to quit at any time." ## Returns the best move to play.#def best_move(total)  move = rand(1..3)  MIN_MOVE.upto(MAX_MOVE) do |i|    move = i if (total + i - 1) % (MAX_MOVE + 1) == 0  end  MIN_MOVE.upto(MAX_MOVE) do |i|    move = i if total + i == GOAL  end  moveend ## Gets the move of the player.#def get_move  print "Your choice between #{MIN_MOVE} and #{MAX_MOVE}: "  answer = gets  move = answer.to_i  until move.between?(MIN_MOVE, MAX_MOVE)    exit if answer.chomp == 'q'    print 'Invalid choice. Try again: '    answer = gets    move = answer.to_i  end  moveend ## Asks the player to restart a game and returns the answer.#def restart?  print 'Do you want to restart (y/n)? '  restart = gets.chomp  until ['y', 'n'].include?(restart)    print 'Your answer is not a valid choice. Try again: '    restart = gets.chomp  end  restart == 'y'end ## Run a game. The +player+ argument is the player that starts:# * 1 for human# * 0 for computer#def game(player)  total = round = 0  while total < GOAL    round += 1    puts "--- ROUND #{round} ---\n\n"    player = (player + 1) % 2    if player == 0      move = best_move(total)      puts "The computer chooses #{move}."    else      move = get_move    end    total += move    puts "Running total is now #{total}.\n\n"  end  if player == 0    puts 'Sorry, the computer has won!'    return false  end  puts 'Well done, you have won!'  trueend # MAINputs DESCRIPTIONrun = truecomputer_wins = human_wins = 0games_counter = player = 1while run  puts "\n=== START GAME #{games_counter} ==="  player = (player + 1) % 2  if game(player)    human_wins += 1  else    computer_wins += 1  end  puts "\nComputer wins #{computer_wins} games, you wins #{human_wins} game."  games_counter += 1  run = restart?endputs 'Good bye!' `

## rust

`use rand::Rng;use std::io; #[derive(Clone)]enum PlayerType {    Human,    Computer,} #[derive(Clone)]struct Player {    name: String,    wins: u32,  // holds wins    level: u32, // difficulty level of Computer    player_type: PlayerType, } trait Choose {    fn choose(&self, game: &Game) -> u8;} impl Player {    fn new(name: &str, player_type: PlayerType, level: u32) -> Player {        Player {            name: String::from(name),            wins: 0,            level,            player_type,        }    }    fn get_name(&self) -> &str {        &self.name[..]    }    fn get_level(&self) -> u32 {        self.level    }    fn add_win(&mut self) {        self.wins += 1    }    fn level_up(&mut self) {        self.level += 1    }} impl Choose for Player {    fn choose(&self, game: &Game) -> u8 {        match self.player_type {            PlayerType::Human => loop {                let max_choice = game.max_choice();                match max_choice {                    1 => println!("Enter a number 1 to win (or quit):"),                    _ => println!("Enter a number between 1 and {} (or quit):", max_choice)                }                let mut guess = String::new();                io::stdin()                    .read_line(&mut guess)                    .expect("Failed to read line");                if guess.trim() == "quit" {                    return 0                }                let guess: u8 = match guess.trim().parse() {                    Ok(num) if num >= 1 && num <= max_choice => num,                    Ok(_) => continue,                    Err(_) => continue,                };                return guess;            },            PlayerType::Computer => match self.level {                5 => match game.get_total() {                    total if total == 20 => 1,                    total if total == 19 => 2,                    total if total == 18 => 3,                    _ => 1,                },                4 => match game.get_total() {                    total if total == 20 => 1,                    total if total == 19 => 2,                    total if total == 18 => 3,                    _ => rand::thread_rng().gen_range(1, 3),                },                3 => match game.get_total() {                    total if total == 20 => 1,                    total if total == 19 => 2,                    total if total == 18 => 3,                    _ => rand::thread_rng().gen_range(1, 4),                },                2 => match game.get_total() {                    total if total == 20 => 1,                    total if total == 19 => 2,                    _ => rand::thread_rng().gen_range(1, 3),                },                1 => 1,                _ => match game.get_total() {                    total if total == 20 => 1,                    total if total == 19 => 2,                    total if total == 18 => 3,                    _ => match game.get_remaining() % 4 {                        0 => rand::thread_rng().gen_range(1, 4),                        _ => game.get_remaining() % 4,                    },                },            },        }    }} struct Game {    players: Vec<Player>,    turn: u8,      total: u8,     start: u8, // determines which player goes first} impl Game {    fn init(players: &Vec<Player>) -> Game {        Game {            players: players.to_vec(),            turn: 1,            total: 0,            start: rand::thread_rng().gen_range(0, 2),        }    }    fn play(&mut self) -> &Player {        loop {            println!(                "Total now {} (remaining: {})",                self.get_total(),                self.get_remaining()            );            {                let player = self.whose_turn();                println!("Turn: {} ({} turn)", self.get_turn(), player.get_name());                let choice = player.choose(&self);                if choice == 0 {                    self.next_turn();                    break; // quit                }                println!("{} choose {}", player.get_name(), choice);                self.add_total(choice)            }            if self.get_total() >= 21 {                break;            }            println!("");            self.next_turn();        }        self.whose_turn()    }    fn add_total(&mut self, choice: u8) {        self.total += choice;    }    fn next_turn(&mut self) {        self.turn += 1;    }    fn whose_turn(&self) -> &Player {        let index: usize = ((self.turn + self.start) % 2).into();        &self.players[index]    }    fn get_total(&self) -> u8 {        self.total    }    fn get_remaining(&self) -> u8 {        21 - self.total    }    fn max_choice(&self) -> u8 {        match self.get_remaining() {            1 => 1,            2 => 2,            _ => 3        }    }    fn get_turn(&self) -> u8 {        self.turn    }} fn main() {    let mut game_count = 0;    let mut players = vec![        Player::new("human", PlayerType::Human, 0),        Player::new("computer", PlayerType::Computer, 1),    ];    println!("21 Game");    println!("Press enter key to start");    {        let _ = io::stdin().read_line(&mut String::new());    }    loop {        game_count += 1;        let mut game = Game::init(&players);        let winner = game.play();        {            let mut index = 0;            while index < players.len() {                if players[index].get_name() == winner.get_name() {                    players[index].add_win();                }                index += 1            }        }        println!("\n{} won game {}\n", winner.get_name(), game_count);        // limit game count        if game_count >= 10000 {            break;        }        // ask player if they want to keep on playing        println!("Press enter key to play again (or quit):");        let mut reply = String::new();        io::stdin()            .read_line(&mut reply)            .expect("Failed to read line");        if reply.trim() == "quit" {            break;        }        // level up computer        if winner.get_name() != "computer" {            println!("Computer leveling up ...");            players.level_up();            println!("Computer now level {}!", players.get_level());            println!("Beware!\n");        }    }    println!("player: {} win: {}", players.get_name(), players.wins);    println!("player: {} win: {}", players.get_name(), players.wins);} `

## Scala

` object Game21 {   import scala.collection.mutable.ListBuffer  import scala.util.Random   val N = 21 // the same game would also work for N other than 21...   val RND = new Random() // singular random number generator; add a seed number, if you want reproducibility   /** tuple: name and a play function: (rest: remaining number, last: value of opponent's last move) => new move    */  type Player = (String, (Int,Int) => Int)   // indeed, the following could also be written using a class and instances, I've choosen a  // more functional and math way (using tuples)...  val playerRandom:Player = ("RandomRobot", { (rest, last) =>    if (rest <= 3) rest    else 1 + RND.nextInt(3)  })  val playerBest:Player = ("BestRobot", { (rest, last) =>    val i = rest % 4    if (i > 0) i else 1 + RND.nextInt(3)  })  val playerHuman:Player = ("YOU", { (rest, last) =>    println("Rest: "+rest)    println("Last: "+last)    var in = ""    while (in!="1" && in!="2" && in!="3") {      in = scala.io.StdIn.readLine("Your move (1,2,3,q)> ").trim      if ("q" == in)        throw new Exception("q => quit")    }    in.toInt  })   /** Execute a whole game. NOTE that we're counting DOWN from N to 0!    * @param players    * @return list of all moves    */  def play(players:Seq[Player]):Seq[Int] = {    require(players.size == 2)    var last = -1    var rest = N    var p = 0 // player 0 always starts    val l = ListBuffer[Int]() // list of all moves    while (rest > 0) {      last = players(p)._2(rest,last)      require(1<=last && last<=3,"Player must always play 1,2,3: "+last)      l += last      rest -= last      p = 1 - p // other player's turn    }    l.toSeq  }   /** Evaluate a whole game.    * @param game list of moves of one game    * @param rest mainly for recursion    * @return evaluation, for each move a tuple: (rest, what was played, whether this player won in the end)    */  def evaluate(game:Seq[Int],rest:Int=N):Seq[(Int,Int,Boolean)] = {    if (game.size == 0) Seq()    else Seq((rest,game.head,game.size%2 == 1)) ++ evaluate(game.tail,rest - game.head)  }   def main(args: Array[String]): Unit = {    // here you can put whatever player combination you like    val players = Seq(playerRandom,playerRandom) // random robot vs random robot    //val players = Seq(playerRandom,playerBest) // random robot vs best robot    //val players = Seq(playerHuman,playerBest) // You vs best robot    var p0won = 0    val n = 1000 // number of games to play    var m = 0 // games actually played (a human player might quit before n)    try {      (1 to n).foreach { i =>        val g = play(players)        require(g.sum == N) // some validity checks        val e = evaluate(g)        require(e.size == g.size && e.last._3 && e(0)._3 != e(1)._3) // some validity checks        if (e(0)._3) p0won += 1        m += 1        println(i + ": " + players(0)._1 + " " + (if (e(0)._3) "won" else "lost") + " against " + players(1)._1 + ". " + g + " => " + e)      }    } catch {      case t:Throwable => println(t.getMessage)    }    println("Player0: "+players(0)._1)    println("Player1: "+players(1)._1)    println(f"Player0 won \${p0won} times out of \${m}, or \${p0won * 100.0 / m}%%")  }} `

## Visual Basic .NET

Platform: .NET

Works with: Visual Basic .NET version 2019

To compile this program you need to create a Visual Basic .NET project called Game21vb in Microsoft Visual Studio and paste (removing the previous content) to the MainWindow.xaml and MainWindow.xaml.vb files the source code given below.

The file MainWindow.xaml.vb with Visual Basic source code.

`' Game 21 in VB.NET - an example for Rosetta Code Class MainWindow    Private Const GOAL As Integer = 21    Private total As Integer = 0    Private random As New Random     Private Sub Update(box As TextBox, player As String, move As Integer)        total = total + move        box.Text = move        boxTotal.Text = total        If total + 1 > GOAL Then button1.IsEnabled = False        If total + 2 > GOAL Then button2.IsEnabled = False        If total + 3 > GOAL Then button3.IsEnabled = False        If total = GOAL Then            winner.Content = \$"The winner is {player}."        End If    End Sub     Private Sub Ai()        Dim move As Integer = 1        For i = 1 To 3            If (total + i - 1) Mod 4 = 0 Then move = i        Next i        For i = 1 To 3            If total + i = GOAL Then move = i        Next i        Update(boxAI, "AI", move)    End Sub     Private Sub Choice(sender As Object, e As RoutedEventArgs) _            Handles button1.Click, button2.Click, button3.Click        Update(boxHuman, "human", sender.Content)        If total < GOAL Then Ai()    End Sub     ' StartGame method handles both OnLoad (WM_INIT?) event     ' as well as the restart of the game after user press the 'restart' button.    '    Private Sub StartGame(sender As Object, e As RoutedEventArgs) Handles restart.Click         total = 0         boxAI.Text = ""        boxHuman.Text = ""        boxTotal.Text = ""        'first.Content = "" ' It is not necessary, see below.        winner.Content = ""         button1.IsEnabled = True        button2.IsEnabled = True        button3.IsEnabled = True         ' The random.Next(2) return pseudorandomly either 0 or 1. Generally        ' random.Next(n) Return a value from 0 (inclusive) To n - 1 (inclusive).        '        If random.Next(2) = 0 Then            first.Content = "First player is AI player."            Ai()        Else            first.Content = "First player is human player."        End If    End SubEnd Class`

The file MainWindow.xaml with GUI source code written in XAML.

`<Window x:Class="MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"        xmlns:local="clr-namespace:Game21vb"        mc:Ignorable="d"        Title="Game 21" Height="292" Width="409" Loaded="StartGame">    <Grid>        <TextBlock             HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="64" Width="376">            Game 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 by the player whose chosen number causes the running total to reach exactly 21.            The running total starts at zero.        </TextBlock>        <Label Content="AI" HorizontalAlignment="Left" Margin="60,121,0,0" VerticalAlignment="Top" Width="49" HorizontalContentAlignment="Right"/>        <Label Content="Human" HorizontalAlignment="Left" Margin="60,152,0,0" VerticalAlignment="Top" HorizontalContentAlignment="Right"/>        <Label Content="Total" HorizontalAlignment="Left" Margin="60,183,0,0" VerticalAlignment="Top" Width="49" HorizontalContentAlignment="Right"/>        <TextBox x:Name="boxAI" HorizontalAlignment="Left" Height="23" Margin="114,125,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" IsReadOnly="True"/>        <TextBox x:Name="boxHuman" HorizontalAlignment="Left" Height="23" Margin="114,156,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" IsReadOnly="True"/>        <TextBox x:Name="boxTotal" HorizontalAlignment="Left" Height="23" Margin="114,187,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" IsReadOnly="True"/>        <Button x:Name="button1" Content="1" HorizontalAlignment="Left" Margin="114,220,0,0" VerticalAlignment="Top" Width="25"/>        <Button x:Name="button2" Content="2" HorizontalAlignment="Left" Margin="144,220,0,0" VerticalAlignment="Top" Width="25"/>        <Button x:Name="button3" Content="3" HorizontalAlignment="Left" Margin="174,220,0,0" VerticalAlignment="Top" Width="25"/>        <Button x:Name="restart" Content="restart" HorizontalAlignment="Left" Margin="215,220,0,0" VerticalAlignment="Top" Width="75"/>        <Label x:Name="winner" HorizontalAlignment="Left" Margin="245,184,0,0" VerticalAlignment="Top" Width="133"/>        <Label x:Name="first" HorizontalAlignment="Left" Margin="10,79,0,0" VerticalAlignment="Top"/>    </Grid></Window> `

## Wren

Translation of: Go
Library: Wren-fmt
Library: Wren-ioutil
`import "/fmt" for Convimport "/ioutil" for Inputimport "random" for Random var total = 0var quit = false var getChoice = Fn.new {    while (true) {        var input = Input.integer("Your choice 1 to 3: ", 0, 3)        if (input == 0) {            quit = true            return        }        var newTotal = total + input        if (newTotal > 21) {            System.print("Too big, try again")        } else {            total = newTotal            System.print("Running total is now %(total)")            return        }    }} var rand = Random.new()var computer = Conv.itob(rand.int(2))System.print("Enter 0 to quit at any time\n")if (computer) {    System.print("The computer will choose first")} else {    System.print("You will choose first")}System.print("\nRunning total is now 0\n")var round = 1while (true) {    System.print("ROUND %(round):\n")    for (i in 0..1) {        if (computer) {            var choice = (total < 18) ? 1 + rand.int(3) : 21 - total            total = total + choice            System.print("The computer chooses %(choice)")            System.print("Running total is now %(total)")            if (total == 21) {                System.print("\nSo, commiserations, the computer has won!")                return            }        } else {            getChoice.call()            if (quit) {                System.print("OK, quitting the game")                return            }            if (total == 21) {                System.print("\nSo, congratulations, you've won!")                return            }        }        System.print()        computer = !computer    }    round = round + 1}`
Output:

Sample game:

```Enter 0 to quit at any time

You will choose first

Running total is now 0

ROUND 1:

Your choice 1 to 3: 3
Running total is now 3

The computer chooses 2
Running total is now 5

ROUND 2:

Your choice 1 to 3: 3
Running total is now 8

The computer chooses 1
Running total is now 9

ROUND 3:

Your choice 1 to 3: 3
Running total is now 12

The computer chooses 3
Running total is now 15

ROUND 4:

Your choice 1 to 3: 2
Running total is now 17

The computer chooses 3
Running total is now 20

ROUND 5:

Your choice 1 to 3: 1
Running total is now 21

So, congratulations, you've won!
```