Суббота, Сентябрь 19, 2020

Home

home form   

    abstract class Location
    {
        public Location[] Exits;
        private string name;
        public string Name
        {
            get { return name; }
        }
        public Location(string name){
            this.name=name;
        }
        public virtual string Description
        {
            get
            {
                string description = "Вы находитесь в "+ name+ ". Вы видите двери, ведущие в: ";
                for (int i = 0; i < Exits.Length; i++)
                {
                    description += " " + Exits[i].Name;
                    if (i != Exits.Length - 1)
                        description += ",";
                }
                description += ". ";
                return description;
            }
        }
    }

 

    class Room:Location
    {
        private string decoration;
        public override string Description
        {
            get
            {
                return base.Description+" Вы видите " +decoration + ".";
            }
        }
        public Room(string name, string decoration)
            : base(name)
        {
            this.decoration = decoration;
        }
    }

 

    class Outside:Location
    {
        private bool hot;
        public bool Hot { get { return hot; } }
        public Outside(string name, bool hot)
            : base(name)
        {
            this.hot = hot;
        }
        public override string Description
        {
            get
            {
                string NewDescription = base.Description;
                if (hot)
                    NewDescription += " Очень жарко.";
            
                return NewDescription;
            }
        }
    }

 

    interface IHasExteriorDoor
    {
        string DoorDescription { get; }
        Location DoorLocation { get; set; }
    }

 

    class RoomWithDoor:Room,IHasExteriorDoor
    {
        private string doorDescription;
        public string DoorDescription
        {
            get { return doorDescription; }
        }
        private Location doorLocation;
        public Location DoorLocation
        {
            get { return doorLocation; }
            set { doorLocation = value; }
        }
        public RoomWithDoor(string name,string decoration, string doorDescription)
            : base(name, decoration)
        {
            this.doorDescription = doorDescription;
        }
    }

    class OutsideWithDoor:Outside,IHasExteriorDoor
    {
        private string doorDesription;
        public string DoorDescription
        {
            get { return doorDesription; }
        }
        private Location doorLocation;
        public Location DoorLocation
        {
            get { return doorLocation; }
            set { doorLocation = value; }
        }
        public override string Description
        {
            get
            {
                return base.Description+" Вы видите "+doorDesription+".";
            }
        }
        public OutsideWithDoor(string name,bool hot, string doorDesription)
            : base(name, hot)
        {
            this.doorDesription = doorDesription;
        }
    }

 

public partial class Form1 : Form
    {
        Location currentLocation;

        RoomWithDoor livingRoom;
        Room diningRoom;
        RoomWithDoor kitchen;

        OutsideWithDoor frontYard;
        OutsideWithDoor backYard;
        Outside garden;
        public Form1()
        {
            InitializeComponent();
            CreateObject();
            MoveToANewLocation(livingRoom);
        }
        private void CreateObject()
        {
            livingRoom = new RoomWithDoor("Гостиная","старинный ковер","дубовая дверь с латунной ручкой");
            diningRoom = new Room("Столовая","хрустальная люстра");
            kitchen = new RoomWithDoor("Кухня","плита из нержавеющей стали","сетчатая дверь");
            frontYard = new OutsideWithDoor("Лужайка",false, "дубовая дверь с латунной ручкой");
            backYard = new OutsideWithDoor("Задний двор",true, "сетчатая дверь");
            garden = new Outside("Сад", false);

            diningRoom.Exits = new Location[] { livingRoom, kitchen };
            livingRoom.Exits = new Location[] { diningRoom };
            kitchen.Exits = new Location[] { diningRoom };
            frontYard.Exits = new Location[] { backYard, garden };
            backYard.Exits = new Location[] { frontYard, garden };
            garden.Exits = new Location[] { backYard, frontYard };

            livingRoom.DoorLocation = frontYard;
            frontYard.DoorLocation = livingRoom;
            kitchen.DoorLocation = backYard;
            backYard.DoorLocation = kitchen;
        }
        private void MoveToANewLocation(Location newLocation)
        {
            currentLocation = newLocation;

            exits.Items.Clear();
            for (int i = 0; i < currentLocation.Exits.Length; i++)
                exits.Items.Add(currentLocation.Exits[i].Name);
            exits.SelectedIndex = 0;

            description.Text = currentLocation.Description;

            if (currentLocation is IHasExteriorDoor)
                goThroughTheDoor.Visible = true;
            else
                goThroughTheDoor.Visible = false;
        }
        private void goThroughTheDoor_Click(object sender, EventArgs e)
        {
            IHasExteriorDoor hasDoor = currentLocation as IHasExteriorDoor;
            MoveToANewLocation(hasDoor.DoorLocation);
        }

        private void goHere_Click(object sender, EventArgs e)
        {
            MoveToANewLocation(currentLocation.Exits[exits.SelectedIndex]);
        }
    }

//В модели дома классы будут представлять комнаты и прочие помещения, а интерфейс соответсвует двери.
//1)Начнем с модели классов.
//Каждая комната и помещение должны быть представлены отдельным объектом.
//Внутренние комнаты наследуют от класса Room, а внешние от класса Outside.
//Для этих классов в свою очередь имеется базовый класс Location с двумя полями: Name для названия помещения
//и Exits массив объектов, связанный с отдельными помещениями.
//В итоге запись diningRoom.Name будет иметь значение "Столовая",а запись dining.Exits будет соответствовать массиву {LiningRoom, Kitchen}.

home location
//2)Нарисуем план дома
//В доме три комнаты: лужайка(frontYard), задний двор(backYard) и сад(garden).
//Внешних дверей две: одна ведет из livingRoom на frontYard, а вторая - из kitchen на backYard.

home plan

 

//3)Для комнат с внешней дверью создадим интерфейс IHasExteriorDoor.
//Помещения с ведущими наружу дверями(frontYard, backYard, livingRoom и kitchen) должны реализовывать интерфейс IHasExteriorDoor.
//Предназначенное только для чтения свойство DoorDescription содержит описание двери(передняя дверь "Дубовая с латунной ручкой",
//в то время как сзади у нас "Калитка"). Свойство DoorLocation содержит ссылку на помещение, в которое ведет дверь(kitchen).

home interface

 

//4)Клаcc Location
    abstract class Location
    {
//Конструктор задает значение поля name, которое является
//предназначенным тольк для чтения полем Name.
        public Location(string name)
        {
            this.name = name;
        }
        private string name;
        public string Name
        {
            get { return name; }
        }
//Открытое поле Exits является массивом ссылок Location, котрый отслеживает,
//какие помещения связаны с тем, в котором находитесь вы.
        public Location[] Exits;
//Свойство Description возвращает строку с описание комнаты и всех прилегающих
//к ней помещений(их список содержится в поле Exits[]). Так как в производных
//классах описание будет меняться, свойство требуется перекрыть.
//Класс Room перекрывает и расширяет метод Description, добавляя к нему интерьер.
//К методу Outside он добавит температуру.
        public virtual string Description
        {
            get
            {
                string description = "Вы находитесь в " + name + ". Вы видите двери, ведущие в: ";
                for (int i = 0; i < Exits.Length; i++)
                {
                    description += " " + Exits[i].Name;
                    if (i != Exits.Length - 1)
                        description += ", ";
                }
                description += ". ";
                return description;
            }
        }
    }

 

//5)Создание классов
//Начнем с классов Room и Outside. Затем создадим еще два класса:
//OutsideWithDoor, наследующий от класса Outside и реализующий
//интерфейс IHasExteriorDoor и RoomWithDoor,который является производным
//от класса Room и также реализует интерфейс IHasExteriorDoor.
//Класс Room наследует от класса Location и добавляет вспомогательное
//поле для чтения свойства Decoration. Значение Decoration задает конструктор.
    class Room:Location
    {
        private string decoration;
        public override string Description
        {
            get
            {
                return base.Description+"Вы видите "+decoration+". ";
            }
        }
        public Room(string name, string decoration)
            : base(name)
        {
            this.decoration = decoration;
        }
    }

 

interface IHasExteriorDoor
    {
        string DoorDescription { get; }
        Location DoorLocation { get; }
    }

 

//Класс Outside во мнгом подобен классу Room. Он тоже является производным
//от класса Location и добавляет вспомогательное поле для свойства Hot.
//Это свойство используется в свойстве Desription.
    class Outside:Location
    {
        private bool hot;
        public bool Hot { get { return hot; } }
        public Outside(string name, bool hot)
            : base(name)
        {
            this.hot = hot;
        }
        public override string Description
        {
            get
            {
                string NewDesription = base.Description;
                if (hot)
                    NewDesription += " Очень жарко.";
                return NewDesription;
            }
        }
    }

 

//Касс RoomWithDoor наследует класс Room и реализует интерфейс IHasExteriorDoor
//В дополнение к функциям класса Room в конструктор добавляется описание
//внешней двери. Появляется ссылка DoorLocation, указывающая, куда именно
//ведет дверь. Интерфейс IHasExterior требует свойств DoorDesrition и DoorLocation.
    class RoomWithDoor:Room,IHasExteriorDoor
    {
        private string doorDescription;
        public string DoorDescription
        {
            get { return doorDescription; }
        }
        private Location doorLocation;
        public Location DoorLocation
        {
            get { return doorLocation; }
            set { doorLocation = value; }
        }
        public RoomWithDoor(string name, string decoration, string doorDescription)
            : base(name, decoration)
        {
            this.doorDescription = doorDescription;
        }
    }

 

//Класс OutsideWithDoor наследует класс Outside и реализует интерфейс IHasExteriorDoor.
//По виду он напоминает RoomWithDoor
    class OutsideWithDoor:Outside,IHasExteriorDoor
    {
        private string doorDescription;
        public string DoorDescription
        {
            get { return doorDescription; }
        }
        private Location doorLocation;
        public Location DoorLocation
        {
            get { return doorLocation; }
            set { doorLocation = value; }
        }
        //Свойство Description базового класса получает значение в зависимости
        //от того, будет ли жарко в рассматриваемом помещении. Оно зависит от
        //исходного свойства Description класса Location и поэтму включает
        //информацию о помещении ивыходах.
        public override string Description
        {
            get
            {
                return base.Description+" Вы видите " +doorDescription+".";
            }
        }
        public OutsideWithDoor(string name, bool hot, string doorDescription)
            : base(name, hot)
        {
            this.doorDescription = doorDescription;
        }
    }

 

//6)Как работают объекты.
//Рассмотрим архитектуру объектов frontYard и diningRoom. Из-за наличия дверей они должны
//быть экземплярами класса, реализующего интерфейс IHasExteriorDoor. Свойство DoorLocation
//хранит ссылку на помещение, расположенное по другие стороны дверей.

home object

 

//7)Закончим создание классов и создадим их экземпляры.
//Практически все готово для построения объектов. Вам осталось:
// * Убедиться, что конструктор класса Outside задает предназначенное только для чтения
//свойство Hot и перекрывает свойство Description, добавляя текст "Тут очень жарко",
//когда переменная Hot имеет значение true. Жарко должно быть на заднем дворе, но не
//на лужайке и не в саду.
// * Конструктор класса Room должен задавать свойство Decoration и перекрывать свойство
//Description, добавляя "Здесь вы видите (интерьер)". В гостиной находится старинный
//ковер, в столовой - хрустальная люстра, а на кухне - плита из нержавеющей стали и сетчатая
//дверь, ведущая на задний двор.
// * Форма должна создавать объекты и хранить на них ссылки. Добавьте метод CreatObjects(),
//который будет вызываться конструктором формы.
// * Создайте по экземпляру для шести помещений дома. Вот пример для гостиной:
        RoomWithDoor livingRoom = new RoomWithDoor("Гостиная",
            "старинный ковер", "дубовая дверь с латунной ручкой");
//Метод CreatObjects() должен добавлять поле Exits[] к каждому объекту:
        //Exits(массив ссылок Location), создает массив из двух строк.
        frontYard.Exits=new Location[]{backYard,garden};

 

//8)Построение формы
//Создадим простую форму для экскурсии по дому. Потребуется большое текстовое поле description,
//в котором будут появляться описания помещения. Элемент ComboBox с именем exits содержит список
//выходов из комнаты. Кнопка goHere перемещает вас в помещение, выбранное в ComboBox, а кнопка
//goThroughTheDoor появляется при наличии выхода наружу.

//9)Заставим форму работать.
//Осталось сединить друг с другом отдельные части.
// * Форме требуется поле с именем currentLocation, определяющее текущее положение.
// * Добавьте метод MoveToANewLocation() с параметром Location, присваивающий
//currentLocation новое значение. Затем он будет очищать раскрывающийся список
//при помощи метода Items.Add(). Наконец останется отобразить первый пункт
//раскрывающегося списка, присвоив его свойству SelectedIndex значение ноль.
// * В текстовом поле должно появиться описание текущего помещения.
// * Оператор is проверяет наличие дверей в помещении. При их обнаружении нужно
//отобразить кнопку Go through the door, воспользовавшись свойством Visible.
// * Щелчок на кнопке Go here должен перемещать в помещение, выбранное в
//раскрывающемся списке.
// * Щелчок на кнопке Go through the door должен приводить к перемещению через
//дверь.
        Location currentLocation;//Форма отслеживает, в какой комнате вы находитесь.
        //При помощи этих ссылочных переменных форма следит за каждым помещением в доме.
        RoomWithDoor livingRoom;
        Room diningRoom;
        RoomWithDoor kitchen;
        OutsideWithDoor frontYard;
        OutsideWithDoor backYard;
        Outside garden;
        public Form1()
        {
            InitializeComponent();
            CreateObject();
            MoveToANewLocation(diningRoom);
        }
        private void CreateObject()
        {
            //Создание объектов начинается с создания экземпляров и передачи
            //конструкторам этих экземплярв нужной информации.
            livingRoom = new RoomWithDoor("Гостиная", "старинный ковер", "дубовая дверь с латунной ручкой");
            diningRoom = new Room("Столовая", "хрустальная люстра");
            kitchen = new RoomWithDoor("Кухня", "плита из нержавеющей стали", "сетчатая дверь");
            frontYard = new OutsideWithDoor("Лужайка", false, "дубовая дверь с латунной ручкой");
            backYard = new OutsideWithDoor("Задний двор", true, "сетчатая дверь");
            garden = new Outside("Сад", false);
            //Здесь заполняется массив Exits[] для каждого из экземпляров.
            //Данная процедура возможна только после создания всех экземпляров!
            diningRoom.Exits = new Location[] { kitchen, livingRoom };
            livingRoom.Exits = new Location[] { diningRoom};
            kitchen.Exits = new Location[] { diningRoom };
            frontYard.Exits = new Location[] { garden, backYard };
            backYard.Exits = new Location[] { frontYard, garden };
            garden.Exits = new Location[] { frontYard, backYard };
            //Для объектов IHasExteriorDoor нужно указать положение дверей.
            livingRoom.DoorLocation = frontYard;
            frontYard.DoorLocation = livingRoom;
            kitchen.DoorLocation = backYard;
            backYard.DoorLocation = kitchen;

        }
        //Показывает в форме новое помещение.
        private void MoveToANewLocation(Location newLocation)
        {
            currentLocation = newLocation;
            //Сначала нужно очистить раскрывающийсясписок
            exits.Items.Clear();
            //Затем заполняем список названиями помещений.
            for (int i = 0; i < currentLocation.Exits.Length; i++)
                exits.Items.Add(currentLocation.Exits[i].Name);
            //Присвоение переменной SlectedIndex значения ноль
            //отображает первый пункт списка.
            exits.SelectedIndex = 0;
            description.Text = currentLocation.Description;
            //Проверяем - у комнаты есть дверь наружу?
            if (currentLocation is IHasExteriorDoor)
                //Да есть. Делаем кнопку видимой
                goThroughTheDoor.Visible = true;
            else
                //Нет. Делаем кнопку невидимой.
                goThroughTheDoor.Visible = false;
        }
        private void goThroughTheDoor_Click(object sender, EventArgs e)
        {
            //Оператор as осуществляет нисходящее приведение currentLocation
            //к IHasExteriorDoor, что дает нам доступ к полю DoorLocation
            IHasExteriorDoor hasDoor = currentLocation as IHasExteriorDoor;
            MoveToANewLocation(hasDoor.DoorLocation);
        }
        //Пермещаемся в выбранное помещение.
        private void goHere_Click(object sender, EventArgs e)
        {
            MoveToANewLocation(currentLocation.Exits[exits.SelectedIndex]);
        }
    }


Back to Top