今からはじめるプログラミング(目次)

自己紹介

(作成中・・・というか以下の記事内に過去自分が参加したプロジェクトなどについて書いているので、いつかまとめます。)

・最初なので大したことは書いておりませんが。最初の記事。目標はeclipseのインストールとぐぐれること。

今から始めるプログラミング1 - yo2an’s blog

・2ページ目・・・とにかく1画面表示してみるプログラム。ステップ数10行ぐらい。

今から始めるプログラミング2 - yo2an’s blog

・3ページ目・・・画面プログラムの解説、クラスの解説、イベント処理の解説。ステップ数20行弱。

今から始めるプログラミング3 - yo2an’s blog

・4ページ目・・・入力画面と出力画面、画面遷移。ステップ数40行ぐらい。

今から始めるプログラミング4 - yo2an’s blog

・5ページ目・・・クラス分割。こちらは60行ぐらい。

今から始めるプログラミング5 - yo2an’s blog

・6ページ目・・・画像の表示。40行は書いていない?くらい。

今から始めるプログラミング6 - yo2an’s blog

・7ページ目・・・HTMLを取得するプログラム。いつも使っているだけのブラウザについて考えてみる。30ステップよりおおい。

今から始めるプログラミング7(ぶれいく) - yo2an’s blog

・8ページ目・・・フラグについて。ノベルゲームの途中のクラス群。

今から始めるプログラミング8 - yo2an’s blog

・9ページ目・・・とりあえず画面遷移を何ページか進める。

今からはじめるプログラミング9 - yo2an’s blog

・10ページ目・・・フラグについて。ノベールゲームのなんとか形になったもの?全部で200ステップぐらい。

今からはじめるプログラミング10 - yo2an’s blog

 ・11ページ目・・・RPGをつくれないかなぁという感じ。テーブルで画像を表示してドラクエみたいなフィールドを構成してみる。

今からはじめるプログラミング11 - yo2an’s blog

・12ページ目・・・フィールドの上にキャラクターを表示して、東西南北(東のみ)に移動する。

今からはじめるプログラミング12 - yo2an’s blog

 

ある程度出来上がったら、また下記のBoothさんに100円でプロジェクトファイルを追加したいと思います。

ma2-ys - BOOTH

 

googleドライブのリンク(12までのプログラムをふくんでいるはず)

sample.zip - Google ドライブ

 

今からはじめるプログラミング12

自分のスケジュールの中では、前回のフィールドの表示で、

フィールドの移動も実装したかったのですが、

怠け者なので、結局1日寝てしまい。

今頃に実装したのです。(寝ぼけていて日本語がおかしいのは、申し訳ありませんが、寝ぼけていなくてもおかしいです。)

 

そしてその実装もちょっと微妙です。

うぅ。

とりあえず

FieldMapをがらっと変えて(追加して)ます。

---------------------------------------------------

package sample7;

 

import javax.swing.JPanel;

import javax.swing.JTable;

 

public class FieldMap extends JPanel {

 

private JTable tblField = null;

 

private String map = new String {

{ "2", "2", "2", "2", "2" },

{ "2", "1", "1", "1", "2" },

{ "2", "1", "1", "1", "2" },

{ "2", "1", "1", "1", "2" },

{ "2", "2", "2", "2", "2" }, };

 

public String getMap() {

return this.map;

}

public static final int V_NORTH =1;

public static final int V_SOUTH =2;

public static final int V_EAST =3;

public static final int V_WEST =4;

 

public void shift(int vector) {

if(vector==V_SOUTH) {

//save

String sv =new String[5];

for(int i = 0;i<5;i++) {

sv[i] = map[0][i];

map[0][i] = map[1][i];

map[1][i] = map[2][i];

map[2][i] = map[3][i];

map[3][i] = map[4][i];

map[4][i] = sv[i];

}

}

if(vector==V_NORTH) {

//save

String sv =new String[5];

for(int i = 0;i<5;i++) {

sv[i] = map[4][i];

map[4][i] = map[3][i];

map[3][i] = map[2][i];

map[2][i] = map[1][i];

map[1][i] = map[0][i];

map[0][i] = sv[i];

}

}

if(vector==V_EAST) {

//save

String sv =new String[5];

for(int i = 0;i<5;i++) {

sv[i] = map[i][0];

map[i][0] = map[i][1];

map[i][1] = map[i][2];

map[i][2] = map[i][3];

map[i][3] = map[i][4];

map[i][4] = sv[i];

}

}

if(vector==V_WEST) {

//save

String sv =new String[5];

for(int i = 0;i<5;i++) {

sv[i] = map[i][4];

map[i][4] = map[i][3];

map[i][3] = map[i][2];

map[i][2] = map[i][1];

map[i][1] = map[i][0];

map[i][0] = sv[i];

}

}

 

}

 

public void init() {

String map = this.getMap();

tblField = new JTable(5, 5);

//テーブルに値を設定

for (int i = 0; i < 5; i++) {

for (int j = 0; j < 5; j++) {

tblField.setValueAt(map[i][j], i, j);

 

}

}

//テーブルにレンダラーを設定

for (int j = 0; j < 5; j++) {

tblField.getColumnModel().getColumn(j).setCellRenderer(new FieldRenderer());

tblField.getColumnModel().getColumn(j).setPreferredWidth(32);

}

//最後にキャラクターを表示する(キャラクターのコードを0として)

 

tblField.setValueAt("0", 2, 2);//まんなか

//テーブルをパネル(自分)に追加

this.add(tblField);

}

 

public void resetValue(String map) {

//テーブルに値を設定

for (int i = 0; i < 5; i++) {

for (int j = 0; j < 5; j++) {

tblField.setValueAt(map[i][j], i, j);

 

}

}

 

//最後にキャラクターを表示する(キャラクターのコードを0として)

 

tblField.setValueAt("0", 2, 2);//まんなか

}

 

public FieldMap() {

this.init();

}

}

---------------------------------------------------

次に画面(MainFrame)これはまぁかんたん?

---------------------------------------------------

package sample7;

 

import java.awt.BorderLayout;

import java.awt.Dimension;

 

import javax.swing.JButton;

import javax.swing.JFrame;

 

public class MainFrame extends JFrame {

 

private FieldMap filedMap = null;

 

public MainFrame() {

 

this.filedMap = new FieldMap();

 

this.setTitle("field");

this.setLayout(new BorderLayout());

this.getContentPane().add(filedMap,BorderLayout.CENTER);

JButton btnEast = new JButton("東");

JButton btnWast = new JButton("西");

JButton btnSouth = new JButton("南");

JButton btnNorth = new JButton("北");

 

btnEast.addActionListener(new EastListener(this.filedMap));

 

this.getContentPane().add(btnEast,BorderLayout.EAST);

this.getContentPane().add(btnWast,BorderLayout.WEST);

this.getContentPane().add(btnSouth,BorderLayout.SOUTH);

this.getContentPane().add(btnNorth,BorderLayout.NORTH);

 

this.setSize(new Dimension(400,450));

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setVisible(true);

 

}

 

}

---------------------------------------------------

そしてマップを動かしているリスナーさん(EastListener)

 

---------------------------------------------------

 

package sample7;

 

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

 

public class EastListener implements ActionListener {

 

private FieldMap filedMap = null;

 

public EastListener(FieldMap filedMap) {

this.filedMap = filedMap;

}

 

@Override

public void actionPerformed(ActionEvent e) {

// 2次元テーブルの値を東に移動

this.filedMap.shift(FieldMap.V_EAST);

this.filedMap.resetValue(filedMap.getMap());

 

 

}

 

}

---------------------------------------------------

 忘れてはいけない起動クラス(MainClass7)

まぁ画面を表示しているだけですが。

---------------------------------------------------

package sample7;

 

public class MainClass7 {

 

public static void main(String[] args) {

// TODO Auto-generated method stub

new MainFrame();

}

 

}

---------------------------------------------------

どうですかね、そんなわけで”東”ボタンしか実装していません。

コードは現在googleドライブにアップ中です。(回線がとまってしまっている?)終わったら追記します。ひとつひとつ参照だとめんどくさいので、zip形式にまとめました。

夜勤前の睡眠前なので、なかなか雑なプログラム、対応ですいませんが、

まぁブレスレット、ブレスレットでお願いします。

 

ところで、eclipseでjarファイルを作ると画像が表示されなくて、パスの設定だと思うのですが、どうすると楽にできるかな。いやこれだけいろんなプロジェクトに参加して、リリース担当とか一度もやってなくて・・・。

antとかmavenとかの知識がおざなりです。。。。

 

 

f:id:yo2an:20210410092223p:plain

フィールドの移動(移動前)

f:id:yo2an:20210410092223p:plain

フィールドの移動(東ボタン押下)

 

今からはじめるプログラミング11

前回のプログラムはどうでしたでしょうか。

時間があるようでしたら、

MainClassのmainメソッドから順番にコードを1行ずつ眺めて、画面を表示するまでのコード。

画面でボタンを押されてから次の画面を表示するまでのコード。

チェックボックスにチェックを入れた時のコード。

チェックボックスにチェックを入れた後、ボタンをおして画面を表示するまでのコード。

そんな感じで処理の順番を追っていくと・・・そしてこれをまずテキストに書き出して、クラスごとに並べて、シーケンス図のできあがり、みたいな。(というかgoogleドライブからコードをひとつひとつ取得するのが面倒かもしれないですね。すいません。)

 

とうとつですが、高級言語プログラムということがどういうことか?まずコンピュータが処理するためのマシン語へ変換(こんぱいる)する前の言語ということですが、要するに我々が理解できるようにしたものですね。

そして、プログラムというのは、その我々が理解できる言語で、コンピュータに指示をする、ということなので、プログラムの処理を追うことによって、何をしているのかが、わかるはずなのです。

ただ、効率的なプログラムや処理速度を追求したものなどは、正直読み辛くなっていきます。

そして今回のプログラムはどうでしょう?

コーディング量としてはかなり少なく。少し英語の知識があれば、我々の言語に近い感覚で読み取れませんでしょうか?

オブジェクト思考言語は、かなり高級言語というか我々の言語に近い感覚でコーディングができる言語だなぁと思うのですが、まぁ僕が最初に勉強したCOBOLという言語に比べて、ということかもしれません。

でも、実際僕がJavaのプログラムを勉強した時は、結構英語の辞書を横に置いて調べながら勉強したので、そして英文読解よりは簡単に理解できたので、皆さんもがんばってみて欲しいです。google翻訳というのもありますし。

そんなこんなで。

今回は、ドラクエっぽいもの!を作ってみたいと思っています。

システム開発に携わってから3年目くらいの時に1度作ってみたことがあるので、もう一度。思い出しながらという感じです。

とはいえ現在の3Dアクションとかかっこいいものではなく、初代のドラクエをイメージしています。ウィザードリィなども好きでしたが、最初にプレイしたRPGなので作ってみたいと思いました。

昔もそんあ感じで作ったのですが、中身は業務アプリケーション。データの管理にRDBなんかを使ってしまいました・・・w

まぁ今回も同じような感じになるかもしれませんが、せめてRDBを使わないでいこうと思っています。

あまり難しいコードはなるたけ避けていきますので、とはいえブラックボックスはあるので、説明があやふやだったりもありますが、めげずにいきましょう。

そしてなんで?きっかけは?とか質問されそうなので。

まず何を持ってできそう!と考えたのか・・・

 

最初のプロジェクトでエクセルみたいなテーブルを表示する画面です。

テーブル以外の要素もあったのですが、同じプロジェクトでテーブルに画像を表示(アイコンですね)していたりする画面もあったので、「こんなこともできるんだー」程度に思ったのですが、ふとその構造をみてみると、TableCellEditorとTableCellRendererというものを使って、表示する際は画像を実際の値はコード値を保持しているのです。

WEBアプリケーションではラベルバリュービーンみたいなイメージです。

ふとドラクエのマップの画面がつくれないかな?と思ったわけです。

ちなみにこの描画を別に行っていく手法というのは現行のゲームを処理速度の遅いパソコンで実行したりすると、目で処理がわかるというか、マイクラなどで、フィールドが、わくから形成されて画像が覆っていくような感じで表示されていくのが見えますよね。そんな感じで、あながちゲームの構造も違っていないような気がします。もっと高度にメモリなどを使っていると思いますが。

 

そんなこんなで、とりあえず、まずはコードだけのテーブルを表示してみます。

FieldMap

--------------------------------------------------

package sample7;package sample7;
import javax.swing.JFrame;import javax.swing.JTable;
public class FieldMap {
    private String map = new String {  { "2", "2", "2", "2", "2" },  { "2", "1", "1", "1", "2" }, { "2", "1", "1", "1", "2" },  { "2", "1", "1", "1", "2" },  { "2", "2", "2", "2", "2" }, };
    public String getMap() {

        return this.map;

    }
    public static void main(String args) {

        FieldMap filedMap = new FieldMap();

        String map = filedMap.getMap();

        JTable tbl = new JTable(5, 5);

        for (int i = 0; i < 5; i++) {

           for (int j = 0; j < 5; j++) {

               tbl.setValueAt(map[i][j], i, j);
           }

        }

        JFrame frame = new JFrame("field"); 

        frame.getContentPane().add(tbl); frame.setSize(400, 400);   

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

        frame.setVisible(true);

    }

}

-------------------------------------------------

2次元配列というものを使って文字列の基本となるデータを保持しています。とりあえず1と2で1を囲むように2を配置しています。

これを実行すると下記のような画面が表示されます。

f:id:yo2an:20210408120440p:plain

FieldMap実行1

大きさなどを考えていないため、まばらな感じで表示されていますが、2で1を囲った感じでテーブルが表示されています。

つぎに表示を画像に置き換えるコーディングです。

FieldRendererというクラスをつくりました。Rendererというのは描画をするもの、という意味ですね。

FieldRenderer

-----------------------------------------------------

package sample7;

 

import java.awt.Component;

 

import javax.swing.Icon;

import javax.swing.ImageIcon;

import javax.swing.JLabel;

import javax.swing.JTable;

import javax.swing.table.TableCellRenderer;

 

public class FieldRenderer implements TableCellRenderer {

 

@Override

public Component getTableCellRendererComponent(JTable table, Object value,

boolean isSelected, boolean hasFocus,

int row, int column) {

String tableValue = (String)table.getValueAt(row, column);

int mapCode = Integer.parseInt(tableValue);

 

JLabel label = new JLabel();

 

Icon icon = null;

 

switch(mapCode) {

  case 1:

    // 式を評価した値が定数1と一致したときに実行される処理

  icon= new ImageIcon("/Users/matsuiyoshikazu/eclipse-workspace/sample/src/resource/11/glass.png");

  label.setIcon(icon);

    break;

  case 2:

    // 式を評価した値が定数2と一致したときに実行される処理

 

  icon = new ImageIcon("/Users/matsuiyoshikazu/eclipse-workspace/sample/src/resource/11/sea.png");

  label.setIcon(icon);

    break;

}

return label;

}

 

 

}

-----------------------------------------------------

リソースとなる画像を用意するのが面倒ですが、WindowsであればPaintとか、とりあえずMacでアルパカさんで作ってみました。

32*32ピクセルの画像を2種類。

まずは緑色と水色の2種類、という感じでもいいです。

そして最初に作ったFieldMapクラスのコードに追加したRendererを書き加えます。

FieldMap(レンダラー追加)

--------------------------------------------------

package sample7;

 

import javax.swing.JFrame;

import javax.swing.JTable;

 

public class FieldMap {

 

private String map = new String {

{ "2", "2", "2", "2", "2" },

{ "2", "1", "1", "1", "2" },

{ "2", "1", "1", "1", "2" },

{ "2", "1", "1", "1", "2" },

{ "2", "2", "2", "2", "2" }, };

 

public String getMap() {

return this.map;

}

 

public static void main(String args) {

FieldMap filedMap = new FieldMap();

String map = filedMap.getMap();

JTable tbl = new JTable(5, 5);

 

for (int i = 0; i < 5; i++) {

for (int j = 0; j < 5; j++) {

tbl.setValueAt(map[i][j], i, j);

 

}

}

for (int j = 0; j < 5; j++) {

tbl.getColumnModel().getColumn(j).setCellRenderer(new FieldRenderer());

 

}

 

JFrame frame = new JFrame("field");

frame.getContentPane().add(tbl);

frame.setSize(400, 400);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setVisible(true);

}

}

--------------------------------------------------

 テーブルを回しながら、追加していくところが少し馬鹿っぽいですが、逆にこれは、テーブルのカラム(列)ごとに別のレンダリングが可能ということです。

というかfor文の書き方を忘れていてぐぐりながら書きました・・・w

そして下記の画面が実行結果です。

f:id:yo2an:20210408121804p:plain

フィールドマップ(画像)

テーブルのセルの間隔などを調整すれば、マップ画面ができてしまった気がしませんか?

とりあえず今回はこんなところです。

 

・・・16パネルゲームをimportして実行してみたら動きました。(下記です。)

こちらもテーブルを使っているのですが、今の僕にはなかなか難しいコーディングをしていますね。(こんな難しいコードが書けたのか・・・10年前くらいの僕は・・・)

https://ma2-ys.booth.pm/items/2784565

 

実行画面

f:id:yo2an:20210408122732p:plain

16パネルゲーム実行

話がとびとびですいませんが、

こんな感じで、プログラミングという行為が、発想→コーディング→失敗→調査→みたいな感じで、自然にできたら、Javaでのシステム開発はかなり楽になっていくのではないですかね?

そうはいってられないプロジェクトがいっぱいなのかもしれませんが。

 

僕の経験としては、やはり上下関係でシステム開発をしているところは、うまく行かなかったことが多い気がします。

通信・金融・官公庁関連など様々なシステム開発にいくつか参加しましたが、まさにデスマーチという言葉がぴったりだった。

同じく業務委託で会社的には階層構造にはなってしまっても、チーム内では平等というかメンバー同士が差別なく、スキルの弱い人でもフォローできるフランクなプロジェクトはとてもスムーズにプロジェクトが進んでいた気がします。

 

今からはじめるプログラミング10

お疲れ様です。フラグについてようやくなるべくシンプルに実装したいという目標を回収できそうな、構成を思いついたので、実装してみました。

2画面目の上にそのままフラグというチェックボックスを設けて、チェックを入れた状態(フラグを立てた状態)とチェックを入れない状態(フラグが立ってない状態)で違う画面に遷移するようにしています。

ソースが少し多くなって、ブログにコピペだと、みづらいので、GoogleDriveのリンクをはります。

 

sample - Google ドライブ

 

今までのサンプルも入っているので、復讐しつつ、フラグ回収のソースコードもみていただければと思います。

ポイントとしては、

SimpleStoryFrameのコンストラクタにフラグを追加したものを作り、前からあるコンストラクタと共有するプログラムを組み換えている。

FlgListenerとFlgManageクラスを新規作成、インスタンスをひとつにするコーディングにすることで、どの画面からもリスナーからも同じフラグを参照、操作する。

SimpleStoryActionでフラグが立っていた場合に別ルートへ分岐する記述。

物語・・・になっていませんが、ちょっと水彩に合わせて、適当なテキストを追加してみました。

水彩はBoothさんで画集として登録しているので、もしよろしかったら、あと現状で実行形式もつくってアップしようと思います。

ma2-ys - BOOTH

今後の課題としては、TODOに記述している通り、

・コンテンツを外部リソースかして、プログラムをいじらなくても、テキストの入れ替えや更新ができるようにする。

・戻るボタンがないので作成する。

・エラー処理。

・保存と読み込み。

あたりが主な課題ですかね?次回は別のことをしていると思いますが、ゆっくりお付き合いください。

 

ところで、皆さんは最初のプロジェクトで何ステップぐらいコーディングすることになるのでしょうか?あるいは何ステップコーディングしましたか?

ステップカウンターで数えて報告するプロジェクトもありましたが、僕は、最初のJava画面アプリで10000ステップ以上コーディングしました。

4画面で最後の難しい画面で半分以上。。。ようするに最後はスパゲッティコードを作成しています。あまり設計とかわからなかったし、とりあえず動くことを目指して。。。

最初にそんなステップ数をコーディングすることは稀だと思いますが、みなさん体を大切に仕事に従事しましょう。ちなみに2番目のプロジェクトでは、いよいよWEBアプリケーションのプロジェクトに参加するわけですが、プロジェクトの内容を知ったのは一週間くらい前で、フレームワークなるものを使って、実装するということで、再び一週間で勉強してプロジェクトに臨む・・・そんなはめになりました。結局2つめのプロジェクトは自分の関係のないところで、失敗に終わるのですが、 作業場所も遠く、残業も多く・・・業界の闇をひしひしと感じるプロジェクトでした。プロジェクトのメンバーはみんないい人ばかりだったんですけれど。世の中ってどうしてこんな感じなんでしょうね。結局新しいものをつくる、という場合に、何をどう見積もるのか、計画がもう立てられなかったのかな、と思います。では自分では計画できたのか、と問われるとうーむ。と唸ってしまいますが・・・。

難しいですね。

今からはじめるプログラミング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

 

 

 

 

今からはじめるプログラミング(目次)

自己紹介

(作成中・・・というか以下の記事内に過去自分が参加したプロジェクトなどについて書いているので、いつかまとめます。)

・最初なので大したことは書いておりませんが。最初の記事。目標はeclipseのインストールとぐぐれること。

今から始めるプログラミング1 - yo2an’s blog

・2ページ目・・・とにかく1画面表示してみるプログラム。ステップ数10行ぐらい。

今から始めるプログラミング2 - yo2an’s blog

・3ページ目・・・画面プログラムの解説、クラスの解説、イベント処理の解説。ステップ数20行弱。

今から始めるプログラミング3 - yo2an’s blog

・4ページ目・・・入力画面と出力画面、画面遷移。ステップ数40行ぐらい。

今から始めるプログラミング4 - yo2an’s blog

・5ページ目・・・クラス分割。こちらは60行ぐらい。

今から始めるプログラミング5 - yo2an’s blog

・6ページ目・・・画像の表示。40行は書いていない?くらい。

今から始めるプログラミング6 - yo2an’s blog

・7ページ目・・・HTMLを取得するプログラム。いつも使っているだけのブラウザについて考えてみる。30ステップよりおおい。

今から始めるプログラミング7(ぶれいく) - yo2an’s blog

・8ページ目・・・フラグについて。ノベルゲームの途中のクラス群。

今から始めるプログラミング8 - yo2an’s blog

・9ページ目・・・とりあえず画面遷移を何ページか進める。

今からはじめるプログラミング9 - yo2an’s blog

・10ページ目・・・フラグについて。ノベールゲームのなんとか形になったもの?全部で200ステップぐらい。

今からはじめるプログラミング10 - yo2an’s blog

 ・11ページ目・・・RPGをつくれないかなぁという感じ。テーブルで画像を表示してドラクエみたいなフィールドを構成してみる。

今からはじめるプログラミング11 - yo2an’s blog

・12ページ目・・・フィールドの上にキャラクターを表示して、東西南北(東のみ)に移動する。

今からはじめるプログラミング12 - yo2an’s blog

 

ある程度出来上がったら、また下記のBoothさんに100円でプロジェクトファイルを追加したいと思います。

ma2-ys - BOOTH

 

googleドライブのリンク(12までのプログラムをふくんでいるはず)

sample.zip - Google ドライブ

 

今から始めるプログラミング8

少しは画面のプログラムがかけるようになっていただけていたら、嬉しいです。

画面遷移だけでしたら、前回までのソースで、最初の画面と次の画面を作って、最初の画面のイベント(リスナー)で次の画面の初期化を呼べばいいので結構簡単に実装できますね。

真っ直ぐに進むだけ、のノベルだけならこれでいいと思います。

次によくよく理解したいことといえば、「フラグ」でしょうか。

恋のフラグとか死亡フラグとか、そういうもののフラグと同じというか、このプログラムのフラグが語源ですよね?

フラグを制御して、ルート分岐する。

キーとなるアイテムをもっているかどうか、フラグで制御する。

ノベルゲームでは、このフラグが、ゲームの肝かもしれません。

とはいえ、すでにここまでのプログラムの中で実はフラグは使っています。

直近のファイルチューザーを使ったコーディングでファイル選択の戻り値をif文で判断して処理を分岐しています。

そうです明確に「フラグ」ではないものの、ここではint型の選択されたか、どうかでルート分岐しているのです。下記の記事ですね。

今から始めるプログラミング6 - yo2an’s blog

 

今更かもしれませんが、プリミティブ型というものをそろそろ理解したいと思います。一番簡単な(小さい?)型として「フラグ」そのものである「boolean」というものがあります。これは要するにオンとオフしか表現できません。容量も少ないので、if文やroopの制御に使用できます。

if(フラグ){

   フラグがオンの時の処理

}

とか

while(フラグ){

 フラグがtrueのときずっと繰り返し

}

みたいな感じです。プログラムもわかりやすいですよね。

なのでなかなか重宝する型です。

では、int型はどうでしょう。こちらは数値の型です。数字なのですが、基本的に計算用の型ですが、先ほどのフラグで3つの条件分岐を行うにはどうでしょうか、フラグを2つにするとかすればできそうですが、いきなり読みづらいコードになりそうですね。

そういう時は、異世界生活でいうところの「ステータス」を表現できそうな、幅を持つ数値(数値でなくてもいいですが)を使います。

ある意味コード化するのに好都合な型です。数値にそれぞれ意味を持たせてプログラムします。ファイル選択を行う場合の操作を思い浮かべると、「ファイルが選択された場合」、「ファイルが選択されなかった場合」、さらに「処理をキャンセルした場合」などのステータスが考えられます。それぞれ1,2,3を割り当てると、戻り値で

if(戻り値==1){

}else(戻り値==2){

}else(戻り値==3){

という感じで分岐することができます。

ただの数値だとわからないので、定数を使うことが多いです。ここでも「JFileChooser.APPROVE_OPTION」という定数を使用していました。

こういう実際の値とその意味を設計することをコード設計といって、システム開発では重要な工程の一つなので理解しておくといいと思います。コード定義とか。

話が長くなりましたが、「フラグ」はプログラムの重要な要素であることは理解いただけたと思います。

というわけで、これからつくるノベルゲームも、ルート分岐を作ってハッピーエンドとバッド?エンドを設定しようかな、とか考えています。

とはいえ、ルート分岐の前までコーディングしないと実際のプログラムがまだまだわからないですよね。

次回は、分岐の画面ぐらいまでは作りたいですので、しばらくかかると思います。

とはいえプログラムが何もないのは寂しいので、今できているクラスをぺけぺけと貼り付けておきます。作り途中なので、「TODO」が多いです。「TODO」コメントはエクリプスがToDoリストを作ってくれるきのうなので、書いておくと忘れてもいいですよ。僕のような記憶の容量の小さい人間には必須の機能です。

MainClass

-----------------------------------

package sample5;

 

public class MainClass {

 

public static void main(String[] args) {

new Menu();

}

 

}

-----------------------------------

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() {

// TODO ロードしたいものがあればここで処理する

 

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 MenuListener());

// ボタンを画面に追加

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

-----------------------------------

package sample5;

 

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

 

public class MenuListener implements ActionListener {

 

@Override

public void actionPerformed(ActionEvent e) {

 

//TODO 次の画面

}

 

}

-----------------------------------

CloseListener

-----------------------------------

package sample5;package sample5;
import java.awt.event.ActionEvent;import java.awt.event.ActionListener;
public class CloseListener implements ActionListener {
@Override public void actionPerformed(ActionEvent e) {

System.exit(0);

}
}

-----------------------------------

ImageTextPanel

-----------------------------------

package sample5;

 

import javax.swing.JPanel;

import javax.swing.JTextArea;

 

public class ImageTextPanel extends JPanel {

private String imageSource = "";

private String textSource = "";

private JTextArea area = new JTextArea();

 

public boolean setImageSource(String source) {

//TODO

return false;

}

 

public boolean setTextSource(String source) {

//TODO

return false;

}

 

public ImageTextPanel(String img,String text) {

//TODO

}

 

}

-----------------------------------

 

ジャンクプログラムもよろしくです。

ma2-ys - BOOTH

 

今から始めるプログラミング7(ぶれいく)

クラス分割とかすっかり忘れているのですが、その上でコーヒーブレイクしています。すいません怠け者です。

現在地方のライン工として働いているのですが、コーヒーをかなり我慢していました。紅茶も好きなのですが、コーヒーは吐くほどハマってしまうので、お金を使い過ぎてしまいそうだったので、わざと買わないようにしていたのですが、つい先日紅茶味のホットケーキを作ったので今度はコーヒー味のホットケーキを作ろう、と思って、ついにインスタントコーヒーを購入してしまいました。

それはさておき、目標としては、ノベルゲームでも作ろうとおもっていたこの講習?ブログですが、いろいろ思うものはあって、本当に役立つには別のことも絶対必要だな、ということを考えます。

今回は作るつもりはありませんが、WEBアプリケーションやスマフォアプリケーションが全盛の現在、HTMLを扱えないと仕事としてはどうしようもない。

とはいえ素直にそれらのアプリケーションを作るのは、ポリシーが・・・。

ということで、単純にURLからHTMLを取得してくるクラスを作ってみました。

 

GetHTML1クラス

---------------------------------------------

package sample4;

 

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.URL;

import java.net.URLConnection;

 

/**

* HTMLの取得

* @author matsuiyoshikazu

*

*/

public class GetHTML1 {

 

/**

* HTMLを取得します

* @param url

* @param flgLineNumber

* @return

*/

public StringBuffer getHTML(String url, boolean flgLineNumber) {

String charset = "UTF-8";

StringBuffer sb = new StringBuffer();

InputStream is = null;

InputStreamReader isr = null;

BufferedReader br = null;

try {

URLConnection conn = new URL(url).openConnection();

is = conn.getInputStream();

isr = new InputStreamReader(is, charset);

br = new BufferedReader(isr);

 

String line = null;

int lineNumber = 0;

if (flgLineNumber) {

lineNumber = 1;

}

 

while *1 != null) {

 

if (flgLineNumber) {

sb.append(lineNumber + ":" + line + "\r\n");

lineNumber++;

 

} else {

sb.append(line);

}

}

 

} catch (Exception e) {

e.printStackTrace();

 

} finally {

try {

br.close();

} catch (Exception e) {

}

try {

isr.close();

} catch (Exception e) {

}

try {

is.close();

} catch (Exception e) {

}

}

return sb;

}

 

public static void main(String[] args) {

String url = "http://yo2an.hatenablog.com/entry/2021/03/22/171025\"";

GetHTML1 getHtml1 = new GetHTML1();

StringBuffer sb = getHtml1.getHTML(url, false);

;

System.out.println(sb);

sb = getHtml1.getHTML(url, true);

;

System.out.println(sb);

 

}

}

---------------------------------------------

 参考にしたのは下記のページです。自分のブログなどよりきれいにで凹みました。

Java URLConnectionクラスを使ってサイトからHTMLを取得(ダウンロード)する | javalife

 

そのままだとエラーになるので、URLをhttpsからhttpに変更してみたりしています。変更してもエラーのページが返っていますね、301・・・リダイレクトされている?このあたりのHTMLのコードについては、ググってみてください。権限がないとかページがないとか、そんな感じのコードがいろいろ出てきます。301の説明はちょっとメンドイので割愛です。

まぁざっくりつくった(パクった)コードだと現在の複雑なページはきちんと取得できないですね、昔再帰的なプログラムとか画像ファイルの処理とかでちょっとしてhtmlのダウンロードプログラムを作ってみたこともあるのですが、ちょっと思い出したぐらいで、つらつらと必要な処理が出てくるので、「ぶれいく」にならなくなってきたので、この辺でやめておきます。

でも、話がそれますが、ブラウザというアプリケーションがどれだけすごいことやってるのかがよくわかりますね。

ちょっとしたメディアプレイヤーだったり、書籍のインデックスたるリンクだったり、何気なく利用させていただいているこのアプリケーションは世の中のエンジニアの方々の努力の結晶なんだなぁ、と感じられます。

初めのプロジェクトでは、WEBアプリケーションを作りませんでしたが、(別のチームでは作っていたようです)半年後に参加した次のプロジェクトでは、WEBアプリケーションを作成しました。

とはいってもこれは日の目をみなかったのですが。

 

次はその失敗プロジェクトについてと、プログラムについてはフラグについて?記事にしたいと思います。

よろしければジャンクコードなど(来週あたりもう一つ追加しようかなWInPCを入手したら。)

ma2-ys - BOOTH

*1:line = br.readLine(