Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.09.2011, 17:07   #1
AJlekceu
Пользователь
 
Регистрация: 20.11.2010
Сообщений: 16
По умолчанию Миниигра наподобие Civilization

Всем зашедшим - привет.
И сразу к делу. Предположим, есть игра - пошаговая стратегия по типу Цивилизации Сида Мейера (Sid Meier's Civilization). Действие в ней происходит на прямоугольной доске вклетку размером Width x Height. Каждая клетка имеет набор свойств:

1. Особенность ландшафта:
- океан;
- мелководие;
- лёд;
- тундра;
- поле;
- пустыня.
2. Рельеф:
- без рельефа;
- холмы (только для тундры, поля и пустыни);
- горы (только для тундры, поля и пустыни).

По карте могут протекать реки. Река является непрерывной ломаной линия без самопересечений, которая идёт по границам клеток. Ни один сегмент реки не может проходить ни по одному из четырёх границ карты.

Есть игроки, в распоряжении которых имеются города и юниты. Город занимает одну клетку. На одной клетке не может быть более одного города. Юнит тоже занимает одну клетку. На одной клетке может быть бесконечное число юнитов одного игрока.

Игроки ходят по очереди, и если их, например, три, то очередность ходов будет такой 1, 2, 3, 1, 2, 3, ...

За ход игрок может давать поочерёдные указания любым своим юнитам перемещаться на одну клетку влево, вверх, вправо или вниз, и если указания легальны (см. ниже), то юниты исполняют их и затем утрачивают способность двигаться на этом ходу. Игрок за ход может приказать городам (всем, ни одному или выборочно) создавать разные юниты. Создание юнитов происходит моментально: приказ отдан - юнит появился на клетке с городом.

Каждый юнит имеет очки силы (некоторое натуральное число). Юниты бывают морские и сухопутные. Среди сухопутных есть также особый юнит, не имеющий очков силы - рабочий, о котором позже. Морские могут быть построены только в городе, клетка которого граничит с хотя бы одной морской клеткой. После постройки юнит оказывается в городе. Этот юнит может находиться только в океане, мелководии или на сухопутных клетках с городами своего игрока. Сухопутные юниты могут быть только на суше (в том числе на льду), кроме клеток с горами. Таким образом, юниту не может быть отдан приказ на перемещение на клетку, где он находиться не может. Кроме того, некоторые типы сухопутных юнитов не имеют возможности пересекать реку.

Наличие на клетке юнита(ов) этого же игрока не мешает другим его юнитам занимать эти клетки (как говорилось, на клетке может быть сколько угодно юнитов одного игрока). Однако если на клетке есть юнит(ы) другого игрока, то происходит битва по некоторым правилам между атаковавшим юнитом и самым сильным юнитом противника на той клетке. Атаку не может производить рабочий. В случае победы, атаковавший юнит теряет некоторое количество очков силы, и если на клетке, куда отдан приказ идти, не осталось юнитов врага, он перемещается на неё, а если юниты есть, то не перемещается. В случае поражения атаковавший юнит исчезает, а защищавшийся теряет некоторое количество очков силы. Очки силы восстановливаются до начального значения после вступления юнита в город своего игрока. Если сухопутный юнит вступает в город другого игрока, город переходит на сторону владельца этого юнита.

Рабочему, кроме приказа на передвижение, может быть отдан приказ на постройку города. Город может быть построен в тундре, поле или пустыне, при этом на клетке не должно быть гор. Приказ на постройку города можно отдать только если рабочий не совершал перемещений на этом ходу. После постройки города рабочий исчезает.

Цель победы - оставить противника без юнитов и городов.


Правил гораздо больше, а некоторые из приведённых выше на самом деле чуть сложнее, но для понимания сути этого достаточно. Для начала вопрос - какие именно классы следует создать, как организовать связи между ними и их объектами, какие, если надо, необходимо использовать паттерны? У меня есть решения этих вопросов, но я не уверен в их оптимальности. Далее следуют объявления необходимых классов, где я также вас прошу пожалуйста указать на изъяны. Понимаю, что tl;dr и всё такое, но всё-таки...
AJlekceu вне форума Ответить с цитированием
Старый 19.09.2011, 17:09   #2
AJlekceu
Пользователь
 
Регистрация: 20.11.2010
Сообщений: 16
По умолчанию

Существуют классы CKletka, CRiver, CMap, CUnit, CCity, CPlayer и CGame.

Реализацию класса клетки на C++ я представляю такой:

Код:
class CKletka {
public:
   UCHAR Land; //0 - океан, 1 - мелководие, ...
   UCHAR Relief; //0 - без рельефа, 1 - холмы, 2 - горы
   short UnitsOwner; //-1 - на клетке нет никаких юнитов, от 0 - номер игрока
   vector<USHORT> Units; //Это список индексов юнитов, находящихся на этой клетке
   short CityOwner; //-1 - на городе нет города, от 0 - номер игрока, чей город расположен на клетке
};
Реализация класса реки:

Код:
class CRiver {
public:
   USHORT StartX; //}
   USHORT StartY; //}координаты стартовой клетки (первый сегмент находится справа или снизу от неё)
   UCHAR StartRotation; //положение первого сегмента относительно стартовой клетки: 0 - справа, 1 - снизу.
   vector<UCHAR> Directions; //направления сегментов относительно предшествующих: 0 - вправо, 1 - вниз, 2 - влево, 3 - вверх

   USHORT X(USHORT Index); //}
   USHORT Y(USHORT Index); //}координаты клетки с индексом Index (StartX = X(0), StartY = Y(0)). 
   USHORT Rotation(USHORT Index); //направление сегмента с индексом Index (StartRotation = Rotation(0)).
};
Этот класс можно оптимизировать, введя массив, где хранятся координаты клеток, чтобы в функциях X и Y не пришлось каждый раз
выполнять циклы. Но в этом случае к StartX, StartY, StartRotation и Directions надо будет ограничить доступ, и воспользоваться, например, паттерном Строитель.


Реализация класса карты:

Код:
class CMap {
   friend class CGame;
public:
   //объявляем Width и Height или переменными, или через функции Get/Set с использованием конструктора, или ещё как-нибудь
   ...
   
   const CKletka& Kletka(USHORT X, USHORT Y) const; //возвращает ссылку на клетку с координатами X и Y
private:
   vector<CKletka> Kletki;   
};
Реализация класса юнита:

Код:
class CUnit {
public:
   bool Moved; //Передвигался на этом ходу или нет
   USHORT X; //}
   USHORT Y; //} координаты юнита
   USHORT Type; //тип юнита - рабочий, лучник, танк, эсминец и т.д.
   USHORT Health; //число текущего количества очков силы в десятых долях от номинально (от 0 до 10)
   double Power() const //возвращает double(MaxPower() * Health) / 10
   USHORT MaxPower() const; //возвращает Power(Type)
   bool CrossRiver() const; //возвращает CrossRiver(Type)

   static USHORT MaxPower(UCHAR _Type) const; //максимальное значение очков силы для типа TYPE юнита
   static bool CrossRiver(UCHAR _Type) const; //может ли юнит типа _Type пересекать реку; 
};
Реализация класса города:

Код:
class CCity {
public:
   bool Built; //На этом ходу город уже произвёл юнит или нет
   USHORT X; //}
   USHORT Y; //} координаты города
};

Реализация класса игрока:

Код:
class CPlayer {
   friend class CGame;
public:
   UCHAR GetUnitsCount() const; //возвращает число юнитов
   UCHAR GetCitiesCount() const; //возвращает число городов
   const CUnit& GetUnit(USHORT Index) const; //возвращает ссылку на юнит с индексом Index
   const CUnit& GetCity(USHORT Index) const; //возвращает ссылку на город с индексом Index
private:
   vector<CUnit> Cities;   
   vector<CUnit> Units;   
};

Реализация класса игры:

Код:
class CGame {
public:
   //всякие функции, связанные с началом и концом игры, а также функции приказов
   ...
   const CMap& GetMap() const; //возвращает ссылку на карту
   UCHAR PlayersCount; //возвращает кол-во игроков
   const CPlayer& Player(USHORT Index) const; //возвращает ссылку на игрока с индексом Index
private:
   CMap Map;
   vector<CPlayer> Players;
};
Разумеется, вопросы скорее по ООП, а не по С++, но скоро появятся другие вопросы, и для конкретизации я буду использовать именно этот язык, как и ответы хотелось бы видеть на нём же.
AJlekceu вне форума Ответить с цитированием
Старый 19.09.2011, 17:13   #3
AJlekceu
Пользователь
 
Регистрация: 20.11.2010
Сообщений: 16
По умолчанию

Буду очень рад даже самым маленьким замечаниям.
AJlekceu вне форума Ответить с цитированием
Старый 19.09.2011, 17:41   #4
the_deer_one
Участник клуба
 
Аватар для the_deer_one
 
Регистрация: 04.04.2010
Сообщений: 1,554
По умолчанию

Ну ты сначала реализуй и что-нибудь обязательно окажется криво, вот оно и будет не оптимальным.
p.s. сам просил маленькие замечания.
the_deer_one вне форума Ответить с цитированием
Старый 19.09.2011, 17:51   #5
AJlekceu
Пользователь
 
Регистрация: 20.11.2010
Сообщений: 16
По умолчанию

Кривым пока ничего не кажется, и я использовал такой подход не в одной своей игре, но вдруг есть подходы покруче?
Главная идея данного - это наличие двойной связи между игроками и картой: у игрока указывается положение юнитов и городов, а у карты указывается индексы юнитов и городов. Стоп. Индексы городов! Забыл, щас подправлю.

Код:
class CKletka {
public:
   UCHAR Land; //0 - океан, 1 - мелководие, ...
   UCHAR Relief; //0 - без рельефа, 1 - холмы, 2 - горы
   short UnitsOwner; //-1 - на клетке нет никаких юнитов, от 0 - номер игрока
   vector<USHORT> Units; //Это список индексов юнитов, находящихся на этой клетке
   short CityOwner; //-1 - на городе нет города, от 0 - номер игрока, чей город расположен на клетке
   USHORT City; //Индекс города игрока CityOwner
Так вот. Этот обход устраняет необходимость использования циклов для получения индекса юнита на клетке, как в случае, если бы связь была односторонней. Но может, связи следует быть отдельным классом? Или ещё что-нибудь.

Последний раз редактировалось AJlekceu; 19.09.2011 в 17:54.
AJlekceu вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Контeйнер TImage наподобие TPanel diamond82 Компоненты Delphi 4 05.07.2010 01:25
Что-то наподобие диаграммы.Help! Elden Microsoft Office Excel 1 08.11.2009 19:19
Функция наподобие Т() motorway Microsoft Office Excel 9 08.07.2009 18:45
Создание интерпретатора формул наподобие Excel-я x8i Microsoft Office Access 0 13.05.2009 15:49
Посоветуйте бесплатную программу наподобие Robosoft-а. G&R Софт 0 28.01.2009 14:03