-2

目的

次のような行列があると想像してください

a11 a12 a13
a21 a22 a23
a31 a32 a33

私がやりたいことは、テキストボックスの値からこの行列を回転させて、たとえば 2 と書いて を押すrotateと、プログラムは行列の両方の対角値 (この場合は a11、a22、a33、a13、a31) を保持し、2 を回転させる必要があります。他の値を時計回りに回します。したがって、結果は次のようになります

a11 a32 a13
a23 a22 a21
a31 a12 a33

すべてのN x Nサイズのマトリックスで機能する必要があり、ご覧のとおり、4回転ごとにマトリックスがデフォルト状態になります。

私がしたこと

アイデアはそのようなもので、2つのフォームがあります。最初に行列のサイズを取得します (1 値、たとえば 5 の場合、5x5 行列を生成します)。押すOKと、そのような2番目のフォームテキストボックスマトリックスが生成されます

フォーム 1 コード

    private void button1_Click(object sender, EventArgs e)
    {
        int matrixSize;
        matrixSize = int.Parse(textBox1.Text);
        Form2 form2 = new Form2(matrixSize);
        form2.Width = matrixSize * 50 + 100;
        form2.Height = matrixSize *60 + 200;
        form2.Show();            
        //this.Hide();
    }

フォーム 2 コードは、指定された値からテキスト ボックス マトリックスを生成し、ランダムな値をこのフィールドに入れます。

public Form2(int matrSize)
        {
            int counter = 0;
            InitializeComponent();
            TextBox[] MatrixNodes = new TextBox[matrSize*matrSize];
            Random r = new Random();
            for (int i = 1; i <= matrSize; i++)
            {
                for (int j = 1; j <= matrSize; j++)
                {
                    var tb = new TextBox();                    
                    int num = r.Next(1, 1000);
                    MatrixNodes[counter] = tb;
                    tb.Name = string.Format("Node_{0}{1}", i, j);
                    Debug.Write(string.Format("Node_{0}{1}", i, j));
                    tb.Text = num.ToString();
                    tb.Location = new Point(j * 50, i * 50);
                    tb.Width = 30;
                    tb.Visible = true;
                    this.splitContainer1.Panel2.Controls.Add(tb);
                    counter++;
                }
            }
           
        }

フォーム 2 には、回転を制御するためのテキスト ボックスが 1 つあります (その他のテキスト ボックスは、プログラムによってオンザフライで生成されます)。私がしたいのは、回転カウントを入力Enterしてこのテキストボックスを押すと、上記で説明したようにテキストボックスマトリックスを回転させたいということです。方法がわかりません。

4

4 に答える 4

9

両方の対角線を別々の配列にコピーしてから、行列を回転させて対角線を置き換えます。以下のコードは各ステップを示しています。

class Program
{
    static void Main(string[] args)
    {
        int matrixSize = 3;
        string[,] matrix = new string[matrixSize,matrixSize];

        //create square matrix
        for (int x = 0; x < matrixSize; x++)
        {
            for (int y = 0; y < matrixSize; y++)
            {
                matrix[x, y] = "a" + (x + 1).ToString() + (y + 1).ToString();
            }
        }

        Console.WriteLine(Environment.NewLine + "Base square matrix");

        for (int x = 0; x < matrixSize; x++)
        {              
            for (int y = 0; y < matrixSize; y++)
            {
                Console.Write(matrix[x, y] + " ");
            }
            Console.Write(Environment.NewLine);
        }
        Console.ReadKey();

        //copy diagonals
        string[] leftDiagonal = new string[matrixSize];
        string[] rightDiagonal = new string[matrixSize];
        for (int x = 0; x < matrixSize; x++)
        {
            leftDiagonal[x] = matrix[x, x];
            rightDiagonal[x] = matrix[matrixSize - 1 - x, x];
        }

        Console.WriteLine(Environment.NewLine + "Diagonals");

        for (int x = 0; x < matrixSize; ++x)
        {
            Console.Write(leftDiagonal[x] + " " + rightDiagonal[x] + Environment.NewLine);
        }
        Console.ReadKey();

        //rotate matrix
        string[,] rotatedMatrix = new string[matrixSize, matrixSize];
        for (int x = 0; x < matrixSize; x++)
        {
            for (int y = 0; y < matrixSize; y++)
            {
                rotatedMatrix[x, y] = matrix[matrixSize - y - 1, x];
            }
        }
        Console.WriteLine(Environment.NewLine + "Rotated");

        for (int x = 0; x < matrixSize; x++)
        {
            for (int y = 0; y < matrixSize; y++)
            {
                Console.Write(rotatedMatrix[x, y] + " ");
            }
            Console.Write(Environment.NewLine);
        }
        Console.ReadKey();

        //rotate matrix again
        string[,] rotatedMatrixAgain = new string[matrixSize, matrixSize];
        for (int x = 0; x < matrixSize; x++)
        {
            for (int y = 0; y < matrixSize; y++)
            {
                rotatedMatrixAgain[x, y] = rotatedMatrix[matrixSize - y - 1, x];
            }
        }
        Console.WriteLine(Environment.NewLine + "Rotated again");

        for (int x = 0; x < matrixSize; x++)
        {
            for (int y = 0; y < matrixSize; y++)
            {
                Console.Write(rotatedMatrixAgain[x, y] + " ");
            }
            Console.Write(Environment.NewLine);
        }
        Console.ReadKey();

        //replace diagonals
        for (int x = 0; x < matrixSize; x++)
        {
            rotatedMatrixAgain[x, x] = leftDiagonal[x];
            rotatedMatrixAgain[matrixSize - 1 - x, x] = rightDiagonal[x];
        }

        Console.WriteLine(Environment.NewLine + "Completed" + Environment.NewLine);

        for (int x = 0; x < matrixSize; x++)
        {
            for (int y = 0; y < matrixSize; y++)
            {
                Console.Write(rotatedMatrixAgain[x, y] + " ");
            }
            Console.Write(Environment.NewLine);
        }
        Console.ReadKey();
    }
}
于 2013-04-05T07:50:46.877 に答える
2

私は C# を知らないので、疑似コードでしか提案できません。

入力: N 行 N 列の行列in

出力: OP で説明されているように回転された入力行列out

for i = 1 to N
    for j = 1 to N
        if N - j != i and i != j // Do not change values on either diagonal
            out[j][N-i] = in[i][j]
        else
            out[i][j] = in[i][j]

免責事項: このアルゴリズムはテストされていません。デバッガを使用して、希望どおりに動作することを確認することをお勧めします。

于 2013-04-07T21:45:43.977 に答える
0

listViewテキスト ボックスの代わりに を使用して問題に取り組むことにしました。これにより、ロジックが簡単になります。この方法を使用して、マトリックスを連続したボックスと考えることができました。外側から始めて中央に向かって移動し、毎回ボックスのサイズを変更します。

また、2つのフォームを使用するのではなく、1つを使用します. 上部には、ユーザーが配列のサイズを入力するテキストボックスと、「Fill」というラベルの付いたボタン (button2) があります。下部には、ユーザーが回転角度を入力するテキスト ボックスがあります。「回転」をクリックすると、リンクされたリストに値を追加し、リストを組み合わせてシフトし、マトリックスに書き戻すプロセスが開始されます。必要以上に複雑にしてしまったと思いますが、とても勉強になりました。

上記の jerry のコードを調べた後、長方形の配列を調べようと思います。:)

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 Recycle
{
  public partial class Form1 : Form
  {
    public int size;
    public LinkedList<string> topRight = new LinkedList<string>();
    public LinkedList<string> bottomLeft = new LinkedList<string>();
    public LinkedList<string> myMatrix = new LinkedList<string>();
    public LinkedList<string> shiftMatrix = new LinkedList<string>();

    public Form1()
    {
        InitializeComponent();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        listView1.Clear();

        size = int.Parse(textBox2.Text);
        int c = 0;
        int q = 0;
        int w = 0;
        string[] content = new string[size];
        Random rnd = new Random();

        for (c = 0; c < size; c++)
        {
            listView1.Columns.Add("", 25);
        }

        for (q = 0; q < size; q++) 
        {
            for (w = 0; w < size; w++)
            {
                content[w] = rnd.Next(9,100).ToString();
            }

            ListViewItem lvi = new ListViewItem(content);
            listView1.Items.Add(lvi);
        }

    }

    public bool iseven(int size)
    {
        if (size % 2 == 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public void button1_Click(object sender, EventArgs e)
    {
        if (listView1.Items.Count < 3)
        {
            MessageBox.Show("Matrix cannot be rotated.");
            return;
        }

        bool even = false;
        int shift = int.Parse(textBox1.Text); //amount to shift by
        int box = listView1.Items.Count - 1; //size of box
        int half = Convert.ToInt32(listView1.Items.Count / 2);
        int corner = 0; //inside corner of box

        if (shift > listView1.Items.Count)
        {
            shift = shift % ((listView1.Items.Count - 2) * 4);
        }

        do
        {
            eachPass(shift, box, corner);
            ++corner;
            --box;
        } while (box >= half + 1);

    }

    public void eachPass(int shift, int box, int corner)
    {
        int x;
        int i;

        //Read each non-diagonal value into one of two lists
        for (x = corner + 1; x < box; x++)
        {
            topRight.AddLast(listView1.Items[corner].SubItems[x].Text);
        }

        x = box;

        for (i = corner + 1; i < box; i++)
        {
            topRight.AddLast(listView1.Items[i].SubItems[x].Text);
        }

        for (x = box - 1; x  > corner; x--)
        {
            bottomLeft.AddLast(listView1.Items[box].SubItems[x].Text);
        }

        x = corner;

        for (i = box - 1; i > corner; i--)
        {
            bottomLeft.AddLast(listView1.Items[i].SubItems[x].Text);
        }

        string myTest = "";

        //join the two lists, so they can be shifted
        foreach (string tR in topRight)
        {
            myMatrix.AddLast(tR);
        }

        foreach (string bL in bottomLeft)
        {
            myMatrix.AddLast(bL);
        }

        int sh;

        //shift the list using another list
        for (sh = shift; sh < myMatrix.Count; sh++)
        {
            shiftMatrix.AddLast(myMatrix.ElementAt(sh));
        }

        for (sh = 0; sh < shift; sh++)
        {
            shiftMatrix.AddLast(myMatrix.ElementAt(sh));
        }

        //we need the sizes of the current lists
        int trCnt = topRight.Count;
        int blCnt = bottomLeft.Count;

        //clear them for reuse
        topRight.Clear();
        bottomLeft.Clear();

        int s;

        //put the shifted values back
        for (s = 0; s < trCnt; s++)
        {
            topRight.AddLast(shiftMatrix.ElementAt(s));
        }

        for (s = blCnt; s < shiftMatrix.Count; s++)
        {
            bottomLeft.AddLast(shiftMatrix.ElementAt(s));
        }

        int tRn = 0;
        int bLn = 0;

        //write each non-diagonal value from one of two lists
        for (x = corner + 1; x < box; x++)
        {
            listView1.Items[corner].SubItems[x].Text = topRight.ElementAt(tRn);
            ++tRn;
        }

        x = box;

        for (i = corner + 1; i < box; i++)
        {
            listView1.Items[i].SubItems[x].Text = topRight.ElementAt(tRn);
            ++tRn;
        }

        for (x = box - 1; x > corner; x--)
        {
            listView1.Items[box].SubItems[x].Text = bottomLeft.ElementAt(bLn);
            ++bLn;
        }

        x = corner;

        for (i = box - 1; i > corner; i--)
        {
            listView1.Items[i].SubItems[x].Text = bottomLeft.ElementAt(bLn);
            ++bLn;
        }

        myMatrix.Clear();
        shiftMatrix.Clear();
        topRight.Clear();
        bottomLeft.Clear();
    }
  }
}
于 2013-04-17T01:22:55.330 に答える
0

これは非常に非正統的な UI プレゼンテーションのように見えますが、機能を実現できるという点ではそう遠くありません。線形配列の代わりに、長方形配列を使用すると、作業がはるかに簡単になります。実際の回転は、単一の回転を繰り返す for ループ (コードのように実装されcase 1ます) で実装できますが、これらを 4 つの可能なケースに組み合わせることにしました。これにより、実際には回転数に負の数を入力できます。そういえば、もっとエラー チェックを行う必要があります。少なくともint.Parse、例外が使用されている場所の両方で (try catch ブロックを使用するか、 に切り替えることによって) 例外をスローしないように保護しint.TryParse、意味のある数値 ( より大きい0、場合によっては 以外の妥当な最大値を設定するint.MaxValue)を返すようにします。matrixSizebutton1_Click

namespace RotatingMatrices
{
    public class Form2 : Form
    {
        // note these class fields
        private TextBox[,] matrixNodes;
        private int matrixSize;

        public Form2(int matrSize)
        {
            InitializeComponent();

            // note these inits
            matrixSize = matrSize;
            matrixNodes = new TextBox[matrixSize, matrixSize];

            Random r = new Random();

            // note the new loop limits
            for (int i = 0; i < matrixSize; i++)
            {
                for (int j = 0; j < matrixSize; j++)
                {
                    var tb = new TextBox();                    
                    int num = r.Next(1, 1000);

                    // note the change in indexing
                    matrixNodes[i,j] = tb;
                    tb.Name = string.Format("Node_{0}_{1}", i, j);
                    Debug.Write(string.Format("Node_{0}_{1}", i, j));
                    tb.Text = num.ToString();
                    tb.Location = new Point(j * 50, i * 50);
                    tb.Width = 30;
                    tb.Visible = true;
                    this.splitContainer1.Panel2.Controls.Add(tb);
                }
            }
        }

        private void buttonRotate_Click(object sender, EventArgs e)
        {
            string[,] matrix = new string[matrixSize, matrixSize];
            int rotations = (4 + int.Parse(textBoxRotations.Text)) % 4; // note the addition of and mod by 4

            switch(rotations)
            {
                case 1: // rotate clockwise
                    for (int i = 0; i < matrixSize; i++)
                    {
                        for (int j = 0; j < matrixSize; j++)
                        {
                            matrix[j, matrixSize - i - 1] = matrixNodes[i, j].Text;
                        }
                    }
                    break;
                case 2:  // rotate 180 degrees
                    for (int i = 0; i < matrixSize; i++)
                    {
                        for (int j = 0; j < matrixSize; j++)
                        {
                            matrix[i, j] = matrixNodes[matrixSize - i - 1, matrixSize - j - 1].Text;
                        }
                    }
                    break;
                case 3: // rotate counter-clockwise
                    for (int i = 0; i < matrixSize; i++)
                    {
                        for (int j = 0; j < matrixSize; j++)
                        {
                            matrix[i, j] = matrixNodes[j, matrixSize - i - 1].Text;
                        }
                    }
                    break;
                default: // do nothing
                   return;
            }

            // restore diagonals
            for(int i = 0; i < matrixSize; i++)
            {
                matrix[i, i] = matrixNodes[i, i].Text;
                matrix[i, matrixSize - i - 1] = matrixNodes[i, matrixSize - i - 1].Text;
            }

            // write strings back to text boxes
            for (int i = 0; i < matrixSize; i++)
            {
                for (int j = 0; j < matrixSize; j++)
                {
                   matrixNodes[i, j].Text = matrix[i, j];
                }
            }
        }
    }
}
于 2013-04-14T17:40:05.537 に答える