Comments
Description
Transcript
心理実験のための C#プログラム実践講座(上)
心理実験のための C#プログラム実践講座 (上) 鈴 木 淳 也 2015 年 3 月 本文中に記載されている会社名、製品名等は、一般に関係各社または団体の商標また は登録商標です。 ii まえがき 2010 年と 2011 年の二度にわたり、富山大学の大学院生命融合科学教育部の津田先 生に同行して、アメリカの福祉機器関連の学会(CSUN カンファレンス)に行きまし た。その折々で、津田先生から、私のプログラミング・ノウハウについて質問を受けま した。その話の中で、私のプログラミングのアクティビティを感じていただけたことに 加え、 「そのノウハウの継承の大切さ」をご示唆いただきました。津田先生は、 「鈴木さ んのノウハウは、どこかにまとまっているの?」と聞かれました。「いいえ、私の頭の 中に全部あります」と答えると、「それは、1 冊にまとめて、多くの人に活用してもら うといい」と言われました。そのような経緯で、この教科書の出版への一歩を踏み出し ました。 とはいえ、私は、プログラミングの実務経験は豊富にあるものの、教科書・教育とな ると素人です!そんな折、富山大学の大学院生命融合科学教育部に入学した守井清吾君 との出会いがありました。守井君は数学が専門でしたが、工学、とりわけ、プログラミ ングの経験はありませんでした。そこで、まず、守井君に、私のプログラミング方法の ノウハウを伝えることから始め、その中で得られた説明方法を、教科書に展開すること を考えました。 この試みは、とても良い結果を生みました。守井君が数学で鍛えた思考能力に加え、 プログラミングの素養があったことが功を奏して、守井君は、私のプログラミング・ノ ウハウを貪欲に吸収してくれました。この経験のおかげで、「私のプログラミング・ノ ウハウは、一般的に教育に寄与する」という実感を得ることができました。 このよう に、実務経験と、小さくとも確かな手ごたえのある教育実践により、この教科書は誕生 しました。この教科書を生かして、「実験に役立つプログラミング・ノウハウ」を身に 着け、思いのままに研究を進めていただけることを祈念しています。 本書の出版の機会を与えていただいた富山大学の大学院生命融合科学教育部の諸先 生方、事務のご担当者に深く感謝いたします。また、本書の内容並びにデザインについ て、詳細なアドバイスとご確認をいただきました木原先生、梅崎先生にお礼申し上げ ます。 iii 目次 学習の前に iv このテキストについて iv 準備 2 1 開発環境の準備 2 2 開発環境の探訪 7 実験 I タッピング 17 第1章 ボタンを押した回数をカウント 参考文献 第2章 実験 II 第3章 29 指定時間内の打鍵回数をカウント 30 文字の判断時間の測定 44 ラベルへの文字表示 参考文献 第4章 19 46 54 単語をランダムに提示 55 0.0 i 第5章 反応時間の記録 64 第6章 音声による単語刺激の提示 73 索引 81 学習の前に iv このテキストについて ここでは、このテキストの特徴について、以下のことを述べる。 1. 2. 3. 4. 対象読者 このテキストの特徴 学習の進め方 各実験の構成 対象読者 まず、ここでは、このテキストの対象読者について述べる。 対象読者 1. プログラミングに興味はあるが、どのように勉強すればよいか困ってい る人 2. 文法の知識は増えても、やりたいことが実現できない人 3. パソコンを使って基礎的な心理実験をしたい人 4. 視覚に障碍があり、画面読み上げソフトを使ってプログラミングをした い人 5. 視覚障碍者にも使いやすいソフトを作っていきたい人 プログラミングに興味はあるが、どのように勉強すればよいか困っている人: コンピュータ・プログラミングというものがあるのは知っているが、どのように勉 強を始めたらよいかわからずにいる人も多いと思う。そんな読者に質問する。「コン ピュータ・プログラミングとは、何を実現するためのものだろうか?」しばらく考えて v みてほしい。ワープロ、表計算ソフト、ゲームなどなど、いろいろなプログラムが思い 浮かぶであろう。実は、「コンピュータはプログラミングをすれば、何でもできるので ある。 」と言われると、ますます困ってしまうであろう。言い換えると、 「やりたいこと がはっきりしていれば、それをコンピュータにさせることができる」のである。つま り、次のようなステップを踏めば、何でもできるのである。 1. 実現したいことをはっきりさせる 2. 実現したいことを、小さなタスクに分解する 3. その小さなタスクを計算問題に置き換える そうなのです、コンピュータ・プログラミングは、まさに、数学の勉強で扱ってきた 「応用問題を解くこと」に他ならないのである。このテキストでは、この「応用問題を 解くこと」を一歩一歩マスターしていく。 文法の知識は増えても、やりたいことが実現できない人: このような人は多いだろう。書店にたくさん並んでいるプログラミングの本は読ん だが、 「文法の知識は身についたが、やりたいことが実現できない」 、と思って、挫折し た人も多いだろう。このテキストでは、下記のステップを踏んで学習を進めていく。 1. 実現したいことをはっきりさせる 2. 実現したいことを、小さなタスクに分解する 3. その小さなタスクを計算問題に置き換える このステップなくして、「実現したいこと」と「プログラミングの文法の知識」は結 び付けられないのである。ぜひ、新たな気持ちで、安心して取り組んでいただきたい。 パソコンを使って基礎的な心理実験をしたい人: 心理学部を希望して入った人の中には、ユング*1 やフロイト*2 が提唱した「心理分 析」に興味を持っている人も多いだろう。一方で、ヴント*3 の提唱した「実験心理」と *1 *2 *3 ユング Carl Gustav Jung 1875-1961. スイスの精神医学者。 分析心理学の創始者。 人間の心の世界には個人的無意識と普遍的無意識という2つの層が存在し、後者は広く人 類に共通であり、そこに元型が存在すると仮定した。 フロイト Sigmund Freud 1856-1939. オーストリアの神経病理学者、精神分析の創 始者。1881 年ウィーン大学医学部を卒業。ヒステリー患者の根本的治療を模索する開業生 活の中で催眠の限界を感じ、リラックスさせた中で自由に心の葛藤を語ってもらう「自由連 想法」からなる「精神分析療法」を開発する。 ヴィルヘルム・ヴント Wilhelm Wundt 1832-1920. 心理学を、哲学から独立した学 問へと導いた、近代心理学の祖の一人。世界で最初の心理学実験室を開設した。心理学で このテキストについて vi いう分野もあり、「心理分析」との違いに戸惑う人も多いだろう。この「実験心理」と いう分野も、人間の心理を探求する、たいへん興味深い分野であるので、ぜひ、足を踏 み入れていただきたいと思う。とはいえ、一番の問題になるのは、「実験計画は立てて みたものの、どうやって実験したらよいか」困ることである。「実験のとき被験者に提 示する刺激はどのように作ったらよいか」、 「被験者の応答をどうやって取得するか」、 「取得したデータをどうやって分析するか」など、さまざまな課題がある。実は、この 問題も、プログラミングは解決してくれるのである。ぜひ、たくさんの実験のアイディ アを持って、このテキストを読み進めてほしい。 視覚に障碍があり、画面読み上げソフトを使ってプログラミングをしたい人: 近年、画面が見えなくても、画面読み上げソフトの進歩のおかげで、文字の読み書 きは、かなり自由にできるようになった。しかし、Windows が GUI(グラフィカル・ ユーザ・インターフェース)であるため、マウスを使わないと使えないソフトも多いの も事実である。また、画面に文字は出ていても、画面読み上げソフトでまったく読まな いことも少なくない。世の中のソフトが、画面読み上げソフトでもしっかりと読み上げ て、キーボードですべての操作ができることは理想である。しかし、それはなかなか難 しいことは想像できるだろう。そこで、考えるのが、「自分の使いやすいソフトを自分 で作ってしまおう」ということである。筆者も、視覚障碍者(全盲)である。筆者自 身、プログラミングをマスターしたことで、仕事や研究の可能性を大きく広げてきた。 ぜひ、この可能性を多くの視覚障碍者にも持っていただきたいと思う。 視覚障碍者にも使いやすいソフトを作っていきたい人: 上にも書いたとおり、世の中のソフトが、画面読み上げソフトでもしっかりと読み上 げて、キーボードで、すべての操作ができることは理想である。これを実現するのは、 技術的には難しいことではない。「どのような対策をすればよいか」を、プログラマが 知らないだけなのである。そこで、このテキストでは、視覚障碍者にも使いやすいソフ トを作るには「どのような対策をすればよいか」を取り上げていく。「そんな対策だけ でいいんだ」と愕然とするであろう。その「小さな対策」が多くのユーザを取り込める のである。ぜひ、ユーザ層を視覚障碍者にも広げたいと考えている読者は、このテキス トで「小さな対策」を身に付けていただきたい。 は、それまでのような間接的経験(物理現象)ではなく、直接的経験、つまり、意識を主体 とした経験こそが心理学の扱うべき分野だとした。 vii このテキストの特徴 次に、このテキストの特徴について述べる。 1. 2. 3. 4. 5. プログラムを作る意義を明確にし、高い学習意欲を維持できる サンプルプログラムで動作確認しながら、プログラミング要素を学んでいける 各章末の練習問題を通して、学習した内容を自分のものにしていける 視覚障碍者が、画面読み上げソフトを使って開発する手順をマスターできる 視覚障碍者にも使いやすいソフトの UI(ユーザ・インターフェース)の実装方 法を身に付けられる このテキストの大きな特徴は上記の通りである。 プログラムを作る意義を明確にし、高い学習意欲を維持できる: 「対象読者」の項で書いたとおり、 「実現したいことがはっきりしていれば、それをコ ンピュータにさせることができる」のである。そのための道具が「プログラム」であ る。言うまでも無く、道具は目的を解決するために使う。この「目的」なくして、プロ グラミング技術の上達は無いのである。一方、これとは逆のことになるが、「道具が目 的、可能性を広げてくれる」ということもある。この「目的 → 道具(スキルアップ) → 目的 → ・・・」という循環が、プログラミングスキルをどんどん高めていく。そし て、この循環こそが、プログラミングの学習の原動力になるのである。このテキストで は、この「目的 → 道具(スキルアップ)→ 目的 → ・・・」という循環を、例題を扱 いながら繰り返していく。このため、実践的な道具としてのプログラミング能力を身に 付けられるのである。 サンプルプログラムで動作確認しながら、プログラミング要素を学んでい ける: ここまで、「目的」が大切であることを述べてきた。では、この「目的」と「プログ ラミング」をどのようにして結びつけていこう。これは、「目的」を実現したサンプル を見ることが近道である。数学の勉強でも、問題文だけを読んでいても、また公式だけ を覚えても理解は進まない。例題と解法をよく読んで、「問題文 → 解答」への道筋を マスターすることが簡便である。これと同じように、プログラミングの学習において も、「目的だけ」が明確になっていても、またプログラミングの文法の知識だけが豊富 になってもだめである。「目的 → プログラムの書き方」の道筋をマスターすることが 簡便なのである。このテキストでは、まず「目的」を定めた上で、次に、その「目的」 このテキストについて viii を実現しているシンプルなサンプル・プログラムを紹介する。これにより、「目的」を 読者がしっかり把握した上で、その後の学習を進められる。学習においては、 1. 「目的」をどのような小目的に分解すれば、プログラムしていけるか 2. その小目的を実現するには、どのようなプログラムを書けばよいか について取り上げる。これにより、プログラミングという道具を自分のものにして、 使いこなせるようになるのである。 各章末の練習問題を通して、学習した内容を自分のものにしていける: 数学の勉強でも、例題をマスターしただけでは自力で解けるようにはならない。自分 で別の問題を解いてこそ、実力を付けられる。このテキストでは、各章でマスターした ことを用いて、自分でプログラミングの練習をする。このステップを踏むことで、学習 したことを確かなものにしていける。 視覚障碍者が画面読み上げソフトを使って開発する手順をマスターできる: 筆者自身、1990 年ごろから C 言語でのプログラミングをしてきた。プログラミング することで、さまざまな問題を解決できる面白さに引かれ、朝が来るまでパソコンに 向かっていたこともしばしばである。しかし、1990 年代後半になると、プログラム開 発環境は Windows ベースになっていった。また、開発ソフトも、Windows 上で動く ものが主流になっていった。それまで、筆者が取り組んできた「コマンドラインでの ソフト」ではできないことが、Windows ベースにすることで、どんどんできるように なっていった。その代表的なものが、画像や音声などのマルチメディアの処理である。 画像や音声を適切に処理して出力を得るだけであれば、コマンドライン・ベースでの ソフトでもある程度実現できる。しかし、録音(録画)や再生をしながら、リアルタ イムに処理などをしたくなると、コマンドライン・ベースでのソフトでは無理である。 Windows ベースでのソフトを作る必要があるのである。そこで、筆者は、国内外の視 覚障碍関連のプログラミング開発環境を調べてみた。しかし、いずれもコマンドライ ン・ベースでの手法ばかりであった。加えて、テキスト(文字)処理に関するプログラ ミングの学習が主流で、マルチメディアを扱っている例は無かった。 そこで、筆者は思い切って、Microsoft Visual Studio(以下 VS と記す)を使ってみ ることにした。幸い、身近に VS を使っている人(晴眼者)がたくさんいたので、使い 方を一から尋ねた。しかし、彼らは、VS を操作するときマウスを使っており、私(視 覚障碍者)が操作できるキーボードでの操作方法は知らなかった。そこで、身近にいる 人に根気強く付き合っていただいて、VS 上で、キーボードを使って開発する方法を紐 解いていった。実は、幸いなことに、VS には、マウスと同等の操作をキーボードでも ix できる機能がほぼ備わっていた。これらのキーボード操作をマスターしていった。こ のテキストでは、このようにして私が整理、獲得した方法を用いて開発を行っていく。 このキーボード操作での開発は、視覚障碍者のみならず、晴眼者にとっても簡便なもの であることを実感していただけるだろう。 実は、視覚障碍者が、VS を使ってプログラム開発をする上で、もう一つ大きな問題 があった。VS で開発をする際、 1. まず、ウィンドウにボタンやテキストボックスなどを並べて画面をデザインし、 2. その上で、画面に配置したものが変化したときに「動く関数」(イベント関数と いう)を作り 3. 初めて、テキスト・エディタでプログラムを書いていけるようになる というステップを踏む必要がある。 2. 以降は、キーボード操作である程度はできることは確認していた。しかし、1. が できないと 2. 以降のステップに進めないのである。出鼻をくじかれてしまったのであ る。そこで、筆者は、1. を実現するためのソフトウェアを開発した。 実は、その「画面をデザインするためのソフトウェア」を開発してしばらくしてか ら、画面デザインをしなくても、キーボードによる入力と音声による出力を使うこと で、かなりのプログラムを実装できることがわかった。筆者は、自分だけが使うソフト ウェアであれば、最近は、画面デザインをしないで、キーボードでの入力と音声での出 力を行うソフトウェアを作っている。この「キーボードでの入力」と「音声での出力」 の方法についても、多くの例を挙げて紹介していく。 視覚障碍者にも使いやすいソフトのユーザ・インターフェースを身に付けら れる: 実は、前述した「1. キーボードでの入力」、 「2. 音声での出力」こそが、視覚障碍者 にも使いやすいソフトのユーザ・インターフェースなのである。これに加えて、「3. 画 面読み上げソフトに、ボタンの名称などを適切に読み上げさせるためのノウハウ」があ る。いうなれば、この三つぐらいの配慮のみで、視覚障碍者にもかなり使いやすいソフ トになるのである。このテキストでは、これらの実装方法についても取り上げていく。 学習の進め方 ここでは、このテキストの学習の進め方について述べる。 「対象読者」の項で書いたとおり、プログラミングの手順は、 1. 実現したいことをはっきりさせる このテキストについて x 2. 実現したいことを、小さなタスクに分解する 3. その小さなタスクを計算問題に置き換える という流れを踏んでいく。プログラムを学習するときも同様で、このステップを踏ん でいくことで、「実現したいこと」と「文法の知識」を結び付けられる。このテキスト では、常に、このステップを踏んで学習していく。 基本的には、「実験1」から学習を進めていくことをお勧めする。なお、学習が進ん できた段階では、各実験の冒頭にある「このステップでマスターすること」を見て、必 要なところを学習していくとよい。 各実験の構成 このテキストでは、基本的な心理実験を扱いながら、プログラミングをマスターして いく。各実験を扱うにあたり、まず、その実験の内容を十分理解しておくことが必要で ある。「実験の目的」、 「被験者に提示する刺激」 、 「取得するデータ」などを整理する。 その上で、各ステップの学習に入る。各ステップは、以下の構成になっている。 各ステップの構成 1. このステップでマスターすること 2. サンプルプログラムの動作確認 3. プログラムの設計・実装 (a)設計 (b)プロジェクトの作成 (c)画面デザイン (d)コントロールの各種設定 (e)イベント関数の生成 (f)動作の実装 (g)動作確認 4. 練習問題 このステップでマスターすること 各実験のためのプログラムは、いくつかのステップを踏んで作り上げていく。まず、 各ステップの学習をはじめる前に「このステップでマスターすること」を整理しておく ことにする。こうすることで、目的が明確になるのに加えて、後に、このテキストを参 xi 照するときに、「目的」から必要な内容を探せるようになる。 サンプルプログラムの動作確認 ここでは、このステップで扱う処理の流れを実装したサンプル・プログラムを実際に 動かして、動作を確認する。サンプル・プログラムは、本書 Web サイトに掲載してい るので、必ず動作確認した上で、以後の学習に進んでほしい。 プログラムの設計・実装 設計と実装は、以下の要素からなる。 1. 2. 3. 4. 5. 6. 7. 設計 プロジェクトの作成 画面デザイン コントロールの各種設定 イベント関数の生成 動作の実装 動作確認 設計 次に、このステップで実現したいプログラムの処理の流れを整理することにする。た とえば、次のようなものである。 1. ユーザが○○をしたら 2. ソフトは△△を計算して表示する 3. その表示を見たユーザが□□をする 実現したいことをできるだけ細かく記述することは、プログラミングの第一歩であ る。この第一歩を、具体例を挙げて説明していく。 ここまでで、やりたいことの整理およびそれを実装した結果の動作確認ができたこと になる。次に、いよいよ設計段階である。「まだ、プログラムを書かないの?」と思う 気持ちを抑えて、このステップに取り組んでいただきたい。設計段階は、プログラミン グの全作業の 90% を占める、と言っても過言ではない。この段階をおろそかにしてお くと、後に、プログラムの書き直しを何度もしなくてはいけなくなったり、意図しない バグ(プログラムの不具合)に悩まされることになる。では、「設計」とはどうやって やるのだろうか? このテキストについて xii 1. まず、「サンプルプログラムの動作確認」で確認したとおりの画面を作ってい く。画面上に何があるか確認していただきたい。 2. 次に、「やりたいことの整理」を行う。画面に配置したもの(ボタンなど)を押 したとき何をさせるか。また、結果を画面のどこ(または音声)に出力するかを 整理する。 このように、ユーザの操作(イベント)と、その操作(イベント)が起きたときの処 理を決めていく。ここで、肝心なことは、プログラム全体の流れは考えなくてよいこと である。個々のイベントが起きたときのことをそれぞれ考えればよいのである。今は、 このありがたさがよくわからないかも知れない。今後、学習が進むにつれて、プログラ ムの規模が大きくなればなるほど、この「部分的な設計」のありがたさがわかってくる。 プロジェクトの作成 このテキストでは、Microsoft Visual Studio という統合開発環境を使う。まずは、 開発環境の探訪を熟読し、Visual Studio (以下 VS と記す)の操作に慣れてほしい。 画面デザイン まず、画面デザインをしていく。 「画面デザイン」とは、プログラムとユーザが対話するための「入力部分」と「出力 部分」を準備することである。VS には、ボタン、スライダー、チェックボックスなど 多数の入力のためのアイテム(コントロールという)が揃っている。また、ラベルやテ キストボックスなどの出力のためのコントロールも揃っている。これらのコントロー ルを画面に並べていく。 コントロールの各種設定 次に、画面に並べた各種入力/出力のためのコントロールの設定をしていく。後で詳 述するが、各コントロールには、さまざまな設定項目(プロパティ)がある。たとえば、 テキスト表示部分であれば、背景の色、表示文字の色、表示文字の大きさなどがある。 また、このコントロールを、プログラムの画面のどこにどのぐらいの大きさで表示する かを決める設定項目がある。これらの項目のことをプロパティという。プロパティは、 VS のプロパティ・ウィンドウでも設定できるし、プログラム・コードの中でも設定で きる。 xiii イベント関数の生成 また、ここで、もう一つ大切なことをする。それは、ユーザが操作したことをつかさ どるための「イベント関数」というものを作ることである。たとえば、ボタンが押され たとき呼び出される関数などである。われわれがプログラムを書くのは、基本的にこの 「イベント関数」の中に書くのである。 動作の実装 いよいよ、プログラミングである。上に書いた「イベント関数」の中に、その関数が 呼ばれたときに実行したいことを書いていく。もちろん、文章ではなく、いくつかの式 のようなものを書いていく。 動作確認 そして、実行してみて、実際に動作を確認する。以後、「イベント関数の中にプログ ラムを書く」→「実行」を繰り返して、プログラムを作り上げていく。 練習問題 ここまでで、各課題で扱う内容を体験的に身に付けられる。しかし、プログラミン グ・ノウハウは、自分で考えてこそ身についていく。サンプルと同じものを作っただけ では、自分自身の力にはならない。そこで、サンプルを少し改良する練習問題を解いて もらう。これにより、既習の内容を自分のものにしてもらう。 準備 2 1 開発環境の準備 Visual Studio のインストール このテキストでは、キーボードによる操作を主にして説明を行うため、Windows 7 に、スクリーンリーダー PC-talker(高知システム開発製)を導入した環境を前提 としている。*1 開発環境として、Microsoft Visual Studio 2012 Professional Edition を使用するものとして説明を行っているが、他のバージョンやエディション を利用することも可能である。*2 ここでは、Windows アプリケーションを作る統合開発環境 Visual Studio のインス トール方法を説明する。 では、早速、プログラム開発環境をインストールしよう。 1. まず、インストール用 DVD を DVD ドライブに入れる。処理方法の選択項目 が出るので、 上下方向のカーソルキーで [vs professional.exe の実行] を選択 して、Enter キーを押す。もし、処理方法の選択項目が出ない場合は、DVD ド ライブをエクスプローラで参照して、DVD の中にある vs professional.exe を実行する。 2. 次の画面で、[ライセンス条項に同意する] という項目にチェックを入れる (図 *1 マウスによる操作を行う場合はスクリーンリーダーは必要ない。ただし、第6章の音声合 成による読み上げを利用したプログラムを実行するためには、別途音声合成エンジンを導 入しておく必要がある。Windows 8、8.1 を使用する場合は、標準で音声合成エンジンが 備わっているため、別途インストールする必要はない。 *2 Microsoft Visual Studio の入手方法と設定方法については、本書のサポート Web サイ トに掲載している情報を参照していただきたい。 3 1.1) 。そして、[次へ] ボタンを押す。 図 1.1 ライセンス条項に同意する 3. 次の画面で、[インストール] ボタンを押す。なお、この画面では何も変更する必 要はない (図 1.2) 。 1 開発環境の準備 4 図 1.2 インストール開始 4. 次に、確認を求める [ユーザーアカウント制御(UAC)による警告画面] が出る ので、[はい] を押して、次に進む。その後、30 分ほどインストール作業が行わ れる。*3 5. [起動] ボタンが出たら、[起動] ボタンを押す。すると、VS が起動する(図 1.3) 。 *3 PC-talker で、インストールの途中経過を確認したい場合は、Alt キーを押しながらCtrl キーを押して、上下方向のカーソルキーを押すことで、状況を読み上げる。「起動」と読み 上げたら、インストール終了である。 5 図 1.3 VS の起動 初回起動時は、既定の環境を設定する画面が出る(図 1.4) 。 1 開発環境の準備 6 図 1.4 既定の環境設定 6. まず、上下方向のカーソルキーで [Visual C#開発環境 ] を選択する。 Tab 7. 続いて、 [Visual Studio の開始 ] という項目まで キーを数回押して移動 して、Space キーを押す。1分ほど経過すると、VS が起動する。これで、VS のインストールが完了する。 7 2 開発環境の探訪 ここでは、Microsoft Visual Studio の基本的な使い方と画面構成を説明し、開 発環境の使い方に慣れていくことにする。 プロジェクトの作成 まず、VS を起動しよう。Windows キーを押すか画面左下のスタートボタンをク リックして、スタートメニューを表示する。[すべてのプログラム] → [Visual Studio 2012] → [Visual Studio 2012] と進むことで、VS を起動できる。*1 VS を起動すると、図 2.1 の画面が出る。 では、早速、簡単なプログラムを作りながら、VS の使い方をマスターしていくこと にする。この画面には、[新しいプロジェクト] ボタンと、[プロジェクトを開く] ボタン がある。(PC-talker では、「新しいプロジェクトの確認」と読み上げる。 ) では、[新しいプロジェクト] ボタンを押してみよう。図 2.2 の画面が出る。この設定 画面を説明していく。 まず、最初にフォーカスがあるところは、開発言語を選択するリストである。この選 択リストは、[Visual C#] のままでよい。選択リストが [Visual C#] となってい ない場合は、上下方向のカーソルキーで [他の言語] という項目を捜し、右向きのカーソ ルキーで項目の一覧を展開してほしい。*2 *1 *2 Windows 8.1 でも、 PC-talker をインストールしている場合は、画面左下のスタートボタ ンをクリックするかWindows キーを押すことにより、スタートメニューが利用できる。 選択リストが [Visual C#] とならない場合は、[ツール] メニューの [設定のインポート とエクスポート] を選択し、環境設定をいったんリセットしたのち、設定コレクションとし 2 開発環境の探訪 8 図 2.1 VS 起動時の画面 図 2.2 新しいプロジェクトの設定画面 1回 Tab キーを押すと、.NET Framework のバージョンを選択する部分に移動 する。Framework (フレームワーク)とは、C# で開発したプログラムを動かすた めの土台のようなものである。このフレームワークという土台の上で、プログラムが実 行される。このフレームワークという大きな土台があるおかげで、Visual C# で書い たプログラムは、コンパイルしてできる実行形式ファイルのサイズがとても小さい。フ レームワークのバージョンは、3.0, 3.5, 4.0, 4.5 などがある。今は、このフレームワー クのバージョンの設定はそのままで良い。 次に、[Windows フォーム・アプリケーション] まで、Tab キーを数回押して移動す る。ここでは、上下方向のカーソルキーで、[Windows フォーム アプリケーション]、 て [Visual C#] を指定してほしい。 9 [WPF アプリケーション]、[コンソール アプリケーション]、[ASP.NET Web アプリ ケーション]、[クラス ライブラリ] などを選択できる。このテキストでは、一番上の項 *3 目の [Windows フォーム アプリケーション] を選択する。 次に、一度 Tab キーを押すと、これから作るプログラムの名前を指定できる。 [WindowsFormApplication1] と書いてあるところに、好きな名前を書き入れら れる。ただし、半角英数字にしたほうが良い。ここでは、 first_project としよう。 次に Tab キーを押すと、保存フォルダーを指定できる。その次のタブ項目に [参照] ボタンがあるので、それを押して、パソコンの中の所望のドライブとフォルダーを指定 できる。このテキストで学習するプログラムは、c:\class_sample に保存していくこ *4 とにしよう。 続いて、Tab キーを押すと、「ソリューション名」を書き入れられる。Windows- FormApplication1 と記入されている。今はこのままでよい。 次のタブ項目に [ソリューションのフォルダーの作成] という名前のチェック・ボッ クスがある。これも、今はそのままでよい。 最後に [OK] ボタンを押すと、WindowsFormApplication1 の雛形が作られ、 Form1 と書かれた画面が開く。この画面のことを「デザイナ画面」という(図 2.3) 。 図 2.3 first project のデザイナ画面 *3 マウスを使用して選択する場合は、[Windows フォーム アプリケーション] という項目を クリックする。 *4 \ は、日本語キーボードでは Yと刻印されている。 2 開発環境の探訪 10 プログラムの実行 では、ここで、 F5 キーを押してみよう。 この F5 キーは、作成中のプログラムを実行するためのボタンである。F5 キーを 押すと、画面が変わったと思う(図 2.4)。 図 2.4 first project の実行画面 これが、「初めて作る Windows プログラム」である。よく見る Windows プログラ ム同様、ウィンドウの表示サイズを変えることができる。また、[最小化]、[最大化] 、 [閉じる] のボタンもある。これが、「Windows フォーム アプリケーション」の骨格な のである。この骨格の上に、ボタンやラベル、テキストボックスなどを配置していくこ とから、プログラム開発はスタートする。 では、この実行画面を一度閉じてほしい。閉じるときは、 Form1 ウィンドウの右上 にある × をクリックするか、Alt キーを押しながら、F4 キーを押すとよい。再び、 VS のデザイナ画面に戻る。 VS の開発画面の構成 ここで、いくつかのウィンドウを紹介する。ファイルの一覧などが表示されるソ リューション エクスプローラーは、[表示] メニューから選択できる。 (図 2.5) 11 図 2.5 ソリューション エクスプローラー ソリューション エクスプローラーのすぐ下にある [プロパティ] ウィンドウには、コ ントロールなどのプロパティが表示される。(図 2.6) 図 2.6 プロパティ ウィンドウ また、左端の [ツールボックス] と書いてあるところをクリックすると、Form に配置 するボタンなどの一覧が出てくる。(図 2.7) 2 開発環境の探訪 12 図 2.7 ツールボックス これらのウィンドウの切り換えをキーボードで行う場合は、 [表示] メニュー(アクセ スキー Alt +V )から、フォーカスを移動したいウィンドウの名前を選び、Enter キーを押す。 画面デザイン では、早速、今表示されている Form1 というウィンドウにボタンを一つ配置してみ よう。 キーボードを使って、ボタンを Form1 に貼り付ける場合は、 [表示] メニューを開 き、上下方向のカーソルキーで、[ツールボックス] を選択してEnter キーを押す。す ると、Form1 に貼り付けられるコントロールなどの一覧が表示されるので、上下方向 のカーソルキーで [Button] を選択して、Enter キーを押す。大きさの指定はできな いが、Form1 の左上に button1 がとりあえず貼り付けられる。上下左右方向のカー ソルキーで、選択されているボタンの位置を移動することができる。(図 2.8) マウスを使う場合は、画面上の [ツールボックス] をクリックすると、Form1(アプ リケーションのウィンドウ)に貼り付けられるコントロールの一覧が出る。この中にあ る [Button] をクリックしたまま、Form1 の適当な位置までマウス・カーソルを移 動する。位置が決まったら、button1 の各辺にある□マークをクリックしたままマウ ス・カーソルを移動することで、button1 の大きさを変えられる。また、button1 全体の位置を移動したい場合は、button1 の中にマウスを移動して、クリックしたま まマウス・カーソルを移動することで、所望の位置に移動できる。 13 図 2.8 button1 の配置 イベント関数の生成 では、次に、この button1 をクリックしたときに、自分の名前をタイトルバーに表 示させてみよう。 まず、button1 が押されたことを、プログラムにどのように伝えよう。この役目を するのが、イベント関数というものである。button1 にもさまざまなイベント関数が ある。ここでは、もっともよく使用する「クリックしたときに呼ばれるイベント関数」 を作ってみよう。作り方は簡単である。 キーボードで操作する場合、まず、 [表示] メニューから [デザイナー] という項目を選 択して、Enter キーを押す。次に、Tab キーを押すごとに、 Form1、button1 と交 互に読み上げる。button1 と読み上げたところでEnter キーを押すと、イベント関数 が作られる。 マウスを使う場合は、Form1 にある button1 をダブルクリックするだけでよい。 では、ここまでの作業で生成されたプログラム・ソースを見てみよう。 プログラム・ソースは、コード画面に表示される。デザイナ画面からコード画面に移 るには、F7 キーを押す。逆に、コード画面からデザイナ画面に戻るには、 Shift キー を押しながらF7 キーを押す。 2 開発環境の探訪 14 リスト 2.1 first project 1 2 3 4 5 6 7 8 9 using using using using using using using using using System ; System . Collections . Generic ; System . Comp onent Model ; System . Data ; System . Drawing ; System . Linq ; System . Text ; System . Threading . Tasks ; System . Windows . Forms ; 10 11 12 13 14 15 16 17 18 namespace first_project { public partial class Form1 : Form { public Form1 () { I n i t i a l i z e C o m p o n e n t (); } 19 private void button1_Click ( object sender , EventArgs e ) { 20 21 22 } 23 } 24 25 } 動作の実装 いきなり 25 行ものプログラム・ソースを見ると、驚くであろう。しかし、驚く必要 はない。この 25 行のプログラム・ソースは、すべて VS が自動的に生成してくれたの である。われわれが注目すべきところは、20 行目から 23 行目だけなのである。この中 の 22 行目に空行がある。ここに、button1 が押されたときに実行したいことを書い ておくと、button1 が押されたときに、そのプログラム・コードが実行される。 では、ここでは、button1 が押されたら、タイトルバーに「あなたの名前」を表示 させてみよう。上のプログラムソースの 22 行目に、以下の1行を書く。 this.Text = "my name"; この 22 行目の意味を説明しよう。まず、this は、Form1 そのもの、つまり、今 作っているプログラムのウィンドウを指している。.Text は、Form1 の Text プロ パティを表す。 ここで改めて、プロパティというものを説明しておこう。あなたには名前がある。ま た、身長や体重などもある。このように、あるものの特徴や状態を表す値を「プロパ ティ」という。そして、このプロパティを表現するときは、 15 you.Name, you.Height, you.Weight などのように .(ピリオド)を用いて表現する。 話を this.Text に戻そう。これは、this つまりプログラムのウィンドウの Text プロパティを指し、つまりプログラムのウィンドウ Form1 のタイトルバーに表示さ れる文字列を意味している。 次に、 = について説明する。プログラミングでは、数学での = とは異なり、「等 しい」という意味ではない。プログラミングの世界では、 = は代入を意味する。たと えば、a = b と書くと、「b を a に代入する」ということになる。 this.Text = "my name" というのは、this.Text に"my name" という文字列を代 入するということを表している。つまり this.Text = "my name" は、 「プログラムの ウィンドウのタイトルバーに my name と表示しなさい」ということになる。 ちなみに、数学での「等しい」という意味の = を C#で表現するには、a==b のよ うに == を用いる。 動作確認 22 行目への記入ができたら、F5 キーを押して、プログラムを実行してみよう。実 行すると、button1 が現れる。これをクリックしてみよう。すると、タイトルバーに my name と表示される。これが、VS でのプログラム開発の一連の流れである。 (図 2.9) 図 2.9 first project の実行結果 16 2.0 保存と終了 作成 し たプ ロ グ ラ ム を 保 存 す る 場 合 は 、[フ ァ イ ル] メ ニ ュ ー( ア ク セ ス キー Alt +F )から [すべてを保存] を選択し、変更を反映させた後に、Visual Studio を終了する。 では、早速、さまざまな心理実験を例に、プログラムの学習を進めていこう。 実験 I タッピング 18 実験 I では、「タッピング」というものを扱う。「タッピング」というのは、指先で すばやく打鍵を継続させることで、指の運動機能を測定する方法である。脳機能障害の 検出にも用いられている。 実験の目的: 指の運動機能を測定する。 被験者に提示する刺激: 取得するデータ: なし 一定時間内に打鍵する回数。 19 第1章 ボタンを押した回数をカウント このステップでマスターすること 1. 変数の宣言と初期化 2. 変数の値を1ずつ増やす 3. 変数の値を表示 サンプルプログラムの動作確認 こ こ で は 、こ の テ キ ス ト の Web サ イ ト に あ る サ ン プ ル・プ ロ グ ラ ム を 実 際 に 動かし、その動作を確認する。今回は、sample\push_counter_001\ を参照する。 こ の フ ォ ル ダ ー の 中 に は 、い く つ か の フ ァ イ ル と フ ォ ル ダ ー が あ る 。そ の 中 の push_counter\bin\Debug\ とたどっていくと、push_counter.exe というファイ ルがある。これを実行してほしい。 実行するには、ファイルを選択し、キーボード操作の場合は、Enter キーを押す。マ ウスによる操作の場合は、ファイルのアイコンを選択した状態でダブルクリックする。 実行すると、画面にフォーム(プログラムのウィンドウ)が現れ、その中に一つだけ ボタンがある。このボタンを押してほしい。ボタンを押すたびに、タイトルバーに 1、 2、3 と、ボタンを押した回数が表示されることがわかる。(図 1.1) 第 1 章 ボタンを押した回数をカウント 20 図 1.1 サンプルプログラムの動作確認 このプログラムは、単純なものであるが、プログラミングに必要なたくさんの要素を 含んでいる。また、このプログラムを使うことで、さまざまな実験もできる。たとえ ば、指の運動機能を測る方法として、「タッピング試験」というものがある。このプロ グラムを使うことで、タッピング試験をパソコンを使って簡単に行うことができる。 では、この便利なプログラムの作成に取り掛かろう。 プログラムの設計・実装 設計 では、今、動作を確認したプログラムの動作を列挙してみよう。 1. プログラムを起動すると、ボタンを一つ表示する。 2. このボタンを押すと、押した回数を数える変数の値が1ずつ増えて、 3. その値を、随時タイトルバーに表示する。 単純ではあるが、このようになる。このように、プログラムの動作を細かく記述し たものをアルゴリズムという。では、このアルゴリズムを、もう少し詳細に書いてみ よう。 1. プログラムを起動すると、ボタンを一つ (button1) 表示する。 2. このボタンを押すと、button1 を押したときに呼ばれる関数の中身が実行さ 21 れる。 3. その関数が呼ばれるたびに、ボタンを押した回数を数える変数の値が1ずつ増 えて、 4. その値を、タイトルバーに表示する。 このようになる。 関数などと言われてもよくわからないと思う。後で説明するので安心してほしい。こ こでは、プログラムを作る前に、このように、動作を整理しておくことが大切であるこ とだけを知っておいてほしい。 プロジェクトの作成 では、早速、サンプルプログラム push_counter と同じものを作ってみよう。 まず、VS を起動してほしい。スタートページが現れるので、ここでは、 [新しいプロ ジェクト...] を選択して Enter キーを押すかマウスでクリックする。 すると、これから作成するプログラムに必要な設定項目が出てくる。これらの項目 は、Tab キーで移動できる。 まず、[Visual C#]、という項目があることを確認してほしい。[Visual C#] は 開発言語の種類を表している。このテキストでは、C# を用いるので、この項目を選択 *1 しておいてほしい。 次に、Tab キーを何回か押して、[Windows フォーム アプリケーション] という 項目があることを確認してほしい。[Windows フォーム アプリケーション] は、ア プリケーションの種類を表している。このテキストでは、Windows フォーム アプリ ケーションを作るので、この項目もそのままにしておいてほしい。 次に、[プロジェクト名] という入力ボックスがある。ここには、プログラムの用途な どがわかるような名前を記入する。ここでは、push_counter と記入しよう。 次に、保存場所を設定する項目がある。ここは、そのままでもよいが、[参照] を選択 して、明示的に C ドライブの class_sample というフォルダーを指定することにしよ う。まだ、class_sample というフォルダーが無い場合は作成してほしい。 最後に [OK] を押すと、数秒経つと、タイトルバーに Form1 と書かれたウィンド ウが現れる。これが、アプリケーションの骨格である。この骨格の上にさまざまなボタ *1 [Visual C#] という項目が見当たらない場合は、上下方向のカーソルキーで [他の言語] という項目を捜し、右向きのカーソルキーで項目の一覧を展開してほしい。VS の [ツール] メニューから [設定のインポートとエクスポート] を選び、既定の設定をリセットして指定 し直すと、[新しいプロジェクト...] のテンプレートの最初に [Visual C#] が来るように できる。 第 1 章 ボタンを押した回数をカウント 22 ンや表示部分などを配置してプログラムを作成していくのである。 画面デザイン では、早速、この Form1 にボタンを一つ配置してみよう。ボタンを貼り付けるに は、まず、ツールボックスを開く。ツールボックスを開くには、[表示] メニューの [ツー ルボックス] を選択する。すると、画面に貼り付けられるものが 150 数個も一覧され る。この中から、貼り付けたいものを選んで Enter キーを押すと、Form1 に貼り付 く。*2 マウスを使って操作する場合は、まず、画面左端にある [ツールボックス] タブをク リックする。すると、画面に貼り付けられるものが 150 数個も一覧される。この中 から、貼り付けたいものをマウスで選んで、クリックしたまま、マウス・カーソルを Form1 に移動すると、好きな位置に貼り付けられる。ここでは、[Button] を選んで 貼り付ける。 コントロールの各種設定 今、プログラムのウィンドウである Form1 にボタン button1 が貼り付けられた ものができた。 ボタンなど、画面に貼り付けたすべてのものには、プロパティというものがある。プ ロパティというのは、そのものの特徴を表すさまざまな要素のことである。人であれ ば、名前、年齢、身長、住所、電話番号などがプロパティである。ボタンには、サイズ (Size)、表示位置 (Location)、背景の色 (BackColor)、文字の色 (ForeColor) などさ まざまなプロパティがある。 ここで、button1 のプロパティを変更する方法を扱うことにする。VS では、ボタ ンを複数貼り付けると、button1、button2、button3 と連続した番号が Name プロパ ティと Text プロパティに割り振られる。しかし、このままだと、何をするためのボタ ンかわからない。そこで、各ボタンの役割がわかりやすくなるように、ボタンに表示さ れるテキストを示す Text プロパティを変更してみよう。 *2 ボタンは [Form] の左上に貼り付けられる。上下左右方向のカーソルキーを使用して、選 択されているボタンの位置を移動することができる。 23 図 1.2 ボタンのプロパティ一覧 キーボードで操作する場合、まず [表示 ] メニューの中にある [デザイナー] を選択し て、デザイナ画面に移動する。次に、 Tab キーを押して button1 を選択する。次 に、F4 キーを押すと、button1 に関するプロパティの一覧が出てくる。この中か ら、Text というプロパティを上下方向のカーソルキーで選び、Tab キーを一度押す と、button1 の Text プロパティを書き換えられる。初期値は button1 となってい *3 るので、ここでは Push me! と書き換えてみよう。 Text プロパティを変更すると、図 1.3 のように、ボタンに表示されるテキストが Push me! になる。 イベント関数の生成 次に、button1 が押されたことをつかさどるイベント関数を作ろう。マウスを使う 場合、Form1 にある button1 をダブルクリックするだけでよい。 キーボードで操作する場合、まず、 [表示] メニューから [デザイナー] という項目を選 択して、Enter キーを押す。次に、Tab キーを押すごとに、 Form1、button1 と交 互に読み上げる。button1 と読み上げたところで Enter キーを押すと、イベント関 数が作られる。 *3 マウスで操作する場合、まず button1 をクリックして選択状態にする。次に、画面右 下にある [プロパティ] という項目をクリックすると、button1 に関するプロパティの一 覧が出てくる(図 1.2)。この中から、Text というプロパティを書き換える。初期値は、 button1 となっているので、ここでは Push me! と書き換えてみよう。 第 1 章 ボタンを押した回数をカウント 24 図 1.3 デザイナ画面 動作の実装 では、ここで、サンプル・プログラムのソースを見てみよう。 サンプル・プログラムのソースは、 c:\sample\first_project\first_project\Form1.cs にある。テキストエディタなどで開いて内容を見ることができる。 リスト 1.1 push counter 001.cs 1 2 3 4 5 6 7 8 9 using using using using using using using using using System ; System . Collections . Generic ; System . Comp onent Model ; System . Data ; System . Drawing ; System . Linq ; System . Text ; System . Threading . Tasks ; System . Windows . Forms ; 10 11 12 13 14 15 16 17 namespace push_counter { public partial class Form1 : Form { public Form1 () { I n i t i a l i z e C o m p o n e n t (); 25 } 18 19 // 関 数 の 外 で 宣 言 し た 変 数 は 、 ど の 関 数 か ら で も 利 用 で き る 。 int count = 0; 20 21 22 private void button1_Click ( object sender , EventArgs e ) { count = count + 1; // c o u n t e r の 値 を 1 ず つ 増 や す // 変 数 " counter " を タ イ ト ル バ ー に 表 示 this . Text = count . ToString (); } 23 24 25 26 27 28 } 29 30 } 今回も 30 行もソースがある。しかし、注目するところはわずかである。 なお、// の後に書かれたテキストはコメントとして扱われ、コンパイラに無視さ れる。 ■変数の宣言と初期化 まず、21 行目に、 int count = 0; とある。int というのは、整数 (integer) をあらわす宣言である。変数名の前に int と書くと、その変数が整数であることを表す。ところで、変数とは何だろう? 数学で 扱ってきた変数と同じと考えてよい。「値を入れておくための箱」である。では、なぜ、 「整数であること」を明示しなければならないのだろう。C#のプログラムでは、整数だ けでなく、小数、文字、さらにそれらが連なったものなどを扱うことができる。実は、 整数、小数、文字などによって、コンピュータの中で割り当てるメモリの大きさが違う のである。コンピュータのメモリを効率よく使うために、それぞれ適切な大きさの箱を 用意する必要がある。 次に count について説明しよう。これが、変数(箱)の名前である。 =は、プログラムの世界では、代入を表す。つまり、 count = 0 というのは、変数 count に 0 を代入することを意味する。この count = 0 のような 文を「変数の初期化」という。 行の最後に、;(セミコロン)があるのは、文章でいうところの句点(。)のようなも のである。; があると、そこで式が終わることを表す。逆に言うと、C#では、一つの 文を何行に分けて書いてもかまわない。 第 1 章 ボタンを押した回数をカウント 26 ■変数の値を1ずつ増やす では、次に、25 行目を見てみよう。 count = count + 1; もう想像できた読者も多いだろう。この行では、右辺で、count の値を 1 増やし、 その結果を、左辺の count に代入している。こうすることで、count の値を 1 ずつ増 やしているのである。 ■変数の値を表示 最後に、27 行目を見てほしい。 this.Text = count.ToString(); 左辺は、this つまり、このプログラムのウィンドウそのもの (Form1) の Text プ ロパティを表現している。Text プロパティというぐらいであるから、文字列を代入で きることは想像がつくであろう。 では、右辺を見てみよう。まず count という整数型の変数がある。C# では、文字 型の変数に整数や小数などの数値型の変数の値を代入することはできないのである。そ のため、変数 count の中身を文字に変換しなければならない。この変換をするのが、 ToString() というものである。count.ToString() と書くことで、変数 count の 中身を文字列に変換してくれるのである。 動作確認 では、ここまで理解して、サンプルと同じようにソースを書いたら、F5 キーを押し て、実行してみよう。プログラムを実行すると、 Push me! というボタンが現れるの *4 タ で、マウスでクリックするか、Space キーを押して、このボタンを押してみよう。 イトルバーの数字がどんどん増えていくことを確認できるだろう。(図 1.4) 保存と終了 [ファイル] メニュー(アクセスキー Alt +F )から [すべてを保存] を選択し、変更 を反映させた後で、Visual Studio を終了する。 *4 ボタンにフォーカスがあるときに Space キーを押すと、マウスをクリックしたときと同 等なクリックイベントが発生する。 27 練習問題 リセットボタンの実装 タッピング実験を何回もする場合、このままでは、カウンタをリセットするために は、プログラムを起動しなおさなければならない。そこで、リセットボタンを設けて、 何度でも実験できるようにしたい。 ここでは、考える上でのヒントを記すので、自分で考えてみてほしい。 まず、[Push me!] の他に、もう一つボタンが必要である。そして、そのボタンが 押されたときに count の値を 0 にするとよい。 図 1.4 push counter の動作確認 100 からマイナス・カウントする 100 回押した時間を測定したいような場合もある。初期値が 100 で、ボタンを押す ごとに 1 ずつ値が小さくなるようにしたい。この場合はどうだろう。 まず、21 行目の int count = 0; の部分を書き換える必要がある。 また、ボタンを押したときに値が 1 ずつ減ってほしいから、25 行目の 第 1 章 ボタンを押した回数をカウント 28 count = count + 1; を書き換える必要がある。つまり、count を 1 増やした値ではなく、count を 1 減 らした値を count に代入することになる。 29 参考文献 [1] [2] [3] [4] Aoki, T. & Kinoshita, H.: Temporal and force characteristicsof fast double-finger, single-finger and hand tapping., Ergonomics, 44: 1368-1383, 2001. Aoki, T., Francis, P. R. & Kinoshita, H. : Differences in the abilities of individual fingers during the performance of fast, repetitive tapping movements., Exp. Brain Res., 152: 270-280, 2003. Aoki, T., Furuya, S. & Kinoshita, H. : Finger-tapping ability in male and female pianists and nonmusician controls, Motor Control, 9: 23-39, 2005. Aoki, T., Tsuda, H., Takasawa, M., Osaki, Y., Oku, N., Hatazawa, J. & Kinoshita, H. : The effect of tapping finger and mode differences on cortical and subcortical activities: a PET study., Exp. Brain Res., 160: 375-383, 2005. 30 第2章 指定時間内の打鍵回数をカウ ント このステップでマスターすること 1. 時間計測の開始 2. ボタンを押せるようにする、または押せないようにする 3. 警告音(ビープ音)を出す サンプルプログラムの動作確認 ここでは、このテキストの Web サイトにあるサンプルプログラムを実際に動 かし、その動作を確認する。今回は、sample\push_counter _002\ を参照する。 こ の フ ォ ル ダ ー の 中 に は 、い く つ か の フ ァ イ ル と フ ォ ル ダ ー が あ る 。そ の 中 の push_counter_002\bin\Debug\ とたどっていくと、push_counter_002.exe とい うファイルがある。これを実行してほしい。実行すると、画面にフォーム(プログラム のウィンドウ)が現れる。スタートボタンを押すと、タイマーがスタートし、指定時間 内に Push me! ボタンを押した回数をカウントする。このプログラムを使うと、指定 した時間内に何回打鍵できたか計測することができる。 では、この便利なプログラムの作成に取り掛かろう。 31 プログラムの設計・実装 設計 では、今、動作を確認したプログラムの動作を列挙してみよう。 1. 2. 3. 4. 5. プログラムを起動すると、スタートボタンと Push me! ボタンが現れる。 スタートボタンを押すと、タイマーがスタートし、 スタートボタンが押せなくなり、 Push me! ボタンが押された回数をカウントする 指定時間が経過すると、打鍵を受け付けなくする スタートボタンを押した状態の画面は次のようになる。 (図 2.1) 図 2.1 push counter 002 の実行画面 プロジェクトの作成 では、早速、サンプルプログラム push_counter_002 と同じものを作ってみよう。 まず、VS を起動してほしい。スタートページが現れるので、ここでは、[新しいプロ ジェクト...] をクリックする。すると、これから作成するプログラムに必要な設定項目 が出てくる。これらの項目は、Tab キーで移動できる。 まず、[Visual C#]、[Windows フォーム アプリケーション] という項目がある 32 第 2 章 指定時間内の打鍵回数をカウント ことを確認してほしい。[Visual C#] は開発言語を表している。このテキストでは、 C# を用いる。 また、[Windows フォームアプリケーション] は、アプリケーションの種類を表し ている。このテキストでは、Windows フォームアプリケーションを作るので、この項 目はそのままにしておいてほしい。 次に、[プロジェクト名] という入力ボックスがある。ここには、プログラムの用途な どがわかるような名前を記入する。ここでは、push_counter_002 と記入しよう。次 に、保存場所を設定する項目がある。ここでは、[参照] を選択して、明示的に C ドライ ブの class_sample というフォルダーを指定することにしよう。まだ class_sample というフォルダーが無い場合は作成してほしい。 最後に、[OK] を押して、数秒経つと、タイトルバーに Form1 と書かれた画面が現 れる。これが、アプリケーションの骨格である。この骨格の上に、さまざまなボタンや 表示部分などを配置してプログラムを作成していく。 画面デザイン では、早速、この Form1 にボタンを二つ配置してみよう。ボタンを貼り付けるに は、まず、ツールボックスを開く。ツールボックスを開くには、[表示] メニューの [ツー ルボックス] を選択する。すると、画面に貼り付けられるものが 150 数個も一覧され る。この中から、貼り付けたいものを選んで、Enter キーを押すと、Form1 に貼り 付く。 マウスを使って操作する場合は、まず、画面左端にある [ツールボックス] タブをク リックする。すると、コントロールの一覧が表示される。貼り付けたいものを選んで、 クリックしたままマウス・カーソルを、Form1 に移動すると、好きな位置に貼り付け られる。 [Button] を選んで、Form1 に 2 回貼り付ける。 次に、タイマーを実装するために、timer というコントロールを Form1 に貼り付 けよう。 timer を貼り付けるには、[表示] メニューの [ツールボックス] を選択する。 上下方向のカーソルキーで timer を選んで、Enter キーを押す。timer は、画面に 表示されるコントロールではないので、Form1 に貼り付けると、デザイナ画面の下部 のコンポーネントトレイに追加される。(図 2.2) 33 図 2.2 push counter 002 のデザイン イベント関数の生成 前章では、ボタンに名前を付けるため、button1 のプロパティ・ウィンドウで [Text] プロパティを選択し、あらかじめ文字列を書き入れた。本章では、これと同じことをプ ログラムによって行う方法を紹介する。 そのためには、プログラムのウィンドウ Form1 が表示された時に実行されるイベ ント関数を作る必要がある。 Form1 が選択された状態で、Enter キーを押すと、イベント関数 private void Form1_Load(object sender, EventArgs e) が作成される。マウスを使用する場合は、Form1 をダブルクリックするとイベント関 Shift キーを押しながら 数が追加される。コード画面からデザイナ画面に戻るには、 F7 キーを押す。逆に、コード画面を表示するには、F7 キーを押す。 次に、今貼り付けた button1、button2 ががクリックされたとき、および timer1 が呼ばれたときに実行されるイベント関数を作ることにする。これは、前章と同じく、 button1、button2、timer1 がそれぞれ選択された状態で、Enter キーを押すだ けでよい。マウスを使用する場合は、button1、button2、timer1 を順にダブルク リックするだけでよい。 ここまでで、プログラムを書くための準備が完了した。 第 2 章 指定時間内の打鍵回数をカウント 34 コントロールの各種設定 今、プログラムのウィンドウである Form1 に二つのボタン button1、button2 が貼り付けられたものができた。ここで、button1 に表示されるテキスト、つまり Text プロパティを変更しよう。 ここで、 this.Text = "my name"; と書くと、タイトルバー(Form1 の Text プロパティ)に文字列 my name が代 入される、つまり、タイトルバーに my name と表示されたことを思い出してほしい。 これと同じことが、ボタンでも行える。ソース 2.1 の 25 行目と 26 行目を見てほしい。 button1.Text = "スタート"; button2.Text = "Push me!"; このように書くことで、Form1 が表示された時の button1、button2 の Text プロパティ、つまり、ボタンに表示される文字列を指定できる。 動作の実装 まず、サンプル・プログラムのソースを見てみよう。 リスト 2.1 push counter 002.cs 1 2 3 4 5 6 7 8 9 using using using using using using using using using System ; System . Collections . Generic ; System . Comp onent Model ; System . Data ; System . Drawing ; System . Linq ; System . Text ; System . Threading . Tasks ; System . Windows . Forms ; 10 11 12 13 14 15 16 17 18 namespace p u s h _ c o u nt e r _ 0 0 2 { public partial class Form1 : Form { public Form1 () { I n i t i a l i z e C o m p o n e n t (); } 19 20 21 // 関 数 の 外 で 宣 言 し た 変 数 は 、 ど の 関 数 か ら で も 利 用 で き る 。 int counter ; 35 22 private void Form1_Load_1 ( object sender , EventArgs e ) { button1 . Text = " スタート " ; button2 . Text = " Push m e ! " ; 23 24 25 26 27 button1 . Enabled = true ; // 押 せ る button2 . Enabled = false ; // 押 せ な い 28 29 } 30 31 private void button1_Click ( object sender , EventArgs e ) { counter = 0; // 初 期 化 this . Text = counter . ToString (); // 初 期 値 を 表 示 t i m e r 1 _ t i c k _ c o u n t = 0; // 初 期 化 timer1 . Enabled = true ; // t i m e r 1 の カ ウ ン ト を 開 始 button1 . Enabled = false ; // 押 せ な い button2 . Enabled = true ; // 押 せ る } // t i m e r 1 が コ ー ル さ れ た 回 数 を カ ウ ン ト す る 変 数 int t i m e r 1_ t i c k_ c o u n t ; 32 33 34 35 36 37 38 39 40 41 42 43 private void button2_Click ( object sender , EventArgs e ) { counter = counter + 1; // c o u n t e r の 値 を 1 ず つ 増 や す // 変 数 " counter " を タ イ ト ル バ ー に 表 示 this . Text = counter . ToString (); } 44 45 46 47 48 49 50 private void timer1_Tick ( object sender , EventArgs e ) { t i m e r 1 _ t i c k _ c o u n t ++; // 1 ず つ 値 を 増 や す ( イ ン ク リ メ ン ト ) 51 52 53 54 if ( t i me r 1 _ t i c k _ c o u nt == 100) // 10 秒 経 過 し た ら { button1 . Enabled = true ; // 押 せ る button2 . Enabled = false ; // 押 せ な い Console . Beep (800 , 1000); timer1 . Enabled = false ; } 55 56 57 58 59 60 61 } 62 63 } 64 65 } 今回は 65 行もソースがある。しかし、注目するところはわずかである。ソースを上の 行から順に見ていこう。 まず、21 行目に int counter; とある。これは、マウスをクリックした回数をカウントするための整数型の変数 counter を使用するための宣言である。 第 2 章 指定時間内の打鍵回数をカウント 36 25 行目から 29 行目で、button1 のプロパティの設定をしている。まず 25 行目と 26 行目では、button1 と button2 に表示されるテキストを設定している。 ■ボタンを押せるようにする、押せないようにする 次に、28 行目と 29 行目を見てみよう。 button1.Enabled = true; // 押せる button2.Enabled = false; // 押せない これは、 「button を押せるように」し、 「button2 を押せないように」設定している。 次に、button1 が押されたときの処理内容を見ていこう。 ■カウンターの初期化 counter = 0; // 初期化 this.Text = counter.ToString(); // 初期値を表示 スタートボタンが押されると、マウスをクリックした回数をカウントするための変数 counter を 0 に初期化する。そして、次の行でその値をタイトルバーに表示している。 ■時間計測の開始 timer1_tick_count=0; // 初期化 timer というのは、文字どおり時間計測をするためのコントロールである。この timer が動き出すと、その timer に関連付けられたイベント関数が、指定した時間ご とに呼び出される。このイベント関数の中で変数の値を 1 ずつ増やすことで、時間の計 測を行える。このときに使う変数が、timer1_tick_count である。ここでは、この変 数の値を 0 に初期化している。 timer1.Enabled = true; この行で、timer1 による時間計測をスタートさせている。ちなみに、時間計測を停止 するには、 timer1.Enabled = false; とする。 button1.Enabled = false; // 押せない button2.Enabled = true; // 押せる 37 そして、時間計測が始まると、計測開始のボタン button1 を押せなくし、打鍵のため のボタン button2 を押せるようにしている。 次に、timer1 が呼ばれる度に動くイベント関数 timer1_Tick の中を見てみよう (53 行目から 60 行目) 。 timer1_tick_count++; によって、timer が呼ばれた回数を数えている。*1 次に、55 行目から 61 行目を見てほしい。この「if{ ... }」の形をしている文を if 文 という。if 文は、その名のとおり、「もし条件1ならば、タスク1を実行する」とい う条件付きの実行をしたいときに書く。 if (条件1) { タスク1を実行 } のように書く。また、「もし、条件1ならばタスク1を、条件2ならばタスク2を、そ れ以外ならばタスク3を実行したい場合は次のように書く。 if (条件1) { タスク1を実行 } else if (条件2) { タスク2を実行 } else { タスク3を実行 } では、55 行目から 61 行目を解釈してみよう。 if (timer1_tick_count == 100) 「timer1_tick_count の値が 100 であれば」という意味になる。この条件が成り 立てば、以下の{...} 内(57 行目から 60 行目)が実行されることになる。では、 *1 ++ は単項演算子と呼ばれるもので、変数の値を 1 増やす働きをする。次のように書いた 場合と同じ結果を与える。 timer1 tick count = timer1 tick count + 1; 第 2 章 指定時間内の打鍵回数をカウント 38 「timer1_tick_count の値が 100 であれば」というのは、「どのぐらいの時間が経過 したら」という意味だろう? 実は、この例の場合は、timer1 は 100 ミリ秒に1回ず つ呼ばれ、そのつど timer1_Tick 関数が呼び出されてその中身が実行されている。こ れは、timer1 の Interval というプロパティの初期値が 100 に設定されているから である。ということは、timer1_tick_count == 100 、つまり、timer1 が 100 回呼 ばれたということであるから、 「100 ミリ秒 × 100 回 = 10,000 ミリ秒 = 10 秒」とな る。これと同じ設定は、プログラム内(たとえば 36 行目の前)で、、 timer1.Interval = 1000; と書くと、timer1 が1秒ごとに呼び出されるようになるので、55 行目は、 if (timer1_tick_count == 10) と書くことになる。 では、次に、57 行目から 60 行目を見ていこう。if 文の中身である。つまり、この場 合、timer1 が動作してから 10 秒後に実行される内容である。まず、 button1.Enabled = true; によって、button1 つまりスタートボタンを再び押せるようにしている。代わりに、 button2.Enabled = false; によって、button2 つまり Push me! ボタンを押せなくしている。計測を終了した ので、Push me! ボタンを受け付けては困るのである。 ■警告音(ビープ音)を出す ここで、「計測が終了したこと」を、ユーザに伝える必要がある。文字で伝える方 法もあるが、何かのタスクに集中しているときなどは気づきにくい。そこで、音で伝え ることにしよう。ここで、一番簡単な「ビープ音の鳴らし方」を扱うことにする。 Console.Beep(800, 1000); この文は、「800Hz のビープ音を 1000 ミリ秒(1秒)鳴らす」ことを意味している。 ビープ音の周波数や長さを変えることで、さまざまな意味を持たせることもできる。 timer1.Enabled = false; この行で、timer1 が停止する。計測停止である。 では、次に、button2 つまり Push me! ボタンが押されたときの動作を見てみよ 39 図 2.3 push counter 002 の動作確認 う。これは、簡単である。まず、 counter = counter + 1; によって、button2 が押された回数をカウントしている。 次に、 this.Text = counter.ToString(); によって、counter の値を、逐次タイトルバーに表示している。 動作確認 では、ここまで理解して、サンプル・プログラムと同じようにソースを書いたら、 F5 キーを押して実行してみよう。プログラムを実行すると、スタートと Push me! という二つのボタンが現れるので、まず、スタートボタンを押してみよう。 (マウスで 2 クリックするか Space キーを押す)* 続けて、Push me! ボタンを素早くクリック し続けてみよう。タイトルバーの数字がどんどん増えていくことを確認できるだろう。 そして、10 秒たつと、800Hz のビープ音が1秒鳴って、計測が終了する。 (図 2.3) *2 ボタンにフォーカスがあるときに Space キーを押すとクリックイベントが発生する。 第 2 章 指定時間内の打鍵回数をカウント 40 保存と終了 [ファイル] メニューから [すべてを保存] を選択し、変更を反映させた後で、Visual Studio を終了する。 練習問題 2 分間測定できるようにする すばやい打鍵を 2 分もやり続けることは、かなり大変である。このような実験によっ て、筋肉の疲労の進み方を見ることができる。では、この過酷な「2 分タッピング」に プログラムを改良してみよう。 ここで、timer1 が呼び出されるのは、100 ミリ秒に1度である。この値は、timer1 の Interval プロパティで設定できる。今回は、この timer1 の Interval プロパティ つまり timer1.Interval はそのままにしておこう。となると、どこを変更すると 2 分測定できるようになるだろうか。それは、55 行目の if (timer1_tick_count == 100) である。では、この右辺の「100」をいくつに変更したらよいだろう。「2 分 = 100 ミ リ秒 × 1200」であるから、「1200」となる。これだけの変更で、2 分間測定をし続け ることができるようになる。 途中経過と終了を知らせるビープ音の実装 次に、測定を開始して 1 分経過したことを「800Hz の 1 秒のビープ音」で、また、測 定を開始して 2 分経過し、測定が終了したことを「1600Hz の 2 秒のビープ音」で、知 らせるように、プログラムを変更してみよう。 この場合、注目するのは、元のプログラムの 55 行目の if (timer1_tick_count == 100) である。この、終了判定を行う if 文の前に、1 分経過したことをつかさどる if 文が必 要になる。この追加する if 文の条件の右辺の値はいくつにしたらよいだろうか? 次に、この追加した if 文の中では、測定を開始して 1 分経過したことを「800Hz の 1 秒のビープ音」で知らせたい。59 行目の 41 Console.Beep(800, 1000); を参考に考えてみよう。 また、測定を開始して 2 分経過し、測定が終了したことを「1600Hz の 2 秒のビープ 音」で知らせたい。この場合は、どこに、「1600Hz の 2 秒のビープ音」を鳴らすコー ドを書くと良いだろう? if (timer1_tick_count == 100) // 10 秒経過したら の下の if ブロックの中をよく見てみよう。*3 構文演習 if 文 ここでは、if 文をマスターするために、いくつかの演習をすることにする。 例題1 問題 変数 x が偶数ならば偶数、奇数ならば奇数と表示させる if 文を書け。 ヒント 偶数と奇数の判別は、変数 x を 2 で割った余りで判断できる。C# で、x を y で割っ たときの余りを求めるには、x % y と書く。 たとえば、 z = x % y; と書くことで、変数 x を y で割ったときの余りを z に代入できる。いうまでもなく、偶 数を 2 で割った余りは 0、奇数を 2 で割った余りは 1 になる。 ヒント2 数値を入力するためのボックスは、TextBox コントロールを利用する。 C#では、 x = Convert.ToInt32(this.textBox1.Text); *3 練習問題の解答については、本書 Web サイトに掲載しているサンプル・プログラムを参 照してほしい。 第 2 章 指定時間内の打鍵回数をカウント 42 と書くことで、テキストボックスに入力した値を変数 x に代入できる。*4 解答例 if (x % 2 == 0) this.Text = "偶数"; else this.Text = "奇数"; 図 2.4 例題 1 の実行 例題2 問題 変数 x が 0 未満ならばマイナス、0 より大きければプラスと表示させ、さらに、絶対 値を表示させる if 文を書け。 *4 ここでは、整数のみを扱うものとしている。Int32 は、32 ビットの整数を意味する。 43 ヒント 0 よ り 小 さ い か 大 き い か の 判 別 は 、変 数 x と 0 と の 間 の 不 等 式 の 真 偽 に よ っ て判断できる。C# で、x と y の大小関係を判断するには、数学の式と同じく、 x<y, x<=y, x>y, x>=y と書く。 解答例 if (x<0) { this.Text = "マイナス " + (-x).ToString(); } else if (x > 0) { this.Text = "プラス " + x.ToString(); } 図 2.5 例題 2 の実行画面 実験 II 文字の判断時間の測定 45 実験 II では、表示された単語が「動物の名前かそうでないか」を判断させる実験を 行う。この判断実験において、「文字の大きさ」、 「文字の色」、 「背景の色」、 「文字の表 示位置」など、さまざまなパラメータを変更したとき、反応時間や判断にどのように影 響するかを観察していく [1] [2] [3] 。 実験の目的: 文字の色、大きさ、位置などのパラメータが、文字の意味情報を判断す るのにどのように影響するかを調べる。 被験者に提示する刺激: 取得するデータ: 動物の名前および動物の名前でない単語 単語を表示してから、被験者が、その単語が動物の名前か否かを答 えるまでの時間および回答 46 第3章 ラベルへの文字表示 この章でマスターすること 1. キーボードからの入力を受け付ける 2. ラベルへの文字表示 サンプルプログラムの動作確認 ここでは、このテキストの Web サイトにあるサンプルプログラムを実際に動かし、 その動作を確認する。今回は、sample\animal_name_001\ を参照する。このフォル ダーの中には、いくつかのファイルとフォルダーがある。その中の bin\Debug\ とた どっていくと、animal_name.exe というファイルがある。これを実行してほしい。実 行すると、画面にフォーム(プログラムのウィンドウ)が現れ、 label1 と書かれたラ ベルが一つ現れる。そして、キーボードの A 、B 、C 、Z のキーを押すと、そのラ ベルに単語が表示される。また、Escape キーを押すと、ラベルの文字が消える。さ らに、F1 、F2 のキーを押すと、ラベルの位置が移動する。 (図 3.1) このプログラムを使うことで、さまざまな単語を画面のさまざまな位置に表示して、 それに対する被験者の反応を調べる実験をすることができる。では、この便利なプログ ラムの作成に取り掛かろう。 47 図 3.1 animal name の動作確認 プログラムの設計・実装 設計 では、今、動作を確認したプログラムの動作を列挙してみよう。 1. 2. 3. 4. プログラムが起動すると、画面にラベル label1 が一つ表示される。 所定のキーを押すと、ラベルにそのキーに割り当てられた単語が表示される。 また、ラベルの単語を消す機能もある。 さらに、ラベルの表示位置を変更できる。 単純ではあるが、このようになる。 プロジェクトの作成 では、早速、サンプルプログラム animal_name と同じものを作ってみよう。 VS を起動し、[新しいプロジェクト...] を選択して、Windows フォームアプリケー ションを新規に作ろう。 [プロジェクト名] を animal_name_001 とし、C ドライブの class_sample フォル ダーに保存しよう。 第 3 章 ラベルへの文字表示 48 画面デザイン では、早速 Form1 にラベルを一つ配置してみよう。Form1 にラベルを配置するに は、[表示] メニューの [ツールボックス] を選択し、ツールボックスを表示する。上下方 向のカーソルキーで移動し、[Label] を選択して、Enter キーを押す。 コントロールの各種設定 今、プログラムの画面である Form1 にラベル label1 が貼り付けられたものがで きた。 次に、この Form1 の画面で、キー入力を受け付けるための設定をしよう。これに は、次の二つのステップが必要である。 ■KeyPreview の設定 まず、デザイナ画面を開き、Form1 を選択して Form1 のプロパティ・ウィン ドウを開こう。[表示 ] メニューから、[プロパティ ウィンドウ] を選択するか、ショー トカット・キー F4 を押すと、[プロパティ ウィンドウ] が選択される。プロパティ 項目の中に、[KeyPreview] という項目がある。まず、上下方向のカーソルキーで、 [KeyPreview] という項目を探してほしい。[KeyPreview] が見つかったら、Tab キーを一度押してほしい。すると、KeyPreview の設定を、True または False のど ちらかに設定できる。初期値では False になっているので、上下方向のカーソルキー で、True に変更しよう。 イベント関数の生成 次に、キーボードのキーが押されたときに呼び出されるイベント関数を作ろう。ここ *1 では、キーボードのみで操作する方法を説明する。 Form1 のプロパティ・ウィンドウで、Tab キーを数回押すと、「項目別ボタン」 (または「カテゴライズの確認」)と読み上げるところがある。(左端の [項目別] ボタ ン)ここで、[右移動] カーソルキーを数回押して、「イベントボタン」 (または「イベ ントの確認」)と読み上げるところまで移動する。そこで Space キーを押すと、イ *1 マウスによる操作の場合は次のようになる。Form1 のプロパティ・ウィンドウで、[イ ベント] ボタン(稲妻のアイコン)をクリックすると、イベント関数の一覧が出てくる。 [KeyDown] を選択し、ダブルクリックする。 49 ベント関数の一覧が出てくる。上下方向のカーソルキーで、[KeyDown] を選択し、 Enter キーを押す。これで、Form1 上でキーボード入力が行われたときに呼び出さ れる KeyDown イベント関数が作られる。 (図 3.2) 図 3.2 Form1 の KeyDown プロパティ ソースを見てみると、 private void Form1_KeyDown(object sender, KeyEventArgs e) という行が追加されていることがわかる。 動作の実装 では、サンプル・プログラムのソースを見てみよう。 リスト 3.1 1 2 3 4 5 6 7 8 using using using using using using using using animal name 001.cs System ; System . Collections . Generic ; System . Comp onent Model ; System . Data ; System . Drawing ; System . Linq ; System . Text ; System . Windows . Forms ; 9 10 11 12 13 14 15 16 17 namespace animal_name { public partial class Form1 : Form { public Form1 () { I n i t i a l i z e C o m p o n e n t (); } 18 19 20 21 private void Form1_KeyDown ( object sender , KeyEventArgs e ) { if ( e . KeyCode == Keys . A ) 第 3 章 ラベルへの文字表示 50 { 22 label1 . Text = " りんご " ; 23 } 24 25 if ( e . KeyCode == Keys . B ) { label1 . Text = " バナナ " ; } 26 27 28 29 30 if ( e . KeyCode == Keys . C { label1 . Text = " 猫 " ; } 31 32 33 34 ) 35 if ( e . KeyCode == Keys . Z ) { label1 . Text = " 動物園 " ; } 36 37 38 39 40 if ( e . KeyCode == Keys . Escape { label1 . Text = " " ; } 41 42 43 44 ) 45 if ( e . KeyCode == Keys . F1 ) { label1 . Location = new Point (10 , 20); } 46 47 48 49 50 if ( e . KeyCode == Keys . F2 ) { label1 . Location = new Point (10 , 50); } 51 52 53 54 55 } 56 } 57 58 } 今回も 58 行もソースがある。しかし、注目するところはわずかである。 ■キーボードからの入力を受け付ける まず、19 行目に private void Form1_KeyDown(object sender, KeyEventArgs e) とある。これが、今作ったイベント関数である。 では、「どのキーが押されたか」をどのように認識しているのだろうか。これを判断 しているのが、21 行目の if( e.KeyCode == Keys.A ) 51 などの if 文である。この if 文は、「 A キーが押されたら」という意味である。 ■ラベルへの文字表示 では、次に、23 行目を見てみよう。 label1.Text = "りんご"; この 1 行の意味は、もう解釈できるだろう。label1 の Text プロパティにりんごとい う文字列を代入している。つまり、「label1 にりんごと表示すること」を意味してい る。これと同様のことを、26 行目から 39 行目まで行っているので、どのキーが押され たときにどの単語が label1 に表示されるのか考えてみよう。 では、 if( e.KeyCode == Keys.Escape { label1.Text = ""; } ) は、Escape キーが押されたときに実行される文であるが、 label1.Text = ""; はどのような意味だろう? 右辺の"" は、何もない文字列である。つまり、label1 に 何も表示しないこと(クリア)を意味する。 最後に、46 行目以後を見てほしい。 { label1.Location = new Point(10, 20); } この文は、F1 キーが押されたとき、何をさせているのだろう? label1.Location = new Point(10, 20); は、label1 の表示位置(左上の角)を (10, 20) に指定している。*2 この座標指定は、 数学の座標指定とは異なり、画面の左上を原点 (0, 0) とするものである。そして、こ の x 座標が大きくなれば右に行き、y 座標が大きくなれば下に行くことになる。 *2 new はインスタンスを生成する宣言である。ここでは、(10, 20) という座標インスタン ス(具体的な座標)を生成し、label1 の Location プロパティに代入している。 第 3 章 ラベルへの文字表示 52 動作確認 では、ここまで理解して、サンプルと同じようにソースを書いたら、F5 キーを押し て実行してみよう。 プログラムを実行すると、 label1 というラベルが現れる。キーボードの A 、B 、 C 、Z ,を押してみよう。ラベルの文字が変わることを確認できるだろう。 また、Escape キーを押すと、ラベルの文字をクリアできる。さらに、F1 または F2 のキーを押すと、ラベルの位置が変わる。 保存と終了 [ファイル] メニューから [すべてを保存] を選択し、変更を反映させた後、Visual Studio を終了する。 練習問題 ■さらにいろいろな単語を表示できるようにする 21 行目から 39 行目を参考に、D から Y のキーを押したとき、いろいろな単 語を label1 に表示するようにしよう。 ■ラベルの背景色と文字色の変更 背景と表示文字のコントラストを変えると、文字の見易さに影響する。これを調 べる実験をするために、背景色と文字色を変更してみよう。Label には、背景色を設 定するための BackColor プロパティと文字色を設定するための ForeColor プロパ ティがある。これらのプロパティの設定例を紹介する。 label1.BackColor = Color.White; // 背景を白に label1.ForeColor = Color.Green; // 文字を緑に 53 図 3.3 練習問題の動作 54 参考文献 [1] [2] [3] Glaser,W.R. & Glaser,M.0. 1989 Context effects in Stroop-likeword and picture processing. Journal of Experimental Psychology: General, 118,13-42. Lupker,S.J.,& Katz,A.N. 1981 Input,decision, and response factors in picture-word interference. Journal of Experimental Psychology: Human Learning and Memory, 7, 269-282. Springer,C.J. 1986 Graphemic and semantic similarity effects in the picture-word interference task. British Journal of Psychology, 77, 207-222. 55 第4章 単語をランダムに提示 このステップでマスターすること 1. 同じ型のデータをまとめて扱う配列の利用 2. 乱数の生成 3. データのランダムな取り出し サンプルプログラムの動作確認 ここでは、このテキストの Web サイトにあるサンプルプログラムを実際に動かし、 その動作を確認する。今回は、sample\animal_name_002\ を参照する。このフォル ダーの中には、いくつかのファイルとフォルダーがある。その中の bin\Debug\ とた どっていくと、animal_name_002.exe というファイルがある。これを実行してほし い。実行すると、画面にフォーム(プログラムのウィンドウ)が現れる。Space キー を押すと、タイトルバーにランダムな数字が表示される。後で詳しく説明するが、この 番号は、ラベルに表示する単語のインデックス番号である。次に、Enter キーを押す と、タイトルバーに表示されているインデックス番号に紐付けられた単語がラベルに表 示される。このプログラムを使うことで、ランダムに単語を表示して、被験者の反応を 見ることができる。(図 4.1) 第 4 章 単語をランダムに提示 56 図 4.1 animal name 002 の動作確認 では、この便利なプログラムの内容の確認に取り掛かろう。 プログラムの設計・実装 設計 では、今、動作を確認したプログラムの動作を列挙してみよう。 プログラムが起動すると、ラベルが表示される。 Space キーを押すと、表示する単語のインデックス番号が生成され、タイトル バーに表示される 3. Enter キーを押すと、タイトルバーに表示されたインデックス番号に紐付けら 1. 2. れた単語がラベルに表示される 単純ではあるが、このようになる。では、このアルゴリズムを、もう少し詳細に書い てみよう。 1. 2. 3. 4. プログラムが起動すると、ラベルが表示される。 ラベルに表示したい単語の一覧を格納した配列を用意する この配列の個々の要素を扱うためのインデックス用の変数を用意する Space キーを押すと、表示する単語のインデックス番号をシャッフルし、タイ トルバーに表示する 57 5. Enter キーを押すと、タイトルバーに表示されたインデックス番号に紐付けら れた単語がラベルに表示される このようになる。 プロジェクトの作成 では、早速、サンプルプログラム animal_name_002 と同じものを作ってみよう。 1. sample フォルダーの中の animal_name_001 フォルダーを class_sample フォルダーにコピーする。*1 2. フォルダー名を animal_name_001 から animal_name_002 に変更する。 3. class_sample\animal_name_002 フォルダーの中の animal_name_001.sln というファイルを選択する。 4. キーボード操作の場合は、Enter キーを押す。マウスによる操作の場合は、ファ イルのアイコンを選択した状態でダブルクリックする。*2 5. VS が起動し、プロジェクトが読み込まれる。 Tab キーを押して、[ソリューション エクスプローラー] を選択し、上下方向のカー ソルキーで [Properties] を選んでEnter キーを押すと、ソリューションのプロパ ティ画面が表示される。 (図 4.2) 図 4.2 ソリューションのプロパティ画面 Tab キーを押して、[アセンブリ名] を選択し、animal_name_002 と書き換える。こ れにより、作成される実行形式ファイルの名前が animal_name_002.exe に変わる。 *1 *2 自分で作成した第 3 章の課題のプロジェクトファイルを利用してもかまわない。 ソリューション・ファイル(.sln)の名前も変更してかまわない。だが、それと同じ階層の フォルダー animal_name_001 の名前を変更してしまうと、プロジェクトが読みこまれな くなるので注意してほしい。 第 4 章 単語をランダムに提示 58 [表示] メニューから [ソリューション エクスプローラー] を選択し、上下方向のカー ソルキーで Form1.cs を選んでEnter キーを押すと、Form1 のデザイナ画面が表示 される。 画面デザイン 今回は、追加するコントロールはない。 コントロールの各種設定 コントロールのプロパティ設定もそのままでよい。 イベント関数の生成 イベント関数も、すでに生成してある Form1_KeyDown だけでよい。 動作の実装 まず、サンプル・プログラムのソースを見てみよう。 リスト 4.1 1 2 3 4 5 6 7 8 9 using using using using using using using using using animal name 002.cs System ; System . Collections . Generic ; System . Comp onent Model ; System . Data ; System . Drawing ; System . Linq ; System . Text ; System . Threading . Tasks ; System . Windows . Forms ; 10 11 12 13 14 15 16 17 18 namespace a n im a l_ nam e_ 00 2 { public partial class Form1 : Form { public Form1 () { I n i t i a l i z e C o m p o n e n t (); } 19 20 21 22 23 24 string [] sData = { " アヒル " , " イヌ " , " ウサギ " , " エビ " , " オカ " , " カメ " , " キツネ " , " クマ " , " ケイト " , " コマ " , " サル " , " シカ " , " スイカ " , " セトモノ " , " ソラ " , " タヌキ " , " チドリ " , " ツバメ " , " テツボウ " , " トビラ " , " ナス " , " ニワトリ " , " ヌマチ " , 59 " ネコ " , " ノハラ " , " ハト " , " ヒレ " , " フネ " , " ヘイワ " , " ホコ " , " マリモ " , " ミカン " , " ムクチ " , " メグロ " , " モグラ " , " ヤリ " , " ユキ " , " ヨル " , " ラッパ " , " リス " , " ルス " , " レモン " , " ロバ " , " ワラ " }; 25 26 27 28 29 int idx ; 30 31 private void Form1_KeyDown ( object sender , KeyEventArgs e ) { if ( e . KeyCode == Keys . Space ) { int [] shuffle = new int [ sData . Length ]; int seed = Environment . TickCount ; Random rnd = new Random ( seed ++); idx = rnd . Next (0 , sData . Length - 1); 32 33 34 35 36 37 38 39 40 this . Text = " idx = " + idx . ToString (); label1 . Text = " " ; 41 42 } 43 44 if ( e . KeyCode == Keys . Enter ) { label1 . Text = sData [ idx ]; } 45 46 47 48 } 49 50 } 51 52 } 今回も 52 行もソースがある。しかし、注目するところはわずかである。 ■同じ型のデータをまとめて扱う配列の利用 まず、20 行目から string[] sData={"アヒル", "イヌ", .... , "ワラ"}; という行がある。*3 これが配列というものである。配列というのは、「同じ型の変数が連なったもの」で ある。例を挙げて説明しよう。今、44 人分のカードが必要だとしよう。各カードの表 にはカード番号が、裏には単語が書かれているものとする。 表 4.1 のような単語カードがあるとしよう。この場合、カード番号を指定すること で、単語を調べることができる。このようなデータの集まりを配列という。 *3 ここでは、見やすいように改行を入れているが、一行で記述してもかまわない。 第 4 章 単語をランダムに提示 60 表 4.1 単語カード カード番号 単語 0 アヒル 1 イヌ 2 ウサギ 3 エビ 4 オカ .. .. 43 ワラ では、表 4.1 のデータを sData という配列に格納するにはどうしたらよいだろう。 これを行っているのが、20 行目からの string[] sData={"アヒル", "イヌ", ..., "ワラ"}; である。では、これらの行の意味を説明しよう。string というのは、変数 sData の 型である。整数を扱うときは int 型を使ってきた。string 型は文字列を格納するため の型である。では、string[ ] のように [ ] が付いているのは、どういう意味だろう。 これが、変数の配列であることを表すものである。したがって、string[] sData と書 くことで、文字列を扱う変数の配列 sData を意味する。 では、この行の右辺はどのような意味だろう? {....} の中に、"アヒル", "イ ヌ", "ウサギ" のように、単語(文字列)が"..." で囲まれて、, (コンマ)区切り で並んでいる。これが、配列 sData の中身である。プログラムの中で、sData[0] と 指定するとアヒル、sData[1] と指定するとイヌという単語を呼び出すことができる。 「なぜカード番号が 0 から始まっているのだろう」と思ったと思う。C#では、配列の 番号は、0 から始まることになっている。 次に、この配列 sData のデータを指定して取り出すためのインデックス番号を 30 行目で宣言している。以後、この変数を使って配列 sData の中身を取り出すことに なる。 次に、34 行目から 48 行目を見ていこう。 if( e.KeyCode == Keys.Space ) は、Space キーが押されたときに実行される if 文である。 では、この if 文の中では、何をしているのだろうか? 61 ■乱数の生成 int seed = Environment.TickCount; Random rnd = new Random(seed); idx=rnd.Next(0, sData.Length-1); この 3 行で、配列 sData からランダムに一つの要素を取り出すためのインデックス番 号を生成している。では、この 3 行を詳しく見ていこう。 まず、 int seed = Environment.TickCount; で、乱数を発生させるための seed を生成している。その後、所定のルールで乱数を発 生している。このとき、乱数を発生させるための元になる数(シード)が必要になる。 この元になる数がいつも同じだと、同じ乱数列が生成されてしまう。そのため、 int seed = Environment.TickCount; によって、毎回異なる seed を生成している。右辺の Environment.TickCount はシ ステム起動後の経過時間(ミリ秒)を取得するためのものである。これによって、毎回 異なる数値の seed を得ているのである。 次に、今生成した seed を使って、 Random rnd = new Random(seed); とすることで、乱数 rnd を生成している。そして、 idx = rnd.Next(0, sData.Length-1); とすることで、0 から sData の長さ-1 の範囲の整数から、任意の一つの整数を生成 し、idx に代入している。これにより、 if( e.KeyCode == Keys.Space ) が実行されるたびに、新しいインデックス番号 idx を生成しているのである。 では、この if 文の中の残りの 2 行を見てみよう。 this.Text = "idx=" + idx.ToString(); では、新しく生成したインデックス番号 idx をタイトルバーに表示している。また、 第 4 章 単語をランダムに提示 62 label1.Text = ""; では、label1 の表示をクリアしている。 ■データのランダムな取り出し では、次に、上で生成したインデックス番号 idx を用いて、単語を表示する部分 を見ていこう。 if( e.KeyCode == Keys.Enter ) { label1.Text = sData[idx]; } Enter キーを押すと、インデックス番号 idx の単語を表示している。このように、 配列の中の要素をランダムに取り出すには、その配列のインデックス番号をシャッフル すればよいのである。 動作確認 では、ここまで理解して、サンプルと同じようにソースを書いたら、 F5 キーを押して実行してみよう。プログラムを実行すると、label Space キー を押すたびに、インデックス番号がシャッフルされ、その値がタイトルバーに表示され る。また、Enter キーを押すと、シャッフルによって得られたインデックス番号の単 語を label1 に表示する。 保存と終了 [ファイル] メニューから [すべてを保存] を選択し、変更を反映させた後で Visual Studio を終了する。(図 4.3) 63 図 4.3 animal name 002 の実行 練習問題 繰り返しのないシャッフル提示 ここで扱ってきたサンプルでは、配列 sData に 0 から sData.Length-1 の乱数 を生成して、ランダムに単語を表示させた。この場合、同じインデックス番号が出現す ることもあるので、同じ単語を複数回表示することもありうる。では、配列 sData そ のものをシャッフルして、同じ単語を繰り返さずに、ランダム提示するにはどうしたら よいだろう? これを実現するには、配列 sData をランダムに並び替えるとよい。C# では、配列 のランダムな並び替えは、以下の 1 行で行うことができる。 sData = sData.OrderBy(i => Guid.NewGuid()).ToArray(); 配列のシャッフルが完了したら、新たな実験開始に先立ち、必要なことがある。(あ る変数を初期化する必要がある。) そして、シャッフルした sData を 0 から sData.Length-1 まで、順番に表示して いくようにするとよい。配列の要素番号 idx を 1 ずつ増やして、単語を表示していけ ばよい。 64 第5章 反応時間の記録 このステップでマスターすること 1. Stopwatch による経過時間の計測 2. テキストファイルへのデータの書き出し サンプルプログラムの動作確認 ここでは、このテキストの Web サイトにあるサンプルプログラムを実際に動 かし、その動作を確認する。今回は、class_sample\animal_name_003\ を参照す る。このフォルダーの中には、いくつかのファイルとフォルダーがある。その中の animal_name_002\bin\Debug\ とたどっていくと、animal_name_003.exe という ファイルがある。これを実行してほしい。実行すると、画面にフォーム(プログラムの ウィンドウ)が現れ、ラベル label1 が表示される。Space キーを押すと、単語の配 列がシャッフルされ、インデックス番号が一つ、タイトルバーに表示される。 Enter キーを押すと、タイトルバーに表示されているインデックス番号の単語が label1 に表示され、応答時間の計測が始まる。 被験者は、表示された単語が、動物の名前であれば Y キーを、動物の名前でなけれ ば N キーを押す。 Y または N のキーが押されると、応答時間の計測を終了し、提 示した単語、応答時間、Yes/No の情報がテキストファイルに記録される。(図 5.1) 65 図 5.1 animal name 003 の動作確認 では、この便利なプログラムの作成に取り掛かろう。 プログラムの設計・実装 設計 では、今、動作を確認したプログラムの動作を列挙してみよう。 1. Space キーが押されたら、0 から sData.Length-1 の間の整数の乱数が生成 され、そのうちの一つが、タイトルバーに表示される。 Enter キーを押すと、 タイトルバーに表示されている番号の単語が label1 に表示され、Stopwatch をリセット後、計測を開始する。 2. N キーが押されると、Stopwatch が停止し、計測結果(提示した単語、応答 時間、”No”)が、テキストファイルに記録される。 3. Y キーが押されると、Stopwatch が停止し、計測結果(提示した単語、応答 時間、”Yes”)が、テキストファイルに記録される。 プロジェクトの作成 では、早速、サンプルプログラム animal_name_003 と同じものを作ってみよう。 sample フォルダーの中の animal_name_002 フォルダーを class_sample フォル 第5章 66 反応時間の記録 *1 ダーにコピーし、フォルダー名を animal_name_003 に変更する。 その animal_name_003 フォルダーの中の animal_name_002.sln というファイル を選択し、Enter キーを押す。マウスによる操作の場合は、ファイルのアイコンを選 択した状態でダブルクリックする。VS が起動し、プロジェクトが読み込まれる。[アセ ンブリ名] を変更し、デザイナ画面を表示する。*2 画面デザイン 今回は課題4のままでよい。 コントロールの各種設定 今回は課題4のままでよい。 イベント関数の生成 今回は課題4のままでよい。 動作の実装 まず、サンプル・プログラムのソースを見てみよう。 リスト 5.1 1 2 3 4 5 6 7 8 9 using using using using using using using using using animal name 003.cs System ; System . Collections . Generic ; System . Comp onent Model ; System . Data ; System . Drawing ; System . Linq ; System . Text ; System . Threading . Tasks ; System . Windows . Forms ; 10 11 using System . Diagnostics ; 12 13 14 15 namespace a n im a l_ nam e_ 00 2 { public partial class Form1 : Form *1 *2 自分で作成した第 4 章の課題のプロジェクトファイルを利用してもかまわない。 操作方法については、p. 57 を参照してほしい。 67 16 17 18 19 20 { public Form1 () { I n i t i a l i z eC o m p o n e n t (); } 21 22 23 24 25 26 27 28 29 30 31 32 33 string [] sData = { " アヒル " , " イヌ " , " ウサギ " , " エビ " , " オカ " , " カメ " , " キツネ " , " クマ " , " ケイト " , " コマ " , " サル " , " シカ " , " スイカ " , " セトモノ " , " ソラ " , " タヌキ " , " チドリ " , " ツバメ " , " テツボウ " , " トビラ " , " ナス " , " ニワトリ " , " ヌマチ " , " ネコ " , " ノハラ " , " ハト " , " ヒレ " , " フネ " , " ヘイワ " , " ホコ " , " マリモ " , " ミカン " , " ムクチ " , " メグロ " , " モグラ " , " ヤリ " , " ユキ " , " ヨル " , " ラッパ " , " リス " , " ルス " , " レモン " , " ロバ " , " ワラ " }; int idx ; Stopwatch wc = new Stopwatch (); 34 35 36 private void Form1_KeyDown ( object sender , KeyEventArgs e ) { 37 38 39 40 41 42 if ( e . KeyCode == Keys . Space ) { int seed = Environment . TickCount ; Random rnd = new Random ( seed ); idx = rnd . Next (0 , sData . Length - 1); 43 this . Text = " idx = " + idx . ToString (); 44 45 } 46 47 48 49 50 51 52 if ( e . KeyCode == Keys . Enter ) { label1 . Text = sData [ idx ]; wc . Reset (); wc . Start (); } 53 54 55 56 57 if ( e . KeyCode == Keys . N ) { // w c の 停 止 wc . Stop (); 58 // Shift J I S で 書 き 込 む // 書き込むファイルが既に存在している場合は、追記する System . IO . StreamWriter sw1 = new System . IO . StreamWriter ( @ " d :\ test . txt " , true , System . Text . Encoding . GetEncoding ( " shift_jis " )); // データの書き込み sw1 . Write ( label1 . Text + " \ t " + wc . E l a p s e d M i l l i s e c o n ds + " \ tNo \ r \ n " ); sw1 . Close (); // 閉じる 59 60 61 62 63 64 65 66 67 68 69 } 70 71 72 73 74 if ( e . KeyCode == Keys . Y ) { wc . Stop (); 第5章 68 // Shift J I S で 書 き 込 む // 書き込むファイルが既に存在している場合は、追記する System . IO . StreamWriter sw1 = new System . IO . StreamWriter ( @ " d :\ test . txt " , true , System . Text . Encoding . GetEncoding ( " shift_jis " )); // データの書き込み sw1 . Write ( label1 . Text + " \ t " + wc . E l a p s e d M i l l i s e c o n ds + " \ tYes \ r \ n " ); sw1 . Close (); // 閉じる 75 76 77 78 79 80 81 82 83 84 } 85 } 86 } 87 88 反応時間の記録 } 今回も 88 行もソースがある。しかし、注目するところはわずかである。 ■Stopwatch による経過時間の計測 まず、11 行目に using System.Diagnostics; の 1 行を追加している。これは、時間計測をするために Stopwatch というものを使 うためである。では、ここで、この using について説明しよう。.Net Framework で は、C# で開発するための多くの部品を備えている。この部品をクラスという。電子回 路で用いる IC チップのようなものである。クラスには、さまざまな機能が盛り込まれ ている。このさまざまな機能のことを関数(function ) という。たくさんの関連する クラスが一まとまりになっている。このまとまりのことを名前空間 ( namespace ) と いう。今、namespace1 という名前空間の中に class1 というクラスがあり、そのク ラスの中に function1 という関数があるとしよう。この function1 をプログラムか ら呼び出す場合、 namespace1.class1.function1(); と書く。このように書いてもよいが、タイプ量が多くなり、ミスにもつながる。また、 プログラムの可読性も悪くなる。そこで、プログラムの冒頭で、 using namespace1; と書いておくことで、 class1.function1(); と書くだけで呼び出すことができる。 69 次に、18 行目を見てほしい。 Stopwatch wc = new Stopwatch(); これは、後で説明する「経過時間の計測」をするためのものである。まさに、この行 では、Stopwatch クラスを呼び出しているのである。この Stopwatch クラスは、 System.Diagnostics という名前空間にあるので、 using System.Diagnostics; を書き加えることで、 Stopwatch wc = new System.Diagnostics.Stopwatch(); と書かずに、 Stopwatch wc = new Stopwatch(); と書けるのである。 次に、48 行目から 52 行目を見てほしい。Enter キーを押したときの動作である。 label1.Text = sData[idx]; この行で、インデックス番号 idx に割り当てられた単語を表示させている。 wc.Reset(); この行は、文字どおり Stopwatch wc をリセットしている。 wc.Start(); この行で、Stopwatch をスタートさせている。 では、次に、N キーを押したときの処理を見てみよう。55 行目から 69 行目である。 被験者は、表示された単語が「動物の名前ではない」と判断すると、N キーを押すよ うに教示されているので、ここでのプログラムのタスクは以下のようになる。 1. Stopwatch を停止する 2. 「表示された単語」、「応答時間 (ミリ秒)」、「No と答えたこと」をテキストファ イルに書き出す。 まず、 wc.Stop(); 第5章 70 反応時間の記録 により、Stopwatch を停止している。 ■テキストファイルへのデータの書き出し 次に、59 行目から 68 行目を見てみよう。この部分が、結果の書き込みの部分であ る。まず、61 行目から 64 行目の System.IO.StreamWriter sw1 = new System.IO.StreamWriter... で、テキストファイルへの書き込みの準備をしている。このような準備をしておくと、 以後、sw1 というものを使って、ファイルへの書き込みをすることができる。61 行目 から 64 行目は、この sw1 の設定、つまり、テキストファイルに書き込むときの条件 を指定している。*3 では、どのような書き込み条件を指定しているか見てみよう。 @"d:\test.txt" これは、書き込むファイル名をフルパスで指定している。*4 「@」を先頭に置くと、エ スケープを行わずに\ を文字列に含められるので、パスを指定する場合に可読性が高く なる。true は、データを追記するか否かを指定している。true では、ファイルが存在 しているときファイルの末尾に追加して書き込む。false であれば、既存のファイルに 上書きする。 System.Text.Encoding.GetEncoding("shift_jis") は、文字コードを指定している。shift jis 以外に utf-8 などを指定できる。そして、 実際にテキストの書き込みをしているのは、 sw1.Write( label1.Text + "\t" + wc.ElapsedMilliseconds + "\tNo\r\n" ); の行である。 sw1.Write("テキスト"); で、「テキスト」という文字列を、テキストファイルに書き込むことができる。文字列 にタブを入れるときは、\t と書き、改行したいときは、\r\n と書く。つまり、 *3 C ドライブの直下(ルートフォルダー)には書き込めない場合が多いので、ここでは D ド ライブを指定している。パスはそれぞれの環境に合わせて適宜変更してほしい。 *4 フルパス(Full Path)とは、ルートフォルダーから目的のフォルダーまで順々に記述した パスのこと。絶対パスとも呼ぶ。 71 文字列1<タブ>文字列2<改行> という文字列を書き出す場合は、 sw1.Write("文字列1\t 文字列2\r\n"); のように書く。書き込みが終わったら、必ず sw1.Close(); と書いて、ファイルを閉じる必要がある。では、ここまで学んだことを参考に、71 行 目から 85 行目を解釈してみよう。 動作確認 では、ここまで理解して、サンプル・プログラムと同じようにソースを書いたら、F5 キーを押して実行してみよう。 プログラムを実行すると、画面にフォーム(プログラムのウィンドウ)が現れ、ラベ ル label1 が現れる。Space キーを押すと、単語の配列がシャッフルされ、インデッ クス番号が一つタイトルバーに表示される。Enter キーを押すと、タイトルバーに 表示されているインデックス番号の単語が label1 に表示され、応答時間の計測が始 まる。 被験者は、表示された単語が、動物の名前であれば Y キーを、動物の名前でなけ れば N キーを押す。Y または N のキーが押されると、応答時間の計測を終了し、 「提示した単語」 、 「応答時間」 、 「Yes/No」の情報が以下のようにテキストファイルに記 録される。 テキストファイルへの出力例 シカ 722 Yes スイカ 768 No ソラ 241 No イヌ 571 Yes 保存と終了 [ファイル] メニューから [すべてを保存] を選択し、変更を反映させた後で Visual Studio を終了する。 第5章 72 反応時間の記録 練習問題 応答した日時の記録 ここでは、応答時間を、Stopwatch wc の ElapsedMilliseconds プロパティを 使って取得した。 では、「単語を提示したときの日時」と「応答したときの日時」も記録するにはどう したらよいだろうか?(実験したときの日時を記録しておくと、データを解析するとき に役立つことも多い。) C# では、パソコンの現在日時を取得するには、DateTime.Now メソッドを使う。 この命令によって得られた現在日時は、DateTime 型というものである。これを利用 して、「提示した単語」、「応答時間」、「Yes/No」に加えて、「単語を提示したときの日 時」と「応答したときの日時」をテキストファイルに書き出すように改良してみよう。 ToString() メソッドを思い出してほしい。 テキストファイルへの出力例 トビラ 1287 No 2015 年 1 月 26 日 14:34:35 2015 年 1 月 26 日 14:34:35 サル 1127 Yes 2015 年 1 月 26 日 14:34:37 2015 年 1 月 26 日 14:34:37 ナス 2103 No 2015 年 1 月 26 日 14:34:47 2015 年 1 月 26 日 14:34:47 ネコ 1079 Yes 2015 年 1 月 26 日 14:34:51 2015 年 1 月 26 日 14:34:51 73 第6章 音声による単語刺激の提示 このステップでマスターすること 1. 音声合成による文字列の読み上げ サンプルプログラムの動作確認 こ こ で は 、こ の テ キ ス ト の Web サ イ ト に あ る サ ン プ ル プ ロ グ ラ ム を 実 際 に 動 か し 、そ の 動 作 を 確 認 す る 。今 回 は 、sample\animal_name_04\ を 参 照 す る 。 こ の フ ォ ル ダ ー の 中 に は 、い く つ か の フ ァ イ ル と フ ォ ル ダ ー が あ る 。そ の 中 の animal_name_04\bin\Debug\ とたどっていくと、animal_name_004.exe という ファイルがある。これを実行してほしい。 実行すると、画面にフォーム(プログラムのウィンドウ)が現れ、ラベル label1 が 現れる。Space キーを押すと、単語の配列がシャッフルされ、インデックス番号が一 つタイトルバーに表示される。Enter キーを押すと、タイトルバーに表示されている インデックス番号の単語が label1 に表示され、応答時間の計測が始まる。ここまで は、課題5と同じである。加えて、ここでは、ラベルに単語が表示されると同時に、音 声でも読み上げる。 被験者は、聞き取った単語が動物の名前であれば Y キーを、動物の名前でなければ N キーを押す。Y または N のキーが押されると、応答時間の計測を終了し、「提 示した単語」、「応答時間」、 「Yes/No」の情報がテキスト・ファイルに記録される。 この実験により、文字によるカテゴリ判断と、音声によるカテゴリ判断の判断時間を 比較することができる。 第6章 74 音声による単語刺激の提示 では、この便利なプログラムの作成に取り掛かろう。 プログラムの設計・実装 設計 では、今、動作を確認したプログラムの動作を列挙してみよう。 1. Space キーが押されたら、0 から sData.Length-1 の間の整数の乱数が生成さ れ、そのうちの一つがタイトルバーに表示される。 Enter キーを押すと、タイ トルバーに表示されている番号の単語が label1 に表示され、Stopwatch を リセット後、計測を開始する。 label1 に単語が表示されると同時に、音声合成で単語を読み上げる。 N キーが押されると、Stopwatch が停止し、計測結果(提示した単語、応答 時間、”No”)が、テキスト・ファイルに記録される。 4. Y キーが押されると、Stopwatch が停止し、計測結果(提示した単語、応答 2. 3. 時間、”Yes”)が、テキスト・ファイルに記録される。 プロジェクトの作成 では、早速、サンプルプログラム animal_name_004 と同じものを作ってみよう。 sample フ ォ ル ダ ー の 中 の animal_name_003 フ ォ ル ダ ー を class_sample *1 そ の フ ォ ル ダ ー に コ ピ ー し 、フ ォ ル ダ ー 名 を animal_name_004 に 変 更 す る 。 animal_name_004 フォルダーの中の animal_name_002.sln というファイルを、と いうファイルを選択し、Enter キーを押す。マウスによる操作の場合は、ファイルの アイコンを選択した状態でダブルクリックする。 VS が起動し、課題5のプロジェクトが読み込まれる。[アセンブリ名] を変更し、デ ザイナ画面を表示する。*2 画面デザイン 課題5から変更する点として、「音声合成を使うための準備」が必要になる。.NET Framework では、さまざまな機能を追加するためのモジュールがたくさん用意されて *1 *2 自分で作成した第 5 章の課題のプロジェクトファイルを利用してもかまわない。 操作方法については、p. 57 を参照してほしい。 75 いる。このモジュールを、自分のプロジェクトに取り込んで利用する方法を、「音声合 成を使うための準備」を例に説明しよう。*3 ここでは、まず、参照の追加という作業をする。参照とは、.NET Framework に用 意されているモジュールにアクセスできるようにするための設定である。 参照を追加するには、以下のようにする。 1. [プロジェクト] メニューから [参照の追加] を選択する。 2. すると、.NET Framework で用意されているモジュールの一覧が出る。この中 から System.Speech を選択してチェックボックスをクリックするかまたは、 System.Speech をダブルクリックして選択する。 3. [OK] をクリックするか Enter キーを押して戻る。 図 6.1 System.Speech への参照の追加 この作業により、System.Speech というモジュールの中にある関数を呼び出して 利用できるようになる。このようなモジュールのことをアセンブリといい、モジュール の中にある機能ごとのユニットのことをクラスという。さらに、各クラスの中には、さ まざまな機能を実現するためのメンバ関数がある。 *3 Windows 7 の環境で、音声合成による読み上げを利用したプログラムを実行するために は、別途 PC-talker やドキュメントトーカなどの音声合成エンジンを導入しておく必要が ある。Windows 8、8.1 を使用する場合は、標準で備わっているため、別途音声合成エン ジンをインストールする必要はない。 第6章 76 音声による単語刺激の提示 コントロールの各種設定 今回は課題5のままでよい。 イベント関数の生成 今回は課題5のままでよい。 動作の実装 まず、サンプル・プログラムのソースを見てみよう。 リスト 6.1 1 2 3 4 5 6 7 8 9 using using using using using using using using using animal name 004.cs System ; System . Collections . Generic ; System . Comp onent Model ; System . Data ; System . Drawing ; System . Linq ; System . Text ; System . Threading . Tasks ; System . Windows . Forms ; 10 11 using System . Diagnostics ; 12 13 14 using System . Speech ; using System . Speech . Synthesis ; 15 16 17 18 19 20 21 22 23 24 namespace a n im a l_ nam e_ 00 2 { public partial class Form1 : Form { public Form1 () { I n i t i a l i z eC o m p o n e n t (); } 25 26 27 28 29 30 31 32 33 34 35 string [] sData = { " アヒル " , " イヌ " , " ウサギ " , " エビ " , " オカ " , " カメ " , " キツネ " , " クマ " , " ケイト " , " コマ " , " サル " , " シカ " , " スイカ " , " セトモノ " , " ソラ " , " タヌキ " , " チドリ " , " ツバメ " , " テツボウ " , " トビラ " , " ナス " , " ニワトリ " , " ヌマチ " , " ネコ " , " ノハラ " , " ハト " , " ヒレ " , " フネ " , " ヘイワ " , " ホコ " , " マリモ " , " ミカン " , " ムクチ " , " メグロ " , " モグラ " , " ヤリ " , " ユキ " , " ヨル " , " ラッパ " , " リス " , " ルス " , " レモン " , " ロバ " , " ワラ " }; 77 36 int idx ; 37 38 Stopwatch wc = new Stopwatch (); 39 40 Spee c h S y n t h es i z e r syn = new S pee c hS yn the s iz e r (); 41 42 private void Form1_KeyDown ( object sender , KeyEventArgs e ) { if ( e . KeyCode == Keys . Space ) { int seed = Environment . TickCount ; Random rnd = new Random ( seed ); idx = rnd . Next (0 , sData . Length - 1); 43 44 45 46 47 48 49 50 this . Text = " idx = " + idx . ToString (); 51 } 52 53 if ( e . KeyCode == Keys . Enter ) { label1 . Text = sData [ idx ]; syn . Speak ( sData [ idx ]); wc . Reset (); wc . Start (); } 54 55 56 57 58 59 60 61 if ( e . KeyCode == Keys . N ) { wc . Stop (); // タ イ マ ー を 停 止 す る 62 63 64 65 // Shift J I S で 書 き 込 む // 書 き 込 む フ ァ イ ル が 既 に 存 在 し て い る 場 合 は 、 追 記 す る System . IO . StreamWriter sw1 = new System . IO . StreamWriter ( @ " d :\ test . txt " , true , System . Text . Encoding . GetEncoding ( " shift_jis " )); // データの書き込み sw1 . Write ( label1 . Text + " \ t " + wc . E l a p s e d M i l l i s e c o n ds + " \ tNo \ r \ n " ); sw1 . Close (); // フ ァ イ ル を 閉 じ る 66 67 68 69 70 71 72 73 74 75 } 76 77 if ( e . KeyCode == Keys . Y ) { wc . Stop (); // タ イ マ ー を 停 止 す る 78 79 80 81 // Shift J I S で 書 き 込 む // 書 き 込 む フ ァ イ ル が 既 に 存 在 し て い る 場 合 は 、 追 記 す る System . IO . StreamWriter sw1 = new System . IO . StreamWriter ( @ " d :\ test . txt " , true , System . Text . Encoding . GetEncoding ( " shift_jis " )); // データの書き込み sw1 . Write ( label1 . Text + " \ t " + wc . E l a p s e d M i l l i s e c o n ds + " \ tYes \ r \ n " ); sw1 . Close (); // フ ァ イ ル を 閉 じ る 82 83 84 85 86 87 88 89 90 91 } 92 } 93 94 } 第6章 78 95 音声による単語刺激の提示 } 今回も 95 行もソースがある。ついに 100 行近くになったが、注目するところはわずか である。ここでは、課題5から変更された「音声合成による読み上げ」の部分に注目し て見ていくことにする。 ■音声合成による文字列の読み上げ まず、13、14 行目に using System.Speech; using System.Speech.Synthesis; の 2 行を追加している。これは、先に参照の追加をした System.Speech の中の関数 を呼び出すことを宣言するものである。 この 2 行を追加することで、 System.Speech.function_1(); System.Speech.Synthesis.function_2(); などと書く代わりに、単に function_1(); function_2(); と書くだけでよくなる。 次に、41 行目を見てみよう。 SpeechSynthesizer syn = new SpeechSynthesizer(); これは、System.Speech というモジュールの中にある SpeechSynthesizer とい うクラスを実際に使えるようにするためのものである。実は、クラスは部品の一般名称 のようなもので、実際に実装するにはその実体を作らなければならない。電子回路に 例えると、「抵抗」というのは一般名称だが、実際に実装するときは、R1, R2, R3, .... のように個別に名称をつけて実装していく。このようなイメージになる。ここで は、SpeechSynthesizer という部品を syn という名前で実装しているとイメージし てほしい。 次に、いよいよ単語を読み上げる部分を見てみよう。57 行目を見てほしい。 syn.Speak(sData[idx]); 79 この 1 行で、文字列 sData[idx] を読み上げさせている。 動作確認 では、ここまで理解して、サンプルと同じようにソースを書いたら、F5 キーを押し て実行してみよう。 プログラムを実行すると、画面にフォーム(プログラムのウィンドウ)が現れ、ラベ ル label1 が現れる。Space キーを押すと、単語の配列がシャッフルされ、インデッ クス番号が一つタイトルバーに表示される。Enter キーを押すと、タイトルバーに表 示されているインデックス番号の単語が label1 に表示され、さらに、その単語が読み 上げられる。そして、応答時間の計測が始まる。 被験者は、聞き取った単語が動物の名前であれば Y キーを、動物の名前でなければ N キーを押す。Y または N のキーが押されると、応答時間の計測を終了し、「提 示した単語」、 「応答時間」、 「Yes/No」の情報が以下のようにテキスト・ファイルに記 録される。 テキストファイルの出力例 シカ 722 Yes スイカ 768 No ソラ 241 No イヌ 571 Yes 保存と終了 [ファイル] メニューから [すべてを保存] を選択し、変更を反映させた後で Visual Studio を終了する。 練習問題 読み上げスピードの変更 提示された単語の読み上げスピードも、カテゴリ判断に影響するだろう。それを確 認するために、読み上げスピードを変えられるようにしよう。SpeechSynthesizer syn の読み上げスピードは、Rate プロパティで取得したり変更することができる。設 定できる値は、-10 から 10 までである。例えば、 第6章 80 syn.Rate = 4; syn.Rate = -4; 音声による単語刺激の提示 // 速く // 遅く のように指定してから読みあげを実行すると、指定されたスピードで読み上げる。 81 索引 ++, 37 .NET Framework, 8 =, 15 [ ], 60 %, 41 BackColor, 22 Beep, 38, 41 Close, 71 DateTime, 72 DateTime.Now, 72 ElapsedMilliseconds, 72 else, 37 Enabled, 36 F5 キー, 10 ForeColor, 22 Form1, 14 Framework, 8 function, 68 Point, 51 Random, 61 Rate プロパティ, 79 seed, 61 Space キー, 39 Speak, 79 SpeechSynthesizer, 78 Stopwatch, 69 StreamWriter, 70 string, 60 System.Speech, 78 Text プロパティ, 14 Text プロパティの変更, 22 this, 14 timer, 32, 36 ToInt32, 42 ToString(), 26 using, 68 Write, 70 if, 37 if 文, 37 int, 25 Interval, 38 KeyCode, 60 KeyDown, 49 KeyPreview, 48 Location, 51 Microsoft Visual Studio 2012 Professional Edition, 2 namespace, 68 アセンブリ, 75 アセンブリ名, 57 新しいプロジェクト, 7 アルゴリズム, 20 イベント関数, xiii, 13 イベントボタン, 48 インストール, 2 改行, 71 開発言語, 7 画面デザイン, xii 関数, 68 索引 82 クラス, 68, 75 変数, 25 変数の初期化, 25 現在日時の取得, 72 コード画面, 13 コントロール, xii ボタン, 22 ボタンの配置, 12 メンバ関数, 75 参照, 75 参照の追加, 75 シード, 61 剰余, 41 設計, xi セミコロン, 25 ソリューション エクスプローラー, 10 ソリューションのプロパティ, 57 大小関係, 43 代入, 15, 25 タイマー, 32 タッピング, 18 タブ, 71 ツールボックス, 11, 12, 22 テキストファイル, 70 デザイナ画面, 9 名前空間, 68 背景の色, 22 配列, 59 配列のシャッフル, 63 バグ, xi ビープ音, 38 表示メニュー, 12 ファイルへの書き込み, 70 ファイルを閉じる, 71 フレームワーク, 8 プログラム開発環境, 2 プログラムの実行, 10 プロジェクトの作成, 21 プロジェクトを開く, 7 プロパティ, xii, 14, 22 プロパティ ウィンドウ, 11 文字コード, 70 文字の色, 22 乱数, 61 ランダムな並び替え, 63 ■著者略歴 本書サポートページ URL: http://www.u-toyama.ac.jp/ 上記 URL には、本書に関するサポート情報や課題および練習問題の解答例のデータ を掲載しております。 心理実験のための C#プログラム実践講座(上) 2015 年 3 月 6 日 初版 発行 著 者 鈴木 淳也 監 修 木原 寛 発行者 富山大学大学院生命融合科学教育部 〒930-8555 富山市五福 3190 番地