Аватар для Leonin
6 / 6 / 3
Регистрация: 31.08.2015
Сообщений: 56

Игра "Змейка": советы по улучшению кода

31.08.2015, 06:29. Показов 5302. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем здрасте Только что зарегистрировался на форуме. Начал изучать программирование и c# где-то месяца полтора назад и вот сделал свою первую небольшую, но полноценную игрульку, пусть и на консоли: классическую змейку. А вопрос вообщем заключается в том, что я хотел бы узнать: какие я допустил ошибки в этой змейке, что посоветуете на будущее. Понимаю, что программирование инженерная профессия и каждый реализует свой проект по-своему. Но чем правильнее структура кода, тем легче идет дальнейшее продвижение проекта. Так вот жду ваших советов на основе этого кода. Интересно было бы узнать как бы вы сделали на моем месте. Змейку прикрепил в архиве.
Вложения
Тип файла: rar Snake game.rar (46.7 Кб, 158 просмотров)
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
31.08.2015, 06:29
Ответы с готовыми решениями:

Игра на WinForm: советы по улучшению
Доброе утро али день али ноч... Не важно! Главное что бы было добрым =) Я тут решил игру написать но так как я не чем кроме WF не...

Советы по улучшению и поиск косяков
Здравствуйте... Я сейчас занялся серьёзным созданием приложения.. Более мение интерфейс подогнал, радио воткнул, загрузку сделал. Вопрос!...

Оценка кода и советы по улучшению
Привет всем! Недавно закончил писать код, реализующий в консоли игру "Очко" (Двадцать одно). Хотелось бы получить конструктивную...

10
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10421 / 5151 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
31.08.2015, 08:10
Лучший ответ Сообщение было отмечено Leonin как решение

Решение

Leonin, В целом код хороший.
Несколько замечаний:
1) В C# принята в основном CamelNotation, а у вас почти все идет через подчеркивание:
Check_control_keys_in_RT -> CheckControlKeysInRt
2) Метод Check_control_keys_in_RT сделан неоптимально, повторяющийся код.
3) if (Game.started == false) -> if (!Game.started)
4) В классе Apple: Random rnd; -> static Random rnd;
5) Местами неоптимален алгоритм. Например при создании яблока: "//Проверяем, не совпадает ли она с какой либо позицией сегментов змейки" Зачем? Ведь есть класс field, который содержит все занятые клетки.
6) Сам алгоритм змейки тоже неоптимален. Зачем вы сдвигаете все сегменты змейки каждый раз? Ведь достаточно передвинуть голову и забрать один сегмент из конца. Заодно и структура Turn - не понадобится (она лишняя в любом случае, да еще и неоднородно внутри).
7) Поля public List<Turn> turns; и public List<Point> eated_places; - не нужны.
8) Зачем класс Segment содержит направление? Направление имеет только голова, остальные части змеи - нет. Соотвественно направление - это свойство Snake а не Segment.
9) Публичные поля принято обозначать с большой буквы.
10) В целом код получился сложноватым для змейки. Но если высделаете оптимизацию, описанную выше, должен стать значительно проще.
11) Классы слишком связанные. Например в методы Segment вы передаете в параметрах класс Snake. Это неправильно. Segment не должен брать на себя функции класса в который он агрегирован. Это все равно что пилот самолета будет спрашивать советов у пассажира.
Аналогично и в некторызх других классах.
12) Вы слишком злоупотребляете методом Equals. Лучше все таки использовать ==. Особенно для структур. Они боксятся при передаче в Equals.
1
 Аватар для rockandroll
16 / 16 / 8
Регистрация: 05.08.2015
Сообщений: 79
31.08.2015, 08:19
я не являюсь большим критиком. и смотрел немного бегло. понравилась игра в плане как начинающего) ну есть небольшие косяки но это ерунда. она трушно программерская.
есть куда улучшать в графическом плане и плане управления.

вот что мне в коде понравилось это наличие комментарием и вроде даже адекватно написанных. Плюс отформатированный код без лишних плобелов. Молодец. Складывается мнение что это не прям первая программа.

Но местами комментов много. например не стоит давать коммент конструктору что он конструктор. разве что давать коммент что за параметры у него.

+ вопрос по второй структуре Turn почему нельзя было использовать для dir_x,..._y ту же структуру Point?

+ наводящий вопрос. можно ли было максимально больше методов вынести из статического класса Game? и вообще сделать его отдельным классом, а в Main только конфигурации запуска и запуск- остановка игры?

+ в классе Inout заметил коммент к глобальному полю класса а написанно "создаем". лушче описывать по существу что за поле и коротко

+ класс Field имеет объявленные переменные: ширину и высоту. Почему они паблик? можно в процессе менять?
Можно ли было использовать в этом случае не поля а именно props (это там где есть {get; set;}? конечно
это спорный момент но я наверное чаще использую проперти чем просто паблик поля. Спорный немного момент, конечно.
Обработчики (циклы всякие) в этом конструкторе можно вынести в приватный метод чтобы не захламлять сам конструктор, если он увеличится в размерах в будущем.

+почему я не видел нигде приватных переменных кроме класса apple переменная rnd?

+ небольшой совет. комменты можно ставить к методам ( иэто будет более нагляднее и приятно и потмо можно в документацию закинуть) просто нажав "///" и сгенерируется авто-паттерн под коммент. http://habrahabr.ru/post/41514/

+ Небольшое замечание. У меня как пользователя англ. версии винды не отображаются русские слова в консоле правильно. На случай, если захочешь предусмотреть это в следующей версии программы

А так мне понравился код. Очень адекватное начало. Я, конечно, далеко не гуру. Просто проходил мимо.
1
 Аватар для Leonin
6 / 6 / 3
Регистрация: 31.08.2015
Сообщений: 56
31.08.2015, 09:28  [ТС]
Storm23,
2,3) Лучше вынести "if (!Game.started) Game.started = true;" в отдельный приватный метод input'a? или лучше, наверное, в публичный метод Game'a?
4) Я так понял, статик -- это глобальная переменная для всех экземпляров?
5) Изначально я и смотрел на . Но почему-то захотел сравнивать именно позиции сегментов змейки, не затрагивая field. Просто хотел посмотреть, получиться ли)
6) Попробую сделать замену головы хвостом)
7) Если удастся реализоваться 6 пункт, то да)
9) А если публичные поля будут совпадать с именем типа? Тот же Snake Snake. Посчитал, что как-то неправильно) та же проблема у меня возникает при перечислении формальных и фактических параметров, когда их названия совпадают... например, direction и dir_x)
12) Компилятор ругается на "==" , мол, не может применяться к операндам этого типа... Как сделать, чтобы пользовательские типы можно было сравнивать или, например, складывать?

По остальным замечаниям учту

rockandroll,
Это не совсем первая, но первая законченная)
По струтурам turn... Посчитал, что будет запутанно, если для характеристики движения вместо directionX или Y будет точка Point...
О том, чтобы вынести Game тоже думал. В принципе игра ведь 1 на программу и создание экземпляра game можно избежать, если использовать сам класс со статическими экземплярами как сам экземпляр не знаю, как правильнее
С шириной и высотой, думаю, просто сделать их readonly. Я долго пытался сделать так, чтобы x и y считались с начала игрового поля, а не с рамки. Но в итоге запутался с get set'ами... Особенно, когда используешь get set с массивами.
С приватными да, я, наверное, переборщил, сделав почти все публичным Наверное, нарушается инкапсуляция. Но уже говорил, что запутался с getset'ами)

Спасибо обоим за советы. Следующий шаг будет попытка запилить рогалик)
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10421 / 5151 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
31.08.2015, 10:21
Цитата Сообщение от Leonin Посмотреть сообщение
Лучше вынести "if (!Game.started) Game.started = true;" в отдельный приватный метод input'a? или лучше, наверное, в публичный метод Game'a?
C#
1
2
3
4
5
6
7
8
9
10
            switch (cki.Key)
            {
                //При нажатие на клавишу управления змейкой -- игра начинается
                case ConsoleKey.DownArrow:
                case ConsoleKey.UpArrow:
                case ConsoleKey.RightArrow:
                case ConsoleKey.LeftArrow:
                        Game.started = true;
                        break;
                ....
Цитата Сообщение от Leonin Посмотреть сообщение
4) Я так понял, статик -- это глобальная переменная для всех экземпляров?
Да, это поле, принадлежащее классу (не объекту). Но я имел ввиду то, что Random нельзя создавать в конструкторе Apple. Его нужно создать один раз, а не для каждого яблока отдельно, и далее использовать этот один экземпляр. Иначе его значения будут не совсем случайными (ведь вы будете создавать постоянно новый объект Random).

Цитата Сообщение от Leonin Посмотреть сообщение
9) А если публичные поля будут совпадать с именем типа? Тот же Snake Snake.
Как это в Snake может быть поле Snake? Это не логично даже с умозрительной точки зрения.
Если вдруг имя будет совпадать с чем либо, можно поставить знак подчеркивания в конце. Но такое бывает очень редко. Обычно поля не могут иметь такое же имя как сам класс, и они обычно не совпадают с именами методов.

Цитата Сообщение от Leonin Посмотреть сообщение
12) Компилятор ругается на "==" , мол, не может применяться к операндам этого типа... Как сделать, чтобы пользовательские типы можно было сравнивать или, например, складывать?
Структура Point должна выглядеть так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    struct Point
    {
        public int X;
        public int Y;
 
        public Point(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
 
        public static bool operator ==(Point p1, Point p2)
        {
            return p1.X == p2.X && p1.Y == p2.Y;
        }
 
        public static bool operator !=(Point p1, Point p2)
        {
            return !(p1 == p2);
        }
 
        public override bool Equals(object obj)
        {
            if (!(obj is Point))
                return false;
            return (Point)obj == this;
        }
    }
Ну или так, что бы было проще и не заморачиваться с операторами:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    struct Point
    {
        public readonly int X;
        public readonly int Y;
 
        public Point(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
 
        public bool EqualsTo(Point other)
        {
            return X == other.X && Y == other.Y;
        }
    }
Обратите также внимание на то, в неймспейсе System.Drawing уже есть структура Point, и ее можно использовать, если присоеденить длл System.Drawing.
1
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
31.08.2015, 21:49
Цитата Сообщение от Storm23 Посмотреть сообщение
1) В C# принята в основном CamelNotation
сamel с маленькой, с большой это Pascal
0
Фрилансер
735 / 352 / 96
Регистрация: 05.05.2014
Сообщений: 2,621
31.08.2015, 22:37
Leonin, Ты за 1.5 месяца все так быстро понял. Для первого проекта - отлично. Хотя я бы сделал все совсем по-другому и уместил бы строк в 150 мб чуть больше. Но все приходит с опытом
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
01.09.2015, 10:19
pro_100_gram, не уверен, что правильно разнеся змейку на модули получится 150 строк Я ради интереса тоже начал писать, но быстро забил - правильную архитектуру даже для змейки продумывать утомляет немного За несколько заходов можно сделать разве что.

Добавлено через 1 минуту
За 1.5 месяца вполне достойный результат, если человеку это дело всё нравится. Мою змейку я через полгода писал, правда она была на гуе и событиях Но это ведь не важно, все же понимают
0
Фрилансер
735 / 352 / 96
Регистрация: 05.05.2014
Сообщений: 2,621
01.09.2015, 10:42
Psilon, http://habrahabr.ru/post/202476/
150 это так - нормально. Люди в 30 строк умудряются накодить. Надо будет как-нить ради интереса узнать свой минимум строк в змейке

Добавлено через 1 минуту
Тут конечно ООП роль играет, но все же
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
01.09.2015, 11:08
pro_100_gram, вот именно, что "Накодить". А я говорю, написать. Чтобы не пришлось спойлеры с кодом там называть. ООП тут не при чем, вопрос в архитектуре. Автор на неё вообще положил, чтобы поменьше кода было. Ну, его право.

Добавлено через 2 минуты
Я уже молчу про то, что там по куче операции в одной строке
JavaScript
1
2
3
    if(newEl.className.indexOf('f') > 0) {
        newEl.className = newEl.className.replace(' f', ''), length++, hasFood = false;
    }
Я так вообще могу в 1 строчку уместить всё, что хочешь
0
7972 / 2922 / 489
Регистрация: 05.10.2013
Сообщений: 7,829
Записей в блоге: 209
02.09.2015, 09:37
Leonin, молодец! Мне понравиласть игра! Только цель бы добавить, например, набрать 20 для победы. Открываются ворота и она уходит. А то она растёт, пока не умрёт - это неоптимистично. Отличная писать игры с целью изучения C#!

Замечу, что если писать с использованием специализированного на играх инструменте, то кода будет значительно меньше, времени уйдёт тоже меньше: Unity 2D Snake Tutorial
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
02.09.2015, 09:37
Помогаю со студенческими работами здесь

Дайте советы по улучшению кода
Как можно улучшить код чтобы сократить время его выполнения до минимума? Можно как нибудь игнорировать первую строку без использования...

Нужны советы по улучшению кода
Хотелось получить рекомендации по устранению критериев &quot;плохого кода&quot;(длинные,сложные методы,дублирование кода и.т.п) (Это небольшая...

Приму советы по оптимизации и улучшению кода обработки клавиш
Вот, собственно, код: function KbdProc(Code: Integer; wParam: Word; lParam: Longint) : Longint; stdcall; type ...

Проверка кода и советы по его улучшению. Генерация случайных чисел и проверка на уникальность
Привет народ! Занимаюсь изучением Java, захотелось реализовать выборку случайных чисел для лотереи. Вроде бы все прописал и программа даже...

советы по улучшению юзабилити
Привет, я совсем нуб в дизайне и почти нуб вюзабилити. Веду свой блог exp-seo.ru. Из-за замыленности взгляда, уже не могу адекватно оценить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

Новые блоги и статьи
Логирование в C# ASP.NET Core с помощью Serilog, ElasticSearch, Kibana
stackOverflow 25.04.2025
Помните те времена, когда для анализа проблемы приходилось подключаться к серверу, искать нужный лог-файл среди десятков других и вручную фильтровать тысячи строк в поисках ошибки? К счастью, эти дни. . .
Полностью асинхронный счётчик на логике (сумматорах) трёх состояний и асинхронных регистрах трёх состояний. Структура "электронный Buttom Up"
Hrethgir 25.04.2025
Программа для симуляции схемы - Logisim Evolution В общем какое-то время отвлёкся, так было надо, теперь когда запилю это на verilog и FPGA , досоставлю заявку в ФИПС на полезную модель - не готов. . .
Автоматизация Amazon Web Services (AWS) с Boto3 в Python
py-thonny 25.04.2025
Облачные вычисления стали неотъемлемой частью современной ИТ-инфраструктуры, а Amazon Web Services (AWS) занимает лидирующие позиции среди провайдеров облачных услуг. Управление многочисленными. . .
Apache Kafka vs RabbitMQ в микросервисной архитектуре
ArchitectMsa 25.04.2025
Современная разработка ПО всё чаще склоняется к микросервисной архитектуре — подходу, при котором приложение разбивается на множество небольших, автономных сервисов. В этой распределённой среде. . .
Параллельное программирование с OpenMP в C++
NullReferenced 24.04.2025
Параллельное программирование — подход к созданию программ, когда одна задача разбивается на несколько подзадач, которые могут выполняться одновременно. Оно стало необходимым навыком для. . .
Цепочки методов в C# с Fluent API
UnmanagedCoder 24.04.2025
Современное программирование — это не только решение функциональных задач, но и создание кода, который удобно поддерживать, расширять и читать. Цепочки методов и Fluent-синтаксис в C# стали мощным. . .
Мульти-тенантные БД с PostgreSQL Row Security
Codd 23.04.2025
Современные облачные сервисы и бизнес-приложения всё чаще обслуживают множество клиентов в рамках единой программной инфраструктуры. Эта архитектурная модель, известная как мульти-тенантность, стала. . .
Реализация конвейеров машинного обучения с Python и Scikit-learn
AI_Generated 23.04.2025
Мир данных вокруг нас растёт с каждым днём, и умение эффективно обрабатывать информацию стало необходимым навыком. Специалисты по машинному обучению ежедневно сталкиваются с задачами предобработки. . .
Контроллеры Kubernetes Ingress: Сравнительный анализ
Mr. Docker 23.04.2025
В Kubernetes управление входящим трафиком представляет собой одну из ключевых задач при построении масштабируемых и отказоустойчивых приложений. Ingress — это API-объект, который служит вратами. . .
Оптимизация кода Python с Cython и Numba
py-thonny 23.04.2025
Python прочно обосновался в топе языков программирования благодаря своей простоте и гибкости. Разработчики любят его за читабельность кода и богатую экосистему библиотек. Но у этой медали есть и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru