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

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

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 03.08.2015, 15:45   #1
Buron Hoise
Заблокирован
 
Регистрация: 03.08.2015
Сообщений: 28
По умолчанию Как запрограммировать поле сапера используя ООП?

Мне сказали что я не разбираюсь в ООП, учу.

Пытаюсь сделать солвер для сапёра. До этого момента я всё делал в одном классе, сейчас создал ещё один, для поля сапёра. Для вот такого:



Для хранения этого поля я создал класс Field, который внутри - двухмерный массив классов Cell. Cell - число _number плюс геттеры сеттеры и немного вспомогательных методов.

Следующий шаг - добавить итерацию по всем ячейкам этого поля, и отложить нужные ячейки в список до лучших времен. Здесь начинаются "проблемы".

Я не уверен, делать Cell классом или структурой. Как я понял, разница между классом и структурой в том, что структуры всегда передаются целиком, а для классов передаётся только ссылки-указатели на них. Структура не будет так мучить сборщик мусора, поэтому это звучит как более удачное решение.

Если всё оставить по-простому, и делать доступ к нужной ячейке по её икс и игрек координатам, тогда итератор должен возвращать только икс игрек координаты вместо самих ячеек, и я должен запоминать сами координаты вместо конкретных Cell объектов. Не очень красиво.

Если всё сделать в лоб, то можно чтобы каждая Cell ещё и хранила свои координаты. Но это дублирование данных.

Если Ячейка будет классом, то можно сделать так, что итератор будет возвращать ссылки на эти ячейки, и список будет эти ссылки сохранять. Если потребуется узнать координаты ячейки, можно будет пройтись по всему Полю и сравнить каждую Ячейку с нужной. В C# ведь есть сравнение объектов на "одинаковость", что это один и тот же объект? Но это наверное не достаточно быстро.

Можно сделать чтобы итератор возвращал и Ячейку и координаты. Однако yield return не может возвращать более одной переменной за раз? Хотя можно и создать новый класс CellWithCoordinates только для этого.

Мне нужен совет.
Buron Hoise вне форума Ответить с цитированием
Старый 03.08.2015, 20:29   #2
Akeloya
Форумчанин
 
Регистрация: 27.01.2014
Сообщений: 115
По умолчанию

Ну и примерчик

ООП не начинается с решения проблем доступа к данным. ООП - это подход, при котором приложение представляется в виде объектов и их взаимосвязей.

http://habrahabr.ru/post/147927/
http://habrahabr.ru/hub/oop/
http://professorweb.ru/my/csharp/cha...level3/3_1.php

Например, первый объект - игрок (счет, статистика, набор последних действий). Ячейка, хранящая данные о своем состоянии.
Поле, набор ячеек, функционал для рандомного размещения мин, установка состояний ячеек и проч.
Приложение - реализация игры.
Это если не особо вникать в суть вопроса.

Цитата:
В C# ведь есть сравнение объектов на "одинаковость", что это один и тот же объект?
сравнение объектов в лоб ничего не даст. Нужно писать реализацию IComparier.

Цитата:
Однако yield return не может возвращать более одной переменной за раз?
Не выдумываем и читаем MSDN

Цитата:
Если используется ключевое слово yield в инструкции, то это означает, что метод, оператор или метод доступа get в котором оно встречается, является итератором. Использование yield для определения итератора исключает необходимость применения явного дополнительного класса (в котором содержится состояние перечисления; в качестве примера см. IEnumerator) при реализации шаблонов IEnumerable и IEnumerator для пользовательского типа коллекции.

public static System.Collections.Generic.IEnumera ble<int> Power(int number, int exponent)
{
int result = 1;

for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}
https://msdn.microsoft.com/ru-ru/lib...v=vs.120).aspx

Замените тип данных int на любой другой, в частности, если вспомнить основы-основ программирования - структура и, в целом, класс, это составные типы данных. Понимаете, что вы можете вернуть ссылку на любой набор данных, особенно если он составной?

Последний раз редактировалось Akeloya; 03.08.2015 в 20:33. Причина: ыф
Akeloya вне форума Ответить с цитированием
Старый 03.08.2015, 22:30   #3
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Нужно писать реализацию IComparier.
нужно перегрузить Equals, и лучше еще и реализовать IEquatable.
IComparer более нужен для сортировки.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 03.08.2015, 23:04   #4
Buron Hoise
Заблокирован
 
Регистрация: 03.08.2015
Сообщений: 28
По умолчанию

В сишарпе возможно определить, что вот этот объект является именно этим объектом, а не очень похожим на него объектом с одинаковыми полями? Более строгое равенство, как это назвать лучше. Что две переменные ссылаются на один и тот же объект.

yield return не может зайелдить несколько переменных за раз? foreach (var x, y in AllCoordinates())
Buron Hoise вне форума Ответить с цитированием
Старый 04.08.2015, 08:24   #5
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

есть ReferenceEqual равенство ссылок.
так же можно переопределить object.Equals что он проверял на точное равенство.

вы можете возвращать структуру Point например.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 04.08.2015, 09:22   #6
Selestis
Форумчанин
 
Аватар для Selestis
 
Регистрация: 21.01.2009
Сообщений: 719
По умолчанию

Ну и как бы обычное равно (a == b) для объектов работает именно так - проверяет равенство ссылок. Если не переопределен оператор сравнения. И не надо никаких Equals и IComparer.
Изобретатель велосипедов
Selestis вне форума Ответить с цитированием
Старый 04.08.2015, 10:06   #7
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Вот здесь есть инструкция по созданию сапёра. Там пишется он за 85 строк кода на C#.
8Observer8 вне форума Ответить с цитированием
Старый 04.08.2015, 10:38   #8
Buron Hoise
Заблокирован
 
Регистрация: 03.08.2015
Сообщений: 28
По умолчанию

Знаете что, я сделаю для них вот такой интерфейс, а дальше пусть крутится как хочет. Мне должно быть без разницы что там внутри.
Код:
Cell Field.GetCell(int x, int y)
IEnumerable<Cell> Field.IterateAllCells()
IEnumerable<Cell> Field.IterateNearbyCells()
Field.DebugMessageBox()
static Field Field.ReadFieldFromScreen()
Field Field.Clone()

bool Cell.IsNumber()
int Cell.GetNumber()
bool Cell.IsEmpty()
bool Cell.IsMine()
Cell сделаю ссылкой на поле и координатами.

Стоп, если я сделаю редактирование Поля через Ячейку, мне придётся делать внутреннее состояние Поля как public. Но как тогда сделать, чтобы никто не мог менять состояние Поля напрямую, в обход Ячейки? Как-то объявить переменную внутри Поля как [accessableOnlyFrom(Cell)].

Я вообще знаете как всё это себе представляю? Как граф зависимости классов, который не просто нарисован где-то там на бумаге, а который есть прямо на мониторе, привязан к коду, и который проверяется на корректность при изменении кода. Чтобы неправильный доступ подчёркивался прямо в IDE. Интересно, кто-нибудь уже сделал такое? Это кажется базовой функциональностью, почему никто ещё не сделал этого?

И вообще мне нужны утилиты по визуализации кода, как можно нагляднее и работающие и для чужого кода. И ещё для парсинга и быстрого модифицирования. Надеюсь вы знаете что-нибудь такое.

И надеюсь ответите побыстрее, ждать от (большинства из) вас двух предложений два дня несколько...

ПРАВКА: Мне нашлось nested classes, думаю самое оно. Не самое гибкое решение, но для этой задачи будто создано. Для задач посерьёзней надо бы какой-то контроль доступа более настраиваемый.

Что делать с кодом для дебага? Я там добавил немного мелочи вроде месседжбоксов, чтобы посмотреть как оно работает. Удалять жалко, потом может понадобиться. В комментариях держать как-то тоже не очень, надо чтобы студия всё видела. Нерешительность. Может в if(false) поместить? Никогда не выполняющийся код помещается в ехе, или оптимизируется в ничто? Как там посмотреть на сгенерированный код и что-то понять?

Хотите на код посмотреть? Покритиковать там, всё такое.

Последний раз редактировалось Stilet; 10.09.2015 в 11:58.
Buron Hoise вне форума Ответить с цитированием
Старый 05.08.2015, 21:44   #9
Buron Hoise
Заблокирован
 
Регистрация: 03.08.2015
Сообщений: 28
По умолчанию

Надо бы это на Enum переделать. Наверное.

Код:
        public static readonly string[] familiarFieldsFileNames = new string[] 
        { "_", "0", "1", "2", "3", "4", "5", "6", "7", "8", "+", "X", "F", "W", "O" };
        private static readonly int[] familiarFieldsNumbers = new int[] 
        { -1,   0,   1,   2,   3,   4,   5,   6,   7,   8,  -2,  -3,  -4,  -5,  -6 };
Строки - это имена изображений, цифры - для перевода значения ячейки в число.

Строки использую тогда, когда надо изменить или сравнить значение ячейки. Например, бомба там в 5,14 или флаг. А ещё я всё поле через МесседжБокс вывожу, используя именно строки. Удобно, но криво - шрифт не моноширинный, и я не знаю как это исправить.

Цифры для хранения. И так чуть проще узнать, число находится в ячейке, или например ячейка ещё не раскрыта. Если больше или равно 0 - значит цифра.

Там ещё кучка геттеров и сеттеров, которые показывают ячейку нужным боком по требованию. Когда надо - строка, когда надо - цифра.

Поначалу мне это показалось хорошей идеей, сейчас я в этом сомневаюсь.

Люблю эту скорость. Вас 7 миллиардов, но вы шевелитесь так медленно.

Статическая переменная, установленная в null, и проверка на null перед первым использованием работает так же как синглтон. Однако синглтон проверяет перед любым обращением, без него проверка должна быть скопипащена перед каждым обращением к переменной.

Ненавижу выбор. Выбирать сложно. Почему есть так много решений, как выбрать лучшее?

Последний раз редактировалось Stilet; 10.09.2015 в 11:59.
Buron Hoise вне форума Ответить с цитированием
Старый 05.08.2015, 23:54   #10
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Сообщение от Buron Hoise Посмотреть сообщение
Статическая переменная, установленная в null, и проверка на null перед первым использованием работает так же как синглтон. Однако синглтон проверяет перед любым обращением, без него проверка должна быть скопипащена перед каждым обращением к переменной.

Ненавижу выбор. Выбирать сложно. Почему есть так много решений, как выбрать лучшее?
могу добавить в копилку выбора еще и класс Lazy
Цитата:
Надо бы это на Enum переделать. Наверное.
я часто там делаю некий класс, одно поле хранит читаемое, второе внутреннее.
Цитата:
Люблю эту скорость. Вас 7 миллиардов, но вы шевелитесь так медленно.
кого нас? тут пользователей всего 4349 зарегистрировано.
Цитата:
Я вообще знаете как всё это себе представляю? Как граф зависимости классов, который не просто нарисован где-то там на бумаге, а который есть прямо на мониторе, привязан к коду, и который проверяется на корректность при изменении кода. Чтобы неправильный доступ подчёркивался прямо в IDE. Интересно, кто-нибудь уже сделал такое? Это кажется базовой функциональностью, почему никто ещё не сделал этого?
потому что редко все же рисуют потом генерируют. да и вроде в последней студии что-то подобное видел.
обычно это редко нужно.

вы можете инкапусировать достаточно.
например имея модификатор internal у set-тера свойства вы сможете присвоить значение только из той же сборки(проекта)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.

Последний раз редактировалось Пепел Феникса; 05.08.2015 в 23:57.
Пепел Феникса вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Используя ООП создать в динамической памяти фигуру, представляющую связный список отдельных объектов (C#) BaHDaJl Помощь студентам 0 20.06.2012 15:42
Добавить в XML дополнительное поле используя appendChild. Alfiks Microsoft Office Excel 1 14.03.2011 12:59
Как можно используя IdHttp обратиться к серверу по IP не используя доменное имя. Chasow Работа с сетью в Delphi 1 06.04.2010 04:16