/// <summary>
        /// Do the loading in the background
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void loadingBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // read file if option is checked
            if (settings.CanImport)
            {
                try
                {
                    clues = ReadFile();
                } catch (Exception)
                {
                    // set error to true, cannot throw from background to main thread
                    fileError = true;
                    loadingBackgroundWorker.ReportProgress(100);
                }
            }
            else
            {
                // if no file is specified, randomly generate grid sizes
                Size gridSize = GetGridSize();
                maxRows = Utilities.GetRandomInt(gridSize.Width, gridSize.Height);
                maxCols = Utilities.GetRandomInt(gridSize.Width, gridSize.Height);
            }

            gridButtons = new GridButton[maxRows, maxCols];

            // generate GridButtons according to sizes
            for (int row = 0; row < maxRows; row++)
            {
                // to report background progress
                int rowProgress = (row + 1) * 99 / maxRows;

                for (int col = 0; col < maxCols; col++)
                {
                    int colProgress = (col + 1) * maxCols / (maxRows * maxCols);
                    gridButtons[row, col] = new GridButton(row, col, PANEL_MAX_HEIGHT / maxRows, PANEL_MAX_WIDTH / maxCols);

                    // report progress to main thread
                    int progress = rowProgress + colProgress;
                    loadingBackgroundWorker.ReportProgress(progress <= 100 ? progress : 100);
                }
            }
        }
        /// <summary>
        /// Submits guess and checks if the game is finished
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GridButtons_Click(object sender, EventArgs e)
        {
            GridButton button = (GridButton)sender;

            // if button has not already been revealed to have a clue
            if (!button.IsClue)
            {
                // evaluate guess and update images
                GuessResult result = scanalyzer.EvaluateGuess(new Clue(button.Row, button.Column));
                button.Image         = result.Image;
                guessesLabel.Text    = scanalyzer.Guesses.ToString();
                cluesFoundLabel.Text = $"{scanalyzer.CurrentSample}/{cluesNum}";

                if (result.IsCorrect)
                {
                    button.IsClue = true;
                    ResetButtonsAfterCorrectGuess();
                    if (scanalyzer.AllCluesFound())
                    {
                        FinishGame();
                    }
                }
            }
        }