Pull to refresh

Comments 36

В 2018 году такие статьи не могут вызвать большой интерес для широкой аудитории.
Неужели кто-то еще использует WinForms?

Их и в 2038 будут использовать, технология в освоении проста аки грабли и со своими задачами прекрасно справляется.

UFO just landed and posted this here
Я использую и думаю не только я, для enterprise систем самое то.
В WinForms максимум функционала на единицу площади экрана и привычный для пользователей графический интерфейс.
И что не так с моими тетрисами? Первый я писал на первом курсе, второй как пример для моего 3д движка.
Можно сократить:

case Keys.A: 
    for (int i = 0; i < 4; i++)
        shape[1, i]--;
    if (FindMistake())
        for (int i = 0; i < 4; i++)
            shape[1, i]++;
break;
case Keys.D:
    for (int i = 0; i < 4; i++)
        shape[1, i]++;
    if (FindMistake())
        for (int i = 0; i < 4; i++)
    shape[1, i]--;
break; 


до

case Keys.A: Keys.D: 
    for (int i = 0; i < 4; i++)
        shape[1, i] = e.KeyCode == Keys.A ? shape[1, i]-1 : shape[1, i]+1;
    if (FindMistake())
        for (int i = 0; i < 4; i++)
            shape[1, i] = e.KeyCode == Keys.A ? shape[1, i]+1 : shape[1, i]-1;
break;


Upd1. Пофиксил синтакс.

Как насчет


...
shape[1, i] += e.KeyCode == Keys.A ? -1 : 1;
...
Так короче, грац! Увы, на количество строк не влияет.
Короче — лучше. количество строк не главное. давайте по-честному, считать символы. а то можно так все в одну строку записать )
«Все-в-одну-строку» — слишком тривиально, чтоб об этом дискутировать. «До этого любой ламер додумается». Уменьшение же «честных» строк кода уже может привести к чему-то интересному

Кстати, вопрос знатокам: можно ли написать отображение, переводящее индекс фигуры в фигуру (0 -> { 2, 3, 4, 5 }, { 8, 8, 8, 8 } )? С таким отображением получится выкинуть еще 8 строк.
а почему не сделать по-нормальному — функцию bool move(dx, dy)? она же еще в куче мест пригодится, например, движение вниз, движение обратно итд.
Спасибо за предложенное сокращение! На самом деле, это далеко не единственный вариант уменьшения кода. Можно убрать еще пару десятков строк. Но это, в основном, благодаря использованию LINQ. Например, заполненные строки в поле можно найти вообще в один запрос:
(from i in Enumerable.Range(0, field.GetLength(1)) where (Enumerable.Range(0, field.GetLength(0)).Select(j => field[j, i]).Sum() >= width - 1) select i).ToArray().Take(1) 
Кстати, не стоит забывать про строки связанные с дизайнером формы.

...

public Graphics gr;
private PictureBox FieldPictureBox { get; }
private Timer TickTimer { get; }
[STAThread]
public static void Main() {
var frm = new Form1();
frm.ShowDialog();
}

private Form1() {
KeyDown += Form1_KeyDown;
FieldPictureBox = new PictureBox {Dock = DockStyle.Fill, Parent = this};
TickTimer = new Timer {Interval = 1000, Enabled = true};
TickTimer.Tick += TickTimer_Tick;

...

Всё замечательно, фигуры падают, тетрис тетрисится. ЧТО ДАЛЬШЕ? К чему вся эта статья, а особенно замечание «в 100 строк»? Неужели где-то есть программисты, которые гордятся самым коротким кодом, будто они каждый символ выжигают у себя на коже??
Статья и не обучающая, и не познавательная… тупо пришёл мальчик «я написал тетрис». Ну… как бы молодец, иди домой! :) Что вы хотите от читателей-то?
Показать всю ущербность C# по сравнению с JS где все угодно вмещается в 30 строк?
Ущербность языка здесь абсолютно не причем. Всё дело в реализации. Как пример, в коде на JS все состояния фигурок хранятся в одной строке. Я же счёл, что это нанесёт непоправимый вред читаемости кода и честно крутил фигурки)
Друг, это местный фольклор. Пару лет назад на хабре была серия «Х в 30 строк на JS». «Победителем» вышел товарищ, ужавший игру в 0 строк.
В каком-то смысле, чем короче код — тем лучше. Меньше лишнего, меньше ошибок, проще читать, быстрее править.
А можно мне понять ход мыслей минсующих? Я вот давно уже программирую, но может чего не знаю?
Ну про печально известную «программу из одной строки» вы наверняка слышали. Можно её назвать читаемой?
Начиная с определенного момента, приемы, направленные на сокращение длины кода, начинают ухудшать читаемость.
А еще не забываем про закон Парето применительно к программированию — «80% кода занимает обработка ошибок». Поэтому короткий код может означать «надеемся, что все получится».

P.S.: не минусовал.
Ну я не в ответе за тот, код, который написан в одну строчку. Я говорил «код короче», а не меньше строчек. Понято, что код можно сокращать сколь угодно, абстрагируя логику все сильнее и сильнее. Вот, скажем, в обсуждении выше люди начали оптимизировать размер кода, выкидывая из него повторяющиеся куски. Например, есть же Linq — там можно написать одну строку, простую и понятную. Если вы начинаете ее расписывать — у вас получается пара экранов кода. Пока вы въедете, что он делает — пройдет минут пять, а то и больше, а строка linq прочитается и поймется за полминуты, хотя есть и такие извращенцы, которые пишут linq запросы в несколько строчек. Это ведь тоже можно сделать проще — например, не переносить на следующую строку, а сохранить часть выражения в переменную, дав ей осознанное имя. Такой код будет читать проще. Я не призываю сокращать код до нечитаемого мяса, я лишь говорю о том, что много кода писать — плохо. Когда вы начинаете задумываться об этом, вы не будете писать каждую вторую строчку, а в масштабах проекта это отодвинет неизбежную потерю контроля над кодом, снизит количество багов, и упростит вам жизнь.
хотя есть и такие извращенцы, которые пишут linq запросы в несколько строчек
Ну зачем же вы так. LINQ в несколько строчек может быть вполне себе читаемым. Как раз тот случай, когда можно добавлять строки кода ради читаемости.
var result = source.Select(dto => dto.ToModel())
    .Where(model =>  model.IsActive)  // 2 where for a simpler debug
    .Where(model => model.MatchesSecurityPolicy())
    .GroupBy(model => model.businessGroupKey)
    .ToDictionary(
        group => groupKey, 
        group => group.Sum(elem => elem.Karma));

Можно и в 32 строчки вместиться:


Но зачем?
using System;using System.Linq;using System.Drawing;using System.Windows.Forms;
public partial class Form1:Form{public const int width=15,height=25,k=15;public
int[,]shape=new int[2,4];public int[,]field=new int[width,height];public Bitmap
bitfield=new Bitmap(k*(width+1)+1,k*(height+3)+1);public Graphics gr;public
Form1(){InitializeComponent();gr=Graphics.FromImage(bitfield);for(int a=0;a<
width;a++)field[a,height-1]=1;for(int a=0;a<height;a++){field[0,a]=1;field[width
-1,a]=1;}SetShape();}public void FillField(){gr.Clear(Color.Black);for(int a=0;a
<width;a++)for(int b=0;b<height;b++)if(field[a,b]==1){gr.FillRectangle(Brushes.
Green,a*k,b*k,k,k);gr.DrawRectangle(Pens.Black,a*k,b*k,k,k);}for(int a=0;a<4;a++
){gr.FillRectangle(Brushes.Red,shape[1,a]*k,shape[0,a]*k,k,k);gr.DrawRectangle(
Pens.Black,shape[1,a]*k,shape[0,a]*k,k,k);}FieldPictureBox.Image=bitfield;}void
h(object a,System.EventArgs b){if(field[8,3]==1)Environment.Exit(0);for(int c=0;
c<4;c++)shape[0,c]++;for(int c=height-2;c>2;c--){int d=(from t in Enumerable.
Range(0,field.GetLength(0)).Select(e=>field[e,c]).ToArray()where t==1 select t).
Count();if(d==width)for(int f=c;f>1;f--)for(int g=1;g<width-1;g++)field[g,f]=
field[g,f-1];}if(FindMistake()){for(int c=0;c<4;c++)field[shape[1,c],--shape[0,c
]]++;SetShape();}FillField();}void i(object a,KeyEventArgs b){switch(b.KeyCode){
case Keys.A:for(int c=0;c<4;c++)shape[1,c]--;if(FindMistake())for(int c=0;c<4;c
++)shape[1,c]++;break;case Keys.D:for(int c=0;c<4;c++)shape[1,c]++;if(
FindMistake())for(int c=0;c<4;c++)shape[1,c]--;break;case Keys.W:var d=new int[2
,4];Array.Copy(shape,d,shape.Length);int e=0,f=0;for(int c=0;c<4;c++){if(shape[0
,c]>f)f=shape[0,c];if(shape[1,c]>e)e=shape[1,c];}for(int c=0;c<4;c++){int g=
shape[0,c];shape[0,c]=f-(e-shape[1,c])-1;shape[1,c]=e-(3-(f-g))+1;}if(
FindMistake())Array.Copy(d,shape,shape.Length);break;}}public void SetShape(){
var a=new Random(DateTime.Now.Millisecond);switch(a.Next(7)){case 0:shape=new
int[,]{{2,3,4,5},{8,8,8,8}};break;case 1:shape=new int[,]{{2,3,2,3},{8,8,9,9}};
break;case 2:shape=new int[,]{{2,3,4,4},{8,8,8,9}};break;case 3:shape=new int[,]
{{2,3,4,4},{8,8,8,7}};break;case 4:shape=new int[,]{{3,3,4,4},{7,8,8,9}};break;
case 5:shape=new int[,]{{3,3,4,4},{9,8,8,7}};break;case 6:shape=new int[,]{{3,4,
4,4},{8,7,8,9}};break;}}public bool FindMistake(){for(int a=0;a<4;a++)if(shape[1
,a]>=width||shape[0,a]>=height||shape[1,a]<=0||shape[0,a]<=0||field[shape[1,a],
shape[0,a]]==1)return true;return false;}}
Не хватает ссылки на GitHub-репозиторий. ;-)
Но почему дно стакана шириной не в стандартные 10 пикселей?
Признаю, мой косяк) Но это легко изменяется в константе width.
Ну такое…
Вот тут полноценный тетрис со спец.эффектами целиком на GLSL. (кроме опроса клавиатуры разумеется и инициализации)
www.shadertoy.com/view/4d33Dj

ps. Чтобы поиграть надо закомментировать первый return 0; в Buffer A
А я вот не понял, при чём тут C#?, и уж тем более «интересный код»?
Ни ООП, ни мощи .Net…
Даже единственное Linq-выражение записано в SQL-стиле, хотя, что мешало написать:
var cross = Enumerable.Range(0, field.GetLength(0)).Count(j => field[j, i] == 1);
А мне еще очень давно в книге (по-моему, это было «Занимательное программирование»
М. Мозгового) попадались исходники тетриса, где поворот фигур был реализован с помощью матрицы поворота.
Sign up to leave a comment.

Articles