Графический ключ с#

Рейтинг: 1Ответов: 1Опубликовано: 08.04.2023

Пытаюсь сделать простенькую реализацию проверки графического ключа. Есть список пользователей, ключ задается через кнопки. Для начала я регистрирую ключ для какого-либо пользователя, он сохраняется в массиве userKeys. Далее я меняю графический ключ и пытаюсь войти под неправильным ключом, но функция CheckKey возвращает всегда true и у меня получается войти под неверным ключом. Хотя в событии Button_Click каждая измененная кнопка сохраняется в массив Buttons. И в CheckKey уже должен сверяться зарегистрированный ключ с текущим(в массиве Buttons).

 using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
    
namespace InfoLab7
{
    public partial class Form1 : Form
    {
        private const int mapSize = 10;
        private const int cellSize = 30;
        private string curUser;
        private static TextBox UserNameTextBox = new TextBox();
        private List<string> users = new List<string> { "user1", "user2", "user3" };
        private Dictionary<string, Button[,]> userKeys = new Dictionary<string, Button[,]>();
        private static Button[,] Buttons = new Button[mapSize, mapSize];
        public Form1()
        {
            InitializeComponent();

           
            Panel loginPanel = new Panel();
            loginPanel.Location = new Point(mapSize * cellSize, 0);
            loginPanel.Size = new Size(200, this.ClientSize.Height);
            this.Controls.Add(loginPanel);
            // Создаем кнопки для графического ключа
            for (int i = 0; i < mapSize; i++)
            {
                for (int j = 0; j < mapSize; j++)
                {
                    Button button = new Button();
                    button.Location = new Point(j * cellSize, i * cellSize);
                    button.Size = new Size(cellSize, cellSize);
                    button.BackColor = Color.White;
                    button.Click += new EventHandler(Button_Click);
                    button.Name = i + "," + j;
                    Buttons[i, j] = button;
                    this.Controls.Add(button);
                }
            }

            // Создаем TextBox для ввода имени пользователя
            UserNameTextBox.Location = new Point(10, 10);
            UserNameTextBox.Size = new Size(180, 25);
            loginPanel.Controls.Add(UserNameTextBox);

            // Создаем кнопку входа
            Button loginButton = new Button();
            loginButton.Location = new Point(10, 40);
            loginButton.Size = new Size(180, 25);
            loginButton.Text = "Войти";
            loginButton.Click += new EventHandler(LoginButton_Click);
            loginPanel.Controls.Add(loginButton);

            Button logoutButton = new Button();
            logoutButton.Location = new Point(10, 70);
            logoutButton.Size = new Size(180, 25);
            logoutButton.Text = "Выйти";
            logoutButton.Click += new EventHandler(LogoutButton_Click);
            loginPanel.Controls.Add(logoutButton);

            // Создаем кнопку для очистки графического ключа
            Button clearButton = new Button();
            clearButton.Location = new Point(0, mapSize * cellSize);
            clearButton.Size = new Size(mapSize * cellSize, cellSize);
            clearButton.Text = "Очистить";
            clearButton.Click += new EventHandler(ClearButton_Click);
            this.Controls.Add(clearButton);

            // Создаем кнопку для сохранения графического ключа
            Button saveButton = new Button();
            saveButton.Location = new Point(0, (mapSize + 1) * cellSize);
            saveButton.Size = new Size(mapSize * cellSize, cellSize);
            saveButton.Text = "Зарегистрировать ключ";
            saveButton.Click += new EventHandler(SaveButton_Click);
            this.Controls.Add(saveButton);
        }
        
        private void LoginButton_Click(object sender, EventArgs e)
        {
            string userName = UserNameTextBox.Text;
            if (!string.IsNullOrWhiteSpace(curUser))
            {
                MessageBox.Show(curUser + " не вышел из системы");
                return;
            }
            if(users.Contains(userName))
            {
                if (userKeys.ContainsKey(userName))
                {
                    Button[,] key = userKeys[userName];
                    if (CheckKey(key, Buttons))
                    {
                        curUser = userName;
                        MessageBox.Show("Добро пожаловать, " + userName + "!");
                    }
                    else
                    {
                        MessageBox.Show("Графический ключ не верен. Попробуйте еще.");
                    }
                }
                else
                {
                    MessageBox.Show("Графический ключ для пользователя " + userName + " не найден.");
                }
            }
            else
            {
                MessageBox.Show("Пользователь " + userName + " не найден.");
            }

        }
        private void LogoutButton_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(curUser)) {
                MessageBox.Show("Выход пользователя " + curUser);
                curUser = "";
            }
            else MessageBox.Show("Вы уже вышли");
        }
        private void Button_Click(object sender, EventArgs e)
        {
            Button button = sender as Button;
            string[] str = button.Name.Split(',');
            int row = int.Parse(str[0]);
            int col = int.Parse(str[1]);
             if (button.BackColor == Color.White)
        {
            button.BackColor = Color.Blue;
            Buttons[row, col] =button;
        }
        else if(button.BackColor == Color.Blue)
        {
            button.BackColor = Color.White;
            Buttons[row, col] = button;
        }
        }
        private void ClearButton_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < mapSize; i++)
            {
                for (int j = 0; j < mapSize; j++)
                {
                    Buttons[i, j].BackColor = Color.White;
                }
            }
        }
        private void SaveButton_Click(object sender, EventArgs e)
        {

            // Проверить, что графический ключ не пустой
            if (!IsKeyValid())
            {
                MessageBox.Show("Графический ключ не может быть пустым.");
                return;
            }
            string userName = "";
            userName = Microsoft.VisualBasic.Interaction.InputBox("Введите имя пользователя:", "Регистрация пользователя", "");

            // Сохранить ключ в словаре для данного пользователя
            if (userKeys.ContainsKey(userName))
            {
                userKeys[userName] = Buttons;
            }
            else
            {
                userKeys.Add(userName, Buttons);
            }

            MessageBox.Show("Графический ключ для пользователя " + userName + " сохранен.");
        }
      
        private bool IsKeyValid()
        {
            for (int i = 0; i < Buttons.GetLength(0); i++)
            {
                for (int j = 0; j < Buttons.GetLength(1); j++)
                    if (Buttons[i, j].BackColor == Color.Blue)
                        return true;
            }
            return false;
        }
        private bool CheckKey(Button[,] key, Button[,] Buttons)
        {
            for (int i = 0; i < key.GetLength(0); i++)
            {
                for (int j = 0; j < key.GetLength(1); j++)
                    if (key[i, j].BackColor != Buttons[i, j].BackColor)
                        return false;
            }
            return true;
        }
    }
}

Ответы

▲ 3Принят

Всё просто, вы контролы в массив засовываете, а надо цвет. Button - класс, ссылочный тип. То есть вы сравниваете кнопки в массиве ключа сами с собой, поэтому всегда true.

Сделайте вместо Button[,] массив Color[,] и просто скопируйте в него цвета при сохранении.


Вот пример для иллюстрации ошибки

class Test
{
    public int X;
}
var obj1 = new Test();
obj1.X = 123;
var obj2 = obj1;
obj1.X = 42;
MessageBox.Show(obj2.X.ToString());

Этот код выведет 42, хотя я в obj2 ничего не менял. А всё потому что obj1 и obj2 - ссылки на один и тот же объект. Поэтому как бы я не изменял X, if (obj1.X == obj2.X) всегда будет true.