課題 (09:スプレッドシート)

作業について

今回の課題は以下のパッケージに作成してください。

パッケージの名前
j1.lesson09

作成するクラスの名前は問題ごとに指示があります。下記を参照してください

課題の提出方法については下記を参照してください。

また、別のコンピューター上に移動する際には、下記を参考にプログラムを持ち帰ってください。

新しい内容

マスの文字列の内容を比較する

スプレッドシート上のマスに記憶させた文字列を比較するには、次のように「Spreadsheet.isSet」という命令を使います。

package j1.lesson09;

import gpjava.Spreadsheet;

import javax.swing.JOptionPane;

public class IsSetS1 {

    public static void main(String[] args) {
        new IsSetS1().start();
    }

    void start() {
        Spreadsheet.show();
        Spreadsheet.setString(0, 0, "こんにちは");
        Spreadsheet.setString(0, 1, "こんばんは");
        if (Spreadsheet.isSet(0, 0, "こんにちは")) {
            JOptionPane.showMessageDialog(null, "(0, 0)はこんにちは");
        }
        if (Spreadsheet.isSet(0, 0, "こんばんは")) {
            JOptionPane.showMessageDialog(null, "(0, 0)はこんばんは");
        }
        if (Spreadsheet.isSet(0, 1, "こんにちは")) {
            JOptionPane.showMessageDialog(null, "(0, 1)はこんにちは");
        }
        if (Spreadsheet.isSet(0, 1, "こんばんは")) {
            JOptionPane.showMessageDialog(null, "(0, 1)はこんばんは");
        }
    }
}

「Spreadsheet.isSet」という命令は、最初の2つの引数で行番号と列番号を指定して、3つ目の引数で文字列を指定します。指定したマスに、指定した文字列と同じ文字列を記憶させていればtrueが返ってきて、それ以外ではfalseが返ってくるような仕組みです。

例では、if文と組み合わせて次のように使っています。

if (Spreadsheet.isSet([行番号], [列番号], [比較する文字列])) {
    [指定のマスに比較する文字列と同じ文字列を記憶させていた際の命令]
}

なお、整数を比較する場合には次のように書けます。文字列の比較についてはこの授業で取り扱っていないため、「Spreadsheet.isSet」という特別な命令を用意しています。

if (Spreadsheet.getInt([行番号], [列番号]) == [比較する整数]) {
    [指定のマスに比較する整数と同じ値を記憶させていた際の命令]
}

問題

作成するクラスの名前
ScriptEngineS1

ファイルに書かれた「スクリプト (台本)」というものを読み出して、その記述に従って簡単な物語などを表示するようなプログラムを作成してください。

このスクリプトという考え方は複雑な業務手続きや、巨大なゲームのストーリーなどを記述する際によく使われる手法です。これは、プログラムにそのまま手続きを記述するのではなく、それよりも簡単な「スクリプト」というものを作成して、プログラムからはそのスクリプトを元に様々な処理を行います。これによって、プログラムがわからない人もプログラムの作成に参加できるようになり、さらにプログラムで書くと非常に長くなってしまうものも、スクリプトならば数行で書けることもあります。

ただし、スクリプトはこれまでのプログラムのようにJavaのプログラムとして実行することはできません。スクリプトを実行するための「スクリプトエンジン」というプログラムが必要になります。

今回作成するスクリプトエンジンは、スプレッドシート上に読みだしたスクリプトを解釈して「メッセージダイアログの表示」、「0か1を入力して分岐」、「スクリプトの実行終了」という3つの操作だけを行う非常に単純なものです。たとえば、「こんにちは!」とだけ表示するスクリプトは次のようなスプレッドシートのデータです。

SHOW こんにちは!      
END        

a. 操作の種類を表示する

まずはスクリプトが全体を通してどんなものであるかを実感してもらうため、スクリプトにどのような「命令」が書かれているかを表示するプログラムを作成してください。

今回のスクリプトは、「メッセージダイアログの表示」、「0か1を入力して分岐」、「スクリプトの実行終了」の3種類の命令のうち、スプレッドシートの1行につき1つだけ選んで書くことができます。それぞれの行に書いてある命令の種類は、それぞれの行の1列目を見ればわかります。

1列目の文字列 命令の種類
SHOW メッセージダイアログを表示し、次の行へ移動
BRANCH 入力ダイアログを表示し、1が入力されたら別の行へ移動、0が入力されたら次の行へ移動
END スクリプトの実行を終了する

次のプログラムを書き換えて、読みだしたスクリプトに書かれたそれぞれの行がどのような命令であるかを表示するようなプログラムを完成させて下さい。

package j1.lesson09;

import gpjava.Spreadsheet;

import javax.swing.JOptionPane;

public class ScriptEngineS1 {

    public static void main(String[] args) {
        new ScriptEngineS1().start();
    }

    void start() {
        Spreadsheet.show();
        Spreadsheet.load();
        int row = 0;
        while (true) {


        }
    }


}

命令は1行目から順に読んでいき、1列目に書かれた文字列を元に、それぞれの命令が「メッセージダイアログの表示」、「0か1を入力して分岐」、「スクリプトの実行終了」のいずれかであるかを順にメッセージダイアログに表示してください。

なお、1列目がSHOW, BRANCH, ENDのいずれでもない場合、その時点でプログラムを終了させてください。マスの内容を確認するには、先ほど紹介した「Spreadsheet.isSet」を利用すると楽です。

ヒント

ほとんど答えになってしまいますが、次のように書くことになります。

if (Spreadsheet.isSet(<現在の行>, 0, "SHOW")) {
    <1列目が「SHOW」である場合の処理>
    <次の行へ移動する処理>
}
else if (Spreadsheet.isSet(<現在の行>, 0, "BRANCH")) {
    <1列目が「BRANCH」である場合の処理>
    <次の行へ移動する処理>
}
else if (Spreadsheet.isSet(<現在の行>, 0, "END")) {
    <1列目が「END」である場合の処理>
    <次の行へ移動する処理>
}
else {
    <繰り返しを終了する命令>
}

b. SHOW命令の処理

次に、1列目に「SHOW」という文字列を持つ命令を処理できるようにプログラムを書き換えて下さい。これはさきほど「メッセージダイアログの表示」という文字列を表示していた部分で、「SHOW」という命令の2列目に書かれた文字列を代わりに表示するようにしてください。そのあとに、次の行へ移動する処理が必要で、この命令が終わると繰り返しを終了しないでさらに次の行を処理するようにしてください (先ほどの問題と同じです)。

たとえば、script09-show.txtを処理すると「1列目に「SHOW」、2列目にメッセージでメッセージダイアログを表示」「「SHOW」を処理したら次の行の命令を処理します」と順に表示したのちに命令の最後に達して終了するはずです。

SHOW 1列目に「SHOW」、2列目にメッセージでメッセージダイアログを表示      
SHOW 「SHOW」を処理したら次の行の命令を処理します      

c. END命令の処理

次に、1列目に「END」という文字列を持つ命令を処理できるようにプログラムを書き換えて下さい。これはさきほど「スクリプトの実行終了」と表示していた部分の代わりに、「終了します」とだけ表示してスクリプトの実行を終了させます。

たとえば、script09-end.txtを処理すると「1列目に「END」でスクリプトの実行を終了します」「終了します」と順に表示したのちに終了するはずです。この場合、3行目の命令は実行されません。

SHOW 1列目に「END」でスクリプトの実行を終了します      
END        
SHOW この命令は実行されません      

d. BRANCH命令の処理

次に、1列目に「BRANCH」という文字列を持つ命令を処理できるようにプログラムを書き換えて下さい。さきほど「スクリプトの実行終了」と表示していた部分の代わりに、入力ダイアログを表示して整数を入力させます。このとき入力ダイアログには、「BRANCH」という命令の2列目に書かれた文字列を表示してください。

この入力ダイアログに1が入力された場合、「BRANCH」という命令の3列目に書かれた番号の行へ移動してください。この命令が終わっても次の行を処理するようにしますが、1を入力された場合は3列目に書かれた行を次に処理します。入力ダイアログに0が入力された場合は、3列目の値を使わずに「BRANCH」という命令の次の行を処理するようにしてください (先ほどの問題と同じです)。0や1以外の値が入力ダイアログに入力された場合、「0か1を入力してください」とメッセージダイアログに表示し、再度入力ダイアログを表示して再入力させてください。

たとえば、script09-branch.txtを処理すると「1列目に「BRANCH」、2列目にメッセージ、3列目に行番号で」とメッセージダイアログに表示した後に「入力ダイアログで1か0を入力し」と入力ダイアログで表示します。ここに0を入力すると、次の行を処理して「0が入力された場合は次の命令へ」とメッセージダイアログに表示し、3行目の「END」命令で終了します。ここに1を入力すると、3列目に書かれた5行目を処理して「1が入力された場合は3列目に書いた行番号の命令へ」とメッセージダイアログに表示し、6行目の「END」命令で終了します。

SHOW 1列目に「BRANCH」、2列目にメッセージ、3列目に行番号で      
BRANCH 入力ダイアログで1か0を入力し 5    
SHOW 0が入力された場合は次の命令へ      
END        
SHOW 1が入力された場合は3列目に書いた行番号の命令へ      
END        

ヒント

3列目に書く「行番号」は1から始まる整数です。そのまま使うと0から数え始めるスプレッドシートでは1だけずれてしまいます。

おまけ

以上でスクリプトエンジンの作成は終了です。script09-show.txt, script09-end.txt, script09-loop.txtが正しく動作することを確認したら、自分でスクリプトを作成してみましょう。

Eclipseでプロジェクトのコンテキストメニュー(Windowsではプロジェクトを右クリック)して、「新規」「ファイル」の順に選択してください。ファイルを作成するダイアログが表示されますので、そこに「script.txt」と入力して「Finish」を押します。すると、なにも内容が書かれていないエディタが開かれますので、そこに次のように入力してください。

"SHOW", "はじめてのスクリプト"
"BRANCH", "0で終了、1で繰り返し", 1
"END"

この内容を保存したらプログラムを起動して、作成したファイルを選択してみてください。

このように、文字列や整数、実数などのリテラルをカンマで区切り、行ごとに改行を行うとスプレッドシートから読み出すことができます。これを利用して、様々なスクリプトを作成してみてください。

なお、繰り返し処理を行いたい場合、script09-loop.txtなどが参考になると思います。「SHOW」「BRANCH」「END」の3種類だけでどんなスクリプトを作成できるでしょうか。