Pull to refresh

Comments 34

я не разобрался еще как компилировать несколько файлов в один .exe через консоль, да и это не тема нашей статьи, может кто нибудь расскажет в комментариях

Ну, как же так? Просто перечисляете все файлы для компиляции в одной команде. Или делаете вот так, чтобы скомпилировать все файлы в текущей директории:


csc -out:%name%.exe *.cs


Первая же страница документации.

В данном случае предлагаю вместо
ConsoleKeyInfo key = Console.ReadKey();
написать
ConsoleKeyInfo key = Console.ReadKey(true);
это устранит отображение в консоли нажатой пользователем клавиши из-за чего иногда часть змея пропадает.
А проблему поворота на 180 градусов двумя нажатиями — поставив «переключатель»

двумя быстрыми нажатиями змейку можно повернуть на 180 градусов
«переключатель» — работает просто его почему то нет в коде в начале статьи
да, каюсь, забыл, сейчас исправим)
Чтобы на 180 не поворачивалась
// Запрет разворота на 180
// Если попытка поворота на 180 градусов
if ((_direction == Directions.Right && DirectionControl == Directions.Left) ||
    (_direction == Directions.Left && DirectionControl == Directions.Right) ||
    (_direction == Directions.Up && DirectionControl == Directions.Down) ||
    (_direction == Directions.Down && DirectionControl == Directions.Up))
{
	//пропускаем изменение направления;
}
else
{
	_direction = DirectionControl;
}
мой вариант решения
            Direction _direction = direction;
         
            if (key == ConsoleKey.DownArrow)
                direction = Direction.DOWN;
            else if (key == ConsoleKey.UpArrow)
                direction = Direction.UP;
            else if(key == ConsoleKey.LeftArrow)
                direction = Direction.LEFT;
            else if (key == ConsoleKey.RightArrow)
                direction = Direction.RIGHT;
           

            Point p1 = snake.ElementAt(snake.Count - 2);
            Point p2 = GetNextPoint();

            if (p1.Equals(p2)) direction = _direction;

Я конечно понимаю, что Вы — начинающий программист, но использование в одном месте лямбд и таких вот конструций вызывает улыбку :)
(a.x == b.x && a.y == b.y) ? true : false

Почему? По моему это классный способ написать метод в одну строчку.

Не в лямбдах дело :) А в тавтологии вышеуказанного выражения. Достаточно было написать (a.x == b.x && a.y == b.y)

Да, я понял :) мы можем вернуть true/false и без оператора ?:
Логические выражения при их вычисление возвращают истинность (логическое значение true / false).

Так что без ?: будет даже лучше.
Не сразу то и заметно в чем подвох))

Больше всего меня интересуют две вещи:


  1. Почему было принято решение использовать блокнот и консоль?
  2. Почему бы просто в начале игрового цикла (функции Loop) не считать все нажатия которые были и повернуть змейку в последнем направлении? Сразу отпадет необходимость в переключателе.
1. Ну что бы показать, что можно компилировать и без IDE, что сделать игру можно уже сейчас нечего не устанавливая (хотя сам и использовал возможности языка, которые можно скомпилировать только компилятором при VS).
2. Интересное предложение, думаю можно и так сделать.
1. Ну что бы показать, что можно компилировать и без IDE, что сделать игру можно уже сейчас нечего не устанавливая

Вспоминается бородатый анекдот:
лежит на диком пляже молодая изнывающая от скуки девушка. Тут из кустов выходит мужик в ластах, фраке и противогазе.
Девушка: мужчина, давайте займёмся любовью?
Мужик: хорошо, но только в одежде, стоя и в гамаке.
Девушка: о_О почему?
Мужик: Люблю преодолевать трудности.
  1. В этом случае надо будет делать защиту от залипания клавиш
2. Если рассматривать это именно как игру «Змейку», а не упражнение по лямбдам, то нажатия игрока пропускать нельзя. Поворот змейки в обратную сторону как раз делается двумя быстрыми нажатиями двух стрелок на одном шаге, иначе повороты и развороты начинают страшно бесить из-за сложности попадания в тайминг (шаги игры очень мелкие). Короче, для комфортной игры нужен буферизованый ввод. При противоположных командах нужно брать последнюю, игнорируя попытки включить змее реверс.
Так в первой главе под спойлером полный код и выложен
Может и на мой код змейки взглянете.
Змейка отлажена. Новый функционал придумывается и дорабатывается
Особенность в том, что можно включить автопилот и смотреть как она сама еду ищет и ест.
github.com/Cuprumbur/Snake

image

Присоеденяйтесь
Автопилот включается кнопкой 'A'
Когда статья пишется «новичком для новичков», в нее неизбежно проникают «вредные советы» и прочие плохие практики. Разберем по пунктам:

1. Зачем использовать блокнот и консольный компилятор? Слава богу, в 2018 году живем, а не в каменном веке. Есть Visual Studio и VS Code — оба бесплатные, есть отличные автокомплит и отладчик.

2. Лексема => в данном случае не является «лямбда-оператором» — это просто синтаксический сахар для return. А «expression-bodied member» это не «определение текста выражения» (это что, гугл-транслейт?), а «тело, состоящее из одного выражения».

3. Кортежи в данном случае вообще не нужно использовать. Вместо Point p = (1, 2, 'x') можно писать var p = new Point(1, 2, 'x') — получаем более осмысленные подсказки и ошибки.

4. Вместо того, чтобы хранить step и direction, можно было бы хранить вторую переменную типа Point и складывать их, как вектора. Тогда функция GetNextPoint сократилась бы до одной строки.

5. Коллекция List в данном случае не подходит: удаление первого элемента приводит к тому, что все остальные приходится «сдвинуть» на один шаг назад. Для данного случая есть Queue, поддерживающая как раз добавление с одной стороны и удаление с другой.

6. Как уже было сказано, не нужно писать (a == b) ? true : false: это эквивалентно просто a == b.
Вот ради таких комментов и стоило писать, спасибо :)
1. Все ради того, что бы показать, что можно взять файл с текстом и скомпилировать его без всяких сторонних программ, как по мне это полезно знать, может появится желание у людей поподробнее разобраться с этой темой, и в том как устроен компилятор.
2. Да это просто машинный перевод с сайта майкросовтов, поправлю в статье.
3. Я хотел что бы объявление класса выглядело как обычный тип данных, как int i = 1 например, и показать как этого можно добиться.
С остальным полностью согласен!
1. Инструменты разработчика — сильная сторона дотнета. Ими не стоит пренебрегать из аскетических соображений. Если хочется «быстро написать и сразу проверить» код — попробуйте LINQPad. Автокомплит там включается только в платной версии, но он точно стоит своих денег. Консольный же компилятор за ~7 лет работы с платформой еще ни разу не пригодился.

3. Похоже на то, что вы до этого работали со старыми стандартами C / C++ и пытаетесь перенести стиль кода в C#. Это плохая идея по двум причинам. Во-первых, такой код делает двойную работу: вместо того, чтобы передать аргументы сразу в конструктор нужного класса, вы сначала передаете их в конструктор кортежа, а потом забираете из него. Во-вторых, неявное приведение типов считается плохим тоном, поскольку затрудняет понимание кода, и допустимо только в очень редких случаях.

Советую поставить Resharper — там есть огромное количество правил, обнаруживающих «неопрятный» код и позволяющих автоматически его исправить. Со временем эти правила входят в привычку и код становится чище.
Я ни в коем случае не хотел принизить значимость IDE, но полезно знать что там под капотом:)
С# мой первый язык, с С я знакомился только когда пытался смотреть гарвардский курс cs50. С точки зрения производительности, да лучше сразу в конструктор передавать значения, это я понимаю.
Resharper посмотрю, интересно.
Странный вопрос, ник у меня такой
Похоже на отсылку к айкидо: «Uke (literally „one who receives“, the one who takes the fall) and nage (the thrower)», скорее всего имелось в виду, что как новичок, вы скорее всего будете Uke, когда Nage придут читать статью ;)
как ни странно айкидо я занимался пару лет, но ник не имеет к нему отношения:)
Microsoft ® Visual C# Compiler version 2.6.0.62329 (5429b35d) //Это Cummunity 2017
Copyright © Microsoft Corporation. All rights reserved.

Snake.cs(51,12): warning CS0660: 'Point' defines operator == or operator != but does not override Object.Equals(object o)
Snake.cs(51,12): warning CS0661: 'Point' defines operator == or operator != but does not override Object.GetHashCode()

Что я делаю не так? :-)
все нормально, компилятор просто предупреждает, что не реализованы эти два метода, но код все равно должен компилироваться, и можно запустить .exe
Sign up to leave a comment.

Articles