Ответы пользователя по тегу C#
  • Как переделать код (см. внутри)?

    FoggyFinder
    @FoggyFinder
    Давайте попробуем вместе разобраться как решать подобные вопросы.

    В таких случаях первое что нужно сделать это правильно докопаться до корня проблемы.

    Ваша задача убрать использование пространства имен System.Drawing.

    Что для этого нужно сделать?
    1. Убрать вверху заголовочный using
    using System.Drawing;
    2. Удалить ссылку на сборку

    Теперь пробуем скомпилировать проект, получаем ошибки:

    error CS0246: Не удалось найти тип или имя пространства имен "Point" (возможно, отсутствует директива using или ссылка на сборку)


    Значит вопрос можно переформулировать примерно следующим образом:

    Чем можно заменить класс Point из System.Drawing?


    Согласитесь, что чем более конкретен вопрос тем легче на него ответить.

    Итак, всего одна ошибка значит большого труда исправление не составит. Не хватает одного класса Point. Можно пойти посмотреть исходники и скопировать класс оттуда, но мы пойдем другим путем.

    Компилятор пишет что нужен класс? Окей, давайте создадим класс

    class Point
    {
    
    }


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

    if (field[i, j] == "0") current = new Point(i, j);

    1>error CS1061: "Point" не содержит определения "X", и не удалось найти доступный метод расширения "X", принимающий тип "Point" в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку).


    if ((i == current.X) && (j == current.Y))


    1>error CS1061: "Point" не содержит определения "Y", и не удалось найти доступный метод расширения "Y", принимающий тип "Point" в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку).
    1>error CS1061: "Point" не содержит определения "Y", и не удалось найти доступный метод расширения "Y", принимающий тип "Point" в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку).


    Кажется, все понятно. Мы пытаемся использовать несуществующий конструктор и несуществующие свойства.

    Добавляем все необходимое. Компилятор ругается на два свойства и ожидает увидеть конструктор с двумя параметрами? Ага, зависимость видна - каждому параметру соответствует свое свойство с названиями X и Y соответственно.

    Как определить их тип? Смотрим что мы пытаемся туда передать? i , j - целые числа - int. Значит его и ставим.

    class Point
    {
        public int X { get; set; }
        public int Y { get; set; }
    
        public Point(int x, int y)
        {
            X = x;
            Y = y;
        }
    }


    Пробуем скомпилировать? Ошибок нет, можно переходить к этапу проверки работоспособности.
    Ответ написан
    2 комментария
  • Xamarin.Forms Как в функцию передать значение кнопки?

    FoggyFinder
    @FoggyFinder
    Лучше всего будет начать с чтения туториалов по MVVM

    Паттерн Model-View-ViewModel

    Ключевое в таком подходе разделение представления (View) от внутренней логики (Model/VM). В некоторых очень простых случаях (например, демонстрационных примерах) роли Model и VM объединяют в одну.

    Концептуально, то что вы описали в своем вопросе можно определить следующим образом:

    Есть некоторый объект, который содержит информацию об изменяемом значении. Также объект характеризуется двумя состояниями: "нажат" (кнопка окрашена в красный цвет) и "отжат" (кнопка стандартного цвета). В терминах C# можно выразить в виде класса:

    public class Item : ViewModelBase
    {
        private int value;
        private bool isSelected;
        public int Value
        {
            get => value;
            private set => SetProperty(ref this.value, value);
        }
        public bool IsSelected
        {
            get => isSelected;
            set => SetProperty(ref isSelected, value);
        }
    
        public Item(int value, bool isSelected = false)
        {
            Value = value;
            IsSelected = isSelected;
        }
    
        public void IncrementSelected()
        {
            if (IsSelected)
            {
                Value++;
            }
        }
    }


    Обратите внимание что класс унаследован от ViewModelBase это вспомогательный класс для того чтобы сообщать представлению об изменении некоторых свойств объекта.

    Теперь сама страница:

    Здесь у вас есть 3 объекта (Item) которые можно изменять, а также методы для изменения этих самых объектов. Понадобятся всего два метода:

    1. Изменить состояние соответствующего объекта по нажатию на кнопку
    2. Изменить значение для всех объектов для которых IsSelected истинно

    Опишем этом в коде:

    public class MyContext
    {
        public int BaseValue { get; } = 14;
        public Item Item1 { get; }
        public Item Item2 { get; }
        public Item Item3 { get; }
    
        public MyContext()
        {
            Item1 = new Item(BaseValue, true);
            Item2 = new Item(BaseValue);
            Item3 = new Item(BaseValue);
    
            IncrementSelectedCommand =
                new DelegateCommand<object>(_ => IncrementSelected());
            ClickCommand = new DelegateCommand<Item>(
                o => SelectOrDeselect(o),
                o => o is Item);
        }
    
        public ICommand IncrementSelectedCommand { get; }
        public ICommand ClickCommand { get; }
    
        public void IncrementSelected()
        {
            Item1.IncrementSelected();
            Item2.IncrementSelected();
            Item3.IncrementSelected();
        }
    
        public void SelectOrDeselect(Item item)
        {
            item.IsSelected = !item.IsSelected;
        }
    }


    Теперь сама сложная часть - View. Сложная она только тем что я хочу максимально близко оставить вашу разметку.

    Для начала определим простой стиль который будет менять цвет фона у кнопки:

    <Style x:Key="selectableBtn" TargetType="Button">
        <Style.Triggers>
            <DataTrigger
                Binding="{Binding IsSelected}"
                TargetType="Button"
                Value="True">
                <Setter Property="BackgroundColor" Value="Red" />
            </DataTrigger>
        </Style.Triggers>
    </Style>


    Пока все просто - как только IsSelected становится равным True задаем установку свойства BackgroundColor в нужный цвет.

    Последний рубеж - сетка:

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Label
            Grid.Column="1"
            FontSize="Large"
            HorizontalTextAlignment="Center"
            Text="I"
            VerticalTextAlignment="Center" />
        <Label
            Grid.Column="2"
            FontSize="Large"
            HorizontalTextAlignment="Center"
            Text="II"
            VerticalTextAlignment="Center" />
        <Label
            Grid.Column="3"
            FontSize="Large"
            HorizontalTextAlignment="Center"
            Text="III"
            VerticalTextAlignment="Center" />
        <Label
            Grid.Row="1"
            FontSize="Medium"
            HorizontalTextAlignment="Center"
            Text="{Binding BaseValue}" />
        <Button
            Grid.Row="1"
            Grid.Column="1"
            BindingContext="{Binding Item1}"
            Command="{Binding BindingContext.ClickCommand, Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type d:ContentPage}}}"
            CommandParameter="{Binding .}"
            Style="{StaticResource selectableBtn}"
            Text="{Binding Value}" />
        <Button
            Grid.Row="1"
            Grid.Column="2"
            BindingContext="{Binding Item2}"
            Command="{Binding BindingContext.ClickCommand, Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type d:ContentPage}}}"
            CommandParameter="{Binding .}"
            Style="{StaticResource selectableBtn}"
            Text="{Binding Value}" />
        <Button
            Grid.Row="1"
            Grid.Column="3"
            BindingContext="{Binding Item3}"
            Command="{Binding BindingContext.ClickCommand, Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type d:ContentPage}}}"
            CommandParameter="{Binding .}"
            Style="{StaticResource selectableBtn}"
            Text="{Binding Value}" />
        <Button
            Grid.Row="2"
            Grid.Column="3"
            Command="{Binding IncrementSelectedCommand}"
            Text="Add" />
    </Grid>


    Единственную хитрость здесь представляет установка BindingContext для кнопки чтобы реагировать на связанный элемент.

    И как вам уже подсказали чтобы из View передать информацию в VM можно использовать CommandParameter.

    И, завершающий штрих, установка BindingContext для содержимого:

    this.BindingContext = new MyContext();

    код выше можно поместить в конструктор для MainPage

    Напоследок, демонстрация работоспособности

    5f22d822d81b2087880445.gif

    Я намеренно не приводил код для классов ViewModelBase и RelayCommand - это стандартный классы реализации которых вы легко сможете найти.
    Например, тут и тут.
    Ответ написан
    1 комментарий
  • Можно ли во ViewModel узнать ширину элемента View?

    FoggyFinder
    @FoggyFinder
    Зависит от того зачем вам нужна информация о размерах UI - элементов.

    Если это часть пользовательских настроек, то хранить их на уровне ViewModel совершенно нормально и никак не противоречит паттерну.

    Но если это нужно исключительно для временной настройки UI, то и код должен находится на уровне View.

    Для вашего примера решение будет таким: добавьте обработчик события клика на кнопку и выводить информацию там.

    MVVM это не означает что в code-behind не должно быть никакого кода. Это типичная ошибка. В .xaml.cs не должно быть того, что не относится непосредственно к отображению.

    Управление анимацией, вывод вспомогательных сообщений, кастомизация пользовательских элементов управления - все это может быть там.
    Ответ написан
    Комментировать
  • Найти минимальный элемент из максимальных элементов каждой строки двумерного массива?

    FoggyFinder
    @FoggyFinder
    Вы не уточнили какой способ ввода данных, поэтому для демонстрации воспользуемся стандартным классом Random для генерации псевдослучайных чисел.

    Для поиска значения в последовательности можно использовать:

    Max - для максимального.

    Min - для минимального.

    const int n = 5;
    const int m = 5;
    
    const int max = 10;
    
    var rand = new Random();
    
    var array = new int[n][];
    for (int i = 0; i < n; i++)
    {
        array[i] = new int[m];
        for (int j = 0; j < m; j++)
            array[i][j] = rand.Next(max + 1);
    }
    
    Console.WriteLine("Массив = ");
    foreach (var row in array)
    {
        foreach (var value in row)
            Console.Write($"{value,4}");
        Console.WriteLine();
    }
    
    var min = array.Min(row => row.Max());
    Console.WriteLine($"Минимальный элемент из максимальных каждой строки = {min}");


    По хорошему код нужно разбить на функции, но эту часть оставлю вам.
    Ответ написан
    1 комментарий
  • Какое оформление предпочтительнее?

    FoggyFinder
    @FoggyFinder
    Общие замечания (ко всем кусочкам):

    Нет разделения на функции (проблема: дублирование кода, усложняет восприятие)

    Вынесите каждую часть в удобный метод и вызывайте. Например:
    * Получение числа с консоли
    * Поиск минимального из трех чисел
    * Проверка на четность

    Вам будет намного понятнее что выполняет код - ваш взгляд охватит несколько вызовов и не будет отвлекаться на конкретные детали реализации.

    Общие проблемы закончились, теперь сверху вниз:

    1 кусок:

    1. [ Критично ] Нет проверки на корректность ввода. Пользователь может случайно ввести букву и метод Convert.ToInt32 выбросит исключение. Довольно неприятно.

    2. Нарушение соглашения об именовании для переменной FinalResult

    3. Необязательная инициализация переменной FinalResult при объявлении.

    4. [ Субъективно ] Проблемы с форматированием: тернарный оператор занимает слишком много места для одной строки

    5. [ Может рассматриваться как придирка ] Копипаст подход. Вывод сообщения можно вынести из if-ов в - он одинаков для всех случаев.

    2 кусок:

    1. [ Критично ] Аналогично предыдущему

    2. Нарушение соглашения об именования для переменной MuchSmaller

    3. Объявление и лишняя инициализация переменной MuchSmaller намного впереди реального использования.

    4. Слишком сложные условные выражения.

    5. Аналогично п.5 предыдущего примера.

    3 кусок:

    Здесь, ура!, нет основной проблемы которая встречается во всех остальных примерах.

    1. Нарушение соглашения об именовании для переменной Result

    2. Странная смесь английского и русского языка в информационных сообщениях

    3. Странная смесь использования интернирования строк ($) и старого форматирования.

    4 кусок:

    1. [ Критично ] Нет проверки на корректность ввода. Пользователь может случайно ввести букву и метод Convert.ToInt32 выбросит исключение. Довольно неприятно.

    2. [ Существенно ] Копипаст подход для проверки на четность.

    3. Избыточные скобки в switch case

    5 кусок:

    1. [ Критично ] Нет проверки на корректность ввода. Пользователь может случайно ввести букву и метод Parse выбросит исключение.

    2. Проблемы с названием переменных. inputOne

    Итого:

    3-ий вариант условно нормальный. Остальные хуже.

    Упражнение:

    Попробуйте написать свой вариант с учетом замечаний перечисленных выше =)
    Ответ написан
    Комментировать
  • WPF ListBox как вручную отсортировать список перетаскиванием элементов мышкой?

    FoggyFinder
    @FoggyFinder
    Есть замечательная библиотека которая практически все делает за вас:

    GongSolutions.WPF.DragDrop

    Все, что вам нужно в простейших сценариях, это установить на разрешение перетаскивать ИЗ и В:

    dd:DragDrop.IsDragSource="True"
    dd:DragDrop.IsDropTarget="True"


    Обновляю ответ в связи с комментарием:

    Общая рекомендация:

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


    Привожу минимальный пример демонстрирующий что перетаскивание в пределах списка не является проблемой.

    VM:

    public class MainVM
    {
        private IEnumerable<FileInfo> GetFiles() =>
            Directory.EnumerateFiles(Directory.GetCurrentDirectory())
                        .Select(path => new FileInfo(path));
        public MainVM()
        {
            FileList = new ObservableCollection<FileInfo>(GetFiles());
        }
        public FileInfo CurrentFile { get; set; }
        public ObservableCollection<FileInfo> FileList { get; }
    }


    View:

    пространство имен:

    xmlns:dd="urn:gong-wpf-dragdrop"

    сам список:

    <ListBox
        dd:DragDrop.IsDragSource="True"
        dd:DragDrop.IsDropTarget="True"
        ItemsSource="{Binding FileList}"
        SelectedItem="{Binding CurrentFile}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>


    Гиф с результатом:

    5dee28369295b074649445.gif
    Ответ написан
    6 комментариев
  • Почему происходит NullReferenceException при добавлении экземпляра класса в лист?

    FoggyFinder
    @FoggyFinder
    List нужно предварительно инициализировать:

    public List<Node> children = new List<Node>();

    Но, обычно, публичные поля это далеко не лучшая стратегия.
    Ответ написан
    1 комментарий
  • Как динамически создавать элементы сетки Grid?

    FoggyFinder
    @FoggyFinder
    Можно установить в качестве панели UniformGrid, тогда все строки будут иметь одинаковую высоту.

    <ListBox Grid.Column="1" ItemsSource="{Binding Notes}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Columns="1" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Title}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ListBox>


    За идею спасибо Athari
    Ответ написан
    Комментировать
  • Проблемы с NETStandard.Library в Xamarin?

    FoggyFinder
    @FoggyFinder
    В списке источников NuGet:

    Tools -> NuGet Package Manager -> Package Manager Settings -> Package Sources.

    должен находится стандартный:

    https://api.nuget.org/v3/index.json


    Если его там нет, то нужно будет добавить.
    Ответ написан
    Комментировать
  • Как построить график функции в windows forms c#?

    FoggyFinder
    @FoggyFinder
    Тут у вас сразу несколько ошибок:

    1. Нужно явно приводить к double иначе при делении двух int получите тоже целое.
    2. Вы берете очень большие границы. Рост знаменателя намного превышает скорость роста числителя. Сами посмотрите: возведите 50 в куб, что получите? График вы конечно построите, но наглядности будет немного.

    Что более важно: ваш отрезок OA = 2*a, а это значит что ваша правая граница точно должна быть меньше чем 2*a;

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

    Собирая все вместе, попробуйте что-то вроде такого:

    double a = 3;
    double step = 0.1;
    
    for (double x = 0; x < 2 * a - 1; x += step)
    {
        var n = x * x * x;
        var d = 2 * a - x;
        chart1.Series[0].Points.AddXY(x, Math.Sqrt(n / d));
        chart1.Series[1].Points.AddXY(x, -Math.Sqrt(n / d));
    }


    Здесь 1 (x < 2 * a - 1) вычитается только для примера, чтобы вы сравнили результат. В реальности вам придется определять границу более сложным путем чтобы для разных a и левой границы (x) получать наглядное представление. Но, по крайней мере, у вас есть от чего отталкиваться.
    Ответ написан
    Комментировать
  • Как связать конкретную фигуру с выбранным элементом?

    FoggyFinder
    @FoggyFinder
    Пока нет возможности написать пример, но попробую дополнить ответ когда она появится.

    Если количество отображаемых элементов не слишком большое (в пределах 100-1000), то, вероятно, лучшим вариантом будет вынести часть информации в ViewModel (а именно, координаты расположения линий и состояние IsSelected). В вашем примере этот класс назван Model, но я рекомендую его переименовать, в дальнейшем это может сбить с толку.

    Тогда вы привяжите коллекцию к ItemsControl, где панелью будет выступать Canvas.
    Координаты привяжите индивидуально. Реагировать на изменение цвета можно будет или через триггер или через конвертер, но если вариантов всего 2, то проще, на мой взгляд, будет использовать именно триггер.

    При выделении элемента в коллекции сбрасываете состояние IsSelected предыдущего элемента в False и указанному соответственно ставите True.

    Обновлено:

    Появились несколько свободных минут, привожу пример:

    Для начала, для удобства создадим ViewModelBase, чтобы несколько раз не реализовывать интерфейс INPC:

    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(storage, value))
                return false;
            storage = value;
            this.OnPropertyChanged(propertyName);
            return true;
        }
    }


    Теперь, как я уже писал выше, нам понадобиться отдельная ViewModel для ячейки, элемента списка:

    public class LineVM : ViewModelBase
    {
        private bool isSelected;
        public bool IsSelected
        {
            get { return isSelected; }
            set { SetProperty(ref isSelected, value); }
        }
    
        public LineVM(string name, int x, int y)
        {
            Name = name;
            X = x;
            Y = y;
        }
        public string Name { get; set; }
    
        public int X { get; private set; }
    
        public int Y { get; private set; }
    }


    Здесь нет необходимости в изменении координат во время работы программы, поэтому сеттеры оставим приватными.

    Главная ViewModel :

    public class ItemsVM : ViewModelBase
    {
        private LineVM selectedVM;
    
        public ObservableCollection<LineVM> Models { get; }
        public LineVM SelectedModel
        {
            get { return selectedVM; }
            set
            {
                if (SelectedModel != null)
                    SelectedModel.IsSelected = false;
                value.IsSelected = true;
                SetProperty(ref selectedVM, value);
            }
        }
    
        public ItemsVM()
        {
            Models = new ObservableCollection<LineVM>
            {
                new LineVM ("A", 10, 20 ),
                new LineVM ("B", 10, 40),
                new LineVM ("C", 10, 60),
                new LineVM ("D", 10, 80)
            };
        }
    }


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

    Теперь View часть. Привожу только измененный третий столбец:

    <ItemsControl Grid.Column="2" ItemsSource="{Binding Models}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Line
                X1="0"
                X2="100"
                Y1="0"
                Y2="00">
                    <Line.Style>
                        <Style TargetType="Line">
                            <Setter Property="Stroke" Value="Blue" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsSelected}" Value="True">
                                    <Setter Property="Stroke" Value="Red" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Line.Style>
                </Line>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="{Binding X}" />
                <Setter Property="Canvas.Top" Value="{Binding Y}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>


    Тут тоже все достаточно просто - триггер реагирует на изменение свойства IsSelected и меняет цвет на красный для текущего элемента.

    И, для наглядности, оставляю гифку:

    5dd6e7e03664e626729135.gif
    Ответ написан
    2 комментария
  • Как открыть файл определенного формата в c#?

    FoggyFinder
    @FoggyFinder
    Можно использовать метод Path.GetExtension чтобы получить расширение.

    Останется только убедится что файл в списке подходит под параметры:

    foreach (var filename in filenames)
        if (Path.GetExtension(filename) == ".exe")
            System.Diagnostics.Process.Start(filename);
    Ответ написан
  • Как упростить переменную в C#?

    FoggyFinder
    @FoggyFinder
    Можно вынести в отдельную функцию:

    string CreateASCIIStr(string value) => Encoding.ASCII.GetString(Convert.FromBase64String(value));


    или, в локальную, с использованием LocalData:

    string CreateASCIIStr(string value) =>
                    LocalData + Encoding.ASCII.GetString(Convert.FromBase64String(value));


    Добавлено:

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

    В данном случае у вас есть многократный последовательный вызов двух методов:

    Convert.FromBase64String и Encoding.ASCII.GetString

    для удобства их совмещаем в один вызов и получаем

    Encoding.ASCII.GetString(Convert.FromBase64String(value))

    Пример:

    string LocalData = "0";
    string CreateASCIIStr(string value) =>
        LocalData + Encoding.ASCII.GetString(Convert.FromBase64String(value));
    
    var data = new[] {
        CreateASCIIStr("Тут"),
        CreateASCIIStr("Все"),
        CreateASCIIStr("значения"),
        CreateASCIIStr("будут"),
        CreateASCIIStr("совершенные"),
        CreateASCIIStr("Разные")
    };


    Здесь возвращается массив, но если ваши совершенно разные значения в действительности являются массивом, то и обрабатывать их лучше как массив ;-)
    Ответ написан
    3 комментария
  • Как сделать, что бы после закрытия messageboxа не открывались следующие?

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

    Код в обработчике button1_Click выполняется последовательно. После того как сработает первое условие вы уменьшаете значение на единицу и следующий if тоже становится верным.

    Первое что вам нужно сделать это вынести количество попыток в приватную переменную.
    kolvopotytok не самое подходящее название (и хотя я, например, могу понять что тут имеется ввиду количество попыток) лучше использовать названия на английском. Давайте возьмем countOfAttempts . Так как вы хотите отслеживать количество, то вам нужно завести еще одну переменную для учета их изначального (максимального) числа:

    public Form2(int digitfrom, int digitto)
    {
        InitializeComponent();
    
        Random rnd = new Random();
        r = rnd.Next(digitfrom, digitto);
        maxCountOfAttempts = countOfAttempts = 3;
    }
    private int r;
    private int maxCountOfAttempts, countOfAttempts;


    Затем вы можете заметить что каждый раз код внутри проверочного условия одинаковый.
    А теперь представьте, что диапазон будет достаточно широкий (скажем около сотни), а количество попыток увеличиться до 10. Копировать один и тот-же участок раз за разом не слишком эффективно. Давайте тогда вынесем весь код в отдельную функцию, которая будет принимать значение и в зависимости от него выводить информационное сообщение. Если пользователь угадал, то функция вернет true, в противном случае - false:

    private bool CheckResult(int a)
    {
        if (a == r)
        {
            MessageBox.Show($"Поздравляем!!! Вы угадали число с {countOfAttempts - 1} раза.");
            return true;
        }
        else if (a > r)
        {
            MessageBox.Show($"Число которое загадал ИИ меньше вашего!\nУ вас осталось {countOfAttempts - 1} попытки.");
            return false;
        }
        else
        {
    
            MessageBox.Show($"Число которое загадал ИИ больше вашего!\nУ вас осталось {countOfAttempts - 1} попытки.");
            return false;
        }
    }


    Теперь немного изменим сам обработчик:

    private void button1_Click(object sender, EventArgs e)
    {
        if (IsDigitsOnly(answer.Text))
        {
            int a = Convert.ToInt32(answer.Text);
            if (CheckResult(a))
                this.Close();
            else
            {
                countOfAttempts--;
                if (countOfAttempts == 0)
                {
                    MessageBox.Show("К сожелению вы проиграли\nЗагаданное число: " + r);
                    this.Close();
                }
            }
        }
        else
        {
            MessageBox.Show("Некорректный ввод данных", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        answer.Clear();
    }


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

    И, если позволите, небольшой совет на будущее: старайтесь избегать использования goto.
    Ответ написан
    Комментировать
  • NET Core. Как перенести с виндовс на mac os?

    FoggyFinder
    @FoggyFinder
    Собрать приложение под другую платформу можно с помощью команды publish

    dotnet publish

    с указанием правильного runtime. Например:

    dotnet publish -c Release --framework netcoreapp2.0 --runtime osx-x64
    Ответ написан
  • Проблема с get и set. Почему не работает?

    FoggyFinder
    @FoggyFinder
    Свойства по сути маскируют в себе обычные методы для извлечения/установки полей.
    Представим что есть такой метод:

    public string GetValue()
    {
        return GetValue();
    }


    Здесь содержится только новый рекурсивный вызов. Какой результат будет получен при вызове такого метода? Естественно, StackOverflowException.

    Поэтому каждому свойству должно соответствовать какое-то поле.

    private string _actNumber;
    public string ActNumber {
        get { return _actNumber; }
        set { _actNumber = value; }
    }

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

    public string ActNumber { get; set; }

    Что, конечно, может сбить с толку когда потребуется дополнительные условия.

    ----

    По поводу второй части вопроса. Обрабатывать null - результат нужно на самом верхнем (допустимом) уровне.

    В C# для этого есть целый набор null-операторов:

    ?., ??, ??=

    о которых можно прочитать, например, в справке:

    ?? and ??= operators

    Null-conditional operators ?. and ?[]
    Ответ написан
    2 комментария
  • Вывод текста в label при клике c# windows forms?

    FoggyFinder
    @FoggyFinder
    В WinForms проектах конструктор форм прячет детали пользовательского интерфейса в файл Form1.Designer.cs (вместо Form1 будет название конкретного класса). Поэтому при копировании из других проектов или примеров нужно не забывать перенести также все подписки.

    Чтобы проверить их наличие (или отсутствие), в конструкторе форм выделите элемент и перейдите к просмотру его свойств (Properties).

    По умолчанию откроется вкладка свойств контрола. Для просмотра информации о событиях нужно перейти на следующую за ней (с нарисованной молнией):

    5db6e64c1bdca244908136.jpeg

    В списке находите требуемый элемент. Если справа ничего не присвоено, значит дело в отсутствующей подписке. Через выпадающий список (ComboBox) выбираете обработчик из доступных:

    5db6e7036cb33351827234.jpeg

    Запускаете, проверяете.
    Если все работает, значит проблема найдена правильно.

    Для подписки не обязательно использовать конструктор форм, можно создавать их самостоятельно, например, в конструкторе форм:

    button1.Click += Button1_Click;

    Но лучше придерживаться одного стиля, так и код будет проще восприниматься и лишних подписок не будет.
    Ответ написан
    Комментировать
  • Обработка события нажатия ЛКМ на заголовке DGV?

    FoggyFinder
    @FoggyFinder
    Обрабатывайте общее событие CellMouseClick. У выделенной на скриншоте ячейки оба индекса равны -1:

    private void DataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        var row = e.RowIndex;
        var column = e.ColumnIndex;
    
        if(row == -1 && column == -1)
        {
            // Do something
        }
    }
    Ответ написан
  • Если объект соприкасается с чёрным цветом, то выполнять вывод в консоль?

    FoggyFinder
    @FoggyFinder
    Вначале небольшое лирическое отступление.

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

    Теперь к вопросу.

    Ваш объект (obj) это PictureBox , элемент управления, у которого, что не удивительно, нет своего метода intersects.

    Но вы можете использовать свойство Bounds чтобы получить местоположение и размеры ваших объектов:

    if(pictureBox1.Bounds.IntersectsWith(pictureBox2.Bounds))
    {
    // put your code here
    }


    По поводу второй части - проверки что объект определенного цвета. Чтобы быть уверенным что картинка полностью одного цвета придется проверять каждый пиксель.
    Но, я думаю, что вы можете добиться цели намного более простым способом.

    Например, если ваш объект может менять цвета, а вас интересует является ли он черным, то в момент смены цветы храните это состояние (isBlack) в свойстве Tag вашего pictureBox.

    Если вы пишите какую-то простую игру по типу змейки, то пока не завязли, советую уделить немного времени на разделение кода на смысловые части - определите классы описывающую ваши объекты, логику взаимодействия и отдельно их отображение на форме.
    Ответ написан
    5 комментариев
  • Не запускается таймер c# (xamarin), что не так?

    FoggyFinder
    @FoggyFinder
    В Xamarin.Forms можно использовать Device.StartTimer
    Ответ написан
    Комментировать