none
Трудный вопрос RRS feed

  • Вопрос

  • Скачать программу:

    http://gordon.ucoz.com/Fayls/Files/Fayls/Fayls/X-O_Along_dsfjanjadsfs.rar


    Проблемный код:

            int a;
    
            private void labels_Mouse_Down(object sender, MouseEventArgs e)
            {
                if (((Label)sender).Text == "-")
                {
                    for (int once = 0; once < 1; once++)
                    {
                        ((Label)sender).Text = "X";
    
                        var labels = Controls.OfType<Label>().ToList();
    
                        for (int Low = 2, Up = 18; (Low <= 211) & (Up <= 227); Low += 19, Up += 19)
                            for (int i = 0; i < labels.Count; i++)
                                if ((i >= Low) & (i <= Up))
                                {
                                    a = 0;
                                    for (int l = 0; l <= 18 * 2; l += 18)
                                        if (labels[i + l].Text == "X")
                                        {
                                            a += 1;
                                            if ((l == 18 * 2) & (a != 3)) a = 0;
                                        }
                                    if (a == 3) MessageBox.Show("a");
                                }
                    Break: break;
                    }
                }
            }

    Интерфейс:

    Программа, после того как на поле появляются три икса как показано на рисунке, должна показывать сообщение "a" (но не показывает).

    Нумерация элементов Label начинается справа с верхнего угла.

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

    Программа реагирует при каждом нажатии элемента Label.

    Если нужно я могу дать код для захвата пяти иксов.


    Бог движок на котором мы написаны, а Библия компилятор, и верующие постоянно компилируют себя в нём.

Ответы

  • Нашёл ошибку, вот при следующем коде происходить распределение элементов Label после чего нумерация теряется:

            public Form1()
            {
                InitializeComponent();
    
                var labels = Controls.OfType<Label>().ToList();
                for (int i = 0; i < labels.Count; i++)
                {
                    labels[i].Left = Lx;
                    Lx += 25;
                    for (int Up = 18; Up <= 265; Up += 19)
                        if (i == Up) Lx = 0;
                }
                Width = labels[18].Left + labels[18].Width + 17;
            }
    Я убрал этот код, и всё сработало!


    Бог движок на котором мы написаны, а Библия компилятор, и верующие постоянно компилируют себя в нём.


    • Помечено в качестве ответа Doctor Gordon 10 мая 2012 г. 4:41
    • Изменено Doctor Gordon 10 мая 2012 г. 4:41

Все ответы

  • Пару вопросов:

    1. Сообщение должно сработать в случае трех иксов только по диагонали или по прямой линии тоже?

    2. Почему мне кажется что код для 5-ти иксов отличается всего одной строчкой кода? Или я не прав?


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    Отвечающий
  • 1. Сообщение должно сработать в случае трех иксов только по диагонали или по прямой линии тоже?

    Под диагонали, как на рисунке.

    2. Почему мне кажется что код для 5-ти иксов отличается всего одной строчкой кода? Или я не прав?

    Вот работающий код для пяти иксов:

                        for (int Low = 4, Up = 18; (Low <= 175) & (Up <= 189); Low += 19, Up += 19)
                            for (int i = 0; i < labels.Count; i++)
                                if ((i >= Low) & (i <= Up))
                                {
                                    a = 0;
                                    for (int l = 0; l <= 18 * 4; l += 18)
                                        if (labels[i + l].Text == "X")
                                        {
                                            a += 1;
                                            if ((l == 18 * 4) & (a != 5)) a = 0;
                                        }
                                    if (a == 5)
                                    {
                                        End();
                                        goto Break;
                                    }
                                }

    При пяти иксов выполняется метод End().

    Вот программа:

    http://gordon.ucoz.com/Fayls/Files/Fayls/Fayls/X-O_Along_dsfjanjadsfs.rar


    Бог движок на котором мы написаны, а Библия компилятор, и верующие постоянно компилируют себя в нём.

  • Ваш код мне показался малость усложненным и главное методом простого подсчета получается что следующий диагональный X идет +20, а в вашем коде такой цифры нет. Может я недопонял вал алгоритм, но как я уже и сказал он малость усложнен (именно усложнен а не сложен).

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    Отвечающий
  • и главное методом простого подсчета получается что следующий диагональный X идет +20,

    Я проверил и 18, 19, 20 не получилось. Отмечу что если индекс элемента Label 1 значить в цикле for нумеруется как ноль.


    Бог движок на котором мы написаны, а Библия компилятор, и верующие постоянно компилируют себя в нём.


  • На рисунке показывает сообщение, под окном сообщение икса нет.

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


  • Я потому и спросил про отличие в одну строчку. 5 иксов определяются, а 3 нет и при этом методы сильно разнятся. Мне не понятно почему так, ведь если заменить строку

    if (a == 5)

    на

    if (a == 3)

    тоесть использовать метод для 5-ти, но с цифрой 3 то все будет работать. Если так не пойдет, то значит я не понял правил игры. Кстати будет не плохо если вы опишите правила игры, так будет проще.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!


    Отвечающий
  • У меня замечания общего характера.

    Приведение типа

    (Label)sender

    довольно тяжелая операция. Поэтому лучше не делать её несколько раз в одном месте. Лучше так:

    Label label = (Label)sender;
    if (label.Text == "-")
    {
        ...
            label.Text = "X";
            ...

    Потом не ясен смысл цикла, который заведомо будет выполняться один раз:
    for (int once = 0; once < 1; once++)

    Зачем он?


    Также весьма затратно каждый раз выполнять этот код:

    var labels = Controls.OfType<Label>().ToList();
    

    Можно сделать labels полем класса, и просто использовать готовую коллекцию в методе.

    Также можно игровое поле сделать отдельной панелью - Panel. На этой панели будут только Label'ы, и тогда можно сразу обращаться к её свойству Controls, без всяких фильтраций.


    • Изменено Petalvik 9 мая 2012 г. 19:54
  • Я потому и спросил про отличие в одну строчку. 5 иксов определяются, а 3 нет и при этом методы сильно разнятся. Мне не понятно почему так, ведь если заменить строку

    if (a == 5)

    на

    if (a == 3)

    тоесть использовать метод для 5-ти, но с цифрой 3 то все будет работать. Если так не пойдет, то значит я не понял правил игры. Кстати будет не плохо если вы опишите правила игры, так будет проще.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!


    Можно добавить одну строку

    else a = 0;
                        for (int Low = 2, Up = 18; (Low <= 211) & (Up <= 227); Low += 19, Up += 19)
                            for (int i = 0; i < labels.Count; i++)
                                if ((i >= Low) & (i <= Up))
                                {
                                    a = 0;
                                    for (int l = 0; l <= 18 * 2; l += 18)
                                        if (labels[i + l].Text == "X")
                                        {
                                            a += 1;
                                            if ((l == 18 * 2) & (a != 3)) a = 0;
                                        }
                                        else a = 0; //добавленная строка
                                    if (a == 3) MessageBox.Show("a");
                                }

    Но это проблему не решает, и действительно не понятно почему так.

    Petalvik цену внимание, но не думаю что проблема из-за этого, хотя как знать.


    Бог движок на котором мы написаны, а Библия компилятор, и верующие постоянно компилируют себя в нём.


  • На самом деле я согласен с Petalvik. Как я и сам писал вше все выглядит усложнённым, то есть пятой точкой чувствую, что можно проще и уж тем более вы написали этот алгоритм и сами затрудняетесь ответить почему для 5-ти работает, а для 3-х нет. На самом деле может там дело в одном символе или еще чего, то есть мелочь которую трудно заметить.

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


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    Отвечающий
  • Вот работающий код для захвата трёх иксов:

                    for (int End = 0; End < 1; End++)
                    {
                        if (((Label)sender).Text == "-")
                        {
                            ((Label)sender).Text = "X";
                        var labels = Controls.OfType<Label>().ToList();
    
                            for (int i = 0; i < labels.Count; i++)
                            {
                                int a = 0;
                                bool win = false;
                                if (labels[i].Text == "X")
                                {
                                    for (int Low = 2, Up = 11; (Low <= 86) & (Up <= 95); Low += 12, Up += 12)
                                        if ((i >= Low) & (i <= Up))
                                        {
                                            a = 0;
                                            for (int l = 0; l <= 11 * 2; l += 11)
                                                if (labels[i + l].Text == "X")
                                                {
                                                    a += 1;
                                                    if ((l == 11 * 2) & (a != 3)) a = 0;
                                                }
                                                else a = 0;
                                            if (a == 3)
                                            {
                                                MessageBox.Show("a");
                                                win = true;
                                                goto End3;
                                            }
                                        }
                                }
                            End3: if ((a == 3) & (win))
                                {
                                    a = 0;
                                    win = false;
                                    EndAll = true;
                                    goto EndAll;
                                }
                            }
                    EndAll: if (EndAll) break;
                    }
                }

    Проблема в том чтобы найти разницу.

    Вот программа данного кода:

    http://gordon.ucoz.com/Fayls/Files/Fayls/Fayls/X-O_Along_sdbfsjbfhbf.rar


    Бог движок на котором мы написаны, а Библия компилятор, и верующие постоянно компилируют себя в нём.

  • Если честно, то работа с координатами, goto и прочими ужасами у меня выхывает головную боль. Посмотрите вот на такое решение (на форме нет ни одного контрола, при клике выводиться максимальня длинна полосы):

    public partial class Form1 : Form
    {
        Label[,] labels = null;
    
        public Form1()
        {
            InitializeComponent();
            int size = 20;
            labels = new Label[size, size];
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    labels[i, j] = new Label() { Location = new Point(j * 20, i * 20), Text = "--", AutoSize = true };
                    labels[i, j].MouseDown += labels_Mouse_Down;
                    this.Controls.Add(labels[i, j]);
                }
            }
        }
    
        private void labels_Mouse_Down(object sender, MouseEventArgs e)
        {
            Label current = (Label)sender;
            Point currentPosition = GetLabelPosition(current);
            current.Text = "X";
            int maxCount = 1;
            for (int di = -1; di < 2; di++)
            {
                for (int dj = -1; dj < 2; dj++)
                {
                    int count = 1;
                    if (di != 0 || dj != 0)
                    {
                        for (int steep = 1; steep < 4; steep++)
                        {
                            if (labels[currentPosition.X + di * steep, currentPosition.Y + dj * steep].Text == "X")
                            {
                                count++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        for (int steep = 1; steep < 4; steep++)
                        {
                            if (labels[currentPosition.X - di * steep, currentPosition.Y - dj * steep].Text == "X")
                            {
                                count++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        if (count > maxCount)
                        {
                            maxCount = count;
                        }
                    }
                }
            }
            MessageBox.Show(maxCount.ToString());
        }
    
        private Point GetLabelPosition(Label label)
        {
            for (int i = 0; i < labels.GetLength(0); i++)
            {
                for (int j = 0; j < labels.GetLength(1); j++)
                {
                    if (labels[i, j] == label)
                    {
                        return new Point(i, j);
                    }
                }
            }
            return new Point(-1, -1);
        }
    
    }

    • Предложено в качестве ответа LXGDARKEditor 9 мая 2012 г. 16:51
    Отвечающий
  • Алексей Лосев,

    Но зачем же лейбы лепить? 400 лейб на форме, елы палы... Каждый контрол это дофига ресурсов системы... И все ради того, что бы нарисовать сотню крестиков и палочек?

    Метод GetLabelPosition тоже удивляет.

    А главное - где-же разделение интерфейса и данных? Автору простительно, а вам - нет :)

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

    Не удержусь и поддержу Вас в том, что goto - это ужос и кошмар ^_^

    DreamSpark Premium User

  • Алексей Лосев,

    Но зачем же лейбы лепить? 400 лейб на форме, елы палы... Каждый контрол это дофига ресурсов системы... И все ради того, что бы нарисовать сотню крестиков и палочек?

    Метод GetLabelPosition тоже удивляет.

    А главное - где-же разделение интерфейса и данных? Автору простительно, а вам - нет :)

    
    

    Мы недавно на WPF писали с приятелем большие крестики нолики с изменненными правилами, так там да, лоика отдельно, данные отдельно, мерились кто круче логику напишет для игры за комп, но на WinForms? Для такой задачи писать MVC? Заморачиваться с рисованием? Не, вот когда я делал пример на генетическое прогграммирование году в 2005, там да. Здесь нет...

    Кстати, уровень ответа должен быть максимально приближен к уровню вопроса, иначе ответ может остаться не понятым, это я вам как преподаватель с восьмилетним стажем говорю :)

    Отвечающий
  • Нашёл ошибку, вот при следующем коде происходить распределение элементов Label после чего нумерация теряется:

            public Form1()
            {
                InitializeComponent();
    
                var labels = Controls.OfType<Label>().ToList();
                for (int i = 0; i < labels.Count; i++)
                {
                    labels[i].Left = Lx;
                    Lx += 25;
                    for (int Up = 18; Up <= 265; Up += 19)
                        if (i == Up) Lx = 0;
                }
                Width = labels[18].Left + labels[18].Width + 17;
            }
    Я убрал этот код, и всё сработало!


    Бог движок на котором мы написаны, а Библия компилятор, и верующие постоянно компилируют себя в нём.


    • Помечено в качестве ответа Doctor Gordon 10 мая 2012 г. 4:41
    • Изменено Doctor Gordon 10 мая 2012 г. 4:41
  • Алексей Лосев,

    Мы недавно на WPF писали с приятелем большие крестики нолики с изменненными правилами, так там да, лоика отдельно, данные отдельно, мерились кто круче логику напишет для игры за комп, но на WinForms? Для такой задачи писать MVC? Заморачиваться с рисованием? Не, вот когда я делал пример на генетическое прогграммирование году в 2005, там да. Здесь нет...

    Кстати, уровень ответа должен быть максимально приближен к уровню вопроса, иначе ответ может остаться не понятым, это я вам как преподаватель с восьмилетним стажем говорю :)

    Я пишу модель и заморачиваюсь с рисованием даже в пятистрочных примерах (и кстати вынесение модели это еще далеко не MVC, это вообще элементарное действие, без которго я вообще не понимаю, как программу можно писать). Результат получается короче и понятнее.

    В общем, вы меня разочаровали :(

    Отвечающий
  • Я пишу модель и заморачиваюсь с рисованием даже в пятистрочных примерах (и кстати вынесение модели это еще далеко не MVC, это вообще элементарное действие, без которго я вообще не понимаю, как программу можно писать). Результат получается короче и понятнее.

    В общем, вы меня разочаровали :(

    Э... Ну что же, значит буду ходить в трауре. Но, лично мое мнение вот такое:

    1. Программа должна решать задачи пользователя.

    2. Программа должна быть написана максимально быстро и понятно.

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

    Да, в данном примере можно было завести массив bool-ов, на их основе отрисовывать минусы и крестики, по клику конвертировать координаты в координаты массива ну и так далее. Но... В исходном примере была коллекция Label? Автор проекта сделал выбор? Ну вот, я ему показал вариант:

    1. Работающий не с одномерной коллекцией, а с двумерной

    2. Не привязанный к координатной сетке (если заказчик попросит изменить размер элемента, в показанном автором топика примере будет опа).

    Э... Если есть желание еще подискутировать на эту тему, то с удовольствием. Создайте топик в Избе болтальне, пообщаемся :)


    Отвечающий