#author("2021-07-21T10:21:29+09:00","default:takataka","takataka") #author("2021-07-21T10:22:17+09:00","default:takataka","takataka") *グラフィックス基礎及び実習 2021年度 第14回 実習と宿題 [#e9701092] #contents //&color(#ff0000){''工事中''}; //**注意 [#notice] **課題のための準備 [#o0bcb890] + サンプルをダウンロードしよう.Graphics チーム から以下のファイルをダウンロードしていつもの場所へ -- SammokuSample.class -- SammokuGUISample.class -- sammokuGUI.css + サンプルを実行してみよう java SammokuSample java SammokuGUISample + SammokuSample の動作を確認しよう -- 盤面の外や既に o/x が置いてある所を指定するとどうなる? -- 勝ち/負け/引き分けの判定はしてないですね -- 終了は,CTRL+C (コントロールキーを押しながらC) + SammokuGUISample の動作を確認しよう -- SammokuSampleクラス使ってます -- 適当にボタンを押してみよう **実習課題A 締切: 次回13:30 [#kadaiA] StepX の X は,課題 A, B と S の間で通し番号になってます. *** Step0 -- Sammoku (ver.0) を作ろう [#step0] [[''Step0''>#step0]] [[Step1>#step1]] [[Step2>#step2]] [[Step3>#step3]] [[Step4>#step4]] &color(#00a000){''(^o^)/ まずはキー入力の処理だけのプログラムを作ってみよう''}; 次のような動作をするプログラムを作ろう.★から右側は解説. #pre{{ 0 1 2 0| | | | 1| | | | ★ 盤面を数字と縦棒で表示 2| | | | 横縦の順に値を入力してね(例: 2 1): 2 1 ★ 右側の 2 1 がキーボードからの入力 (2,1) ★ 入力された値を表示 0 1 2 0| | | | 1| | | | ★ ver.0 では o や x の表示はなく,常に空の盤面を表示するだけ 2| | | | 横縦の順に値を入力してね(例: 2 1): 1 1 (1,1) 0 1 2 0| | | | 1| | | | 2| | | | 横縦の順に値を入力してね(例: 2 1): -1 2 ★ 盤面内の数字かどうかはチェックしたりしてない (-1,2) 0 1 2 0| | | | 1| | | | 2| | | | 横縦の順に値を入力してね(例: 2 1): 99 100 (99,100) 0 1 2 0| | | | 1| | | | 2| | | | 横縦の順に値を入力してね(例: 2 1): 0 hoge ★ 整数として解釈できない入力があると,再入力を促す 横縦の順に値を入力してね(例: 2 1): }} &color(red){''/(*_*) 次のことを守ってプログラムを考えよう''}; + クラス名は Sammoku とする. + ver.0 では,盤面を表示するインスタンスメソッド(引数なし,戻り値なし,名前は自分で決めよう)と,mainメソッドの2つだけを定義する. + mainメソッドは,以下のプログラム例を参考に作ろう. #pre{{ import java.util.*; // for Scanner class public class Hoge{ public static void main(String[] args){ // キー入力を扱う Scanner クラス Scanner sc = new Scanner(System.in); // 空白を区切りとして2つの整数を入力するとその和を出力 // 動作確認のためわざと変な入力をしてみるとよい while(true){ int x, y; boolean done = false; do{ System.out.print("x y : "); try{ x = Integer.parseInt(sc.next()); y = Integer.parseInt(sc.next()); sc.nextLine(); // この行の残りを読みとばす done = true; }catch(NumberFormatException e){ x = y = 0; sc.nextLine(); // この行の残りを読みとばす done = false; } }while(!done); System.out.println("x + y = " + (x + y)); } } } }} //&color(#00a000){''ここまでできた Sammoku のソースファイルを moodle の該当の場所へ提出してください.''}; ファイル名の間違いに注意 ***Step1 -- Sammoku (ver.1) を作ろう [#step1] [[Step0>#step0]] [[''Step1''>#step1]] [[Step2>#step2]] [[Step3>#step3]] [[Step4>#step4]] &color(#00a000){''(^o^)/ キー入力で指定された位置に o や x が表示されるようにしよう''}; 次のような動作をするプログラムを作ろう. 以下の動作例からわかるように,このver.1では,SammokuSample に近いふるまいをするけれど, 「キー入力で指定された位置が盤面内かどうか」,「そこに既にo/xがついているかどうか」,のチェックはしないものでよい(それらの処理はver.2で考えよう).盤面外を指定するとプログラムが例外を発生させて異常終了したり,oやxを上書きできてしまうが,それで構わない. #pre{{ 0 1 2 0| | | | 1| | | | 2| | | | 横縦の順に値を入力してね(例: 2 1): 0 0 (0,0) に置いたで 0 1 2 0|o| | | 1| | | | 2| | | | 横縦の順に値を入力してね(例: 2 1): 0 0 (0,0) に置いたで 0 1 2 0|x| | | 1| | | | 2| | | | 横縦の順に値を入力してね(例: 2 1): 0 hoge 横縦の順に値を入力してね(例: 2 1): 0 100 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100 }} &color(red){''/(*_*) 次のことを守ってプログラムを考えよう''}; 以下の「&color(blue){''クラスの設計を考えよう''};」をよく読んで,その指示に従ってください.よくできる人は全部一から考えたくなるでしょうが,与えられた仕様を満たすように作るのも大事ですから,まずは指示に従って課題をこなして,後で好きな設計を考えてみたらよいと思います. ***クラスの設計を考えよう [#i0e89597] &color(Blue){''/(?_?) Sammokuクラスのオブジェクトは,データとして何を持てばよい?''}; つまり,インスタンス変数やクラス変数としてどんなものを用意してどんな情報を格納するのがよい? → 例えば盤面はどう扱う? 盤面の状態を表す変数を用意するとして,それに○や×などの文字列を直接入れるのはややこしいからやめた方がよい → ○や×などに対応させて適当に整数値を割り当てるのがよいだろう. といっても,マスの数ぶんの変数を一つ一つばらばらに用意するのはいやんですよねぇ → ということは… &color(Blue){''/(*_*) 次のことを守ってプログラムを考えよう''}; - ''盤面を表す変数などは外部から勝手にいじられたりしないように隠蔽しよう''. &color(Blue){''/(?_?) Sammokuクラスにはどんな機能があればよい?''}; 一つのメソッドがいろんな仕事をするように作ると使い勝手が悪いし保守もしにくい. 一つのメソッドはなるべく単純な仕事しかしないように作って組み合わせるのがよい. → そういうわけで,次のような5つの機能に分ける構成としてみよう(より細分化したい人はご自由にどうぞ) - 盤面の初期化: コンストラクタで - 指定された位置のマスの値(○や×を表す整数値)を返す: 引数で指定された位置のマスの値を表す整数値を返す - 指定された位置のマスを指定された値(○や×を表す整数値)にする: マスの内容を表す変数の値を変更するだけ.盤面を表示するものではない(それは↓のメソッドの仕事) - 盤面を表示: ver.0 で作成したメソッドを改造 - キー入力を受け付けて上記のメソッドたちを呼ぶ動作を繰り返す: mainメソッドで ***Step2 -- Sammoku (ver.2) を作ろう [#step2] [[Step0>#step0]] [[Step1>#step1]] [[''Step2''>#step2]] [[Step3>#step3]] [[Step4>#step4]] &color(#00a000){''(^o^)/ 盤面外や既に○×が置いてある場所を指定すると SammokuSample と同様の動作をするように Sammoku を修正しよう.''}; そのためには,指定した位置に○×を置ける/置けないを判定する機能を追加して,それを使うのがよいでしょう. というわけで,次の仕様のメソッドを定義してそれを使うようにすること :boolean isPlaceable(int x, int y)| 位置 (x,y) が置ける場所なら,つまり (x,y) が盤面内でかつその位置のマスが空いているなら true, さもなくば false を返す &color(#00a000){''完成した Sammoku のソースファイルを moodle の該当の場所へ提出してください.''}; ファイル名の間違いに注意 **実習課題B 締切: 次回15:00 [#kadaiB] &color(Red){''注意''};: - 課題A を提出していなければこの課題の点数は付きません - 課題A で提出された Sammoku を使用しますので,「課題Aの提出後に Sammoku を変更」して 「それに基づいて課題Bのプログラムを作成」すると,提出されたプログラムをこちらで正しく評価できなくなる可能性があります.課題Aの提出後は Sammoku を修正しないようにしましょう. ***Step3 -- SammokuGUI を作ろう [#step3] [[Step0>#step0]] [[Step1>#step1]] [[Step2>#step2]] [[''Step3''>#step3]] [[Step4>#step4]] &color(#00a000){''(^o^)/SammokuGUISample と同様のふるまいをするプログラム(SammokuGUI)を作ろう.''}; - Sammokuクラスを利用する(Sammokuのインスタンスを生成してメソッドを呼び出す)プログラムにすること - Button の2次元配列を作るとよい -- この2次元配列の要素について二重 for ループしながら,各要素のイベント処理を設定する,というのが一番簡単そうです.その場合,こんな感じのエラーに遭遇することがあります. #pre{{ エラー: ラムダ式から参照されるローカル変数は、finalまたは事実上のfinalである必要があります if(s.isPlaceable(ix, iy)){ ^ }} この問題に対処するには,二重 for ループの内側で setOnAction 呼ぶ前に, #pre{{ final int fx = ix, fy = jy; }} と書いておく → setOnAction の引数では ix, iy のかわりに fx, fy を使う,というのがよいでしょう.どうしてこういうエラーが出るのかの説明は省略します.興味のある人は takataka に尋ねてね. - ボタンをサンプルのように配置するには,GridPane を使えばよい.%%gridLinesVisible プロパティを true にすればサンプルのように枠線が描かれる.%% (&color(red){ほげ};) - ボタンをサンプルのように配置するには,GridPane を使えばよい.%%gridLinesVisible プロパティを true にすればサンプルのように枠線が描かれる.%% (&color(red){サンプルは枠線描いてないバージョンでした.枠線は描いても描かなくてもどちらでも構いません};) - CSS ファイル sammokuGUI.css で全てのボタンに対するスタイル指定がある(.button のところ)ので,start メソッド内で次のようにするだけでボタンのスタイルが整う. #pre{{ Scene scene = new Scene(root); scene.getStylesheets().add("sammokuGUI.css"); }} &color(#00a000){''完成した SammokuGUI のソースファイルを moodle の該当の場所へ提出してください.''}; ファイル名の間違いに注意 **宿題 [#hw] &color(#00a000){''実習課題以外の宿題はありません''}; **実習課題S(omake) 締切: 次回実習時間終了時 [#kadaiS] //&color(#ff0000){''工事中''}; *** Step4 -- ほげほげしよう [#step4] [[Step0>#step0]] [[Step1>#step1]] [[Step2>#step2]] [[Step3>#step3]] [[''Step4''>#step4]] &color(#00a000){''これはおまけ課題です.やらなくても減点になりません.やったら加点かも''}; - 次のことを実現しよう.これら以外にも工夫したければお好きにどうぞ.何を実現したかわかりやすくコメントつけてくれると助かります -- ソースをちょっといじるだけで盤面のサイズを(20x20などに)変えられるようにする -- 勝ち/負け/引き分けを判定する機能を追加する.Sammokuクラスを修正するか拡張しよう. -- 人対コンピュータで対戦できるようにする.コンピュータは乱数で打たせるのでよい. - 提出するソースファイル名/クラス名は任意です.ファイルは5つまで提出できるようにしてありますので,必要なものを提出してください.