プログラミング実習I : 課題 R9
目標
- 教科書にはない番外編として,二次元配列の使い方を理解する
- 前回勉強した配列は,一次元配列
- 要素が横に一次元的に並べられているイメージ
- 今回勉強する二次元配列は, 要素が縦と横に二次元的に並べられているイメージ
- 縦に並んだ要素数を n,横に並んだ要素数を m として, n×m の二次元配列 と呼ぶ
- 二次元配列を用いた実習として,行列や三目並べを用いた例を取り上げる
- n 行 m 列の行列は,n ×m の二次元配列を用いることでプログラム内で扱えるようになる
- 三目並べの各マスの情報は,3×3 の二次元配列を用いることでプログラム内で扱えるようになる
- 前回勉強した配列は,一次元配列
二次元配列
サンプルプログラム
- 以下のサンプルプログラム(MatrixTest.java) を用いて,二次元配列の定義と利用方法を説明する
- サンプルプログラムの流れ
- 以下の 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の二次元配列変数 a と b に格納されたそれぞれの値をコンソールに出力(標準出力)している
- a と b に同じ値が格納されていることを,実際に実行して確認してみよ
- 標準出力のメソッドの違い
- System.out.print("…") → "…" を出力するだけ(改行しない)
- System.out.println("…") → "…" を出力した後に,改行を行う
- 以下の 2×2の行列 \(\vbf{A}\) の各成分を 2×2の二次元配列変数 a と b にそれぞれ格納
- サンプルプログラムの流れ
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 : 二次元配列の定義と初期値の設定を同時に行う
変数の型[][] 配列変数名 = {{値, 値, ...}, {値, 値, ...}, ...};
- 定義の方法1 : 二次元配列の定義だけ行う
利用
- 要素の参照
- 二次元配列の (i, j) 番目の要素は,以下の形式で参照できる
- ただし 0 ≦i ≦n-1 および 0 ≦j ≦m-1
- 二次元配列の (i, j) 番目の要素は,以下の形式で参照できる
配列変数名[i][j]
- 要素数(縦の要素数 n or 横の要素数 m) の参照
- 縦の要素数 n は,以下で参照できる
※ 1 次元配列の要素数と同じ
配列変数名.length
- i 行目の要素数(全て m) は 以下で参照できる
ただし 0 ≦i ≦n-1
配列変数名[i].length
- 縦の要素数 n は,以下で参照できる
- 要素の参照
R9_1
準備
- 学籍番号(12345677)に 0 を加えた計 9 個の数字を各成分に与えた以下の 3×3 の行列 \(\vbf{A}\) を考える
- これは 3×3 の二次元配列変数 a として,以下のように定義できる
int[][] a = {{1, 2, 3}, {4, 5, 6}, {7, 7, 0}};
課題
- 上記のように,自分の学籍番号(8 桁)に 0 を加えた計 9 個の数字を格納した二次元配列変数 a を定義し,それを,以下の図 1 のようにウィンドウに描くプログラム(MyNumber.java) を作成せよ
図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}};
図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 に変更すればよい
R9_4
準備
以下の図に示すような 3 目並べを行う盤がある.i 列 j 行のマスを (i, j) で表す.
- 「i "行" j "列"」でないことに注意!
図4: 三目並べを行う盤
盤上に黒と白のコマを (0,0), (2,1), (2,2) の順に交互に置くことを以下のような二次元配列変数 moves で表す
int[][] moves = { { 0, 0 }, { 2, 1 }, { 2, 2 } };
課題
- 図 5 のように,二次元配列 moves で表されたコマの配置の様子をアニメーションとして描くプログラム(TicTacToe.java) を作成せよ
- ※ MyFrame2を用いること
ただし,図 5 では,↑の moves が与えられた場合の例を示している
図5: R9_4 で作成するプログラムで表示されるアニメーション(ループ再生)の例(↑の二次元配列 moves が与えられた場合)
(オプション) 任意で,以下のような,すでにコマが配置されているマスに,コマを置くような moves が与えられた場合には,図 6 に示すように, 「Illegal Move!」 という表示を行い,アニメーションを停止すること(出来ていた場合は +1 の加点を行う)
- ヒント: 新たな二次元配列を作成し,コマを置いた場所を記憶するようにすればよい
int[][] moves = { { 0, 0 }, { 2, 1 }, { 2, 1 }, {1, 1}};
図6: R9_4 で作成するプログラムで表示されるアニメーション(ループ再生)の例 (すでにコマが配置されているマスにコマを置くような場合)
提出物
- 作成した TicTacToe.java
R9_5 (オプション)
課題
- R9_4 の TicTacToe.java を拡張して,三目並べの勝敗判定も行えるプログラム (TicTacToe.java) を作成せよ
- 以下の 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}};
図7: R9_4 で作成するプログラムで表示されるアニメーション(ループ再生)の例(黒が勝つ二次元配列 moves が与えられた場合)
図8: R9_4 で作成するプログラムで表示されるアニメーション(ループ再生)の例(白が勝つ二次元配列 moves が与えられた場合)
提出物
- 作成した TicTacToe.java