Задача «Карточная игра "Go fish"»

Задача

Произвести рефакторинг кода на C, реализующего детскую карточную игру Go Fish.

Исходный код

  • fish.c – код программы на одном из старых диалектов C, но, тем не менее, с минимальными модификациями собирается современными компиляторами.

Описание

Поскольку игра мало распространена в России, то приводим краткое описание правил.

  • В игре участвуют от 2 до 10 игроков (в данной программе реализовано 2 игрока).
  • Игра ведётся стандартной колодой на 52 карты.
  • Цель игры – собрать как можно больше стопок с картами одинакового достоинства (все двойки, все тузы, все десятки и т.п.)
  • В начале игры игрокам случайно раздаётся по 7 карт (или по 5 карт, если игроков 5 и более).
  • Оставшиеся карты складываются в общую стопку рубашкой вверх. Эта стопка называется "ocean" или "pool", т.е. "океан" или "бассейн", т.е. место откуда можно выудить рыбу.
  • Игроки ходят по очереди.
  • Игрок, к которому перешёл ход, задаёт противнику вопрос о картах определённого достоинства, например "у тебя есть семёрки?"
    • У игрока должна быть хотя бы одна карта того достоинства, которое он запрашивает у противника.
    • Если у противника запрошенных карт нет, то он отвечает "Go fish" – "сходи поймай", и игрок достаёт себе 1 карту из "океана" – общей колоды.
    • Если у противника есть карты запрошенного достоинства, то он отдаёт их задавшему вопрос.
    • Если игрок забирает у противника запрошенные карты, то ход остаётся у него, и он может сделать ещё один запрос на карту какого-либо достоинства.
    • Если игрок достаёт из общей стопки – "океана" карту запрошенного достоинства, то он получает право взять из общей стопки ещё одну карту. Таким образом возможна ситуация когда игрок подряд достаёт из общей колоды до 4 карт подряд.
  • После того, как игрок "выудил" из общей колоды карту не того достоинства которое запрашивал, ход переходит следующему игроку.
  • Как только у игрока набралось 4 карты одного достоинства, он их выкладывает рядом с собой в отдельную стопочку лицом вверх. Эти карты "выиграны" игроком, и в дальнейшей игре не участвуют.
  • Игра заканчивается после того, как все карты "выиграны" игроками. Побеждает тот, кто "выиграл" больше карт.

В процессе рефакторинга необходимо:

  • Переписать код на C++ (объявление переменных не в начале блока, а там где они реально используются, убрать анахронизмы языка C, и т. п.)
  • Избавиться от define'ов (объявление констант) и глобальных переменных.
  • Избавиться от goto.
  • Текстовый ввод / вывод производить через std::cout и т.п. Выделить текстовый ввод / вывод в отдельный класс / модуль.
  • Обработку ошибок перенести на механизм исключений и std::exception.
  • По возможности заменить примитивные структуры данных наподобие массивов на std::array либо std::vector, std::stack, std::queue или другие.
  • Выделить класс игрока, который занимается вводом / выводом, передачей указаний пользователя.
  • Выделить класс компьютерного игрока, который реализует некоторое AI.
  • Реализовать класс игры, который будет реализовывать правила игры, вызов игроков, сообщать игрокам доступную информацию.
  • Возможно использование паттерна стратегия для этих классов.
  • На дополнительный балл: Подготовить код к возможности игры на 3 и более игроков (1 человек + компьютерные игроки).

Архив с проектами для Visual Studio 2013 и Visual Studio 2015.