今からはじめるプログラミング9
前回フラグのことを散々書いたので分岐まで実装したいのですが、ちょっとつまずいています。
なので、考える時間が欲しいので、とりあえず何画面か作ってみて、イメージが膨らむきっかけにならないかな、とか思っています。
前回のプログラムを修正、クラスを追加して、2画面ほどの画面遷移を作ってみました。課題はかなり多いですが、ノベル(ゲーム)としては、よりイメージできてきたのでは?と思います。
そして今更ですが、汎化ということについて考えてみたいと思います。この考え方というか機能というか、とても難しいと今でも思います。大きく2つ考えられると思います。もっとあるとかありそうですが。。。
ひとつは、クラスとクラスの関係で汎化を行うパターン。オブジェクト思考ではこちらが、よく説明されていると思います。猿とか馬のスーパークラスでいうところの動物、とかとか。
そしてもうひとつは、クラスとオブジェクトの関係で汎化を行うパターン。こちらは、最初は、言われた時「?」という感じで、まったく理解が追いつかなかったのですが、ようするに2つ画面を作るとして、2つクラスを作る必要はない、という形でプログラムを作ることです。要は、違いの部分を外だしして、画面のインスタンスにパラメータとして渡すと同じクラスが違う画面として動くようにクラスをプログラムする、そんなイメージです。
ちょっと難しいですよね。そんなわけでそちらの考え方でプログラムして画面遷移を実現した状態のコードを以下に記載します。
キーワードとしては、プリミティブ型や文字列という形で、リソース(画像ファイルやテキスト)を持つようにして、それらをコンストラクタやアクセサーで渡して、画面をコントロールする、という点ですね。
雑なコーディング、かつ、リファクタリング(いつか解説・・・重要なので。)も必要なもので申し訳ないのですが、なるたけ生のコーディングの方が勉強になると思うので、バグも多いですが、現状のままアップです。
MainClass→そのまま。
Menu
---------------------------------
package sample5;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Menu extends JFrame {
private String imageSource = "/Users/matsuiyoshikazu/eclipse-workspace/sample/src/resource/風邪と電柱.png";
public Menu() {
showMenu();
}
private boolean initialConfiguration() {
return true;
}
private void showMenu() {
this.setTitle("メニュー");
this.setSize(new Dimension(300, 200));
this.setLayout(new BorderLayout());
ImageIcon icon = new ImageIcon(imageSource);
JLabel label = new JLabel(icon);
if (initialConfiguration()) {
// ボタンのオブジェクト生成
JButton btn = new JButton("はじめる");
// ボタンをリスナーに追加
btn.addActionListener(new SimpleStoryAction(0));
// ボタンを画面に追加
this.getContentPane().add(btn, BorderLayout.SOUTH);
this.getContentPane().add(label, BorderLayout.CENTER);
} else {
JLabel message = new JLabel("初期処理に失敗しました");
// ボタンのオブジェクト生成
JButton btn = new JButton("閉じる");
// ボタンをリスナーに追加
btn.addActionListener(new CloseListener());
// ボタンなどを画面に追加
this.getContentPane().add(message, BorderLayout.NORTH);
this.getContentPane().add(btn, BorderLayout.SOUTH);
this.getContentPane().add(label, BorderLayout.CENTER);
}
this.setVisible(true);
}
}
------------------------------------------------------
MenuListener→廃止(復活するかも?)
CloseListener→そのまま。
ImageTextPanel
------------------------------------------------------
package sample5;
import java.awt.GridLayout;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class ImageTextPanel extends JPanel {
public ImageTextPanel(String img, String text) {
// TODO
ImageIcon icon = new ImageIcon(img);
JLabel label = new JLabel(icon);
JTextArea area = new JTextArea();
area.setText(text);
this.setLayout(new GridLayout(1, 2));
JScrollPane scrolLeft = new JScrollPane(label);
JScrollPane scrolRight = new JScrollPane(area);
this.add(scrolLeft);
this.add(scrolRight);
}
}
------------------------------------------------------
SimpleStoryFrame
------------------------------------------------------
package sample5;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
public class SimpleStoryFrame extends JFrame {
public SimpleStoryFrame(String img,String text,String name,int page) {
ImageTextPanel panel = new ImageTextPanel(
img,
text);
this.setTitle(name);
this.setSize(new Dimension(600, 400));
this.setLayout(new BorderLayout());
// ボタンのオブジェクト生成
JButton btn = new JButton("次へ");
// // ボタンをリスナーに追加
btn.addActionListener(new SimpleStoryAction(page));
// // ボタンを画面に追加
this.getContentPane().add(panel,BorderLayout.CENTER);
this.getContentPane().add(btn,BorderLayout.SOUTH);
this.setVisible(true);
}
}
------------------------------------------------------
SimpleStoryAction
------------------------------------------------------
package sample5;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SimpleStoryAction implements ActionListener {
private int page = 1;
private String title_1 = "しーん1(そらへの憧れ)";
private String img_1 = "/Users/matsuiyoshikazu/eclipse-workspace/sample/src/resource/風邪と電柱.png";
private String text_1 = "\r\n" + "風がふいている。" + "\r\n" + "国境の南には何があるのか。" + "\r\n" + "僕にはわからないが、" + "\r\n"
+ "空に浮かぶあの鯨がいったいなんなのか、" + "\r\n" + "とても知りたい。" + "\r\n" + "僕は鳥ではあるものの空を飛べない。" + "\r\n"
+ "その事実は僕を少し悲しくさせるけれど。" + "\r\n" + "まるで空に憧れるヒトのようだな、" + "\r\n" + "ふとそう考えて不思議に思った。" + "\r\n"
+ "「ヒト」僕の周りにはいない、" + "\r\n" + "長老のアシカさんは遥か昔に絶滅したといっている。" + "\r\n" + "今日も僕は鯨をみて、" + "\r\n" + "そして空に憧れるのだ。";
private String title_2 = "しーん2(とんでみる)";
private String img_2 = "/Users/matsuiyoshikazu/eclipse-workspace/sample/src/resource/僕のちたまを守って.png";
private String text_2 = "\r\n" + "いっそ。" + "\r\n" + "日々の疑問をすべて抱えて" + "\r\n" + "とんでみる。" + "\r\n" + "はばたいても、はばたいても"
+ "\r\n" + "あの雲にも届かない。" + "\r\n" + "やはり飛ぶことはなかわないと、" + "\r\n" + "認識しつつ、海へと着水した。" + "\r\n"
+ "くらい海の底へ沈んでいくのを認識しながら、" + "\r\n" + "ふと今度はどうせなら潜れるところまで。" + "\r\n" + "深く" + "\r\n" + "深く。" + "\r\n" + "深く、"
+ "\r\n" + "そして眠るように目をつむった。";
public SimpleStoryAction(int page) {
this.page = page;
}
private void nextPage() {
page++;
if (page == 1) {
new SimpleStoryFrame(img_1, text_1, title_1, 1);
}
if (page == 2) {
new SimpleStoryFrame(img_2, text_2, title_2, 2);
}
System.out.println("page" + page);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO コンテンツ管理
// TODO 次の画面
nextPage();
}
}
------------------------------------------------------
画像とテキストを表示するパネルをつくり、
画面が次へ進む仕組みをつくりました。
あんまりいい実装ともいえないかもしれませんが、まずは、画像のファイルパスと文章が文字列としてSimpleStoryActionに集約されているのとメニューの次の画面と2ページ目の画面は同じ画面クラス(SimpleStoryFrame)としてプログラミングされていることが理解できればいいのかな?と思います。
フラグの制御でルート分岐までコーディングできていませいが、このくらいでまた次の休みに続きを作っていきたいと思います。すいません。
あとジャンクプログラムもよろしくです。こちらと違う実装で参考になるかも?(パズルゲーム)1画面に複数のイベントを処理しています。
https://ma2-ys.booth.pm/items/2784565