- ベストアンサー
2次元配列のコピー
System.arraycopy(~) を使って二次元配列のコピーをしたいのですが、 出来るのでしょうか? 出来るのなら、使い方を教えてください。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
Javaの場合は2次元配列というものはないんです。 配列の中に配列があるという構造になっています。 なので、次のような配列オブジェクトは、 int[][] aryA = {{1, 2, 3}, {4, 5, 6, 7}}; 配列{1,2,3}と、配列{4,5,6,7}の2つを持った配列となります。 1個目の配列と2個目の配列の要素数が異なるので2次元ではないです。ややこしいですね。 2次元配列⇒表のような構造。Javaにはない 配列の配列⇒ツリーのような構造 aryA ├aryA[0] │ ├aryA[0][0] │ ├aryA[0][1] │ └aryA[0][2] └aryA[1] ├aryA[1][0] ├aryA[1][1] ├aryA[1][2] └aryA[1][3] これをコピーする場合には2つの意味があります。 (1)外側の配列をコピー aryA = {配列, 配列} ↓ ↓ aryB = { , } これは、簡単でarraycopyを使うだけです。 int[][] aryB = new int[2][3]; System.arraycopy(aryA, 0, aryB, 0, 2); でもこの場合は、aryA[0][1]=100; とした時に、aryB[0][1]の値も変わってしまったようにみえます。 なぜなら、aryA[0]とaryB[0]は同じ配列オブジェクトを指しているからです。 (2)内側の配列をコピーする aryA = {{1, 2, 3}, {4, 5, 6, 7}} ↓ ↓ aryC = {{1, 2, 4}, {4, 5, 6, 7}} これは、外側の配列を作ってから、内側の配列をarraycopyします。 //aryAの中の配列をコピーする例 int[][] aryC = new int[aryA.length][]; for (int i = 0; i < aryA.length; i++){ aryC[i] = new int[aryA[i].length]; System.arraycopy(aryA[i], 0, aryC[i], 0, aryA[i].length); } こうすると、aryA[0][1]=100; とaryA側の値を変えても、aryCには影響ありません。
その他の回答 (3)
- sasadora
- ベストアンサー率68% (59/86)
あくまでサンプルですが。 Shipは自身のXY座標や、自身を移動するメソッドを実装します。 mainで、すべてのShipを配列で管理し、全Shipを表示するメソッドなどを実装しました。 class Ship{ int point_x; int point_y; Ship(int x, int y){ this.point_x = x; this.point_y = y; } void moveTo(int x, int y){ //自身のX,Y座標を変更する this.point_x = x; this.point_y = y; } } public class Warship_Game { public static void main(String[] args) { //全てのShipを管理する配列 Ship[] ships = { new Ship(1, 1), new Ship(3, 2), }; show(ships); ships[0].moveTo(2, 1); //Ship[0]を移動する show(ships); } static void show(Ship[] ships){ System.out.println("盤面"); for (int y = 0; y < 5; y++){ for (int x = 0; x < 5; x++){ Ship s = findShip(ships, x, y); if (s == null){ System.out.print("□"); } else { System.out.print("■"); } } System.out.println(); } } //座標X,YにあるShipを取得する static Ship findShip(Ship[] ships, int x, int y){ for (int i = 0; i < ships.length; i++){ if (ships[i].point_x == x && ships[i].point_y == y){ return ships[i]; } } return null; } }
お礼
遅くなりましたがありがとうございました。 参考にさせていただきます。
- sasadora
- ベストアンサー率68% (59/86)
うーん、質問されたとおりの回答をするのであれば、配列オブジェクトをnewするのは、mainだけにして、Shipのコストラクタでnewするのをやめたらよいと思います。 つまり、mainでnewした配列dataを、コピーするのではなく、1つの配列オブジェクトを、mainとShipオブジェクトの2箇所で参照すれば、どちら側で変更しても、反映されてみえます。 でも、このWarship_Gameという名前から海戦ゲーム的なものを勝手に推測したうえで、アドバイスすると、 Shipクラスが、自身のx,y座標をもち、main側で複数のShipオブジェクト(駒?)を管理するような形にすれば、フィールド(盤面)の情報は要らないと思います。 サンプルが必要であれば、返信いただければ、書いてみようかと思います。
お礼
何度もありがとうございます。 参考までに、サンプルをお願いしたいのですがよろしいでしょうか? 暇な時でいいのでお願いします。
- sasadora
- ベストアンサー率68% (59/86)
追加で聞かれた質問がよくわからないのですが、 こんな感じですか? class Array{ private int[][] aryA } class Main{ private int[][] aryB } aryAの値が変わったら、aryBの値も変わるというようにしたいと。 構造的には、常に同じ値を維持したいならば、2つ持っている意味はないので、aryA側だけで保持し続ければいいんじゃないでしょうか? つまりMain.aryBは削除して、Array.aryAに対するgetメソッドを用意して、それに対して変更を加えればよいと思います。 class Array{ private int[][] aryA public int[][] getAryA(){ return aryA;} } class Main{ } もしくは、aryAとaryBが同じインスタンスを参照するようにするとか。 int [][] aryB = new int[2][3]; int [][] aryA = aryB; aryB[0][2] = 100; System.out.println(aryA[0][2]); 具体的な不都合がでるソースを見せてもらえれば、もっと正確に回答できると思います。
補足
何度もすいません。 mainクラスではなく、mainとのやりとりです^^; 書き間違えました。 下記がプログラムになります。 class Ship{ int point_x; int point_y; int field_Data[][]; Ship(int[][] keep){ field_Data = new int [keep.length][]; System.arraycopy(keep,0,field_Data,0,5); } public void Direction(int point_x, int point_y){ //配列の値(field_Data)をかえます。 } static void show(int[][] data){ //配列の表示 } } public class Warship_Game{ public static void main(String[] args){ int data[][] = new int[5][5]; Ship.show(data); a.Direction(a.point_x,a.point_y); Ship.show(data); } 一回目のshowで表し、Directionで値を変え その変わった値を二回目のshowで表示するプログラムです。
お礼
配列については、わかりました。 ありがとうございました。 ついでと言ってはなんですが、 例えば、クラスAyyayとmainと同じ値の配列を参照して Arrayでの値が変わったたら、mainでの配列も変わるように したいのですが、どのようにしたらよいでしょうか? まったく検討がつかなく悩んでいます。