今回は受講生(N氏)作成のお題にインスパイアされたアプリを作成していく。
ビルを建築していってそれを一覧するものだ。
Step1(Buildingクラスの作成)
まずはBuildingクラスを作り以下の処理の実現しよう。
実行例1
建物の幅>4
####
####
####
####
実行例2
建物の幅>6
######
######
######
######
######
######
幅を入力するとその値を幅と高さにもつ長方形を描画する。今回はこれをビルに例える。
チャレンジ
クラス名は
Building
フィールドに
int width
コンストラクタに
Building(int width)
メソッドに
void display()
をもつBuildingクラスを作成し、アプリケーションクラスから上記の処理を実現せよ。
解答例
class Building{
int width;
Building(int width){
this.width=width;
}
void display(){
for(int i=0;i<width;i++){
for(int j=0;j<width;j++){
System.out.print('#');
}
System.out.println();
}
}
import java.util.*;
public class BuildingApp{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
System.out.print("建物の幅>");
int width=sc.nextInt();
Building b=new Building(width);
b.display();
}
}
一覧するメソッド
さて、ここからが本題だ。このBuildingインスタンスの入ったリストを受け取るとそれを横並びに一覧する処理を作りたい。以下がBuildingが5つはいったリストを渡した実行例
###############
###############
###############
############ ###############
############ ###############
############ ########## ###############
############ ########## ###############
############ ########## ###############
############ ########## ####### ############### #######
############ ########## ####### ############### #######
############ ########## ####### ############### #######
############ ########## ####### ############### #######
############ ########## ####### ############### #######
############ ########## ####### ############### #######
############ ########## ####### ############### #######
チャレンジ
ではBuildingクラス内にこのメソッド作ってみよう。引数にlistを受け取り上記のような出力が得られるメソッドをクラスメソッドとして作成してみてほしい。
(この際、さきほど作ったdisplayメソッドの利用は考えなくて良い)
static void displayAll(List<Building> list)
解答例
ターミナルでの出力の場合、上から1行ずつ出力していかなければならないため工夫が必要となる。
まずは2次元の描画なので基本は2重for文を考える。
for(行の数ループ){
for(列の数ループ){
}
}
外側のループが行の制御、内側のループが列の制御。
まずは外側のループを何回回せばよいかを考える。
これは引数で入ってきたリストに入っているビルのうち、一番高い高さを採用すればよさそうだ。なのでまずは一番高い高さを求める
//先ほど作成したBuildingクラス内に作成する。
static void displayAll(List<Building> list){
int height=0;
for(Building b:list){
if(b.width > height){
height=b.width;
}
}
for(int i=0;i<height;i++){
for(列の数ループ){
}
}
}
リストを拡張forで回して最大値のアルゴリズムを用いて最大値を求めheightに代入している。これがわかれば外側のループは完成だ。内側のループはリストに入っているビルを一つずつ取り出しながら行うのがよさそうだ。なので列の数のループの上に拡張for文を差し込む
static void displayAll(List<Building> list){
int height=0;
for(Building b:list){
if(b.width > height){
height=b.width;
}
}
for(int i=0;i<height;i++){
for(Building b:list){
for(int j=0;j<b.width;j++){
}
}
System.out.println();
}
}
横幅分のループもできた。
あとは、”#”を打つか” “半角スペースを打つのかを分岐させればよい。
i行目を見ているとき高さは
height-i
となる。
ビルの高さがそれ以上の高さならば#を描画すれば良い。
static void displayAll(List<Building> list){
int height=0;
for(Building b:list){
if(b.width > height){
height=b.width;
}
}
for(int i=0;i<height;i++){
for(Building b:list){
for(int j=0;j<b.width;j++){
if(b.width>=height-i){
System.out.print('#');
}else{
System.out.print(' ');
}
}
//ビルとビルの隙間
System.out.print(' ');
}
System.out.println();
}
}
実行例を見るとビルとビルとの間に隙間があるので18行目で半角スペースを加えている。これでメソッドの完成だ。後はメインメソッドを記述する。
今回は高さがランダムなビルを5個生成し、リストに入れていこう。
import java.util.*;
public class BuildingApp{
public static void main(String[] args){
List<Building> list=new ArrayList<>();
Random rand=new Random();
for(int i=0;i<5;i++){
list.add(new Building(rand.nextInt(20)+2));
}
Building.displayAll(list);
/*
Scanner sc=new Scanner(System.in);
System.out.print("建物の幅>");
int width=sc.nextInt();
Building b=new Building(width);
b.display();
*/
}
}
以上で完成だ。ターミナルで横並びのオブジェクトを表示していくのはなかなかテクニカルだがこういった処理にも少しずつ慣れていってもらいたい。
コメント