Task: 21 game


C++: 

#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()
{
    
    

    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; 
}




Java: 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;
                                
                                for ( int test : valid ) {
                                    if ( total + test == max ) {
                                        guess = test;
                                        break;
                                    }
                                }
                                
                                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]$") ) {
                        
                        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");
                    }
                }
            }
        }
    }

}