用特定模式填充矩阵

时间:2018-08-06 20:43:55

标签: c# arrays algorithm matrix

所以我有一个总是相同尺寸的矩阵,它的定义如下:

public void InitPositionsGrid()
    {
        int munberOfRows = 6;
        for(int i = 0; i < munberOfRows; i++)
        {
            if( i % 2 == 0)
            {
                GridPositions[i] = new int[15];
            }
            else
            {
                GridPositions[i] = new int[14];
            }
        }
    }

现在,我需要一种方法(递归或迭代的方式)填充该矩阵,但要使用特定的模式,以便在所有方向上均等地填充。该方法应采用3个参数(X和Y)来定义起始位置,以及另外一个要填充的位置数。应该看起来像这样:

public void FillGridMatrix(int startingRow, int startingColumn, int numberOfPlacesToFill)
{
    //Fill the matrix with the following algorithm but don't go out of bounds
}

这是显示算法示例的图片:

Algorithm example

想法是:从当前起始位置开始,检查“上方”两个空格(应为x-1,y-1和x-1,y),检查相邻的两个空格(x,y-1和x ,y + 1),最后检查“以下”两个空格(x + 1,y-1和x + 1,y)。坐标可能不完全是这些坐标,但这是一般的想法。请注意,当没有更多空间“上”或“下”时,要填充的位置应在左侧和右侧相等。起始行永远不能是第一行或最后一行。如果已经标记了当前正在检查的位置,请跳过该位置。可以填充的最大位数为87,矩阵本身中的最大元素数也可以为87。在第一轮之后,如果要填充的地方超过7个,则算法从左上角开始,并从起始位置(在本示例中为2和7)以右下角的“ adjacent”成员结束。

任何想法对此的最佳解决方案是什么?首选C#。

编辑:这是最接近我想要实现的解决方案,唯一的问题是这不适合递归,并且迭代解决方案需要太多条件。

public int PopulateMatrixAroundCertainPosition(int[][] matrix, int row, int column, int availableNumbers)
    {
        if(availableNumbers <= 0)
        {
            return 0;
        }
        matrix[row][column] = 1;
        availableNumbers = PopulateSingleMatrixPosition(matrix, row - 1, column - 1, availableNumbers - 1);
        availableNumbers = PopulateSingleMatrixPosition(matrix, row - 1, column, availableNumbers - 1);
        availableNumbers = PopulateSingleMatrixPosition(matrix, row, column - 1, availableNumbers - 1);
        availableNumbers = PopulateSingleMatrixPosition(matrix, row, column + 1, availableNumbers - 1);
        availableNumbers = PopulateSingleMatrixPosition(matrix, row + 1, column - 1, availableNumbers - 1);
        availableNumbers = PopulateSingleMatrixPosition(matrix, row + 1, column, availableNumbers - 1);
        return availableNumbers - 1;
    }

    public int PopulateSingleMatrixPosition(int[][] matrix, int row, int column, int availableNumbers)
    {
        if (availableNumbers <= 0)
        {
            return 0;
        }
        if(matrix[row][column] == 1)
        {
            return availableNumbers + 1;
        }
        matrix[row][column] = 1;
        return availableNumbers;
    }

1 个答案:

答案 0 :(得分:0)

无需递归。只是继续建立内部结构。我创建了一个小状态机来解决难题:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        const int TOTAL_BUTTONS = 61;
        const int BUTTON_SIZE = 40;
        const int SPACE = 10;
        public Form1()
        {
            InitializeComponent();
            BuildMatrix();
        }
        public enum LOCATION
        {
            TOP_ROW,
            LEFT_BUTTON,
            RIGHT_BUTTON,
            BOTTOM_ROW
        }

        List<List<Button>> matrix = new List<List<Button>>();
        int numberButtons = 0;
        public void BuildMatrix()
        {
            int centerX = 0;
            int centerY = 0;

            int loopCounter = 1; //count of number of loops around matrix  

            int numberRows = 0;
            int rowCount = 0;
            int columnCount = 0;
            centerX = this.Width / 2;
            centerY = this.Height / 2;

            LOCATION location = LOCATION.TOP_ROW;
            List<Button> newRow = new List<Button>();
            Button newButton = null;
            Button buttonLeft = null;
            for (int buttonCount = 0; buttonCount < TOTAL_BUTTONS; buttonCount++)
            {
                switch (location)
                {
                    case LOCATION.TOP_ROW :
                        if (columnCount == 0)
                        {
                            newRow = new List<Button>();
                            if (numberRows++ == 0)
                            {
                                matrix.Add(newRow);
                                newButton = AddButton(centerY - (BUTTON_SIZE / 2), centerX - (BUTTON_SIZE / 2));
                                //add first button
                                newRow.Add(newButton);
                                loopCounter++;
                                continue;
                            }
                            else
                            {
                                matrix.Insert(0, newRow);
                                Button buttonDownRight = matrix[1][columnCount];
                                newButton = AddButton(buttonDownRight.Top - SPACE - BUTTON_SIZE, buttonDownRight.Left - ((SPACE + BUTTON_SIZE) / 2));
                            }
                        }
                        else
                        {
                            buttonLeft = matrix[rowCount][columnCount - 1];
                            newButton = AddButton(buttonLeft.Top, buttonLeft.Left + SPACE + BUTTON_SIZE);
                        }
                        //put new button above button below, move up one row, move left half column
                        newRow.Add(newButton);

                        if (++columnCount == loopCounter)
                        {
                            location = LOCATION.LEFT_BUTTON;
                            rowCount++;
                        }
                        break;

                    case LOCATION.LEFT_BUTTON :
                        Button buttonRight = matrix[rowCount][0];
                        newButton = AddButton(buttonRight.Top, buttonRight.Left - SPACE - BUTTON_SIZE);
                        matrix[rowCount].Insert(0, newButton);
                        location = LOCATION.RIGHT_BUTTON;
                        break;

                    case LOCATION.RIGHT_BUTTON :
                        buttonLeft = matrix[rowCount][matrix[rowCount].Count - 1];
                        newButton = AddButton(buttonLeft.Top, buttonLeft.Left + SPACE + BUTTON_SIZE);
                        matrix[rowCount].Add(newButton);
                        rowCount++;
                        if (rowCount >= numberRows)
                        {
                            location = LOCATION.BOTTOM_ROW;
                        }
                        else
                        {
                            location = LOCATION.LEFT_BUTTON;
                        }
                        columnCount = 0;
                        break;

                    case LOCATION.BOTTOM_ROW :
                        if (columnCount == 0)
                        {
                            newRow = new List<Button>();
                            matrix.Add(newRow);
                            numberRows++;
                        }
                        Button buttonTopLeft = matrix[rowCount - 1][columnCount];
                        newButton = AddButton(buttonTopLeft.Top + SPACE + BUTTON_SIZE, buttonTopLeft.Left + ((SPACE + BUTTON_SIZE) / 2));
                        matrix[rowCount].Add(newButton);
                        if (++columnCount == loopCounter)
                        {
                            location = LOCATION.TOP_ROW;
                            columnCount = 0;
                            rowCount = 0;
                            loopCounter++;
                        }


                        break;

                }
            }

        }
        public Button AddButton(int top, int left)
        {
            Button newButton = new Button();
            newButton.Width = BUTTON_SIZE;
            newButton.Height = BUTTON_SIZE;
            newButton.Top = top ;
            newButton.Left = left;
            numberButtons++;
            newButton.Text = numberButtons.ToString();
            this.Controls.Add(newButton);

            return newButton;
        }
    }
}