こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

JAVAで配列を使って * を縦向きのグラフで表示したいです。

JAVAの勉強をしています。
このプログラムは配列に乱数を生成して * を 横向きにするプログラムです。

練習問題で、以下のプログラムを書き換えて、* を縦向きのグラフで表示する問題なのですが、解く方法がわかりません。

どなたか答えもしくはヒントを下さい。
よろしくお願いします。

import java.util.Random;
import java.util.Scanner;

public class Test06_04 {
public static void main (String[] args) {
Random rand = new Random();
Scanner stdIn = new Scanner(System.in);

System.out.print("要素数 : ");
int n = stdIn.nextInt(); //要素数を読み込む
int[] a = new int[n]; //配列を生成

for (int i = 0; i < n; i++) {
a[i] = 1+ rand.nextInt(10);
}

for (int i = 0; i < n; i++) {
System.out.print("a[" + i + "] : ");
for (int j = 0; j < a[i]; j++)
System.out.print('*');
System.out.println();
}
}
}

投稿日時 - 2008-12-28 17:48:51

QNo.4589125

困ってます

質問者が選んだベストアンサー

まずもって、質問のプログラムがどのような処理を行っているか?

まず、コマンドラインで数字を入力させ、その数字が配列の要素数になっている。
例.要素数: 3

配列の各要素に乱数で生成された整数を代入している
例 a[0]=4,a[1]=7,a[2]=5

配列の要素番号順に各要素の数字文だけ*を出力している

a[0]=4なので
****
a[1]=7なので
*******
a[2]=5なので
*****
結果
****
*******
*****
になる

ここで、問題としてグラフを縦にしたい。
図↓(nは空欄)
n*n
n*n
n**
***
***
***
***

しかし、上記のやりかたでは左から数字分だけ出力なので*の左側を空欄にすることができない。

その問題の解決策を自分の書いたソースコードを参照しつつ解説します。

public class Graph{
public static void main(String[] args){
Random rand=new Random();
Scanner stdIn=new Scanner(System.in);
System.out.print("要素数 : ");
int n=stdIn.nextInt();
int[] a=new int[n];
//配列aの最大値
int max=0;
for(int i=0;i<n;i++){
a[i]=1+rand.nextInt(10);
}
for(int i=0;i<n;i++){
----------------------------------------------------------------
参照している要素がmaxより大きかったら
maxに参照している要素を代入
最後まで繰り返すとmaxが配列aの最大値になる
----------------------------------------------------------------
if(a[i]>max){
max=a[i];
}
}
----------------------------------------------------------------
例えば、a[0]=2,a[1]=5,a[2]=3という配列があったらそれを
ftf
ftf
ftt
ttt
ttt(tはtrue,fはfalse)
といった内容のboolean型の2次元配列にしてしまいましょう
これを2重forループでまわし、
trueの時は"*"をfalseの時は" "(空欄)を出力すればよいのです
----------------------------------------------------------------
boolean[][] prot=new boolean[max+1][n];
for(int i=0;i<n;i++){
----------------------------------------------------------------
//プログラムの場合上から下に向かうにつれ数字が大きくなりますが
//一般的なグラフの場合は逆になります
//なのでこのような初期値になります
//例,最大値が5で縦に3個出力したい
" "
" "
"*"←ここを初期値にする必要がある
"*"求める方法としては5(max)-3(a[i])=2になりますが
"*"プログラムの場合0から数えますので↑は数え数字に直すと3になる
----------------------------------------------------------------
for(int j=max-a[i];j<max;j++){
prot[j][i]=true;
}
}
for(int i=0;i<max;i++){
for(int j=0;j<n;j++){
if(prot[i][j]==true)System.out.print("*");
else System.out.print(" ");
}
System.out.println();
}
}
}

投稿日時 - 2008-12-28 20:43:15

補足

とても丁寧にご回答していただいてありがとうございます。
2次元配列という方法があるのですね。
まだ勉強していない部分だったので参考書を読んで考えました。
プログラムの流れの仕組みはよく理解できました。

質問があるのですが、

数え数字になることは理解できるのですが、

a[i] = 1 + rand.nextInt(10);  で+1しているので、

boolean[][] prot = new boolean[max + 1][n];  で+ 1しないで、
boolean[][] prot = new boolean[max1][n];  としても

あとの実行結果に影響しないような感じ
(↓ 縦が0を含めて11個あって、*は最大10個表示される)なのですが、
この理屈がわからなくて困ってます。

  j
  | 0,0   0,1   0,2   0,3 
  | 1,0   1,1   1,2   1,3
  | 2,0   2,1   2,2   2,3
  | 3,0   3,1   3,2   3,3
  | 4,0   4,1   4,2   4,3
  | 5,0   5,1   5,2   5,3
  | 6,0   6,1   6,2   6,3
  | 7,0   7,1   7,2   7,3
  | 8,0 t 8,1   8,2   8,3
  | 9,0 t 9,1   9,2   9,3
  | 10,0 t 10,1  10,2   10,3
  -----------------------------------
           i       n個          

投稿日時 - 2008-12-29 10:56:18

ANo.1

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

その通りですね。

for(int i=0;i<n;i++){
for(int j=max-a[i];j<max;j++){
prot[j][i]=true;
}
}

1+r.nextInt();
でa[i]が1以上であることが保障されています。
つまり、jの初期値は1以下にはならず
prot[j-1][i]としても問題ないので
boolean[][] prot=new boolean[max][n];
と宣言しても大丈夫です。
むしろ、このほうが0番目の要素を使用でき、効率的ですね

どう考えても俺のミスです。
申し訳ない。。。

投稿日時 - 2008-12-29 20:47:06

お礼

そうなんですか、勉強になりました。
とてもわかりやすい解説で良かったです。

ありがとうございました。

投稿日時 - 2008-12-29 21:41:54

あなたにオススメの質問