プログラミング実習I : 課題 R9

目次

目標

  • 教科書にはない番外編として,二次元配列の使い方を理解する
    • 前回勉強した配列は,一次元配列
      • 要素が横に一次元的に並べられているイメージ
    • 今回勉強する二次元配列は, 要素が縦と横に二次元的に並べられているイメージ
      • 縦に並んだ要素数を n,横に並んだ要素数を m として, n×m の二次元配列 と呼ぶ
    • 二次元配列を用いた実習として,行列や三目並べを用いた例を取り上げる
      • n 行 m 列の行列は,n ×m の二次元配列を用いることでプログラム内で扱えるようになる
      • 三目並べの各マスの情報は,3×3 の二次元配列を用いることでプログラム内で扱えるようになる

二次元配列

サンプルプログラム

  • 以下のサンプルプログラム(MatrixTest.java) を用いて,二次元配列の定義と利用方法を説明する
    • サンプルプログラムの流れ
      1. 以下の 2×2の行列 \(\vbf{A}\) の各成分を 2×2の二次元配列変数 a と b にそれぞれ格納
        • a と b では,格納の方法が若干異なることに注意

          \begin{align} \vbf{A} = \begin{pmatrix} 1 & 2 \\ 3 & 4 \\ \end{pmatrix} \end{align}
      2. 2×2の二次元配列変数 a と b に格納されたそれぞれの値をコンソールに出力(標準出力)している
        • a と b に同じ値が格納されていることを,実際に実行して確認してみよ
        • 標準出力のメソッドの違い
          • System.out.print("…") → "…" を出力するだけ(改行しない)
          • System.out.println("…") → "…" を出力した後に,改行を行う
public class MatrixTest {

    public static void main(String[] args) {

        int[][] a = new int[2][2]; // 2×2の二次元配列の定義(定義の方法1)
        a[0][0] = 1;
        a[0][1] = 2;
        a[1][0] = 3;
        a[1][1] = 4;

        int[][] b = { { 1, 2 }, { 3, 4 } }; // 初期値の設定を含めた2×2の二次元配列の定義(定義の方法2)

        System.out.println("a is");
        for(int i = 0; i<a.length; i++) {
            for(int j=0; j< a[i].length; j++) {
                System.out.print(a[i][j] + " "); // 改行なし
            }
            System.out.println(); // 改行だけ行う
        }

        System.out.println("b is");
        for(int i = 0; i<b.length; i++) {
            for(int j=0; j< b[i].length; j++) {
                System.out.print(b[i][j] + " "); // 改行なし
            }
            System.out.println(); // 改行だけ行う
        }

        /* 
           a is
           1 2 
           3 4 
           b is
           1 2 
           3 4
        */
    }
}

n ×m の二次元配列の定義と利用方法

  • 定義

    • 定義の方法1 : 二次元配列の定義だけ行う
      • 配列への初期値の設定は,後から行うパターン
    変数の型[][] 配列変数名 = new 変数の型[n][m];
    
    • 定義の方法2 : 二次元配列の定義と初期値の設定を同時に行う
    変数の型[][] 配列変数名 = {{値, 値, ...}, {値, 値, ...}, ...};
    
  • 利用

    • 要素の参照
      • 二次元配列の (i, j) 番目の要素は,以下の形式で参照できる
        • ただし 0 ≦i ≦n-1 および 0 ≦j ≦m-1
    配列変数名[i][j]
    
    • 要素数(縦の要素数 n or 横の要素数 m) の参照
      • 縦の要素数 n は,以下で参照できる
        • ※ 1 次元配列の要素数と同じ

          配列変数名.length
          
      • i 行目の要素数(全て m) は 以下で参照できる
        • ただし 0 ≦i ≦n-1

          配列変数名[i].length
          

R9_1

準備

  • 学籍番号(12345677)に 0 を加えた計 9 個の数字を各成分に与えた以下の 3×3 の行列 \(\vbf{A}\) を考える
\begin{align} \vbf{A} = \begin{pmatrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 7 & 0\\ \end{pmatrix} \label{eq:A} \end{align}
  • これは 3×3 の二次元配列変数 a として,以下のように定義できる
int[][] a = {{1, 2, 3}, {4, 5, 6}, {7, 7, 0}};

課題

  • 上記のように,自分の学籍番号(8 桁)に 0 を加えた計 9 個の数字を格納した二次元配列変数 a を定義し,それを,以下の図 1 のようにウィンドウに描くプログラム(MyNumber.java) を作成せよ
    • ※ MyFrame2 クラスを用いること
    • ヒント
      • 図形(文字や四角形)を二次元的に描画する方法 → R4_1 で多重ループを用いて行う方法を勉強した
      • 数字をウィンドウに描画する方法 → R5_3 で drawString メソッドを用いて行う方法を勉強した

R9_1.png

図1: R9_1 で作成するプログラムで表示されるウィンドウ(学籍番号 12345677 の場合)

提出物

  • 作成した MyNumber.java

R9_2

準備

  • 以下に示すように 2×2 の行列 \(\vbf{A}\) および行列 \(\vbf{B}\) を考える

    \begin{align} \vbf{A} = \begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \\ \end{pmatrix} ,\ \vbf{B} = \begin{pmatrix} b_{11} & b_{12} \\ b_{21} & b_{22} \\ \end{pmatrix} \end{align}
  • このとき,それぞれの行列の和 \(\vbf{C} = \vbf{A} + \vbf{B}\) と差 \(\vbf{D} = \vbf{A} - \vbf{B}\) は次式で定義される

    \begin{align} \vbf{C} = \vbf{A} + \vbf{B} = \begin{pmatrix} a_{11} + b_{11} & a_{12} + b_{12} \\ a_{21} + b_{21} & a_{22} + b_{22} \\ \end{pmatrix} ,\ \vbf{D} = \vbf{A} - \vbf{B} = \begin{pmatrix} a_{11} - b_{11} & a_{12} - b_{12} \\ a_{21} - b_{21} & a_{22} - b_{22} \\ \end{pmatrix} \end{align}
    • すなわち,行列 \(\vbf{C}\) の \((i, j)\) 成分が \(c_{ij}\) であるとすると,\(c_{ij}\) は次式で与えられる

      \begin{align} c_{ij} = a_{ij} + b_{ij} \end{align}
    • また,行列 \(\vbf{D}\) の \((i, j)\) 成分が \(d_{ij}\) であるとすると,\(d_{ij}\) は次式で与えられる

      \begin{align} d_{ij} = a_{ij} - b_{ij} \end{align}
  • 同様に,3×3 の行列の和と差も定義できる

課題

  • 行列の和 \(\vbf{A} + \vbf{B}\) と差 \(\vbf{A} - \vbf{B}\) を計算し,その結果を,以下の図 2 のようにウィンドウに描くプログラム(MyNumberPlusMinus.java) を作成せよ
    • ただし
      • R9_1 のように自分の学籍番号(8 桁)に 0 を加えた計 9 個の数字を格納した二次元配列変数 a として定義し,3×3の行列 \(\vbf{A}\) とみなす
      • 二次元配列変数 b を以下のように定義し,3×3の行列 \(\vbf{B}\) とみなす
    • ※ MyFrame2 クラスを用いること
int[][] b = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

R9_2.png

図2: R9_2 で作成するプログラムで表示されるウィンドウ(学籍番号 12345677 の場合)

提出物

  • 作成した MyNumberPlusMinus.java

R9_3

準備

  • R9_2 の準備と同様の行列 \(\vbf{A}\) および行列 \(\vbf{B}\) が与えられた時,それらの行列の積 \(\vbf{M} = \vbf{A}\vbf{B}\) は以下のように定義される

    \begin{align} \vbf{M} = \vbf{A}\vbf{B} = \begin{pmatrix} a_{11}\,b_{11} + a_{12}\,b_{21} & a_{11}\,b_{12} + a_{12}\,b_{22} \\ a_{21}\,b_{11} + a_{22}\,b_{21} & a_{21}\,b_{12} + a_{22}\,b_{22} \\ \end{pmatrix} \end{align}
    • すなわち,行列 \(\vbf{M}\) の \((i, j)\) 成分を \(m_{ij}\) とすると,\(m_{ij}\) は次式で与えられる

      \begin{align} m_{ij} = \sum_{k = 1}^{2} a_{ik}\,b_{kj} \label{eq:mat_prob} \end{align}
  • 同様に,3×3の行列の積も定義できる
    • 式 \eqref{eq:mat_prob} における \(\sum\) の範囲を k = 1 〜 3 に変更すればよい

課題

  • 行列の積 \(\vbf{A}\,\vbf{B}\) を計算し,その結果を,以下の図 3 のようにウィンドウに描くプログラム(MyNumberMultiply.java) を作成せよ
    • ただし
      • R9_2 で定義した二次元配列 a および b を,行列 \(\vbf{A}\) および \(\vbf{B}\) とみなす

R9_3.png

図3: R9_3 で作成する作成するプログラムで表示されるウィンドウ(学籍番号 12345677 の場合)

提出物

  • 作成した MyNumberMultiply.java

R9_4

準備

  • 以下の図に示すような 3 目並べを行う盤がある.i 列 j 行のマスを (i, j) で表す.

    • 「i "行" j "列"」でないことに注意!

    tic_tac_toe.png

    図4: 三目並べを行う盤

  • 盤上に黒と白のコマを (0,0), (2,1), (2,2) の順に交互に置くことを以下のような二次元配列変数 moves で表す

    int[][] moves = { { 0, 0 }, { 2, 1 }, { 2, 2 } };
    

課題

  • 5 のように,二次元配列 moves で表されたコマの配置の様子をアニメーションとして描くプログラム(TicTacToe.java) を作成せよ
    • ※ MyFrame2を用いること
    • ただし,図 5 では,↑の moves が与えられた場合の例を示している

      R9_4_1.gif

      図5: R9_4 で作成するプログラムで表示されるアニメーション(ループ再生)の例(↑の二次元配列 moves が与えられた場合)

    • (オプション) 任意で,以下のような,すでにコマが配置されているマスに,コマを置くような moves が与えられた場合には,図 6 に示すように, 「Illegal Move!」 という表示を行い,アニメーションを停止すること(出来ていた場合は +1 の加点を行う)

      • ヒント: 新たな二次元配列を作成し,コマを置いた場所を記憶するようにすればよい
      int[][] moves = { { 0, 0 }, { 2, 1 }, { 2, 1 }, {1, 1}};
      

      R9_4_2.gif

      図6: R9_4 で作成するプログラムで表示されるアニメーション(ループ再生)の例 (すでにコマが配置されているマスにコマを置くような場合)

提出物

  • 作成した TicTacToe.java

R9_5 (オプション)

課題

  • R9_4 の TicTacToe.java を拡張して,三目並べの勝敗判定も行えるプログラム (TicTacToe.java) を作成せよ
    • 黒が勝った場合は,図 7 のように,「Black Wins!」 という表示を行い,アニメーションを停止すること
    • 白が勝った場合は,図 8 のように,「White Wins!」 という表示を行い,アニメーションを停止すること
  • 以下の 2 つの二次元配列 moves をそれぞれ与えた場合に,作成したプログラムが正しく動作することを確認せよ
    • 黒が勝つ moves (※実行結果は 図 7)

      int[][] moves = { { 0, 0 }, { 2, 1 }, { 1, 1 }, {2, 2}, {2, 0}, {1, 0}, {0, 2}};
      
    • 白が勝つ moves (※実行結果は 図 8)

      int[][] moves = { { 0, 0 }, { 2, 1 }, { 1, 1 }, {2, 2}, {0, 2}, {2, 0}};
      

      R9_5_1.gif

      図7: R9_4 で作成するプログラムで表示されるアニメーション(ループ再生)の例(黒が勝つ二次元配列 moves が与えられた場合)

      R9_5_2.gif

      図8: R9_4 で作成するプログラムで表示されるアニメーション(ループ再生)の例(白が勝つ二次元配列 moves が与えられた場合)

提出物

  • 作成した TicTacToe.java

R9_6 (オプション)

課題

  • ライフゲーム(二次元セルオートマトン)を勉強して,その内容をレポートにまとめよ.
  • 任意の位置にグライダーやブロックなどを初期配置し,以下の図のように,ライフゲームを実行するプログラム(CA.java) を作成せよ.

    • 9 では,ライフゲームの時刻 t を表示しているが,提出するプログラムでは表示する必要はない

    R9_6.gif

    図9: ライフゲームの実行例

提出物

  • 作成した CA.java

著者: Yusuke Sakumoto

Created: 2023-10-02 月 09:57

Validate