Последний Minesweeper (C++/QT)

Опубликовано Dec 18, 2012 в Игры, Хорошие проекты студентов | 3 коммент.

, , ,

Последний Minesweeper (C++/QT)

Задача про игру “САПЕР” вызвала живой интерес.

Вариантов прислано даже больше, чем ожидалось, поэтому рассмотрение и обсуждение продвигается медленнее, чем рассчитывали. Это последний вариант решения – теперь на QT, после которого предлагается покрутить другую задачу, например, “МОРСКОЙ БОЙ”.
Отправной точкой было сообщение, c приложенным кодом проекта – реализацией игры, который автор разрешил использовать на сайте для разбора и обсуждения. Первый вариант целиком выкладываться не будет, кроме частей, которые важны с точки зрения сделанных замечаний, а диаграмма классов была такой.

Диаграмма классов игры Сапер

Диаграмма классов игры Сапер

Замечания были такими

Дублирование кода

Очень много дублированного кода, который делает почти одно и то же, в зависимости от того, в какое место под if он попадает. Например, там где идет работа с грейдами игроков. . Еще, например, очень легко переписать метод SapperCell::paint, так, чтобы вызовы fStateCellBegin(painter) и fStateCellPress(painter) были помещены в код по одному разу, а не в каждый if.

void SapperCell::paint(QPainter *painter,
	    const QStyleOptionGraphicsItem *option,
        QWidget *widget)
{
	if(isSet)
	{
		painter->setRenderHint(QPainter::Antialiasing, false);
		painter->setFont(font);
 
		if(stateCell == begin)
			fStateCellBegin(painter);
		if(stateCell == flag)
		{
			fStateCellBegin(painter);
			painter->drawImage(QPointF(1, 2), imageFlag);
		}
		if(stateCell == what)
		{
			fStateCellBegin(painter);
			painter->setPen(Qt::black);
			painter->drawText(QRectF(QPointF(1, 1),
			 QSizeF(width, width)),
			 Qt::AlignHCenter | Qt::AlignVCenter, "?");
		}
		if(stateCell == press)
			fStateCellPress(painter);
		if(stateCell == press_what)
		{
			fStateCellPress(painter);
			painter->setPen(Qt::black);
			painter->drawText(QRectF(QPointF(1, 0),
			 QSizeF(width, width)),
			Qt::AlignHCenter | Qt::AlignVCenter, "?");
		}
		if(stateCell == number)
		{
			fStateCellPress(painter);
			painter->setPen(penNumber[numBombNeighbour - 1]);
			painter->drawText(QRectF(QPointF(1, 1),
			 QSizeF(width, width)),
			 Qt::AlignHCenter | Qt::AlignVCenter,
			 QString::number(numBombNeighbour));
		}
		if(stateCell == burn)
		{
			fStateCellPress(painter);
			painter->drawImage(QPointF(1, 1), imageBurn);
		}
		if(stateCell == bomb)
		{
			fStateCellPress(painter);
			painter->drawImage(QPointF(1, 1), imageBomb);
		}
		if(stateCell == bomb_false)
		{
			fStateCellPress(painter);
			painter->drawImage(QPointF(1, 1), imageBomb);
			painter->drawImage(QPointF(0, 0), imageCross);
		}
	}
}

Дублирование данных

В разных классах имеются поля с одинаковыми именами, и я подозреваю, что и с одинаковым смыслом, например, numBomb. Если это везде одно и то же (количество бомб) и все это как-то синхронизируется, – то от этой избыточности данных имеет смысл избавиться.

Используем ящики опускаем все вниз

Все классы имеют много полей. Возможно, стоит пересмотреть это и, пользуясь правилом “…определять все как можно ниже…” что-то сделать локальными переменными. Однотипные поля нужно объединять в контейнеры – очень хорошо, например,  укладываются в QMap поля, объявленные так:

QImage imageBomb, imageBurn, imageFlag, imageFlagGreen, imageFlagRed, imageCross;

Код проекта бы переработан автором с учетом этих замечаний. Из проекта по договоренности с автором убраны все данные, по которым можно его идентифицировать. Если автор пожелает – он сам имеет возможность указать данные о себе в комментариях.

Этот код рекомендуется к использованию для различных обучающих программ. Его ни в коем случае нельзя рассматривать как результат коммерческой деятельности компании FulcrumWeb


Автор публикации:

3 Коммент. : “Последний Minesweeper (C++/QT)”

  1. Автор программы says:

    Здравствуйте!
    Выполнил одно из тестовых заданий, размещенных на сайте FulcrumWeb. Буду рад Вашим комментариям.

    • Галина says:

      Я получила вашу реализация игры, архив раскрылся и запустился, спасибо.

      Замечание по поводу “Выполнил одно изтестовых заданий “.

      Тестовым заданием подобная задача не является и не может быть последующим причинам.

      1) Она очень известная, следовательно, имеется множество готовых нормальных решений.
      2) Она слишком громоздкая для тестового задания и требует, чтобы соискатель потратил слишком много своего неоплачиваемого времени на компанию,которая может и не стать работодателем, что не совсем корректно по отношению к соискателю.
      3) Будучи хорошо реализованной, данная задача вполне может являться полноценным самостоятельным коммерческим продуктом. Если бы идея игры была новой – вы (или мы) ее вполне бы могли пытаться продать, а для тестового задания эта ситуация очень скользкая и двусмысленная.

      Все эти факторы делают задачу непригодной для тестового задания,но очень хорошей для обучения, – для этого и мы даем подобные задачи на сайте для желающих.

    • Наверное, стоило бы сначала все продумать, а потом начинать кодировать.

Оставить комментарий

Ваш адрес email не будет опубликован.


*