管理人のタツです。
何の機会だったか忘れましたが、
行列を回転させる処理をJavaで作らなければいけなかった時がありました。
自分なりに作ってみたメソッドがありますので、ご紹介します。
ソース
さっそく、ソースは以下です。
/**
* @fn bMatrixAroundRotate
* @brief 行列(2次元配列)の回転を行う
* @param int[][] iArray 回転元行列
* int[][] iArrayRtn 回転後格納配列
* int iRotateCnt 回転数
* @return boolean true : 計算成功
* false : 計算失敗
* @detail 正方行列以外は回転できない
*/
static boolean bMatrixAroundRotate(int[][] iArray, int[][] iArrayRtn, int iRotateCnt)
{
boolean bRtn = true;
//当然、元の行列と答えの行列の行数、列数は一致しないとダメ
int iLengthRowOrigin = iArray.length; //回転前の行列行数
int iLengthRow = iArrayRtn.length; //回転後の行列行数
if(iLengthRowOrigin != iLengthRow)
return false;
int iLengthColOrigin = iArray[0].length; //回転前の行列列数
for(int i = 1; i < iLengthRow; i++)
{
int iLength = iArray[i].length;
if(iLengthColOrigin != iLength)
return false; //長方行列じゃないときはreturn
}
int iLengthCol = iArrayRtn[0].length; //回転後の行列列数
for(int i = 1; i < iLengthRow; i++)
{
int iLength = iArrayRtn[i].length;
if(iLengthCol != iLength)
return false; //長方行列じゃないときはreturn
}
if(iLengthColOrigin != iLengthRow || iLengthCol != iLengthRow)
return false; //正方行列じゃない
//回転処理開始
//内側を埋める(内側は変化なし)
int iLength = iLengthRow;
for(int i = 1; i < iLength - 1; i++)
{
for(int j = 1; j < iLength; j++)
{
iArrayRtn[i][j] = iArray[i][j];
}
}
int iRotate = iRotateCnt % 4;
//一番上の行
for(int i = 0; i < iLength; i++)
{
int iTemp = 0;
switch(iRotate)
{
case 0: //回転なし
iTemp = iArray[0][i];
break;
case 1: //正の方向へ1回転→iArrayの再右列がiArrayRtnの最上行へ
case -3: //負の方向へ3回転→iArrayの再右列がiArrayRtnの最上行へ
iTemp = iArray[i][iLength - 1];
break;
case 2: //正の方向へ2回転→iArrayの再下行がiArrayRtnの最上行へ
case -2: //負の方向へ2回転→iArrayの再下行がiArrayRtnの最上行へ
iTemp = iArray[iLength - 1][iLength - 1 - i];
break;
case 3: //正の方向へ3回転→iArrayの再左列がiArrayRtnの最上行へ
case -1: //負の方向へ1回転→iArrayの再左列がiArrayRtnの最上行へ
iTemp = iArray[iLength - 1 - i][0];
break;
default:
break;
}
iArrayRtn[0][i] = iTemp;
}
//一番左の列
for(int i = 0; i < iLength; i++)
{
int iTemp = 0;
switch(iRotate)
{
case 0: //回転なし
iTemp = iArray[i][0];
break;
case 1: //正の方向へ1回転→iArrayの再上行がiArrayRtnの最左列へ
case -3: //負の方向へ3回転→iArrayの再上行がiArrayRtnの最左列へ
iTemp = iArray[0][iLength - 1 -i];
break;
case 2: //正の方向へ2回転→iArrayの再右列がiArrayRtnの最左列へ
case -2: //負の方向へ2回転→iArrayの再右列がiArrayRtnの最左列へ
iTemp = iArray[iLength - 1 - i][iLength - 1];
break;
case 3: //正の方向へ3回転→iArrayの再下行がiArrayRtnの最左列へ
case -1: //負の方向へ1回転→iArrayの再下行がiArrayRtnの最左列へ
iTemp = iArray[iLength - 1][i];
break;
default:
break;
}
iArrayRtn[i][0] = iTemp;
}
//一番下の行
for(int i = 0; i < iLength; i++)
{
int iTemp = 0;
switch(iRotate)
{
case 0: //回転なし
iTemp = iArray[iLength - 1][i];
break;
case 1: //正の方向へ1回転→iArrayの再左列がiArrayRtnの最下行へ
case -3: //負の方向へ3回転→iArrayの再左列がiArrayRtnの最下行へ
iTemp = iArray[i][0];
break;
case 2: //正の方向へ2回転→iArrayの再上行がiArrayRtnの最下行へ
case -2: //負の方向へ2回転→iArrayの再上行がiArrayRtnの最下行へ
iTemp = iArray[0][iLength - 1 - i];
break;
case 3: //正の方向へ3回転→iArrayの再右列がiArrayRtnの最下行へ
case -1: //負の方向へ1回転→iArrayの再右列がiArrayRtnの最下行へ
iTemp = iArray[iLength - 1 - i][iLength - 1];
break;
default:
break;
}
iArrayRtn[iLength - 1][i] = iTemp;
}
//一番右の列
for(int i = 0; i < iLength; i++)
{
int iTemp = 0;
switch(iRotate)
{
case 0: //回転なし
iTemp = iArray[i][iLength - 1];
break;
case 1: //正の方向へ1回転→iArrayの再下行がiArrayRtnの最右列へ
case -3: //負の方向へ3回転→iArrayの再下行がiArrayRtnの最右列へ
iTemp = iArray[iLength - 1][iLength - 1 - i];
break;
case 2: //正の方向へ2回転→iArrayの再左列がiArrayRtnの最右列へ
case -2: //負の方向へ2回転→iArrayの再左列がiArrayRtnの最右列へ
iTemp = iArray[iLength - 1 - i][0];
break;
case 3: //正の方向へ3回転→iArrayの再上行がiArrayRtnの最右列へ
case -1: //負の方向へ1回転→iArrayの再上行がiArrayRtnの最右列へ
iTemp = iArray[0][i];
break;
default:
break;
}
iArrayRtn[i][iLength - 1] = iTemp;
}
return bRtn;
}
解説
引数の1つ目は回転元行列、2つ目は回転させた行列を格納させます。
3つ目のint型は何回転させるかです。
左回転を正とします。
37行目までは、そもそも回転できる行列(すなわち正方行列)かの判定をし、
回転不能であればfalseを返してます。
- L16~L19 : 引数二つの行数が等しいか判定
- L21~L27 : 回転元が長方行列か判定
- L28~L34 : 回転格納行列が長方行列か判定
- L36~L37 : 回転元行列の列と回転格納行列の行、回転元行列の行と回転格納行列の列が等しくないということは、正方行列ではないのでfalseリターン
L42~L49では、内側は回転対象ではないので、先に埋めておきます。
52行目で、回転数を4で割ります。
4回転と0回転は同じなので。
後は外側をそれぞれ埋めていきます。
回転数によって、回転元のどの行・どの列を取ってくるか、注意します。
- L55~L79 : 回転格納の0行目を埋めます
- L82~L105 : 回転格納の0列目を埋めます
- L109~L133 : 回転格納の最後の行を埋めます
- L136~L160 : 回転格納の最後の列を埋めます
実行結果
main関数内を以下のように記述しました。
public static void main(String[] args)
{
int[][] iArray1 = {{1, 2, 3,4}, {5, 6, 7, 8}, {9, 10, 11, 12},{13, 14, 15, 16}};
int[][] iArray2 = new int[4][4];
for(int i = 0; i < 5; i++)
{
if(bMatrixAroundRotate(iArray1, iArray2, i))
{
Disp(iArray1);
Disp();
Disp("↓↓" + i + "回転後");
Disp();
Disp(iArray2);
}
Disp();
Disp();
}
}
0~4回転させてます。
Dispメソッドについては以前作ったものです。
自分で言うのもですが、結構便利でよく使ってます。
今回は正方行列は確定してるので、
8行目の条件は必ずtrueが返ってきます。
コンソールには以下が表示されました。
![](https://mathvoluntech.com/wp-content/uploads/2024/04/1-1.png)
![](https://mathvoluntech.com/wp-content/uploads/2024/04/2-2.png)
![](https://mathvoluntech.com/wp-content/uploads/2024/04/3-1.png)
一応、自分が期待する応えが出てきました。
今回はここまでです。
コメント