#author("2019-10-29T13:41:41+09:00","default:takataka","takataka") #author("2019-10-29T13:42:01+09:00","default:takataka","takataka") *応用プログラミング及び実習 2018年度 第6回 [#ex06] //&color(#ff0000){工事中}; #contents ** 今日の notebook [#c5575be4] は [[AProg/2018]] からたどってください. Notebook の扱いが分からないというひとはこちら: [[AProg/2018/ex01/Step1#step1_3]] **課題A (self) 期限: 授業当日11:45 [#kadaiA] 今日の notebook を開いてそこに記されたことを読んで&実行して学習しなさい. 完了したらチェックを受けなさい(notebookを開いたままにしておくこと). **課題B (self) 期限: 当日の授業終了まで [#kadaiB] &color(red){''当日中に完了できなかったひとが多い/大事な内容を含む,という理由から,この課題の提出期限を次週第7回10時までに延長します'' }; //[[06exB.ipynb>AProg:06exB.ipynb]] ([[06exB.html>AProg:06exB.html]]) //上記リンク先の Jupyter Notebook を開いてその指示にしたがいなさい. //完了したらチェックを受けなさい. 次のことを全てやりなさい. ***課題B-1 [#zf69916a] 授業の際に作ったファイル 06constants.txt を読み込むプログラムを作ろう. 以下を修正しましょう. #pre{{ ##### AProg2018 第6回課題B-1 # 空のディクショナリを作る constants = {} # ファイルを読み込んで,1列目をキー,2列目を値(浮動小数点数値)として辞書に登録 # キーの一覧を使ってループし,ディクショナリの内容を表示.p.194参照 for k in constants.keys(): print(k) # キー値 k に対応した値を小数点以下2桁まで表示させるように修正しよう }} ***課題B-2 [#id5fa52c] + [[第3回課題C>AProg/2018/ex03#kadaiC]] のプログラム 03exC.py をコピーして 06exB2.py を作りなさい. + [[readscore.py>AProg:readscore.py]] をいつもの場所に保存して,エディタで内容を確認しなさい. + 06exB2.py を,readscore.py を利用するように改造しよう.次のようにしましょう. ++ 06exB2.py から関数 readScore() の定義を削除 ++ 06exB2.py で readscore.py に定義された方の関数 readScore() を使うようにする.ヒント: モジュールを import して「モジュール名」.「関数名」(なんたら) + 動作確認しましょう. **課題C (TA) 期限: 次回2講時開始直後 [#kadaiC] //&color(#ff0000){工事中}; ''顔検出しよう'' + [[facedetect.py>AProg:facedetect.py]] と [[06exC.py>AProg:06exC.py]] をいつもの場所に保存して,エディタで内容を確認しなさい. + 正面を向いた人の顔が写った画像を適当に探して,いつもの場所に保存しなさい.なるべく複数人が写っているものがよい. + 06exC.py の「画像を読み込む」の部分にそのファイル名を指定して,実行しなさい. -- facedetect.py には,龍大計算機室環境じゃないと正しく動作しない部分があります.他の環境でやりたいひとは takataka に相談してください. -- コンピュータが扱う画像の世界では,画像の左上が原点で,右に向かってx軸,下に向かってy軸をとった座標系が使われることが多いです.このプログラムで得られる座標もそうなってます. -- あまり大きい顔/小さい顔は検出できないかもしれません + 06exC.py を修正して,検出した顔に四角い枠をつけた画像を作ってくれるようにしよう. -- 枠線を描くには,OpenCV の cv2.rectangle() 関数を使うとよいです.color や thickness はお好みで. http://lang.sist.chukyo-u.ac.jp/classes/OpenCV/py_tutorials/py_gui/py_drawing_functions/py_drawing_functions.html -- 上記のページの説明だけではわかりにくければ,ぐぐりましょう. **課題D (TA) 期限: 次回12時 [#kadaiD] //&color(#ff0000){工事中}; ''県庁所在地クイズを作ろう'' + [[06kencho.txt>AProg:06kencho.txt]] をいつもの場所に保存して,less コマンドで内容を確認しなさい. + このファイルを読み込んで,次のように「県庁所在地クイズ」ができるプログラムを作ろう(以下の実行例の「★」以降はコメント).プログラムのファイル名は 06exD.py としてください. #pre{{ 何問やる? 50 ★ 「50」はキーボードからの入力.1以上47以下の整数でなければ入力やり直しになる 何問やる? 0 何問やる? 5 1問目: 和歌山県の県庁所在地は? 和歌山市 ★ 「和歌山市」と入力して Enter,以下同様 正解! 2問目: 熊本県の県庁所在地は? くまもん ちゃうで 3問目: 長野県の県庁所在地は? 長野市 正解! 4問目: 秋田県の県庁所在地は? 秋田犬 ちゃうで 5問目: 岡山県の県庁所在地は? 岡山市 正解! 5問中3問正解やったで }} + ディクショナリ使うのが素直な方針でしょう.いきなり全体を考えるのは大変なので,次の段階分けを参考にしたらよい. - Step1: ファイルを読み込んでディクショナリに登録するだけのプログラム.ipython で動作確認したらよいだろう.改行文字の除去を忘れずに. - Step2: ディクショナリのキーを格納したリストを作る. keyList = list(hoge.keys()) # この例では hoge がディクショナリ - Step3: とりあえず札幌からの順番のままで最初の5道県でクイズができる(正解不正解を判定して出力する)ものにする - Step4: キーのリストをランダムにならべかえる(randomモジュール使いましょう) - Step5: 細かいところをちゃんとする.問題数決められるように,最後に正解数出すように,etc. **課題E (TA) 期限: 次々回2講時12時 [#kadaiE] //&color(#ff0000){工事中}; ''三目並べ = oxゲーム = Tic-Tac-Toe を作ろう'' この課題はいつもより少し配点大きくします. ***Step1 [#u85846b7] + 次の内容のプログラム 06sammoku.py を作って実行しなさい. #pre{{ ### AProg2018-ex06 三目並べ = oxゲーム = Tic-Tac-Toe # 盤面の状態を表すディクショナリ mark = {0:" ", 1:"o", -1:"x"} ### リストのリストで表された盤面情報を o,x で表示する # def printBoard(board): print(board) # 実行例のように縦横に o や x が並ぶようにしよう # printBoard の動作確認 board = [[0, 1, -1], [1, 0, -1], [0, 0, 0]] printBoard(board) }} + printBoard() の出力が以下のようになるよう修正しなさい.~ &ref(http://www-tlab.math.ryukoku.ac.jp/~takataka/course/AProg/board.png,nolink); + このプログラムに,次のような仕様の関数 isValid() の定義を追加しなさい.ipython 上で実行して動作確認 & デバグしよう. -- 関数名と引数は以下の通り .board は盤面を表すリストのリスト,(x, y) が盤面位置((横方向,縦方向) isValid(board, x, y) -- 位置 (x, y) が有効(盤面の範囲内かつまだoxがついてない)なら True, さもなくば False ***Step2 [#g4c90e7b] +Step1 の成果と以下を組み合わせなさい.さらに,このままでは入力しても ox がつかないままなので,ちゃんと ox がつくように修正しなさい. #pre{{ ### AProg2018-ex06 三目並べ = oxゲーム = Tic-Tac-Toe # 盤面の状態を表すディクショナリ mark = {0:" ", 1:"o", -1:"x"} ### リストのリストで表された盤面情報を o,x で表示する # def printBoard(board): #中身は自分で.mark 使うこと ### 位置 (x, y) が有効(盤面の範囲内かつまだoxがついてない)なら True, さもなくば False # def isValid(board, x, y): #中身は自分で ### 入力を受け付ける.有効な位置でなければ再入力してもらう # def procUserInput(board): while True: msg = "どこに置く? 「0 1」のようにスペース入れて縦横の数を入力してね: " s = input(msg).split() if len(s) == 2: y, x = int(s[0]), int(s[1]) if isValid(board, x, y): return y, x else: print("そこには置けへんで.", end="") print("入力し直して") # 3 x 3 の盤面 board = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] # o の番なら 1, x の番なら -1 turn = 1 while True: printBoard(board) if turn == 1: print(" o の番ほげ.", end="") else: print(" x の番ほげ.", end="") y, x = procUserInput(board) turn *= -1 }} + 以下の関数 checkGameOver() を使って勝敗判定できるようにしなさい.勝ち負け引き分けが決まったら,盤面を表示したのち「oの勝ち」,「xの勝ち」,「引き分け」と表示してプログラムが終了するようにしよう. #pre{{ ### ゲーム終了かどうか判定.戻り値は次の通り.この関数は修正不要 # # -2: 引き分けでゲーム終了, -1: xの勝利 # 0: まだゲーム終了でない 1: oの勝利 # def checkGameOver(board): boardSize = len(board) # 横一行 mark がそろっていたら mark を返す for i in range(boardSize): mark = board[i][0] if mark == 0: continue j = 1 while j < boardSize and board[i][j] == mark: j += 1 if j == boardSize: return mark # 縦一列 mark がそろっていたら mark を返す for j in range(boardSize): mark = board[0][j] if mark == 0: continue i = 1 while i < boardSize and board[i][j] == mark: i += 1 if i == boardSize: return mark # 右下がりに mark がそろっていたら mark を返す mark = board[0][0] if mark != 0: i = 1 while i < boardSize and board[i][i] == mark: i += 1 if i == boardSize: return mark # 右上がりに mark がそろっていたら mark を返す mark = board[boardSize-1][0] if mark != 0: i = 1 while i < boardSize and board[boardSize-1-i][i] == mark: i += 1 if i == boardSize: return mark # 盤面が埋まってたら引き分け for i in range(boardSize): for j in range(boardSize): if board[i][j] == 0: return 0 return -2 }} ***Step3 [#g4c90e7b] コンピュータと対戦できるように改造しよう.先手番 o は常に人間側(あなた)で後手番 x は乱数使ってランダムに手を打たせるようにしたらよい. ***Step4 [#d28f0147] ここまでのプログラムをうまく作っていたら,盤面を表すリストのリストを 3x3 ではなく 4x4, 5x5 等の適当なサイズにしても動作するようになっているはずです.動作を確認して,そうなっていなければ修正しなさい. **課題S (omake) [#kadaiS] //&color(#ff0000){工事中}; 課題C のプログラムをもとにして,次のことをやりましょう. + 顔領域内の画素値を反転させた画像を作る + 顔検出の結果を利用して何か他におもしろいことをやるプログラムを作る