Виталий Рычков
Пример выполнения задания на Visual C++
Задание: Есть базовый класс "мишень", а также порожденные от него классы "обычная круговая мишень", "мишень в виде человеческого силуэта". Реализация набора мишеней - загрузка из файла мишеней разных видов и их расположения на экране. Выстрел - пользователь вводит координаты и получает сообщение, в какую именно мишень он попал или не попал ни в одну. Создать иерархию классов: базовый класс "Абстрактная мишень" с набором виртуальных функций отрисовки и проверки попадания в мишень, а также порожденные от него классы, перекрывающие виртуальные функции в зависимости от типа мишени. Список мишеней хранится в программе как список указателей на базовый класс, для которых при отрисовке и проверке попадания должны вызываться соответствующие функции.

Так работает эта программа после завершения её реализации.
Запускается приложение, на экране появляется окно с изображениями разных мишеней. Мишени имеют две формы: круговая и силуэтная. При этом мишени отличаются в размерах.
При выборе пункта меню «Стрельба – Координаты…» появляется окно диалога, в которое нужно ввести координаты цели и подтвердить их. В результате на экране появится пятно, которое указывает точку попадания, соответствующую введённым координатам.
В строке состояния появляется сообщение о результатах выстрела.



Как реализована эта программа на Visual C++? 
Это текст заголовочного файла, в котором описаны классы мишеней и списка указателей на объекты базового класса мишени.

#pragma once

#include <list>

 

enum TARGET_TYPE

{

      TARGET_UNKNOWN,

      TARGET_CIRCLE,

      TARGET_HUMAN,

};

 

class CTarget

{

public:

      LPCTSTR GetName();

      POINT GetCoord();

      void  SetCoord(int nX, int nY);

      SIZE  GetSize();

      void  SetSize(int nCX, int nCY);

      virtual enum TARGET_TYPE GetType()

      {

            return TARGET_UNKNOWN;

      }

      virtual BOOL Draw(HDC hdc)

      {

            return FALSE;

      }

      virtual BOOL PtInTarget(POINT pt);

      CTarget(LPCTSTR szName, LPPOINT lpPt = NULL);

      virtual ~CTarget(void);

private:

      POINT m_ptCoord;

      TCHAR m_szName[24];

      SIZE  m_sz;

};

 

typedef CTarget *LPTARGET;

 

class CTargetCircle : public CTarget

{

public:

      CTargetCircle(LPCTSTR szName, LPPOINT lpPt = NULL);

      virtual enum TARGET_TYPE GetType()

      {

            return TARGET_CIRCLE;

      }

      virtual BOOL Draw(HDC hdc);

      virtual BOOL PtInTarget(POINT pt);

      void SetDefaultSize();

};

 

class CTargetHuman : public CTarget

{

public:

      CTargetHuman(LPCTSTR szName, LPPOINT lpPt = NULL);

      virtual enum TARGET_TYPE GetType()

      {

            return TARGET_HUMAN;

      }

      virtual BOOL Draw(HDC hdc);

      virtual BOOL PtInTarget(POINT pt);

      void SetDefaultSize();

};

 

class CTargetList

{

public:

      ~CTargetList();

      LPTARGET GetTarget(LPCTSTR szName);

      LPTARGET TargetByPoint(POINT pt);

      BOOL AddTarget(LPCTSTR szName, enum TARGET_TYPE type);

      BOOL DeleteTarget(LPCTSTR szName);

      size_t GetCount();

      void RemoveAll();

      void ToArray(LPTARGET* lppTarg, size_t nCount);

      BOOL SaveConfig();

      BOOL LoadConfig();

      BOOL DrawTargets(HDC hdc);

      static LPCTSTR szFileCfg;

private:

      std::list<LPTARGET> m_list;

};

 

CTargetList* GetTargetList();


BOOL PtInEllipse(LPRECT pRc, POINT pt);


Кроме этого в другом файле реализован класс CSetCoordDlg, который управляет окном диалога для ввода координат.



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



Как хранятся данные в файле Targets.txt?

type=1;left=50;top=50;width=100;height=100;name=Круг 1
type=2;left=300;top=30;width=60;height=120;name=Силуэт 1
type=1;left=250;top=250;width=150;height=150;name=Круг 3
type=2;left=50;top=230;width=90;height=180;name=Силуэт 3
type=1;left=500;top=30;width=125;height=125;name=Круг 2
type=2;left=525;top=250;width=75;height=150;name=Силуэт 2

Каждая строка в тексте описывает одну мишень. Параметр type определяет форму мишени: 1- круговая, 2 – силуэтная. Параметр name обозначает имя мишени. Каждая мишень должна иметь уникальное имя, мишени с повторяющимися именами игнорируются.
Загрузить данное приложение можно отсюда: Shooter.zip
Благодарю за внимание.