Не обнаружил проекты, которые используются в примерах в лекции, также не увидел список задач. |
Финальный проект
Класс Person
Этот класс является прямым потомком класса Figure. Вместе с тем, класс является клиентом трех других классов семейства - Circle, Rect и LittleCircle, поскольку элементы фигуры, составляющие человечка, являются объектами этих классов.
namespace Shapes { /// <summary> /// Класс Person - потомок класса Figure, /// клиент классов Circle, Rect, LittleCircle. /// </summary> public class Person:Figure { int head_h; Circle head; Rect body; LittleCircle nose; public Person(int head_h, int x, int y): base(x,y) { //head_h - радиус головы, x,y - ее центр. //остальные размеры исчисляются относительно //размера головы. this.head_h = head_h; head = new Circle(head_h,x,y); int body_x = x; int body_y = y + 3*head_h; int body_w =2*head_h; int body_h = 4*head_h; body = new Rect(body_w, body_h, body_x,body_y); nose = new LittleCircle(x+head_h +2, y); } public override void Show(System.Drawing.Graphics g, System.Drawing.Pen pen, System.Drawing.Brush brush) { int h = Convert.ToInt32(head_h*scale); //head int top_x = center.X - h; int top_y = center.Y - h; g.DrawEllipse(pen, top_x,top_y, 2*h,2*h); g.FillEllipse(brush, top_x,top_y, 2*h,2*h); //body top_y += 2*h; g.DrawRectangle(pen, top_x,top_y, 2*h,4*h); g.FillRectangle(brush, top_x,top_y, 2*h,4*h); //nose top_y -=h; top_x += 2*h; g.DrawEllipse(pen, top_x,top_y, 8,8); g.FillEllipse(brush, top_x,top_y, 8,8); } public override System.Drawing.Rectangle Region_Capture() { int h = Convert.ToInt32(head_h*scale); int top_x = center.X - h; int top_y = center.Y - h; return new System.Drawing.Rectangle(top_x,top_y,2*h,2*h); } } }
Список с курсором. Динамические структуры данных
Добавим в проект классы, задающие динамические структуры данных. Конечно, можно было бы воспользоваться стандартными... Но для обучения крайне полезно уметь создавать собственные классы, задающие такие структуры данных. Список с курсором - один из важнейших образцов подобных классов:
using System; namespace Shapes { /// <summary> /// Класс TwoWayList(G) описывает двусвязный список с /// курсором. Элементами списка являются объекты /// TwoLinkable, хранящие, помимо указателей на двух /// преемников, объекты типа G.Курсор будет определять /// текущий (активный) элемент списка. Класс будет /// определять симметричные операции по отношению к /// курсору. /// Конструкторы: /// Конструктор без параметров будет создавать пустой /// список /// Запросы: /// empty: require: true; возвращает true для пустого списка /// item: require: not empty(); возвращает активный элемент типа G; /// require: true; возвращает число элементов списка; /// count: count in[0,n] (count == 0) eqviv empty(); /// index: require: not empty(); возвращает индекс активного элемента. /// search_res: require: true; возвращает true, если последний поиск был успешным. /// Команды: /// put_left(elem): require: true; /// ensure: добавить новый элемент (elem) слева от курсора; /// put_right(elem): require: true; /// ensure: добавить новый элемент (elem) справа от курсора; /// remove: require: not empty(); /// ensure: удалить активный элемент; /// особо обрабатывается удаление последнего и единственного элементов /// операции с курсором: /// start: require: true; /// ensure: сделать активным первый элемент; /// finish: require: true; /// ensure: сделать активным последний элемент; /// go_prev: require: not (index = 1); /// ensure: сделать активным предыдущий элемент; /// go_next: require: not (index = count); /// ensure: сделать активным последующий элемент; /// go_i(i): require: (i in [1, count]); /// ensure: сделать активным элемент с индексом i; /// операции поиска: /// search_prev(elem): require: not (index = 1); /// ensure: сделать активным первый элемент elem слева от курсора; /// Успех или неуспех поиска сохранять в булевской /// переменной search_res /// search_next: require: not (index = count); /// ensure: сделать активным первый элемент elem справа от курсора; /// успех или неуспех поиска сохранять в булевской переменной search_res /// </summary> public class TwoWayList { public TwoWayList() { first = cursor = last = null; count = index = 0; search_res = false; }//конструктор /// <summary> /// first, cursor, last - ссылки на первый, /// активный и последний элементы списка /// Запросы count, index search_res также /// реализуются атрибутами. /// Запросы empty, item реализуются функциями /// </summary> protected TwoLinkable first, cursor, last; protected int count, index; protected bool search_res; //доступ на чтение к закрытым свойствам; public int Count { get { return(count); } } public int Index { get { return(index); } } public bool Search_res { get { return(search_res); } } /// <summary> /// require: true; возвращает true для непустого списка /// </summary> /// <returns></returns> public bool empty() { return(first == null); }//empty /// <summary> /// require: not empty(); возвращает активный /// элемент типа G; /// </summary> /// <returns></returns> public Figure item() { return(cursor.Item); }//item /// <summary> /// require: true; /// ensure: добавить новый элемент (elem) слева /// от курсора; /// </summary> /// <param name="elem">Тип Figure играет роль /// родового типа G /// хранимого элемента elem</param> public void put_left(Figure elem) { TwoLinkable newitem = new TwoLinkable(); newitem.Item = elem; newitem.Next = cursor; if (empty()) //список пуст { first = cursor = last = newitem; index =1; count = 1; } else { if (index == 1) first =newitem; else cursor.Prev.Next = newitem; newitem.Prev = cursor.Prev; cursor.Prev = newitem; count++; index++; } }//put_right /// <summary> /// require: true; /// ensure: добавить новый элемент (elem) справа /// от курсора; /// </summary> /// <param name="elem">Тип Figure играет роль /// родового типа G /// хранимого элемента elem</param> public void put_right(Figure elem) { TwoLinkable newitem = new TwoLinkable(); newitem.Item = elem; newitem.Prev = cursor; if (empty()) //список пуст { first = cursor = last = newitem; index =1; count = 1; } else { if (index == count) last =newitem; else cursor.Next.Prev = newitem; newitem.Next = cursor.Next; cursor.Next = newitem; count++; } }//put_right public void remove() { if(count == 1) { first = last = cursor = null; index=0; } else if(index==1) { first = cursor.Next; cursor.Prev = null; cursor = cursor.Next; } else if(index == count) { last = cursor.Prev; cursor.Next = null; cursor = cursor.Prev; index--; } else { cursor.Prev.Next = cursor.Next; cursor.Next.Prev = cursor.Prev; cursor = cursor.Next; } count--; }//remove /// операции с курсором: /// <summary> /// start: require: true; /// ensure: сделать активным первый элемент; /// </summary> public void start() { cursor = first; index = 1; }//start /// <summary> /// finish: require: true; /// ensure: сделать активным последний элемент; /// </summary> public void finish() { cursor = last; index = count; }//finish /// <summary> /// go_prev: require: not (index = 1); /// ensure: сделать активным предыдущий элемент; /// </summary> public void go_prev() { cursor = cursor.Prev; index--; }// go_prev /// <summary> /// go_next: require: not (index = count); /// ensure: сделать активным последующий элемент; /// </summary> public void go_next() { cursor = cursor.Next; index++; }// go_next /// <summary> /// go_i(i): require: (i in [1, count]); /// ensure: сделать активным элемент с индексом i; /// </summary> /// <param name="i"></param> public void go_i(int i) { if(i >index) while (i>index) { cursor = cursor.Next; index++; } else if(i<index) while (i<index) { cursor = cursor.Prev; index--; } }// go_i /// операции поиска: /// <summary> /// search_prev(elem): require: not (index = 1); /// ensure: сделать активным первый элемент elem /// слева от курсора; /// </summary> /// <param name="elem">искомый элемент</param> public virtual void search_prev(Figure elem) { bool found = false; while (!found && (index !=1)) { cursor = cursor.Prev; index--; found = (elem == item()); } search_res = found; }// search_prev /// <summary> /// успех или неуспех поиска сохранять в булевской /// переменной search_res /// search_next: require: not (index = count); /// ensure: сделать активным первый элемент elem /// справа от курсора; /// успех или неуспех поиска сохранять в булевской /// переменной search_res /// </summary> /// <param name="elem"></param> public virtual void search_next(Figure elem) { bool found = false; while (!found && (index !=count)) { cursor = cursor.Next; index++; found = (elem == item()); } search_res = found; }//search_next } }
Заметьте, класс подробно документирован. Для методов класса указываются предусловия и постусловия. Обратите внимание, в соответствии с принципами контрактного программирования клиент класса, прежде чем вызвать метод, должен проверить выполнимость предусловия, что повышает корректность работы системы в целом. Именно так и будет реализован вызов этих методов в классе формы, где осуществляется работа со списком.