    001: #include <cstdlib>
    002: #include <cmath>
    003: #include <ctime>
    004:
    005: using namespace std;
    006:
    007: #include "ccc_win.h"
    008: #include "ccc_time.h"
    009:
    010: const double PI = 3.141592653589793;
    011:
    012: /**
    013:    A clock that can draw its face.
    014: */
    015: class Clock
    016: {
    017: public:
    018:    /**
    019:       Constructs a clock with a given center and radius.
    020:       @param c the center of the clock
    021:       @param r the radius of the clock
    022:    */
    023:    Clock(Point c, double r);
    024:
    025:    /**
    026:       Sets the current time.
    027:       @param t the time to set
    028:    */
    029:    void set_time(Time t);
    030:
    031:    /**
    032:       Draws the clock face, with tick marks and hands.
    033:    */
    034:    void draw() const;
    035: private:
    036:    /**
    037:       Draw a tick mark (hour or minute mark).
    038:       @param angle the angle in minutes (0...59, 0 = top)
    039:       @param length the length of the tick mark
    040:    */
    041:    void draw_tick(double angle, double length) const;
    042:
    043:    /**
    044:       Draw a hand, starting from the center.
    045:       @param angle the angle in minutes (0...59, 0 = top)
    046:       @param length the length of the hand
    047:    */
    048:    void draw_hand(double angle, double length) const;
    049:
    050:    Time current_time;
    051:    Point center;
    052:    double radius;
    053: };
    054:
    055: /**
    056:    The player of the clock game.
    057: */
    058: class Player
    059: {
    060: public:
    061:    /**
    062:       Constructs a player with no name, level 1, and score 0.
    063:    */
    064:    Player();
    065:
    066:    /**
    067:       Constructs a player with given name and level.
    068:       @param player_name the player name
    069:       @param initial_level the player's level (1...4)
    070:    */
    071:    Player(string player_name, int initial_level);
    072:
    073:    /**
    074:       Increments the score. Moves to next level if current
    075:       level complete
    076:    */
    077:    void increment_score();
    078:
    079:    /**
    080:       Gets the current level.
    081:       @return the level
    082:    */
    083:    int get_level() const;
    084:
    085:    /**
    086:       Gets the player's name.
    087:       @return the name
    088:    */
    089:    string get_name() const;
    090: private:
    091:    string name;
    092:    int score;
    093:    int level;
    094: };
    095:
    096: /**
    097:    The clock game.
    098: */
    099: class Game
    100: {
    101: public:
    102:    /**
    103:       Constructs the game with a default player.
    104:    */
    105:    Game();
    106:
    107:    /**
    108:       Plays the game while the player wants to continue.
    109:    */
    110:    void play();
    111:
    112:    /**
    113:       Reads player name and level.
    114:    */
    115:    void read_player_information();
    116:
    117:    /**
    118:       Plays a round, with up to two guesses.
    119:    */
    120:    void play_round();
    121: private:
    122:    /**
    123:       Makes a random time, depending on the level
    124:       @return the random time
    125:    */
    126:    Time random_time();
    127:
    128:    /**
    129:       Gets a time input from the user
    130:       @return  the time guessed by the user
    131:    */
    132:    Time get_guess();
    133:
    134:    Player player;
    135: };
    136:
    137: /**
    138:    Sets the seed of the random number generator.
    139: */
    140: void rand_seed()
    141: {
    142:    int seed = static_cast<int>(time(0));
    143:    srand(seed);
    144: }
    145:
    146: /**
    147:    Returns a random integer in a range.
    148:    @param a the bottom of the range
    149:    @param b the top of the range
    150:    @return a random number x, a <= x and x <= b
    151: */
    152: int rand_int(int a, int b)
    153: {
    154:    return a + rand() % (b - a + 1);
    155: }
    156:
    157: Clock::Clock(Point c, double r)
    158: {
    159:    center = c;
    160:    radius = r;
    161: }
    162:
    163: void Clock::set_time(Time t)
    164: {
    165:    current_time = t;
    166: }
    167:
    168: void Clock::draw_tick(double angle, double length) const
    169: {
    170:    double alpha = PI / 2 - 6 * angle * PI / 180;
    171:    Point from(
    172:       center.get_x() + cos(alpha) * radius * (1 - length),
    173:       center.get_y() + sin(alpha) * radius * (1 - length));
    174:    Point to(center.get_x() + cos(alpha) * radius,
    175:       center.get_y() + sin(alpha) * radius);
    176:    cwin << Line(from, to);
    177: }
    178:
    179: void Clock::draw_hand(double angle, double length) const
    180: {
    181:    double alpha = PI / 2 - 6 * angle * PI / 180;
    182:    Point from = center;
    183:    Point to(center.get_x() + cos(alpha) * radius * length,
    184:       center.get_y() + sin(alpha) * radius * length);
    185:    cwin << Line(from, to);
    186: }
    187:
    188: void Clock::draw() const
    189: {
    190:    cwin << Circle(center, radius);
    191:    const double HOUR_TICK_LENGTH = 0.2;
    192:    const double MINUTE_TICK_LENGTH = 0.1;
    193:    const double HOUR_HAND_LENGTH = 0.6;
    194:    const double MINUTE_HAND_LENGTH = 0.75;
    195:    for (int i = 0; i < 12; i++)
    196:    {
    197:       draw_tick(i * 5, HOUR_TICK_LENGTH);
    198:       int j;
    199:       for (j = 1; j <= 4; j++)
    200:          draw_tick(i * 5 + j, MINUTE_TICK_LENGTH);
    201:    }
    202:    draw_hand(current_time.get_minutes(), MINUTE_HAND_LENGTH);
    203:    draw_hand((current_time.get_hours() +
    204:       current_time.get_minutes() / 60.0) * 5, HOUR_HAND_LENGTH);
    205: }
    206:
    207: Player::Player()
    208: {
    209:    level = 1;
    210:    score = 0;
    211: }
    212:
    213: Player::Player(string player_name, int initial_level)
    214: {
    215:    name = player_name;
    216:    level = initial_level;
    217:    score = 0;
    218: }
    219:
    220: int Player::get_level() const
    221: {
    222:    return level;
    223: }
    224:
    225: string Player::get_name() const
    226: {
    227:    return name;
    228: }
    229:
    230: void Player::increment_score()
    231: {
    232:    score++;
    233:    if (score % 5 == 0 && level < 4)
    234:       level++;
    235: }
    236:
    237: Game::Game()
    238: {
    239: }
    240:
    241: void Game::play()
    242: {
    243:    rand_seed();
    244:    read_player_information();
    245:    string response;
    246:    do
    247:    {
    248:       play_round();
    249:       response = cwin.get_string(
    250:          "Do you want to play again? (y/n)");
    251:    }
    252:    while (response == "y");
    253: }
    254:
    255: void Game::read_player_information()
    256: {
    257:    string name = cwin.get_string("What is your name?");
    258:    int initial_level;
    259:    do
    260:    {
    261:       initial_level = cwin.get_int(
    262:          "At what level do you want to start? (1-4)");
    263:    }
    264:    while (initial_level < 1 || initial_level > 4);
    265:    player = Player(name, initial_level);
    266: }
    267:
    268: Time Game::random_time()
    269: {
    270:    int level = player.get_level();
    271:    int minutes;
    272:    if (level == 1) minutes = 0;
    273:    else if (level == 2) minutes = 15 * rand_int(0, 3);
    274:    else if (level == 3) minutes = 5 * rand_int(0, 11);
    275:    else minutes = rand_int(0, 59);
    276:    int hours = rand_int(1, 12);
    277:    return Time(hours, minutes, 0);
    278: }
    279:
    280: Time Game::get_guess()
    281: {
    282:    int hours;
    283:    do
    284:    {
    285:       hours = cwin.get_int("Please enter hours: (1-12)");
    286:    }
    287:    while (hours < 1 || hours > 12);
    288:    int minutes;
    289:    do
    290:    {
    291:       minutes = cwin.get_int("Please enter minutes: (0-59)");
    292:    }
    293:    while (minutes < 0 || minutes > 59);
    294:
    295:    return Time(hours, minutes, 0);
    296: }
    297:
    298: void Game::play_round()
    299: {
    300:    cwin.clear();
    301:    Time t = random_time();
    302:    const double CLOCK_RADIUS = 5;
    303:    Clock clock(Point(0, 0), CLOCK_RADIUS);
    304:    clock.set_time(t);
    305:    clock.draw();
    306:
    307:    Time guess = get_guess();
    308:    if (t.seconds_from(guess) != 0)
    309:       guess = get_guess();
    310:
    311:    string text;
    312:    if (t.seconds_from(guess) == 0)
    313:    {
    314:       text = "Congratulations, " + player.get_name()
    315:          + "! That is correct.";
    316:       player.increment_score();
    317:    }
    318:    else
    319:       text = "Sorry, " + player.get_name()
    320:          + "! That is not correct.";
    321:    cwin << Message(Point(-CLOCK_RADIUS, CLOCK_RADIUS + 1), text);
    322: }
    323:
    324: int ccc_win_main()
    325: {
    326:    Game clock_game;
    327:    clock_game.play();
    328:
    329:    return 0;
    330: }