🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

2409閲覧

図形配列をシャッフルして別の配列に格納する方法

kotton92

総合スコア2

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/11/26 00:40

編集2020/11/26 01:33

###前提・実現したいこと

Figure型の配列figures1,2を用意します。
figures1の配列の中身を重複なくランダムにシャッフルしたものをfigures2に格納し、figure2に格納された図形をそれぞれ
図形:面積
という形で出力したいです。

また、可能であればRectangle1,Rectangle2,Circle1,Circle2という風に図形に番号を割り当てたいと考えております。

#求める出力結果
Rectangle1:200
Circle2:78.5
Circle1:1962.5
Rectangle2:600

ここで書いたRectangle,Circle,Circle,Rectangleという順番はあくまで一例なので子の通りでなく、他の順番で出力されてもかまいません。

以下のコードを書いて実行すると、

temp=figures1[index];

のところで、デバッグされ実行できなくなります。

原因が分かる方いらっしゃいましたら、教えていただけると幸いです。
どうぞよろしくお願いいたします。

###ソースコード

import java.util.Random; import java.util.concurrent.ThreadLocalRandom; public class Figures { public static void main(String[] args) { Figure [] figures1 = new Figure[4]; Figure [] figures2 = new Figure[]; Figure temp; Rectangle r1 = new Rectangle(); Rectangle r2 = new Rectangle(30,20); int i = 0; figures1[i++]=r1; figures1[i++]=r2; Circle c1=new Circle(); Circle c2=new Circle(25); figures1[i++]=c1; figures1[i++]=c2; //ここからのコードの理解が浅いので、間違っている可能性が高いです。 Random rnd= ThreadLocalRandom.current(); for(int k=figures1.length-1;k>0;k--) { int index=rnd.nextInt(i+1); temp = figures1[index]; figures1[index]=figures1[k]; figures1[k]=temp; } for(i=0;i<figures2.length;i++) { System.out.println(figures2[i].getClass().getName()+":"+figures2[i].getArea()); } } class Figure{ static int count = 0; double area =0; double getArea() { return 0; } } class Rectangle extends Figure{ int width; int height; String name="Rectangle"; Rectangle(){ setSize(10,20); } Rectangle(int width,int height){ setSize(width,height); } void setSize(int w,int h) { width=w; height=h; } double getArea() { return width*height; } } class Circle extends Figure{ int r; String name="Circle"; Circle(){ setSize(5); } Circle(int r){ setSize(r); } void setSize(int r){ this.r=r; } double getArea() { return r*r*Math.PI; } }

###借用したコード

上記にて理解が浅いと記載した部分のコードにつきましては、以下のwebページから借用いたしました。
https://blog.y-yuki.net/entry/2018/08/22/094000

import java.util.Arrays; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; public class FisherYatesShuffleSample { public static void main(String[] args) { int[] targetArray = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; // シャッフルする前 printArray(targetArray, "No Shuffle"); // シャッフル1回目 shuffle(targetArray); printArray(targetArray, "Shuffle 1 "); // シャッフル2回目 shuffle(targetArray); printArray(targetArray, "Shuffle 2 "); // シャッフル3回目 shuffle(targetArray); printArray(targetArray, "Shuffle 3 "); } public static void shuffle(int[] array) { // 配列が空か1要素ならシャッフルしようがないのので、そのままreturn if (array.length <= 1) { return; } // Fisher–Yates shuffle Random rnd = ThreadLocalRandom.current(); for (int i = array.length - 1; i > 0; i--) { int index = rnd.nextInt(i + 1); // 要素入れ替え(swap) int tmp = array[index]; array[index] = array[i]; array[i] = tmp; } } private static void printArray(int[] array, String headerComment) { System.out.printf("%s -> %s\n\n", headerComment, Arrays.toString(array)); } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2020/11/26 01:04

> 以下のようにコードを書いたところ、うまく結果が出力されませんでした。 「うまく」とはどのようなことなのか、この質問を読んだ者には分かりません。 現状、どのように出力されてしまっているのか。どのように結果が出力されることを望んでいるのかの詳細を、質問文を修正、追記するかたちで示しましょう。
dodox86

2020/11/26 01:28

> ここからのコードの理解が浅いので、間違っている可能性が高いです。 ご自身で書いたコードではないのですか? コードの意図を理解している訳ではなく、どこからか借用したコード、と言うことなのでしょうか。
kotton92

2020/11/26 01:34

@xebmeさん 承知しました。 ご丁寧にありがとうございます。
xebme

2020/11/26 02:28 編集

要点は2つ。 figures2が初期化されていないのは気づいていますか? スワップしないでfigures1の要素をfigures2に移送することに気づいていますか?iをkに置き換えたのは移送したいからでしょう。 <--- いい加減なことを言っているかもしれない。回答します。
guest

回答2

0

次のコードは理解できますか?
これを参考に自分のコードを書いてみてください。

Java

1import java.util.Random; 2 3public class Figures { 4 public static void main(String[] args) { 5 Figure[] fig1 = { 6 new Rectangle(), new Rectangle(30, 20), new Circle(), new Circle(25) 7 }; 8 Figure[] fig2 = { 9 fig1[0], fig1[1], fig1[2], fig1[3] 10 }; 11 Random rnd = new Random(); 12 for (int i = 0; i < fig2.length; i++) { 13 int j = rnd.nextInt(fig2.length); 14 Figure t = fig2[i]; fig2[i] = fig2[j]; fig2[j] = t; 15 } 16 for (int i = 0; i <fig2.length; i++) 17 System.out.println(fig2[i].getName() + ": " + fig2[i].getArea()); 18 } 19} 20 21class Figure { 22 static int count = 0; 23 double getArea() { return 0; } 24 String getName() { return "Figure"; } 25} 26 27class Rectangle extends Figure { 28 int width; 29 int height; 30 String name = "Rectangle_" + ++count; 31 32 Rectangle() { setSize(10, 20); } 33 Rectangle(int width, int height) { setSize(width, height); } 34 void setSize(int w, int h) { width = w; height = h; } 35 double getArea() { return width * height; } 36 String getName() { return name; } 37} 38 39class Circle extends Figure { 40 int r; 41 String name = "Circle_" + ++count; 42 43 Circle() { setSize(5); } 44 Circle(int r) { setSize(r); } 45 void setSize(int r) { this.r = r; } 46 double getArea() { return r * r * Math.PI; } 47 String getName() { return name; } 48}

static int count = 0; がどのように使用されているか、
String と int に +演算子を適用するとどうなるか、
getName() がどういう働きをするのか、などが理解できますか?

投稿2020/11/26 10:30

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kotton92

2020/11/28 05:39

お返事遅くなってしまい申し訳ございません。 ありがとうございます。参考にさせていただきます。
guest

0

ベストアンサー

figure1/figure2の仮定

figure2のインスタンスを用意しているので、figure1はシャッフルしないで元のまま残す、と仮定します。


figure2

figure2のインスタンスをどうするか?figure1の要素を全て設定した後で複製するのが良いでしょう。

Java

1Figure[] figures2 = figures1.clone();

あとはお手本に従ってfigures2をシャッフルしてください。

シャッフルのバグ

シャッフルのループはiをkに変えたのだから全てkに変えてください。

Java

1int index=rnd.nextInt(k+1);

メソッド

複製とシャッフルを行うメソッドを書くとすれば次のようになります。

Java

1 static Figure[] cloneShuffle(Figure[] figures) { 2 Figure[] result = figures.clone(); 3 Random rnd = ThreadLocalRandom.current(); 4 for (int k = result.length - 1; k > 0; k--) { 5 int index = rnd.nextInt(k + 1); 6 Figure temp = result[index]; 7 result[index] = result[k]; 8 result[k] = temp; 9 } 10 return result; 11 }

シャッフルに型は関係ないから型変数を使うと次のようになります。

Java

1 static Figure[] cloneShuffle__(Figure[] figures) { 2 return cloneShuffle_(figures); 3 } 4 5 static <T> T[] cloneShuffle_(T[] figures) { 6 T[] result = figures.clone(); 7 Random rnd = ThreadLocalRandom.current(); 8 for (int k = result.length - 1; k > 0; k--) { 9 int index = rnd.nextInt(k + 1); 10 T temp = result[index]; 11 result[index] = result[k]; 12 result[k] = temp; 13 } 14 return result; 15 }

シャッフル別解

質問に対する[追記・修正依頼]で指摘した方法です。これは難しくなります。バグがあるかもしれません。

figure2の初期化。

Java

1Figure [] figures2 = new Figure[figures1.length];

シャッフル。

Java

1 Random rnd = ThreadLocalRandom.current(); 2 for (int k = figures1.length; k > 0;) { 3 int index = rnd.nextInt(k); 4 temp = (figures2[index] == null) ? figures1[index] : figures2[index]; 5 if (index != --k) { 6 figures2[index] = (figures2[k] == null) ? figures1[k] : figures2[k]; 7 } 8 figures2[k] = temp; 9 }

クラス名にインスタンス番号をつける

カウンターをスレッドセーフにするためにjava.util.concurrent.atomic.AtomicIntegerを使います。int型のcounterを使用すると++counterは2命令になりアトミックではないため。クラス構成にかなり問題がありましたので大幅に手直ししました。

Java

1abstract class Figure { 2 3 final String name; 4 5 public Figure(String name) { 6 this.name = name; 7 } 8 9 abstract double getArea(); 10 11 @Override 12 public String toString() { 13 return name + ":" + String.format("%.1f", getArea()); 14 } 15 16}

Rectangleクラス

Java

1class Rectangle extends Figure { 2 3 static final String NAME = Rectangle.class.getSimpleName(); 4 static final java.util.concurrent.atomic.AtomicInteger counter = new AtomicInteger(0); 5 final int width; 6 final int height; 7 8 Rectangle() { 9 this(10, 20); 10 } 11 12 Rectangle(int width, int height) { 13 super(NAME + counter.addAndGet(1)); 14 this.width = width; 15 this.height = height; 16 } 17 18 @Override 19 double getArea() { 20 return width * height; 21 } 22 23}

Circleも同様です。

投稿2020/11/26 02:48

編集2020/11/26 06:33
xebme

総合スコア1090

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xebme

2020/11/26 07:18

setterは危険なので意図的に削除しました。コンストラクターの中からオーバーライドされる可能性のあるメソッドは呼んではならない。コンストラクターから呼ぶメソッドはfinalかprivateにすること。
kotton92

2020/11/28 05:39

分かりました。 ご丁寧に教えていただきありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問