この冬、高校生向けに「VRとエンタメ技術のクリスマスレクチャー」をお届けします。

「クリスマス・レクチャー」ってご存知ですか?

「クリスマス・レクチャー(Christmas Lectures)」ってご存知ですか?
イギリスの王室が中心になって開催している科学講座です(本家)。クリスマスシーズンに子供たちへのプレゼントとして開かれているので、クリスマス・レクチャーと呼ばれています。クリスマスレクチャーは歴史が古く、1825年にマイケル・ファラデーによって開催された科学講座が最初の講演で、現在も続いているそうです。

普段は出前講義をしない私ですが

2015年7月11日に講演した「夢ナビライブ2015」が受講者数317名とレコード級の大好評だったらしいです。私もびっくりです。

これはニコニコ生放送で配信されたダイジェスト版ですね。
「バーチャルリアリティ技術で人類を楽しくさせたい」

出張講義の御依頼をいただきました

先日、湘南学園中学高等学校 高校1学年担当 植田卓真先生より「高校1年生対象 大学模擬授業(出張講義)講師派遣のお願い」をいただきました。夢ナビのご縁だそうです。

謹 啓
秋涼の候、益々ご清祥のこととお慶び申し上げます。
私は、神奈川県・藤沢市にございます、私立湘南学園中学校・高等学校におきまして、高1学年の担当をしております植田卓真と申します。この度、私どもの学年で行う「大学模擬授業」に是非とも先生のご協力を賜りたく、依頼状を送付させていただきました。
本校では、高校2年次に進級する際、文系・理系いずれかのコースを生徒に選択させます。この決定に向け、高校1年生の生徒たちを対象に、様々なかたちでの進路指導を行っておりますが、中には早くから将来の進路について具体的な目標を掲げ、大学での研究に目標や希望を持つ生徒もいる一方、自分自身の適性や将来の向けての道筋などにつきまして具体的に描くことが難しいと感じている生徒もおります。
そこで、「大学ではどのような学問の世界が広がっているのか・・・」それを具体的に示し、文理選択を主体的に進めていくための一助としたいと願い、毎年、「大学模擬授業」の機会を設けております。各学問分野で教鞭をおとりの先生方を本校にお招きし、45分程度の模擬授業(質疑含めて55分を予定)を行っていただくという取り組みです。
お忙しい先生方に、一つの小さな私学での、このようなささやかな取り組みにご協力いただくのは誠に恐縮でございます。全国学校案内資料管理事務センター主催の「夢ナビプログラム」を利用し、生徒が関心を持っているワードの登録を行ったところ、白井先生の講義「遊びの哲学を持った、これからのコンピュータゲーム研究」に関心が多く集まりました。是非とも、本校にてご講義願えないかと考えた次第です。依頼内容は、下記の通りですのでご確認ください。
いまのところ、1校時・2校時に分けて16テーマ程度の講義を設定したいと考えております。本校の高校1年生生徒(在籍数188名)がその中から2つの分野を選択して講義を受けるという形式です。各講義に出席させていただく生徒数は、おおよそ20数名程度になるかと思います。
ご多忙のこととは存じますが、何卒宜しくお願い申し上げます。
敬 具

大変丁寧な依頼文で感動。

同様のご依頼を東京都立町田工業高等学校さんからもいただいております。

大学のプロモーションって、いろいろ気を使うので、普段はあまり高校生向け出前講義をすることはないのですが、クリスマスの時期ですし、夏の講演が大変勇気付けられる反響でしたので、いくつかの高校で出前講義を受けたいと思いました。

いちおう私も科学コミュニケーたーの端くれですので!

講演予定

12月12日(土) 湘南学園中学高等学校

2校時目 10:40~11:35(この時間帯の中で45分講義、10分質疑)
『遊びの哲学を持った、これからのコンピュータゲーム研究』(仮)

12月18日(金) 東京都立町田工業高等学校

9:45~11:15
『次世代エンタテイメントシステム』(仮)

エンタテイメント(娯楽)システムは、従来の映像中心の家庭用コンピュータゲームや携帯ゲームから、遊園地、インタラクティブな科学館・博物館での展示物、メディア芸術、お年寄りや言葉の通じない外国人 。学校教育といった様々なシーンに利用され始めています。「新しい楽しさ」を「設計する技術」を紹介します。

うちの大学の出前講義面白そう

神奈川工科大学としてはこのような講演を「出前講義プログラム」として提供しているそうです。そんなわけで私の所属プロダクションは神奈川工科大学なので、クリスマスかどうかに関わらず、遠慮なく大学に打診いただけるとよいかと思います。

www.kait.jp/gwy_edu/pdf/2015_demae_kougi.pdf

どれも面白そうですよ。

夏の”夢ナビ”ふりかえり中

さて、高校生のマインドに立ち戻ってみるために、夏の夢ナビの講演を振り返ってみています。特にフィードバックとして聴講された全国の生徒さんたちから「先生へのメッセージ・感想」をいただいておりますのでご紹介とコメントしてみたいと思います。

・あまり関心をもっていなかった分野に興味をもつことができました!(大妻高等学校 高1 女子)
・ニコニコメガネやVRに興味を持っていてこの講義を受けましたが知りたい情報がすべて聞けたので良かったです。(東京農業大学第一高等学校 高1 男子)
・興味をもった。(芝高等学校 高1 男子)
・講義内容がとてもわかりやすかったです。ゲームに興味をもちつつ、人の役に立つか自信がなかったのですが、しっかり進路のひとつとして考えらました。(杉戸高等学校 高2 男子)
・私が知らないすごい技術が沢山あって感動しました。(東京農業大学第一高等学校 高1 女子)
・人に楽しんでもらえるものをやる。すごく感動しました。(成立学園高等学校 高2 男子)
・たのしかったです。(國學院大學久我山高等学校 高1 男子)
・超会議に行ってみたくなった。(朋優学院高等学校 高1 男子)
・人間の娯楽に作用するコンピューターについて様々な話を聞くことができたのでよかった。(芝高等学校 高1 男子)
・とてもおもしろかったです!(東京都市大学等々力高等学校 高1 男子)
・とてもわかりやすかったです。(山村学園高等学校 高2 男子)
・講義はとてもわかりやすく、先生の話し方もよくて、とても満足した。(芝高等学校 高1 男子)
・自分も何か人がよろこぶようなことをしていきたいと感じることができました。(自由ケ丘学園高等学校 高1 男子)
・ニコニコ動画を見たことがあるので、気になって話をきいてみたら思った以上にたのしかったです。(館林高等学校 高2 男子)
・先生の講義を聞きましたがとてもさんこうになりました。(練馬高等学校 高2 男子)
・とてもよかったです。(東京都市大学等々力高等学校 高1 男子)
・神奈川工科大学にとても興味がわきました。(芝高等学校 高1 男子)
・エンターテーメントについての考え方が変わった。(芝高等学校 高1 男子)
・とてもおもしろく指導してくださり、ありがとうございました。(淑徳巣鴨高等学校 高1 男子)
・「クリエイターになるコツ」についてよくわかった。非常に見ていて、たのしかった。(横浜高等学校 高1 男子)
・色々なことをやって、勉強する必要があるのだなと思いました。(富士見高等学校 高1 女子)
・工学に関する理解が深まった。(城西大学付属川越高等学校 高2 男子)
・ありがとうございます。(海城高等学校 高1 男子)
・ニコニコのうらを知れた。(芝高等学校 高1 男子)
→私は中の人ではありませんが、リコメンドエンジンの話や超会議でのオープニング前朝礼などの経験もお話させていただきましたので、”裏側”に目を向ける機会を得られたのであればよかったです。
・コンピューターに使用を娯楽に向けてみると、様々な事に使用されているのが驚いた。(最新スゲー!)(上野学園高等学校 高1 男子)
→「最新スゲー」です!
・ニコニコというワードから受講したが、とてもおもしろかった。(海城高等学校 高1 男子)
→「みんなをニコニコさせる技術」という意味では間違ってないと思います
・自分の事をマンガにしていてとてもおもしろかった。(館林高等学校 高2 男子)
・ニコニコ超会議などで有名な人なので、実際に会えてよかった。話の内容も、興味があるものだったのでとても良かった。(大田桜台高等学校 高1 男子)
・分かりやすくて、面白かったです。(東野高等学校 高2 男子)
・人に求められる楽しいことをするということが本質があった。2つの授業を見て、未来をみてしまった気がする。(芝高等学校 高1 男子)
・とてもわかりやすく、おもしろかったです。ありがとうございました。(練馬高等学校 高1 女子)
・私も、今、簡単なコンピュータプログラムを作っていて、先生の話を聞いてもっとやってみたくなりました。(京華高等学校 高2 男子)
・僕もニコニコ動ったので気持ちなどがよくわかった。本当にありがとうございます。(本庄東高等学校 高2 男子)
・様々な技術の発展がよくわかった。非常におもしろかった。(かえつ有明高等学校 高1 男子)
・クリエイターの仕事内容がよくわかりました。(花咲徳栄高等学校 高2 男子)
・ゲームが正しいことがなく分かりました。いつか使ってみたいです。頑張ってください。(海城高等学校 高1 男子)
・話がおもしろくて、聞くのが楽しかった。(芝高等学校 高1 男子)
・とても興味深い話をありがとうございました。先進的なことを知ることができて面白かったです。(芝高等学校 高1 男子)
・とても楽しい内容でした。(武蔵丘高等学校 高1 男子)
・とても面白かったです。凄くいい話が聞けました。有意義な話をありがとうございました。(クラーク記念国際高等学校 東京キャンパス 高2 男子)
・ゲームなどという見近な物から将来のことについても知り、考えることができました。(神奈川学園高等学校 高1 女子)
・ゲームについての見方がかわりました!最新技術をつかったゲームがもっと普及してほしいです!(昭和女子大学附属昭和高等学校 高2 女子)
・「大学を選ぶときは研究所で選べ」という事が心に残った。また、先生が一つ一つ目標をきめて行動しているのがすごいと思った。(芝高等学校 高1 男子)
→ 研究「室」で選びましょう!
・ニコニコ超会議で絶賛された2D、3Dを一緒に見ることができるニコニコメガネはとてもすごくよかったです!(東京農業大学第一高等学校 高1 男子)
・他の先生と違い漫画で説明していたので、また違った感覚でおもしろかったです。(横浜高等学校 高1 男子)
・ニコニコ超会議で大賞をとったのがすごいと思ったしそのきのうもすごいなと思った。(大田桜台高等学校 高1 男子)
・ニコニコ超会議のあおりにつられ、やってきたが実にオモシロイ。生き方もスゴクオモシロカッタ。また来てみたい。(郁文館高等学校 高1 女子)
・様々なことを経験することは、大きな武器だということがわかりました。(海城高等学校 高1 男子)
・情報化はあまりきょうみなかったけど、おもしろかった。(豊南高等学校 高2 女子)
・自分の子どもたちが遊んでるゲームをつくろうという発想はなかったマンガのやつやニコニコメガネには驚いた。(芝高等学校 高1 男子)
・よく分かりやすかったですありがとうございます。(城西大学付属川越高等学校 高2 男子)
・ゲーム制作についてもともと感心あったけどもっと関心を持ちました。厚木だとうちのおばあちゃんの家の近くだから「行きやすい!」って思ったりしてました。これからもがんばってく
ださい!(武蔵丘高等学校 高1 男子)
・親しみやすい内容でとても面白かった。(芝高等学校 高1 男子)
・先生の話している内容が自分にとって興味がある物なので非常に良かった。(城西大学付属川越高等学校 高2 男子)
・自分が楽しいでなく求められる楽しいという考えはとても勉強になりました。エンタメの考え方が変わりました。(井草高等学校 高3 男子)
・大学選びのポイントや、自分ではなく他人を喜ばせる喜びを教えていただき、ありがとうございました。(淑徳高等学校 高1 男子)
・とてもおもしろかった。(芝高等学校 高1 男子)
・話がとてもおもしろかったです。まんがの絵がうまいと思いました。(芝高等学校 高1 男子)
・面白かったです。(東京農業大学第一高等学校 高1 女子)
・興味がわきました。(安田学園高等学校 高2 男子)
・話の内容もとても面白かったです。(京華高等学校 高1 男子)
・ゲーム作りも楽しそう。きっと、オープンキャンパスに行きます。(三田高等学校 高1 男子)
・「成長のためにもゲームは必要」と意見にとても賛同できた。「人を楽しませる」というワードも自分の中ではかなり納得させられた。(正則高等学校 高2 男子)
・おもしろかったです。(富士見高等学校 高1 女子)
・先生のひげが特長的でマンガのイラストとそっくりですごかったです。ゲームの制作などにとても興味がわきました。(館林高等学校 高2 男子)
・次世代の技術はすごいと思いました。(東洋大学京北高等学校 高1 男子)
・エンターテインメントについて理解すこることができた。それを扱う世界に興味がもてた。(芝高等学校 高1 男子)
・分からなかったことが分かるようになりました。(藤沢翔陵高等学校 高2 男子)
・すごい人生を送ってきてすごく参考になったのですが、もう少しプログラムについて色々聞きたかったです。(明星高等学校 高2 男子)
・とても興味深く、ここの大学で学びたくなった。(明星高等学校 高2 男子)
・エンターテイメントの活用法やバーチャルリアリティなどでできることなど多くの事を知り、興味がいっそう深まりました。(千葉明徳高等学校 高1 男子)
・正直にとても面白かった。(芝高等学校 高1 男子)
・とても奇抜な授業でとてもお面しろかったです。初めての体験で驚きを感じられました。(城西大学付属川越高等学校 高2 男子)
・ニコニコ超会議は1回も行ったことがないので、いつか行って、先生に会いたいです!プログラミングも、いつか自分がやってみたいです!(淑徳巣鴨高等学校 高1 男子)
・多重化技術に対して、物すごい技術だと思うとともに、自分も開発にたずさわってみたいと思える講義でした。(京華高等学校 高1 男子)
・わかりやすい説明でありがとうございました。(豊南高等学校 高2 男子)
・オープンキャンパスに行こうと思いました。ありがとうございました。(大森学園高等学校 高2 女子)
・興味のある話があっておもしろかった。(城西大学付属川越高等学校 高2 男子)
・とても面白いと思った。(芝高等学校 高1 男子)
・講義後も長い時間質問を受けていただきありがとうございました。とても楽しかったです。(獨協高等学校 高1 男子)
・ゲームを主点として子育てや色んなものを見ることに非常に興味がわいた。(芝高等学校 高1 男子)
・ゲームなど好きなので講義を受けました。いろいろなソフトがあるのでそれを使い作っていると思うとあらためてすごいと思った。(藤沢翔陵高等学校 高2 男子)
・自分のやりたいことを現実化するのが、いかに難しいのかということがわかり良かったです。(京華高等学校 高2 男子)
・とてもおもしろかったです。ゲームの道を目指していきたいと思いました。ありがとうございました。(神奈川総合高等学校 高1 女子)
・ゲームクリエイトの楽しさがなんとなく分かった。自分もゲームするので興味もてた。(芝高等学校 高1 男子)
・好きな分野なのでおもしろかったです。(桜丘高等学校 高1 男子)
・先生のトークのテンポがよくて聞いててとても楽しかったです。(東京農業大学第一高等学校 高1 女子)
・超会議について真面目に考えてみると意外と面白かった。(朋優学院高等学校 高1 男子)
・それなりに楽しむことができました。(本庄東高等学校 高2 男子)
・おもしろそうだなと思っていたのがさらに高くなりました。(山村学園高等学校 高2 女子)
・今まであんまり勉強してなくてもこれからやればどうにかなると希望がもてて良かったです。オープンキャンパス行こうかなと思いました。(大妻高等学校 高1 女子)
・世界でここだけの研究ということにおどろきました。自分もゲームが好きなのでそういう研究は楽しそうだと思いました。(東洋大学京北高等学校 高1 男子)
・神奈川工科大学に行きたくなれる講義をありがとうございました。来年のニコニコ超会議も頑張ってください。(東京都市大学等々力高等学校 高1 男子)
・19歳が転機でそこからこれほどの功績を出せる程になったと聞いて、未だやりたい事が決まらずあせっていたが安心した。(海城高等学校 高1 男子)
・先生は神ですゲーマーの神です。(新宿高等学校 高1 男子)
・現代の娯楽、エンターテイメントを深く知ることができた。(芝高等学校 高1 男子)
・説明のとき、スライドがマンガになっていて分かりやすかった。(安田学園高等学校 高2 男子)
・おもしろかったです。(聖学院高等学校 高2 男子)
・プログラムとか工科あたりにすごくきょうみがでてきました。(その他)
・行ってみたいと思いました。(その他)
・分かりやすく面白い内容だった。(その他)

「ニコニコ動画」というキーワードで引き寄せられただけの高校生が、工学,ものづくり,面白いものを,ただ見るだけじゃなくて作る側の視点に立つというきっかけを「地続きで」与えられたのはすばらしいな!と読み返してみて思いました。

というか、これはゲーム業界・エンタメ業界・メディアアート業界のエンジニア感涙のフィードバックだと思いますよ。シェアせざるを得ない。

そういや講演のあとの質問もたくさんの熱い高校生に囲まれたのでした。

忙しいとこういうことも日々のタイムラインに流れていってしまうのが残念。
彼らが再び、私の講義を聴いてくれる日は来るだろうか。

まとめ「師走ですから…ね」

基本的に年末、「師走」って、大学の先生は走り回って忙しないじゃないですか。セワシナイ。

自分から忙しくなることは良い事とは思いませんが、若い生徒たちが、単に受験勉強ばっかり、つまらない作業ばかりにエネルギーを費やすのではなくて、「自分の興味のその先に、楽しい未来や予想もしないような世界が広がっている…!!」って感じるきっかけを伝えるのは、未来がやってくる感がありますよ。フィードバックも素晴らしいし。

そんなわけで、私自身がよい来年を迎えられるように、忙しい年末ではありますが、東奔西走させていただきたいと思います。

クリスマスレクチャーで、僕と握手!

 

ICU講義「コンピュータゲーム」最終課題まとめ

草原真知子先生のご紹介で国際基督教大学(ICU)での非常勤講師「コンピュータゲーム」を担当し始めたのが、たしか2009年だったと記憶しているので、もう7年目になるだろうか。

ここ数年は春学期に開催し、IVRCへの挑戦なども行っていたのだけれど、プレゼン審査で通ったとしても、その後の展開が難しいし、私自身が審査委員も兼ねていることから、ものすごく忙しくなってしまう上に投稿件数が増えるということ以外にメリットがない。そのため2015年度はもともとの開講期である秋学期の月曜日に変更した。

秋の深まりを毎週感じられるICU三鷹のキャンパスも美しく、また今年度も大変、興味深い、個性的な学生が多く存在した。

例年であれば課題はすべてFacebookやメール上でクローズに共有しているのであるが、今年度は「面白さをシェアする」という目的で希望する学生については積極的にシェアできるよう、ご協力をお願いした。

毎年の講義は内容を変えているので参考になるかどうかは保証がないが、以下、講義の内容や「学生視点でのおすすめ」をまとめてみたので振り返りの機会としたい。

まずは学生Hさんのブログより。

哲学言語学メジャーの上位学年だけあって、なかなかよくかけている。

harutoshimoda2.blogspot.jp/2015/11/blog-post.html

講義「コンピュータゲーム」で学んだこと

この講義では「エンターテイメントシステム」という概念を様々な角度から考えました。この授業を受講するまで「エンターテインメントシステム」という言葉すら私は知りませんでしたが、授業では豊富な実例を交えながらその内容に迫りました。白井先生によれば「エンターテインメントシステム」とは「人々の娯楽に作用するようにデザインするシステム」だと定義されます。重要な点は、エンターテイメントシステムはシステムであるので、映画やゲームソフトなどコンテンツそのものとは区別されるということです。コンテンツとコンテンツをどのように享受するのかといった環境まで含めてエンターテイメントシステムだということです。例えば、動画そのものはコンテンツだが、ニコ動やyoutubeなどの動画サイトは動画に対するコメントやオススメ動画の表示などユーザーに対してコンテンツを楽しむための環境を提供しています。このようなとりわけ双方向性のあるサービスはエンターテインメントシステムだと言えるのです。
さて、この授業で学んだことは大きく二つに分けることができると思います。第一に、「エンターテインメントとは何か」という人間に関する要素。次に「エンターテインメントを可能にするシステムにはどのようなものがあるか」という技術、設計に関する要素です。我々受講生はこの二つの要素を様々な実習課題を通して考えました。

「エンターテインメントとは何か」

まずは「エンターテインメントとは何か」の部分です。

この授業は「遊び」とは何かという哲学的な問いからこの授業は始まりました。これは「エンターテインメント・システム」の「エンターテインメント」とは何かという問いと深く関連しています。白井先生は「遊び」という概念を6つの要素にわけることで「遊び」とは何かという問いに迫りました。その6つの要素とは、「いつでもやめられる自由な活動」「日常と非連続で隔離された活動」「現実世界に富を生まない非生産的活動」「現実と区別がつく、虚構の活動」「遊びの世界を支配する、規則のある活動」「選択の自由がある未確定の活動」です。ある活動が「遊び」であるとは、以上6つの要素を満たす活動であるのです。我々は課題として、身近な活動が遊びであるかないかを遊びの6要素からみて検討しました。

ピアジェによる遊びの段階説についても学びました。ピアジェによると人間は発達段階に応じて遊びの質も変化するそうです。まず、生後1〜2歳くらいまでに感覚運動遊びを獲得します。これは、外界を操作したり身体を動かしているだけで楽しいと思う状態です。次に、2〜5、6才までに象徴的遊びを獲得します。これは、ごっこ遊びなどや模倣などの記号化能力が必要とされる遊びです。そして、7歳行以降からルールのある遊びを獲得します。これは、思考の具体的操作,個人間の関係理解,世界観・因果と偶然が理解できる.ルールのある遊び,社会的遊びが含まれます。

次に、「ペルソナ」という概念について我々は学びました。「ペルソナ」とはサービスを享受する人が性、年齢、趣向など、どのような人間であるのかということです。エンターテインメントシステムを設計する上で、ユーザーのペルソナを考えて設計することは非常に重要です。ペルソナを考える上で重要な点のは2点あります。第一に「ペルソナ」は「動的」だということです。ペルソナはエンターテインメントシステムとの関わりの中で、変化するということを忘れてはなりません。例えば、子供の頃「テニスの王子様」や「ファイナルファンタジー」に触れて育った男の子がその後経験を重ねてどのようにペルソナが変化し成長したのかを長期的な時間軸で考えることが、システム設計時に想定されるユーザーを考える上で重要なのです。さらに重要なのは、「ペルソナ」は「複合的」だということです。複合的とはつまりあるエンターテインメントシステムのユーザーは異なる複数のペルソナのセットだということです。例えば、子供向けゲームソフトのプレーヤーは子供ですが、お金を出すのは親なので親にも楽しんでもらえたりすような内容やお金を出しやすい価格帯であることがゲームソフト設計にとって重要なのです。

「エンターテインメントを可能にするシステムにはどのようなものがあるか」

次に、「エンターテインメントを可能にするシステムにはどのようなものがあるか」の部分です。この授業では、かなり数多くのエンターテインメントシステムに関わる技術を紹介しました。ここではそのうちいくつか自分の印象に残った技術を紹介します。

最初に我々はUnityという、ゲームソフトウェア開発環境について知り、簡単な操作をしてみました。この開発環境はゲーム業界では世界的に広く使われているので知っているべきだそうです。Unityでは、3D映像のレンダリングも可能です。レンダリングとは、映像や音声などをコンピュータ上で生成することです。

さらに、白井先生が開発している、画面の多重化技術についても知りました。この技術では一つの画面は二つの映像を同時に提供しており、裸眼ではそのうちの一つの映像を、特殊なメガネをかけた視聴者はもう一つの映像を見ることができる技術です。

MITが開発したping pong plusでは、卓球台にコンタクトマイクを仕込み、それにより卓球の球が当たった位置を把握し、それに連動して映像を卓球台に写したり、音声を再生したりといったことが可能となります。

日本科学未来館ではDigital Content Expo 2015というイベントが開催されました。そこでも数多くの技術が紹介紹介されていました。筑波大学による、複数のカメラの映像を組み合わせてユーザーにスタジアムでサッカーの試合などをズームや角度など自由な視点で試合を楽しめる「自由視点スタジアム」や、東大と慶応大による、赤ちゃんがおしゃぶりをする吸い方、強さ、吸う感覚などの情報を取得しその様子を別デバイスで確認することを可能にする「デジタルおしゃぶり」などユニークな技術を数多く知ることができました。

さらには、2048というスマホゲームのゲームクローンを作る課題を、一部の人がやり、発表がありました。そこでは、各々がCやprocessingやHaskellなど異なる言語で 2048を作っていました。ソースコードも発表し、私はその課題は選ばなかったのですが、非常に刺激になりました。

以上挙げた例を他にも、数多くのエンターテインメントシステム関わる技術が世の中にはあるということをこの授業では学びました、これらの技術がどのようにエンターテインメントに応用されているのかを幾つかの課題を通して学びました。

以下では、課題を通して学んだことを紹介したいと思います。

課題を通して学んだこと

印象に残った課題があります。われわれは課題の一つとして、テクノロジーを利用して従来のスポーツを拡張するという「超人スポーツ」のコンセプトに基づいて、新しいエンターテインメントシステムを企画設計する課題に受講生は取り組みました。この課題は、授業で学んだ「ユーザーの複合動的ペルソナ」、「既存の技術のエンターテインメントシステムへの応用」、「人が楽しいと思うとはどういうことか」について考える絶好の機会となりました。またそれと同時に「技術的な実現性によって、対象ユーザーのペルソナが制限されてしまう」というシステム設計の難しさも実感しました。

私は「魔物スカッシュ」というゲームを提案しました。壁に移された魔物をテニスボール(またはスカッシュボール)で倒すゲームです。技術的には、先に挙げたMITのping pong plusの技術を卓球台だけでなく、壁打ちの壁へ応用するという提案です。これは、感覚運動遊びであり、魔物を倒す世界観のなかで戦士になりきる象徴的遊びであり、一定回数制限時間内に球を魔物にあてなければならないというルールのある遊びです。先に挙げた遊びの6要素も満たしているつもりです。講義で学んだ内容を実際にシステムを提案することで、より体感として理解することができました。

一方で技術的実現性と対象ペルソナのギャップとシステム設計の難しさも感じました。魔物スカッシュを提案した時、テニスの壁打ちゲームかスカッシュの壁打ちゲームかで決めかねていました。システムを運用する難易度はテニスボール/ラケットを使うよりもスカッシュボール/ラケットを使う方が実現しやすいです。場所が小さく室内コートが用意できるからです。一方、私はユーザーの動的複合ペルソナは「リゾート地などでテニスを楽しむ20〜40代の男女」かと「都内室内テニスクラブでテニスする習慣がある10〜40代のテニスプレーヤー」と想定しました。わたしは、ある程度の数の人に主にリゾート地でも楽しんでもらえるようなゲームを提案したかったのです。テニス人口の方がスカッシュ人口よりもかなり多いことと、リゾート地でのプレイ人口がテニスの方が多いことからこのペルソナを想定していました。このように、システム運用の難易度を下げれば、ユーザーのペルソナは制限され、ユーザーのペルソナを自由に設定すれば、システムの運用難易度が上がるというジレンマを感じました。このようなジレンマを乗り越えるには、動的複合ペルソナを注意深く考える力と実現するための技術的、社会・経済的な知識と経験の両方が求められるのだと実感しました。

講義「コンピュータゲーム」で得られた気づき・為になったこと

この授業を通してわたしは、以下気づきを得ました
①どんなユーザーがどんな状況でサービスを享受しているのかに注意深くなった
②「遊びで楽しいと思うこと」も人間の普遍的な活動であることを自覚した
③工学的なさまざまな技術と応用例について知識が広がった

①「コンピュータゲーム」という講義名から、最初に授業をとった時はコンピュータゲームの技術的なことのみを扱うのかなと思っていましたが、実際はエンターテインメントシステムというコンピュータゲームも包括する抽象度の高い内容を扱う授業でいい意味で驚きました。授業では狭い意味でのエンターテインメントシステムではない、三鷹市や武蔵野市のホームページや自動販売機のデザインについても触れ、「受け手が存在するサービスのデザインが受け手のペルソナが考慮されたデザインになっているか」が一つの重要なメッセージだったと思います。そのメッセージは、仏教において受け手に合わせて教えを説く「待機説法」の精神にも通ずると思いました。この授業で得られた視点であらゆるサービスを見て今後の人生に生かそうと思います。

②今まで、遊びとは何かについてあまり考えたことがありませんたが、この授業はその機会を提供してくれました。遊びにおいて楽しいという認知的現象は、人間であれば誰しもに起こりうる現象なのではないかと授業を受講した今、思うに至っています。人間が音楽聴いて美しいと感じたり、言葉を話したりするのと何が同じで何が違うのでしょうか。白井先生が、受講生が2048をプレイする様子を観察する時間を授業内で設けたとき、「実験」という言葉を使っていたのが印象的で、遊びという人間の認知的機能を真剣に考えるきっかけになりました。自分は言語学専攻で、人間に内蔵された認知機構を調べ考えることに関心が高いです。遊びの感情も今後考察対象にしていきたいと思います。「楽しい」という感情の種類も「遊び」や「遊びのルール」などの条件の違いによって変わるのか変わらないのかその関係は興味深いテーマだと思います。

③私は情報科学副専攻だとはいえ、工学的な技術の応用例についての知識はかなり少なかったです。しかし、この授業を受講して工学的技術の知識もこれから増やしていこうという気になりました。特にそれを感じたのは、自分で超人スポーツを提案する課題に取り組んだことです。白井先生のMITの技術があることを知らずに課題は提案できませんでした。「魔物スカッシュ」を提案する前私は「人ロボ混合ダブルス」という企画をしていたのですが、技術的に自分のイメージしていたものを実現するのは現時点で困難だということがわかりました。今後、なにか新しいサービスを提案する時もどんな技術が存在するのかについての知識だけでも持っておくことは不可欠だと実感しました。

後輩へのおすすめ

この授業は様々なバックグラウンドの学生が受講しています。情報科学専攻の学生だけでなく、哲学、社会学、国際関係学、言語学、言語教育、心理学など様々です。その多様な背景の学生が許容される授業の設計となっています。ICU生のだれしもが受講することができ、受講する意味がある授業だと思います。

まず、情報科学専攻の学生をはじめとする、現在プログラマーであったり将来プログラマーになりたい学生にとって大変意味のある講義です。その理由は、この授業では高度なゲームプログラミングの技術を学ぶ授業ではありませんが、なぜそのような技術を使うのかといった一番大事な部分を考える機会を提供してくれます。自分がなんのためにプログラミングをしているのか、出来上がったソフトウェアは誰がどのような環境で利用するものなのかを仕様書などの設計段階から深く考える為にもこの授業はとても有用です。

次に、経営学専攻をはじめとする現在、あるいは将来ビジネスとして新しいサービスを作っていきたいと考える学生にも大変有用です。なぜなら、多くのサービスを設計する上でそのサービスのユーザーの動的複合ペルソナを深く考えることは不可欠であり、さらにサービスを展開する上で工学的技術の知識、技術者との協力関係も極めて重要だからです。この授業では、工学的技術の応用例が数多く紹介されており、Digital Content ExpoやSIGGRAPH ASIAといった研究発表の場がどのように行われているかについて情報を得ることができます。情報収集の場としてとても有用です。

さらに、生物学や心理学、社会学専攻などの生物としての人間、あるいは社会的な存在としての人間に興味がある学生にもこの授業は有用です。なぜなら、「遊び」という人間の一般的現象を改めて考え直す体験を通じて、生物としての人間、社会的存在としての人間に新たな着想をえることにつながるからです。生物学者であれば、他の類人猿における遊びと人間における遊びの比較研究ができるかもしれないし、心理学者であれば遊びの「楽しい」という感情をテーマに心理的実験ができるかもしれません。「遊び」を各専門分野から研究対象にする、それだけ「遊び」は興味深い現象なのだということを再認識させてくれる授業なのです。

授業の内容もこのような動的複合ペルソナを対象に設計されている(と思う)ので自分が何を専攻しててもきっと役立つはずです。もっとも、自分の専門でない分野の知見についても垣間見ることができるので、それだけでもICU生としてはトライしてほしい授業です。ぜひ、自分自身で来年の「コンピュータゲーム」の授業を受講して、「エンターテインメントシステム」について考え、人生の糧としてください。


2048を目コピでクローン作成する課題

情報系メジャーの学生も半数ぐらいいる中、かつての本講義で扱ってきたUnityやProcessingといったフリーで利用できるゲーム開発環境については、すでに独自に取り組んでいたり、ほかの講義で扱っていることもあり、今年度はプログラミングをお触りするような表面的な講義はやめて、「ゲームの本質」に迫るため、「未来のゲームデザイン」p.123で扱っている「ゲームのクローン」を開発することにした。今回のテーマにしたゲームは「2048」。実際にゲームを始めてプレイする体験を記録し、それを観察したのち、ゲームルールを各自が希望する言語で実装した。講義の中ではProcessingやCなどでの実装があった。C言語による実装の場合は約500行程度。中でもHaskellで実装した学生がいたので抜粋して紹介する。

2048をHaskellで真似してみた学生

Haskell詳しくなかったのですが、なんと76行。すばらしい。2048特有の動きを最後の8行で表現できているのが面白い。

github.com/29rou/2048Haskell-/blob/master/2048copy.hs


import Prelude hiding (Left, Right)
import System.Random
import Data.List
import Text.Printf
import Data.Char (toLower)
import System.IO
type Table = [[Int]]
data Move = Up | Down | Left | Right
main :: IO()
main = do
hSetBuffering stdout NoBuffering
putStrLn "Start"
table mainLoop table
where initialize :: IO Table
initialize = do table' IO ()
mainLoop table = do printTable table
if filter ( == 2048) (concat table) /= [] then putStrLn "Finish" else gameFunction table
gameFunction :: Table -> IO ()
gameFunction table
| (getEmpty table == [] && canMove table == False) = do putStr "Game Over"
| otherwise = do putStr "Please input [Up, Down, Left, Right]"
new_table if table == new_table
then do putStr "Please chose other one\n"
mainLoop table
else do new Bool
canMove table = sum ( map (length . getEmpty . flip move table) [Up, Down, Left, Right] ) > 0
printTable :: Table -> IO ()
printTable table = do let showRow :: [Int] -> String
showRow = concatMap(printf "%5d")
mapM_(putStrLn . showRow) table
addNumber :: Table -> IO Table
addNumber table = do let choose :: [a] -> IO a
choose xs = do i (Int, Int) -> Int -> Table
setNumber table (row, col) val = fst ++ [mid] ++ post
where fst = take row table
mid = take col (table !! row) ++ [val] ++ drop (col + 1) (table!!row)
post = drop (row + 1) table
target value [(Int, Int)]
getEmpty table = let singleRow n = zip (replicate 4 n) [0 .. 3]
coordinates = concatMap singleRow [0 .. 3]
in filter (\(row, col) -> (table!!row) !! col == 0 ) coordinates
newTable :: Table -> IO Table
newTable table = do let moves :: [([Char], Move)]
moves = zip ["up", "down", "left", "right"][Up, Down, Left, Right]
moveKey :: IO Move
moveKey = do input return x
Nothing -> do putStr "Plese choose [Up, Down, Left, Right]"
moveKey
key Table -> Table
move Left = map compute
move Right = map (reverse . compute . reverse)
move Up = transpose . move Left . transpose
move Down = transpose . move Right . transpose
compute :: [Int] -> [Int]
compute xs = computed ++ space
where combine (x:y:xs) | x == y = x*2 : combine xs
| otherwise = x : combine (y:xs)
combine x = x
computed = combine $ filter(/= 0) xs
space = replicate (length xs - length computed) 0

コーディング中に気づいた難度に関係する設定

i. 数字(タイル)が発生する場所

今回は何も考えずに乱数を元にランダムで場所を指定した。しかし、ここをばれない程度に弄ればもう少し難しく出来そう。たとえば、序盤は空いている場所を中心指定し、ある程度ゲームが進んだ段階で密度が高い場所を指定するなど。

ii. 数字の大きさ

今回は常に半々の確率で2、4が出るように設定した。しかし、ここも確率を弄れば難しくできそう。出す数字の種類を増やしたり、出す数字の確立を弄ったり等。たとえば、終盤にかけて発生する数字を大きくしたり、序盤は小さな数字ばかりが出るようにするなど。


別の学生、Mさんの解説。

icucg2015mashiko.blogspot.jp/2015/11/blog-post.html

この講義でどのようなことが学べるのか?

この講義で学ぶことが出来たのは、エンターテインメントがどのようであるべきか、そして実際にそれがどのように社会に存在するかということである。これらは、現在という時間軸における話だけでなく、過去または未来におけるエンターテインメントについての話も十分に説明されており、十分に理解できた。具体的にどのような内容であったかを次の五項目に分けて、この講義の内容を紹介したい。一) 遊びについて 二) エンターテインメントシステムについて 三) エンターテインメントシステムのデザインについて 四) 次世代のゲーム(スポーツ)について 五) インタラクティブな新技術について
第一に、遊びとは何だろうかという根源的な問いからこの講義は始まる。歴史的に見ると遊びの原初はラスコー洞窟の壁画にまでたどることが出来るだろう。なぜならば、ラスコー壁画は、最も原始的な人類が、生存のための必要性とは異なる次元で行った活動の所産だと考えることが出来るからである。学生からは、狩りの成果を称えるために描いたのではないか、または逆に、飢えなどの恐怖に対するまじない的効果があったのではないか、といったような意見が有ったが、結論として、このような絵画を描くことで、彼らクロマニョン人は何らかの効用を得ていたというのは間違い無いだろう。
このような人類と遊びの関係は、非常に長い時間をかけて、多くの学者が、様々な視点から研究を進めてきた。特にヨハン・ホイジンガの「ホモ・ルーデンス」という人間観は、人間の’本質’と’遊び’を強く関連づけてるという点でこれら議論の核心に最も近づいたといえるだろう。また、彼の研究(特に遊びの成立条件に関して)はフランスの思想家、ロジェ・カイヨワによって引き継がれ、大きく発展した。彼はどのように遊びの要素を示したのだろうか。
ロジェ・カイヨワによると遊びとは六要素に分類すると言うことが可能だという。その六要素とは、自由性、隔離性、未確定性、非生産性、規則性、そして虚構性ということだった。本講義では、実際の遊びがどのようにこれら要素を満たすのかと言うことを、実践を交えながら実感することができる。
さらに、遊びのなかでも特にゲームの分野は第十芸術というような表現をされることがある。これは音楽、絵画や建築などといったものに次ぐ芸術の一形態として認められつつあると言うことである。これは、単にゲーム自体の価値が広く認められていると言うことを示しているというよりは、ゲームという芸術のあり方自体がより体型だった形で洗練されていく必要があるということを強く意味しているのである。
第二に、エンターテインメントシステムとは何か、という疑問に講義は答えた。エンターテインメントシステムとは「人間の娯楽に作用するようにデザインするシステム」(白井博士 55)だと定義される。つまりエンターテインメントシステムとは、単なるコンテンツ単体ではなく、それを楽しむためのすべて環境・設備・機構をさすのである。つまり、ゲームソフトや映画のDVDだけでは、エンターテインメントシステムと呼ぶことは出来ない。それを再生する設備や楽しむための環境全体を含んではじめてエンターテインメントシステムと呼ぶことができる。その点で言えば、スマートフォンやSNS、動画配信サービスはまさにエンターテインメントシステムの定義にぴったりと当てはまるといえる。
また、エンターテインメントシステムがそれ足るために、継続的な魅力を提供出来ることが重要となる。すなわち、ユーザーを再びそのエンターテインメントシステムに誘うような何らかの魅力が必要なのである。そのために、ハードウェア的にユーザーへの適切な配慮を行うことは必至であるし、それ以上にユーザーの特性を考慮したような設計が求められる。しかしながら、遊びの成立の六要素の話に関連するが、エンターテインメントとしてユーザーに楽しさを与えるというコアの部分を満たすことが何よりも必要だと考えられる。他の利益に強く結びつけられていたり、ユーザーの現実を踏みにじる様なエンターテインメントはもはやその目的を果たさない。例えば、非生産性に近い話だが、かつてのNitendo DSや今日のスマートフォンで流行っている何らかの学習効果を狙ったようなゲームやアプリケーションといった目的性、長時間の連続のプレイをユーザーに強要するようなゲームははたして面白いゲームと呼べるのだろうかといった批判がある。エンターテインメントシステムは面白さを追求しながらも、その本質に反さないことが重要だと考えられる。
第三に、講義はエンターテインメントシステムのデザインについて触れた。エンターテイメントシステムを設計するための一つの思想として、ペルソナというものがある。ペルソナとはつまり人格である。個人がどのような性質を持っているのか、何歳くらいなのか、どのような性であるか、などの要素が含まれうる。しかし、その個々のペルソナへの分析だけでは、実際にシステムを設計するにあたって、大きな不都合に直面することになる。すなわち、特殊性をどの程度まで追求するべきかという問題である。特定の深く分析されたペルソナに従ったデザインを行うことによって、特定のユーザーの満足度は上昇するかもしれないが、他のユーザーは排他される可能性は高い。逆に、大きすぎるペルソナは、ターゲットを絞ることが出来ないがために、ユーザーの心をつかむことが出来ない。すなわち、特殊性と一般性の均衡点を発見するために、単体の固定されたペルソナでは不十分であるということである。
このジレンマを解消するために、動的複合ペルソナの概念が提唱された。動的複合ペルソナは、ユーザーが新しい経験や体験によってそのペルソナが変化すること(動的であること)また、ユーザーが多くの場合に単一ではないと想定すること(複合的であること)の二つの特色を有する。
まず、動的ペルソナは、提供出来るサービスの質を保ちながらも、特定のユーザー、例えばアクティブではないユーザーなどを排他しないような非限定的なシステムを構築することに与する。動的なペルソナは、経験を通して絶えず変化することを示しているが、その経験というのは、一般的経験というよりは、エンターテイメントシステムとの関わりの中で生じるような体験を指すものである。ユーザーはシステムの要素との交流のなかで、一種の耐性のようなものを身につけていく。それは、単に刺激に慣れるということに限らず、コツやシステムの概念を理解したりといったことまで包括的に考慮する。このような経験を組み入れたシステム設計を行うことにより、ユーザーとエンターテインメントシステムとの間のハードルを大きく下げてくれるのである。
一方、複合的ペルソナによって、より現実に即した設計が可能になる。私たちは社会的存在であり、他者との関係を切り離して考えることはできない。実際問題、多くの時間を他者と共有している。だからこそ、エンターテインメントシステムはそれに呼応するような設計を構築することによって、その目的をより良く達成できると考えられる。たとえば、女子高生の一団だったり、男兄弟だったり、人々は余暇を親しい他人と過ごしており、そのような集団が、エンターテインメントシステムと関わりを実際に持っていることは、ゲームセンターやテーマパークなどに行けば、体感的に理解できるだろう。
第四に、次世代のゲーム(スポーツ)に関する内容を講義では取り扱った。特に、次世代のスポーツを企画してみるという課題があり、それは上記のエンターテインメントシステムのデザインなどと大きく関連するものであった。そもそも、次世代スポーツというのは、最先端のテクノロジーや、柔軟な発想をスポーツに取り入れることによって、新たなスポーツを生み出そうというプロジェクトであり、その企画書をプレゼンするという内容だった。プレゼンでは、実現可能性や、ペルソナを考慮した価格設定、遊びとして成立するのか、といった観点から様々な議論がされた。特に印象的だったのは、脳外科手術を受けて、仮想世界でダイビングをするという企画に白井先生が「本当にそれをあなたはやりたいですか?私は脳外科手術を受けてまでこれをしたいとは思わない」とコメントしたのが、痛烈ながらも、エンターテインメントに対してどのような価値、考えを持っているかを端的に示しているように感じた。
最後に、様々な新技術に関してである。エンターテインメントシステムに用いられている技術の殆どは、いわゆる”枯れた技術”で構成されているとしながらも、やはり、新技術をシステムに取り入れることは、将来的に必要なことだと思われる。講義の中では、今年、神戸で開催された、SIGGRAPH ASIAでの展示に関して紹介がされた。UT-HEARTといったような学術的な展示から、アート系の展示、また、現実世界で応用ができそうな技術や、Live 2Dといった非常にユニークかつ高いテクノロジーが求められるような展示があった。また、DCEXPO2015でも様々なテクノロジーが紹介されていた。こちらでは、特にデジタルコンテンツに関する展示が多く、特に3D関連技術のものはめざましい進化を感じさせるものが多かった。これら展示された技術を、単なるイロモノで終わらせるのでなく、一般ユーザーが気軽に利用できるように普及させていくことが強く求められる。

この講義はどのような利益をもたらしたのか?

この講義が私にもたらした利益は、遊びやゲームといった行為の本質に迫ることができたこと、最先端の科学とその実際的応用に関する知見を専門的立場からの意見を含めて知ることができたこと、そして私のライフスタイルに影響を与えたことの三つである。
はじめに、この講義は遊びやエンターテインメントシステムといった、普段あまり真面目に考えられることが少ない分野に関して、深く考える機会を提供してくれた。ゲームという言葉は、一種のスティグマ(汚名)を不当に被り続けており、一方的に、考えるに値しない些細なもの、あるいは、人間に害をもたらすものであるかのように語られてきた。しかしながら、前項で示したように、遊びは人間の根源的な活動であり、それは人間存在と切り離すことはできない。そのような前提の元で、深くゲームや遊びについて考えることができたというのは貴重な経験であり、また、それは、エンターテインメントシステムの溢れる現代というコンテクストにおいて特に重要な意味を持つものであると考えられる。
つぎに、コンピューターゲームの講義は、最先端のテクノロジーに関する知見を与えてくれたと思う。それらテクノロジーは、枯れた技術の組み合わせに過ぎないかもしれないが、それでもなお、ありふれた存在とは一線を画すような生きたテクノロジーである。鮮度の高いテクノロジーを開発者やテクノロジーのバックグラウンドとともに理解できるような機会を得ることができたのは非常に幸福な経験だったと思う。たとえば、UT-Heartの例では、開発者の瀬尾氏のバックグラウンドに関する秘蔵のインタビューとともに、その技術の有効性を知ることができた。このような見識に触れることができたことは、なんらIT関連に限ったことでなく、広く応用していくことが可能なのではないかと思った。
最後に、(これはおまけ程度の話だが、)講義で取り扱った内容が私の生活様式に何らかの変化をもたらした。講義の中ほどで紹介されたARゲーム”Ingress”が予想以上に面白かったということであり、そのプレイが私の日常の一部に組み込まれたということである。その存在自体は、この講義以前から認識していたが、ハードルが高そう似見えたのと、その面白さがいまいち理解できていなかったために、それをプレイすることはなかった。しかし、白井先生のデモに影響されて、プレイを始めたところ、その面白さに一種の衝撃を受けた。それ以降、私はこのアプリケーションを一日に少なくとも五回は起動しているだろう。これは利益であるかは、現状では判断できないが、少なくとも短期的な満足感と言ったようなものを得ることはできたのは事実である。

この講義でどのような発見があったか?

自身の考えていたいわゆる”ゲーム”と”遊び”の間の乖離、ユーザー指向のシステム設計の応用可能性、また、それに関連して、ペルソナの学問領域における類似性を発見した。
まず、この講義を通して、自分の考えていた”ゲーム”と”遊び”の間に大きな乖離がある事に気づいた。私の中でのゲームというものの理解は経済学におけるゲーム理論におけるゲームの定義に近いものだったと思う。すなわち、複数のプレイヤーがなんらかの利益を巡って争うような構造一般をゲームだというように理解していた。それに対して、講義で扱ったゲームすなわち、余暇としての、遊びとしてのゲームはそれよりも範囲が狭いものでありながら、一般的にゲームと考えられるものの枠を越えた範囲まで触れるものであったと思う。たとえば、自販機の設計などは好例だろう。このようなエンターテインメントとしてのゲーム定義は非常に斬新であり、自己の理解と大きく異なっていることに驚いた。
つぎに、エンターテインメントシステムのデザインについての説明は広く用いることができるのではないかと思った。ペルソナやユーザーから何が見えるべきで何が見えないべきかといったような話全般は、なんらエンターテインメントシステムのデザインに限った話ではなく、近いところでは、授業で触れていたようなウェブページのデザイン、遠いところでは、建築やインダストリアルデザインについても広く応用可能であるように思われた。これらもまた、エンターテインメントシステムと呼ぶことも可能かもしれないが、いずれにせよ、ゲームの設計理論というものが、特定の分野にしか通用しないような極めて特殊なものではなく、むしろ、他の分野においてその理論の有効性がより一層担保されるのではないかと感じた。
そのようなユーザー指向のデザインに関して、動的複合ペルソナの説明があったが、これは政治哲学におけるペルソナの説明と似ていることを見つけた。ホッブズは著書リバイアサンにおいて、社会契約を遂行するため、人々は仮の人格=ペルソナを形成するという演繹を行った。この人格は個々の詳細な人格ではなく、自己保存という目的達成のために形作られた概念上の人格であるが、このような仮想の人格を用いて思考を進めるという手段は方法論的に、動的複合ペルソナの概括的決定と類推が可能ではないかと思った。すなわち、ある種の実在するかどうか不明なペルソナを想定することによって、逆説的に、実在する人間の要求を満たす設計が可能になるということは、学問領域にかかわらず、広く認められるということを示しているのである。

この講義はどうして後輩におすすめできるのか?

この講義は情報科学メジャーの生徒に限らず、どのような生徒にもおすすめできる講義であると思う。特に社会科学や人文科学を専攻している生徒にも積極的に取って欲しい講義である。なぜそう言えるのかを、どのような講義がICUの生徒にとって望ましいのか、また、どうして情報科学メジャーの学生および他の分野を専攻している学生に勧めることができるかに分けて述べたい。
まず、どのような講義が好ましい、すなわち、勧めるに値するかという話をしたい。ICUは全人的教育をその目標に掲げる大学であり、入学者の多くは、その目標に少なからず共感し、自身の学習においても分野に依らない学習をしたいと思っているだろうと考えられる。その目標を達成するために、講義として行うべきなのは、その分野の基礎的知識の習得、実践知の獲得、そして、他分野との有機的連携のなかで生じる新たな発見の提供に分けられるだろう。特に300番台(メジャー領域)の講義は、基礎的な情報科学の分野の知識や技術を提供するためのものではない。むしろ、得た知識をどのように実践的に用いるか、あるいは、他の分野と対象の分野を結びつけるかを分析するような内容であるべきである。これら後者二つを提供することによって、学生個々人はそれぞれの学習を深めることが可能であるからこそ、逆に、そのような講義は勧めるに値すると言えるのである。
第一になぜ情報科学メジャーの学生に勧めることができるのかを説明したい。この場合、どうして、コンピュータゲームの講義が進めるに値するかは非常に容易に説明することができる。先に述べたように、300番台の講義として求められる要素二つを満たすからである。コンピュータゲームの授業では、他のクラスで身につけたような基礎的な知識や技術を一つのゲームという作品の制作によって、応用する課程を学ぶことができるのである。また、授業の紹介の部分で述べたように、どうしてこの授業はエンターテインメント、遊び、ゲームといったような存在や行為の本質に迫るものであり、それを追求するために、人文的アプローチは必要不可欠であり、実際に、そのような内容は十分に提供されたと考えられる。よって、これら二つの要素を提供出来るということが認められるので、このような情報科学メジャーの学生にとって、この講義は履修する価値は必要十分だと考えることができる。
第二になぜ社会科学、あるいは、人文科学の分野を専攻する学生に勧めることができるのかを考えたい。この論は非常にトリッキーな説明を要する。なぜならば、情報科学メジャーの学生と異なり、彼らは、情報科学の基礎知識を有しないし、そのゴールも幾分か異なるものであるからである。しかし、このような、いわゆる”文系”の学生にも勧めることができるというのは、授業に求められる理想の三番目から逆説的な演繹を行うことが可能だからである。このような学生は、基礎的な知識は欠如しているが、専攻分野などに関しては、ある程度の知識を有しており、エンターテインメントや遊びといったものへの理解を深めることが可能である。そのようなものへの理解は、エンターテインメントシステムを考えるための核心であるからこそ、その理解はそれ全体への理解の意欲を大きく向上させるに足るのである。というのも、遊びなどの概念を深く分析しようとすることによって、そこから派生する枝葉の部分に触れる必要性を強く感じさせるからである。それによって、情報科学の学生が学ぶのとは逆の方向から学習を進めることが可能になるのである。
では、なぜこれらのメカニズムが生徒にとって効用があると言えるのだろうか。もし前パラグラフで説明したような仕組みによって、生徒が逆方向の学習を十分に行ったとする。この場合。自身の研究と他分野の研究を組み合わせるという目標は達成される。たとえ生徒が、基礎的な知識や研究にまでたどり着くことがないとしても、少なくとも、実践的・発展的内容を自身の既に持っている知と組み合わせることで、あらたな知の連携を形成することが可能だからである。これは、全人的な教育という規範を満たすものである。また、ある程度の基礎知識が欠落しているにせよ、どのような技術が実際に応用されてきたのかといったよう内容を学習することは可能である。また、もし、それ以上の発展的な学習を行うとすれば、この授業は基礎知識の習得や、その応用について学習するための力強いインセンティブを学生に与えたということが結論づけられる。これらは、講義として求められる理想の一番目あるいは二番目を満たすものである。よって、これらの生徒にとってもこのコンピュータゲーム授業は勧めるに値するのだと結論づけられる。


学生自身に「講義の面白さ」をシェアさせてみる

今回、リベラルアーツ&アクティブラーニング比率を高めに設定した。確認として、学生自身の理解を反芻させるために「講義の面白さ」を、ほかのICU学生をペルソナとして設定して作文させた。一部、共有許可を得られたものだけ紹介する。

今学期面白い授業があったので、ICUの皆さんにシェアします。

ComputerGameという情報科学の授業なのですが、タイトルだけだとGameを作るのかなと思うかもしてません。「ゲームに興味ないから、いいや。」と思わずに、ぜひ最後まで目を通してください。
この授業を一言で言うなら、現代のエンターテインメントや、ビジネスをゲームという視点から学ぶ授業です。具体的にどんなことを学んだのか書きます。
まず最初の授業は、最も印象的でしたが、ゲームを遊びの1形態と考え、そもそも遊びがなぜ必要なのかを考えるものでした。前提に対して、批判的に思考することからスタートするのはなんともICUらしい授業でした。ゲームの話をするのかと思いきや、遊びという文化について議論し、遊びはなんで人間にとって必要なのかということに思いを巡らしました。
次に授業では、遊びにどんな要素があるのか、その要素を分類していきます。遊びの6要素というものですが、その要素を使って既存のゲームを説明したり、現代の「遊び」の問題にも話はおよんでいきます。他にも、社会科学的な観点から、さまざまな遊びの理論についても学びます。
ここまできてもまったくコンピューターの要素が出てこないですが、講義は徐々に現代のエンターテインメントシステムに話がうつっていきます。そして、ついには自分たちでエンターテインメントシステムを作る課題が課されます。超人スポーツ(http://superhuman-sports.org)というものを参考に自分でゲーム・スポーツを考案するのは、正直骨が折れましたがいい経験になりました。自分で何かを自由に作り上げる機会は、一般的な大学の講義にはあまり多くない、とても貴重なものです。しかも、特別なプログラミングスキルも必要ありません。情報科学の授業と聞くと敷き居が高く思うかもしれませんが、怖じ気づかないでぜひこの授業を履修してみてください。
そして、僕がこの授業で学んだもっと価値のあることは、既存のヒットゲームや、エンターテインメントシステムについて議論したことです。なぜ、今特定のゲームがヒットしてるのか。電車という、インフラに使われているITのどこを改良できるのか。そんなことを議論してきたことが、僕にはとても刺激的でしたし、今後の自分のキャリアにとても関連していたこともあります。なにより、問題解決を試みることは、どんな行為よりも知的好奇心が満たされるものだと思っています。自分で最先端技術をどんな風に応用できるのか考えることもしました。僕はMulti Plexという、多重化した視覚的な情報を一つの画面に映し出す技術を観光業に使えないか考えました。
この授業はいろんな人におすすめできます。情報科学に興味がある人はもちろんですが、経営を学んでいる人には、ヒット作品や最先端のITについての知見が広がりますし、ゲーム大好きな人も今まで自分がただ純粋に楽しんできたものを学問的な見地から考えられる貴重な機会になります。ぜひ来年もこの授業が開講されるならぜひ受講してみてください。

後輩へのすすめ

最後にこの講義のアピールポイントを紹介する。
まず、学生参加の機会が多い。講義の形式は、先生が黒板の前に立ち学生が机に向かうというような通常のものとは異なり、先生と学生が輪になって座り、先生が講義をしている間も自由に意見を言ったり、それに対してまた別の学生が意見を言ったりしていた。とても自由な雰囲気があり、他の学生の意見が聞けるのは大いに刺激になった。講義の内容も、学生の積極的な参加が求められるような内容で面白かった。例えば、身の回りのエンターテインメントシステムにはどんなものがあるかとか、駅の自動販売機に欠けているものは何か、あるいはそれをエンターテインなものにするにはどうしてら良いかなど、学生にその場で考えさせ議論させるような、次世代的でオープンな場が設けられていた。その他にも、人狼をリアルRPG的に即興でやってみたり、ingressや2048などのゲームを授業中にやったり、普通の授業では無いような面白い学び方だと思った。
毎週出される課題についてもオープンな雰囲気があった。各自がやってきた課題はfacebook上でシェアされ、閲覧したりコメントしたりすることができる。また、課題は次回の講義中に発表することになっていて、先生からアドバイスを頂いたり、意見を交換しあったりする。
この講義は情報科学メジャーの学生だけでなく、様々な分野あるいは学年層からの学生が履修できるように、プログラミングスキルを必須としないなどの配慮があり、実際に哲学や言語学などの他分野メジャーの学生が履修していた。このことは、ICUの教育理念であるリベラルアーツに適ったスタイルであり、「遊び」やゲームに関心がある学生はぜひ履修することをオススメする。


以下、学生視点でのおすすめ作文より

「自分が当たり前と思っているものごと当たり前ではないとしれる、情報科学開講の唯一の授業だよ。情報科学開講というホーム側の講義で、非情報系の人間の考えが知れるのはとても有意義だと思う。確か、文系メジャーの講義を取ることでも非情報系の人間の話は聞くことは出来る。しかし、アウェイ側にいるのと、自分がホーム側にいるのとではやはり受け取れるモノが違う。アウェイにいると、つい気張ってしまうし。ホーム側に、非情報系の人間の人間を眺めることが出来る珍しいチャンスだと僕は思う。」

昔気質の教授の一方通行の授業ではなく、もっとインタラクティブな授業なので、気負わずに参加するといいと思う。固定概念を捨てて新しい物に触れる喜びを見つけるとより楽しめる。近い趣味を持った人と議論できる場なのでより白熱するかも。

 

この講義を通して、新しい技術や企画に触れられたこと、人を楽しませるには結構な苦労がいると気が付いたことが大きな収穫でした。企画を考え、まとめる体験もできました。この体験は社会人になって仕事をする際にも企画を考え、プレゼンすることに生きたいと思います。
授業中も会話があったり、実演が多かったりととても良い授業です。先生もとても楽しい方で、生徒との距離が近く、間違いなく面白い授業です。みなさんも是非とってみることをおすすめします。

私はこの授業全体を通して人の楽しませ方について考えることができました。技術力以上にアイディアや創造性の大切さを感じ、今後の教訓にしたいと思いました。当初はコースタイトルから、ゲームに関しての技術的な話が多くなると予想していましたが、そんな枠には収まらないほどの範囲から講義が行われました。情報科学メジャーではなくとも十分に理解できる内容なので、エンターテイメントに興味がある人でしたら取ってみることを強くおすすめします。

私がこの授業で得た物の中一番重要なものはここまで書いてきたようなことではく、講師が私の就職相談に乗ってくださり、今後の指針を示して頂いたことである。講師はコンピューター・ゲームという授業を開講していることからも分かるとおり、ゲームをはじめとしたデジタルエンタテイメントの専門家であり、ゲーム業界へ就職を志望する私が目標の為にべきことは何か、そのためどような点を直さなければいのかといった事を教えてくださった。以上 触れてきたように、この授業は私とって非常有益なものであり、それゆえ後輩の方々にも受講を勧めるものである。受講にあたって勧めておきたいことは、講師出来るだけコミュニケーションを取ることである。この授業ではFacebookグループを使って情報伝達が行われるので、コミュニケーションが容易である。私の就職相談ようなものも、授業課題流れから生じたものである。このような機会を自分以外の方々にコミュニケーションの中で見出して欲しいと思っている。

 

この講義はまずエンタテイメントについての認識の確認から始まり、身近なビデオゲーム等をテーマにした議論があり、そこからまた視野を広げて先端技術を使ったエンタテインメントの可能性についてといったような流れがあったように思える。また講義を進めていくに当たって学生と教授の距離は近く双方向なやり取りが常だったといえる。課題等に関しても情報系でない学生や、日本語を母語としない学生への配慮があるのでデジタルエンタテインメントに少しでも興味があるのであれば300番台だからと臆することなく取ってみるのも悪くないだろう。

受講生には留学生や非日本語圏の学生も存在するので紹介

Computer game class Introduction for English speaker

In this lecture, you will learn about what is being defined as fun, game, and entertainment system. The concept of creating entertaining and meaning game for other people to enjoy and play will also be discussed throughout the lecture. The lecture is not mainly focus on the actual design of the game itself, rather it’s a course that sparks student’s interest in designing fun and creative proposal for possible game ideas and discusses about many interesting technology news in the entertainment industry today.

The professor is a very knowledgeable person with many experiences in designing some break-through technology, and one will learn a lot from just simply listening to the lecture and having interaction with him. The textbook has many useful information and many interesting ideas that are very intriguing but most people would see them as something normal, which gave me quite a few changes in my thinking about the game design process.

For this class, there’s not that much to prepare for it, but definitely enjoy the lecture, join the discussion, and enjoy the time in the class. The homework isn’t time-consuming, if you think about the homework topic everyday, and then spend a day working on it, you will definitely get a very satisfying result. Also reading about the entertainment world news will also help too. If any questions related to the gaming design, or any interesting news about some cool technology, feel free to let the professor know and have a great discussion with him.

I’ve learned a lot in this class, even though it’s all taught in Japanese, I still really enjoyed it. I learned a lot about the newest technology, and some of the issues that can happen or some possible solution for better technology in Japan. Also, for me, I see a lot of different way of thinking in this class. Everyone has different background and a lot of the proposal is really interesting and really out-of-the-box compared to what I was thinking.

For English speaker taking this class, it’s definitely worth it. It’s fun, creative, and a cool class to take a break and not get too frustrated with other classwork. The professor is very nice, such that he will sometimes stop and explain things in English for me and try to get me into the discussion. But I still strongly recommended that taking this class with some level of Japanese, for me it was two years of Japanese, will be a lot more helpful. Listening isn’t very difficult, and it will definitely be a good practice, it’s worth the time spent in the classroom. Also you get to see the real Japanese discussion if you aren’t taking other Japanese lectured class. So don’t be afraid to take this class, and really do enjoy the time you have in this class.

まとめとふりかえり

秋学期で9回程度の講義で、広範な内容を扱うことは難しいが、それでもICUの幅広い学生の興味に対して、そこそこにスピード感をもって知を共有することができたと考えている。毎回の講義後、自主的に質問してくる学生も多く、19時の講義終了後、最大2時間程度のオフィスアワーを設けて、深く相談に乗ることもできた。

個別に紹介したい学生もたくさんいる。
非常勤という立場だからこそ見えてくることもあり、私自身勉強になることが多かった。

彼らの才能が開花し、世の中に良い意味で「おもしろくする」こと、
社会に対して大きな影響を与えてくれることを期待している。

それこそが、この講義の意義であろう。

本当に、ありがとうございました。

みなさんのご活躍をお祈りしております。

Processingで集合知プログラミング

大学院講義「エンタテイメントシステム」のコーディング練習のために,

オライリー「集合知プログラミング」から映画の評価からオススメを算出するための,各ユーザのユークリッド距離を算出するプグラムを書いた.

集合知プログラミング

言語はProcessing 2.0(書籍はPython).

データファイル(test.csv)はこんな感じ.

id,Name,M1,M2,M3,M4,M5,M6
0,Rose,2.5,3.5,3,3.5,2.5,3
1,Semur,3,3.5,1.5,5,3.5,3
2,Michel P.,2.5,3,3.5,0,0,4
3,Puig,0,3.5,3,4,2.5,4.5
4,LaSalle,3,4,2,3,2,3
5,Matthieu,3,4,0,5,3.5,3
6,Tobby,0,4.5,0,4,1,0

Githubにソースと結果を置いておきました。
github.com/kaitas/ShiraiLabOpen/blob/master/Processing/Euclidean/Euclidean.pde

// Draw Euclidean from "Programming Collective Intelligence" to a PDF
// http://shop.oreilly.com/product/9780596529321.do
// Akihiko SHIRAI (shirai atto mail.com) 20140709
// for Master Lecture "Entainment Systems"
// it may include some errors 

//Libraries
import processing.pdf.*;

// globals
  PGraphicsPDF pdf;
  float L =5; // levels
  int MOVS = 7; // num of movies (1-7)
  int PERS = 7; // num of person (0-6)
  Table table;
  float[][] Critics = new float[7][7];
  String[] Names = new String[7];

//convert to screen coordinates
  float XChange(float x){ 
    x = width*0.1+100*x;
    return x;
  }
   float YChange(float y){ 
    y = height*(1-0.1)-100*y;
    return y;
  }

// To get n! (fact)
  int fact(int n) {
    if (n == 0) {
      return 1;
    } else {
      return n * fact(n - 1);
    }
  }

  void LoadDataFile(){
    table = loadTable("data.csv","header");
    for (TableRow row : table.rows()) {
      int id = row.getInt("id");
      Critics[id][0] = id;
      Names[id] = row.getString("Name");
      for (int mov = 1; mov<=6 ; mov++ ) {
        Critics[id][mov] = row.getFloat("M"+mov);
      }
      print(Names[id] + "(id=" + Critics[id][0] + ")");
      for(int i=1;i<PERS;i++){
        print(" " + Critics[id][i]);
      }
      println("");
    }
  }

//line
  void DrawAxis(int m1, int m2){
    float M =0.1;
    background(255);
    fill(0,0,0);
    strokeWeight(3);
    line(width*M,0,width*M,height);//tate_sen
    line(0,height*(1-M),width,height*(1-M));//yoko_sen
    text("M"+m1,width*(M/2)*0.3,height*(M/2));
    text("M"+m2,width*(1-M)+20,height*(1-M/2));
    for(int i=0;i<L;i++){
      float d1=width*M+i*(width*0.8)/L;
      float d2=height*M+(i+1)*(height*0.8)/L;
      line(width*M*0.8,d1,width*M,d1);
      line(d2,height*(1-M),d2,height*(1-M*0.8));
      text(5-i,width*M*0.3,d1+7);//tate_sen_kazu
      text(i+1,d2-7,height*(1-M*0.3),d2);//yoko_sen_kazu
    } 
  }

  void DrawName(int id,int Mov1,int Mov2){
    fill(0,0,100);
    text("*"+Names[id]+"("+Critics[id][Mov1]+","+Critics[id][Mov2]+")",
    XChange(Critics[id][Mov1]), YChange(Critics[id][Mov2])+10);
  }

  void Draw2Movies(int Mov1, int Mov2){
    for (int i=0; i<Names.length; i++ ) {
      DrawName(i,Mov1,Mov2);
    }
  }

// you can also use dist(x1, y1, x2, y2) from Processing API
float Distance(int m1,int m2,int p1, int p2) {
    return sqrt(
      (Critics[p2][m1] - Critics[p1][m1])*(Critics[p2][m1] - Critics[p1][m1])
      +(Critics[p2][m2] - Critics[p1][m2])*(Critics[p2][m2] - Critics[p1][m2])
    ); 
}

  void DrawDistance(float d, int m1,int m2,int p1, int p2){
   float x,y;
    x = ( Critics[p1][m1] + Critics[p2][m1] ) / 2.0f ;
    y = ( Critics[p1][m2] + Critics[p2][m2] ) / 2.0f ;
    fill(255,0,0,50);  
    text(""+(round(d*100)/100.0f),XChange(x)-10,YChange(y));
  }

  void DrawEuclidean(int m1,int m2,int p1, int p2){
    // println(map(Distance(m1,m2,p1,p2),0,5,50,0)); //How to know map()
    stroke(10,10,10,map(Distance(m1,m2,p1,p2),0,5,50,10));
    strokeWeight(0.5);
    line(XChange(Critics[p1][m1]),YChange(Critics[p1][m2]),
         XChange(Critics[p2][m1]),YChange(Critics[p2][m2]));
  }

  void setup() {  
    size(640,640);
    //Open new PDF file
    pdf = (PGraphicsPDF)beginRecord(PDF, "Eucledean.pdf");
    beginRecord(pdf);

    textSize(15);
    fill(90,90,90);//line_color
    LoadDataFile();
    FloatDict GlobalDist = new FloatDict();
    for (int m1=1; m1<MOVS; m1++) {
      for (int m2=m1+1; m2<MOVS; m2++) {
        println("----Movies(M"+m1+",M"+m2+")-----");
        DrawAxis(m1,m2);
        Draw2Movies(m1,m2);
        FloatDict Dist = new FloatDict(); // for each graph
        // int Combination = fact(7) / ( fact(2) * fact( PERS - 2 ) );
        // println("Combination("+PERS+",2)="+Combination);
        for (int p1=0; p1<PERS-1; p1++) {
          for (int p2=p1+1; p2<=PERS-1; p2++) {
            float d = Distance(m1,m2,p1,p2);
            DrawEuclidean(m1,m2,p1,p2);
            DrawDistance(d, m1,m2,p1,p2); // draw distance on the line
            GlobalDist.set("M"+m1+",M"+m2+","+p1+","+p2, d );
            Dist.set(""+p1+","+p2, Distance(m1,m2,p1,p2));
          }
         }
        Dist.sortValues(); //println(Dist);
        float[] DistVal = Dist.valueArray();
        String[] DistPers = Dist.keyArray();
        fill(255,10,10);
        text("Eucledean[ M"+m1+" - M"+m2+" ]", width*0.6, height*0.05);
        text("min ["+DistPers[0]+"]="+DistVal[0], width*0.6, height*0.1);
        text("Max ["+DistPers[DistPers.length-1]+"]="+DistVal[DistVal.length-1], width*0.6, height*0.15);
        save("png/M"+m1+"-M"+m2+".png");
        pdf.nextPage();         //save a PDF page

      }
    }
    GlobalDist.sortValues();
    println(GlobalDist);
    //close PDF file
    endRecord();
    exit();  // Quit
  }

結果はこんな感じ

大量のPNGファイルは比較して見づらいので、ついでにPDFでも出力するようにしました。

ユークリッド距離の代わりの類似性関数としてピアソン相関を計算しても良いけど、ここでは割愛します。

このあとは、上記図書のP16-17にあるように,類似性を使って評点を正規化して、新規のユーザもしくは未回答の映画に対してオススメを行います。

【追記】PDF出力を追加しました。

EXCEL2010でのヒストグラムの描き方

「身の回りの数学」第9回「データの統計処理」の内容から引用です。

今回の講義の内容は、いつもの板書バリバリの数学チックな講義ではなく、PCの操作ばかりで数学らしくない講義になってしまいました。
自分でもこれは本意ではない、今回限りの特別編ということでご理解いただければ幸いです。
そんなわけで、フォローアップです。各自自宅で自習よろしくお願いいたします。

まずはEXCELでヒストグラムを描く方法です。
個人的には度数分布表をCOUNTIFS()を使って自分で書いて、グラフウィザードで書くのが好みです。
あまりブラックボックス化するのも考えものなので。

ですが、教科書通り、EXCEL2010の「分析ツール」を使う方法も紹介しておきます。
「ファイル→オプション→アドイン→管理」にある「Excelアドイン」の横の「設定」をクリックし「アドイン」ダイアログで「分析ツール」のチェックをONにします。
シートに戻ると「データ」メニューに「分析:データ分析」追加されています。
こちらを実行すると、様々なデータ分析処理が選べますので「ヒストグラム」を選択します。

histgram

・入力範囲:分析対象のデータです。下方向にデータが並びます。
・データ区間:横軸に当たる区間を1行づつ入れていきます。
・「新規ワークシート」、「グラフ作成」にチェックを入れます。

以下の様な度数分布表とヒストグラムが生成されます。

histgramResult

その他、授業内で紹介した数式などはこちらの完成版EXCELを参考にすると良いと思います(chap9statistics)。

以下、演習問題(発展分)の補足解説です。

(6)Q: コイン投げを100回試行して表が1、裏が0としたとき、10回、20回、50回、
 100回までの平均と分散を求め、母平均0.5、母分散0.25に近くなっているか求めなさい。
Ans(example):以下のデータセットをつかってみます。
1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0
1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1
0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0
10 回まで 平均:0:5 分散:0:27777…
20 回まで 平均:0:6 分散:0:25263…
50 回まで 平均:0:6 分散:0:24489…
100 回まで 平均:0:52 分散:0:25212…

(7) 30日分の円ドル相場の終値を調べ、度数分布表とヒストグラムを作成せよ
こちらのURLから生データを入手出来ます。
stocks.finance.yahoo.co.jp/stocks/history/?code=USDJPY=X
2013年5月9日~2013年6月5日までの市場が開いている日の終値は以下の20件でした。
100.59, 101.58, 101.82, 102.35, 102.23, 102.24, 103.18,
102.26, 102.46, 103.15, 102.01, 101.27, 100.93, 102.36,
101.13, 100.72, 100.46, 99.51, 100, 99.06
区間は99,100,101,102,103とした場合、EXCELの分析ツールでの度数分布表は、

 (頻度=)「0,3,4,4,7,2」でした。ヒストグラムは上のEXCELファイルをご参照下さい。

【C++言語】第7回「参照」new,delete,値渡し,ポインタ渡し,参照渡し

本アーティクルは「応用プログラミングA」の2013年5月28日の講義内容の補足です。
内容の正確さは保証しません。
これをそのままコピーしてレポートを書く人がいますが、全く勉強にならないのでやめましょう。

 

問題1「newとdelete」

前回、「C++でのポインタと配列の利用」ではクラスのオブジェクトをいきなり配列にとって、そのポインタを挿げ替えるような初期化を行っていたわけですが、ふつうは(少なくとも最近の言語は)こんな”野蛮な”オブジェクトの生成をしたりはしません。
(もちろんmallocやfreeなどもありますが…)

今回はnew演算子とdelete演算子を使った例を見てみましょう。

// 2013/5/28 Q1
/* new と delete 演算子
 * 三角形を表す Triangle クラスのオブジェクトを、new 演算子を使って作成する。
 * オブジェクトには初期値として、(3,4,5)を与える。
 * 各辺の長さと長さと面積を出力した後に delete でメモリを開放する。
 * なお、 delete 演算子によってデストラクタが呼び出されることを確認するために、
 * デストラクタを追加している。
*/
#include <iostream>
#include <cmath>
using namespace std;
class Triangle {
	double a, b, c; //辺の長さ
public:
	//コンストラクタ
	Triangle(double u, double v, double w) {
		a = u; b = v; c = w;
	}
	//デストラクタ
	~Triangle() {
		cout << "デストラクタが呼び出されました\n";
	}
	void set_a(double x) { a = x; }
	void set_b(double x) { b = x; }
	void set_c(double x) { c = x; }
	double get_a() {return a;}
	double get_b() {return b;}
	double get_c() {return c;}
	double area(); //面積を求める関数
	void show();  //結果を表示する
};
double Triangle::area() {
	double s;
	s = (a+b+c)/2.0f;
	return sqrt(s*(s-a)*(s-b)*(s-c));
}
void Triangle::show() {
	cout << "辺a = " << a << "\n";
	cout << "辺b = " << b << "\n";
	cout << "辺c = " << c << "\n";
	cout << "面積 = " << area() << "\n"; 
} 

int main() { 
	Triangle *tri; 
	tri = new Triangle(3,4,5); 	
/* new演算子はコンストラクタを指定して新しいオブジェクトの実体のポインタを取得する */ 
/* 1行で書くとこんな感じ 
	Triangle *tri = new Triangle(3,4,5); 	*/
	tri->show();
	delete tri;
	return 0;
}

new演算子を使うとメモリの動的確保が行えます。deleteはnewで確保したメモリを開放します。
newとdeleteは演算子でmalloc()やfree()は関数なので書式が異なります。
このサンプルでは

Triangle *tri;
tri = new Triangle(3,4,5);

という書式で、コンストラクタを呼んでクラスのインスタンスを取得しています。

なおnew/deleteを使った配列の場合も覚えておきましょう。たとえばint型10個分の配列を動的確保する場合

int *p;
p = new int[10];
for (int i =0; i<10; i++ ) {
    p[i] = i; 
} 
delete [] p;  //このカッコの付き方に注意 

new演算子を使ってクラスのインスタンスを取得した場合、そのメンバ変数やメンバ関数にアクセスするときはアロー演算子(->)を使用します。

tri->show();

 

問題2「値渡し、ポインタ渡し、参照渡し」

 
C++で関数にオブジェクトを渡す際に、「値渡し」、「ポインタ渡し」、「参照渡し(reference)」といった方法でオブジェクトを渡すことができます。問題2ではこれらを実験するプログラムを作成します。

// 2013/5/28 Q2
/* 値渡し、ポインタ渡し、参照渡し
*/
#include <iostream>
using namespace std;

class Coord {
	double x,y,z;
public:
	void set(double u,double v, double w) {
		x = u; y = v; z = w;
	}
	void show();
};
void Coord::show() {
	cout << "(" << x << "," << y << "," << z << ")";
}
//以下の関数はクラス内のメソッドではなく、オブジェクトの外でやり取りするオペレータ関数
//値渡し
void setCoord1(Coord ob) {
	double u,v,w;
	cout << "数字を3つ入力してください:";
	cin >> u >> v >> w;
	ob.set(u,v,w); //実際にはここで値は設定できないことに注意!
}  //ここでobのスコープが終了するため、設定した値は消滅する。
//ここで生成されたオブジェクトの実体obはobjとは別のメモリ空間にいることに注意

//ポインタ渡し
void setCoord2(Coord *ob) {
  //渡すときは"&obj"、受けるときは"*ob"と書く!
	double u,v,w;
	cout << "数字を3つ入力してください:";
	cin >> u >> v >> w;
	ob->set(u,v,w);  //アロー演算子"->"をつかってメソッドset()を呼ぶ 
}  //ここでobのスコープが終了するため、設定した値は消滅する。
// obは消滅するが、実際のメモリ上のポインタが渡されているため、
// 処理と処理結果はobjに残る

//参照渡し
void setCoord3(Coord &ob) {
  //参照渡しで受け取るときは"&ob"になる。なぜならポインタだから。
	double u,v,w;
	cout << "数字を3つ入力してください:";
	cin >> u >> v >> w;
	ob.set(u,v,w);  //オブジェクトそのものがきているので、"."ドット演算子になる 
}  
//ここでobのスコープが終了するが....
//ポインタ渡しと同様、処理結果はobjに残る

int main() {
	Coord obj;
	obj.set(1.1, 2.3, 5.5);
	cout << "オブジェクトの初期値:";	obj.show(); cout << "\n\n";

	cout << "値渡しで関数にオブジェクトを渡します\n";
	setCoord1(obj);
	cout << "オブジェクトの値:";	obj.show(); cout << "\n\n";

	cout << "ポインタ渡しで関数にオブジェクトを渡します\n";
	setCoord2(&obj);  //アンパサンドを使う scanf(&buf)と同じ! 
                              //関数の入力ではなく受け取り容器
	cout << "オブジェクトの値:";	obj.show(); cout << "\n\n";

	cout << "参照渡しで関数にオブジェクトを渡します\n";
	setCoord3(obj);  //&がつかないので値渡しにそっくりだが、
                             //関数の実装での受け方が違います
	cout << "オブジェクトの値:";	obj.show(); cout << "\n\n";

	return 0;
}

チャック・ノリス問題として出題してみたり。

わかりやすい解説
www.aerith.net/design/argument-j.html

問題3「参照渡しを用いた値の交換」トランプ問題

★レポート締切前なので未完です。

// 2013/5/28 Q3
/* トランプ問題
*/
#include
#include
using namespace std;

enum suit { SPADE, HEART, CLUB, DIAMOND } ;
class PCard {
//from the question
};
//参照渡し仮引数
void swap(PCard &ob1, PCard &ob2) {
	PCard ob;
	ob = ob1;	ob1 = ob2; ob2 = ob;
}

int main() {
	PCard deck[52];
	for ( int i=0; i< 4; i++ ){ //suit
		for (int j =1; j<= 13; j++ ){  //number
			switch(i) {
			case 0:
				deck[i*13+j-1].set(SPADE, j);
				break;
				//★以下すべてのsuitに実施(未実装)
			}
		}
	}
	//カードの初期化終了
	//内容一覧
	for (int i=0; i<52; i++) {
		deck[i].show();
	}

	//シャッフル
	for (int i =0; i<100; i++) {
		int a,b;
		a = rand() % 52;
		b = rand() % 52;
		swap(deck[a], deck[b]);
		//ここにAとBを入れ替えました、的な表示を入れておくとわかりやすい
	}
	//再度内容一覧
	for (int i=0; i<52; i++) {
		deck[i].show();
	}

	return 0;
}

【C++】第6回:C++でのポインタと配列の利用

応用プログラミングA(C++言語)、前回の「C++のフレンド関数」に引き続き、今週は「C++でのポインタと配列の利用」です。

C++言語はオブジェクト指向(クラス指向)ではありますが、C言語のパワフルなポインタも使えることは意外と知られていません。
(とはいえ実用上はオブジェクトの配列を使うことが多いと思います)

今回は「学生の成績を管理するクラス」を作成して、ここまでの復習を兼ねた総合問題という設計になっています。

出題された課題は3問あります。
Q1、Q2、Q3…と順に解いていかないと、最後までたどり着けませんので注意です。

またサンプル中に出てくる学生の名前は昨年のAKB48からガラッと変わって『ラブライブ!』からの引用が多いようですが、打つのが大変なのと、私自身が思い入れがないので適当なボカロあたりの名前に差し替わっております。
このあたり、まるまるコピーした場合は減点対象となりますので要注意。

まずQ1です。

ここでは学生のデータを管理するStudentListクラスを作成します。

class StudentList {
	char name[50]; //学生の氏名
	int id, grade; //学籍番号、学年
public:
	void set(char *n, int i, int g);
	void show();
};

このオブジェクトの配列に10人分のデータをコンソールから入力し、すべて入力し終わったらコンソールに出力する基本となるプログラムを作ります。

「独習C++(第4版)」の例4.2を参考にするとよいようです。
独習C++ 第4版

//配列とポインタ:クラスオブジェクトを配列でとった場合も、C言語におけるポインタと同様に扱える。
#include <iostream>
#include <cstring>
using namespace std;
class StudentList {
	char name[50];
	int id, grade;
public:
	void set(char *n, int i, int g);
	void show();
};
void StudentList::set(char *n, int i, int g) {
	strcpy(name, n);
	id = i;		grade = g;
}
void StudentList::show() {
	cout << "氏名:" << name;
	cout << "\t学籍番号:" << id;
	cout << "\t学年:" << grade << "\n";
}

int main() {
	StudentList slist[10];		 //入力用にオブジェクトの配列を宣言
	int id, grd;	char nm[50]; //入力用変数
	int max = 3;				 //最大件数
	StudentList *ptr;			 //配列の操作用にポインタ変数を宣言
	ptr = slist; //ポインタ渡し,ここで配列とポインタを接続
	for (int i=0; i<max ; i++ ) {
		cout << i+1 << "人目のデータを入力します\n";
		cout << "名前を入力してください:";  cin >> nm;
		cout << "学籍番号を入力してください:"; cin >> id;
		cout << "学年を入力してください:";  cin >> grd;
		//仮の入力用変数からポインタの先頭にデータを格納し、ポインタを進行させる.
		ptr->set(nm, id, grd); ptr++;
		//※このptr++で配列1行分、ポインタが進む
	}
	ptr = slist;  //ふたたびポインタをリセット
	for (int i = 0; i < max; i++ ) {
		cout << i+1 << "\t";
		ptr->show(); //このような形でメソッドが呼べることに注意
		ptr++;
	}
	return 0;
}

実行すると、10人分の名前と学籍番号、学年の入力を強いられるだけのマゾプログラムです。
しかも最後の return 0; にブレイクポイントを仕込んでおかないと結果が一瞬で流れて消えます。
それではあまりにご無体ですので、ここではmax=3として端折っています。レポートではmax=3としたら誤りです。

ちなみに講義中はptrのことを『ハンドル』と呼んでしまいましたが、厳密には異なります。
ここは固定のメモリアドレスをptrに渡しているので『ポインタ』と呼ぶのが適切でしょう。
『ハンドル』とは、動的にメモリ配置が変わる場合、たとえばガーベージコレクションなどを備えたJavaやC#のような環境において、実メモリアドレスが移動しても、捕まえておけるオブジェクトのことを『ハンドル』と呼ぶべきようです。

つづいてQ2です。タイトルは「総合問題1」となっています。

先ほどのQ1の続きからはじめて、成績を管理するResultListクラスを追加します。
先述のStudentListクラスをPublicに継承して、公開メンバとして100個までの科目名を格納し、その単位異数と評価を格納します。また格納されている科目数を記憶する変数を非公開メンバ変数として持ちます。関数は評価を格納するための関数Regist()と、全科目の科目名、単位数、評価を出力するshowResult()を持ちます。

以下のようなクラス設計、継承(inheritance)の関係がイメージできましたでしょうか?

Classes
(Visual Studio 2010の「クラスダイアグラム」機能で描画してみました)

継承をコードにするとこんな感じになります。

class ResultList : public StudentList {
	char	course[100][50];	//科目名
	int		credit[100];		//単位数
	char	grade[100];			//評価
	int		number;				//格納してある科目数
public:
	ResultList() { number = 0; }
	void regist(char *title, int crd, char grd);
	void showResult();
};

なお、今回のプログラムでは入力チェックなどは一切行いません。削除や変更もしませんし、科目名の重複もチェックしません。

//Q2:総合問題1 成績管理(入力)
#include <iostream>
#include <cstring>
using namespace std;
class StudentList {
	char name[50];
	int id, grade;
public:
	void set(char *n, int i, int g);
	void show();
};
void StudentList::set(char *n, int i, int g) {
	strcpy(name, n);
	id = i;		grade = g;
}
void StudentList::show() {
	cout << "氏名:" << name;
	cout << "\t学籍番号:" << id;
	cout << "\t学年:" << grade << "\n";
}
//ここから上はQ1と同じ
//ここから下はテキストにある通り、StudentListを継承したResultListを宣言
class ResultList : public StudentList {
	char	course[100][50];	//科目名
	int		credit[100];		//単位数
	char	grade[100];			//評価
	int		number;				//格納してある科目数
public:
	ResultList() { number = 0; }
	void regist(char *title, int crd, char grd);
	void showResult();
};
void ResultList::regist(char *title, int crd, char grd) {
	strcpy(course[number], title);
	credit[number] = crd;
	grade[number]  = grd;
	number++;
}
void ResultList::showResult() {
	//格納してある科目数すべてについてリストする
	for (int i = 0; i < number; i++ ) {
		cout << "科目名:" << course[i];
		cout << "\t単位数:" << credit[i];
		cout << "\t評価:" << grade[i] << "\n";
	}
}

int main() {
	ResultList rlist[10];
	int i,n; char str[50]; char c;
	//名前学籍学年データ , 継承したResultListの配列にセットします
	rlist[0].set("高坂穂乃果",1123005, 3);
	rlist[1].set("絢瀬絵里", 1023003, 4);
	rlist[2].set("南ことり", 1123008, 3);
	rlist[3].set("園田海未", 1123039, 3);
	rlist[4].set("初音ミク", 1023010, 3);
	rlist[5].set("ルカ",	 1223007, 2);
	rlist[6].set("リン",	 1023007, 4);
	rlist[7].set("レン",	 1223008, 2);
	rlist[8].set("かいと",   1023015, 4);
	rlist[9].set("らぴす",   1323013, 1);

	while (1) {
		cout << "学生一覧\n";
		for (i = 0; i < 10 ; i++ ) {
			cout << i+1 << "\t";
			rlist[i].show(); //普通はこう呼ぶほうが多いですよね。継承元のStudentList::show()です
		}
		cout << "何番の学生の成績を入れますか?\n";
		cin >> i;
		cout << "成績を入力してください\n入力終了はendを科目名に入れて下さい\n";
		while(1) {
			cout << "科目名:"; cin >> str;
			if (strcmp(str, "end") == 0) break;
			cout << "単位数:"; cin >> n;
			cout << "評価:";   cin >> c;
			rlist[i-1].regist(str, n, c );
		}
		rlist[i-1].show();
		cout << "この学生のデータを入力しました。\n終了するなら1を続けるなら0を:";
		cin >> n;
		if (n == 1) break;
	}
	//結果表示
	for (i = 0; i < 10; i++ ) {  //個々の学生についてループ
		rlist[i].show();		//個々の学生の情報について表示
		rlist[i].showResult();	//個々の科目の成績について表示
		cout << "\n";
	}
	return 0;
}

【実行結果】
cpp0521q2

9番目の「かいと」(KAIT!?)と10番目の「らぴす」の成績を入力しています。
「応用プログラミングA」が同じ名前なのですが、見た目には動作しています、が、デバッガ仕掛けるとわかりますが、別の科目になっています。
重複チェックを入れるのはさほど難しいことではないので考察としてやってみてもよいのでは。
また結果を表示するshow()ももう一工夫してもいいように思います(Q3にもありますので…)。
それに「end」と入れずに[0]を入れると終わるなど、工夫のしようはありそうです。
cinとifを使ったコマンドプロンプトによる対話は、インタラクティブなプログラムの基本中の基本なので しれっと 書けるようになってください。

さて最後のQ3「総合問題2」です。

前述Q2のResultListクラスに総合成績評価をあらわすGPAを追加します。
GPAは成績評価のSを4、Aを3、Bを2、Cを1、それ以外を0とした取得講義の平均で求めます。
また先ほどのRegist()を拡張してすでに同盟の科目の成績が入力されている場合には評価を上書き修正するようにします。
さらに科目と成績を削除するdel()も実装します。

0521q3class

以下、サンプルソースです。
main()がないととっかかりがつかみづらいと思いますので。
★レポート締切前なので、ResultListクラスの個々のメソッド実装は未公開です。

//0521 課題3 総合問題2
#include <iostream>
#include <cstring>
using namespace std;

class StudentList {
	char name[50];
	int id;
	int grade;
public:
	void set(char *n, int i, int g);
	void show();
};
void StudentList::set(char *n, int i, int g) {
	strcpy(name, n);
	id = i;
	grade = g;
}
void StudentList::show()	{
	cout << "氏名:" << name;
	cout << "\t学籍番号:" << id;
	cout << "\t学年:" << grade << "\n";
}
class ResultList : public StudentList {
	char course[100][50];
	int credit[100];
	char grade[100];
	int number;
	double gpa;  //今回追加
public:
	ResultList() { number = 0; gpa = 0; }
	void regist(char *title, int crd, char grd);
	void showResult();
	void del(char *title);
	double get_gpa() { return gpa; }
};

void ResultList::regist(char *title, int crd, char grd) {
	int i, sumc = 0, sumg = 0;
	for (i = 0; i < number; i++)	{
		if (strcmp(course[i], title) == 0) {
			credit[i] = crd;
			grade[i] = grd;
			break;
		}
	}
	if (i == number)	{
		strcpy(course[number], title);
		credit[number] = crd;
		grade[number] = grd;
		number++;
	}
	for (i = 0; i < number; i++) {
		sumc += credit[i];
		switch (grade[i])	{
			case 'S':
				sumg += 4 * credit[i];
				break;
			case 'A':
				sumg += 3 * credit[i];
				break;
			case 'B':
				sumg += 2 * credit[i];
				break;
			case 'C':
				sumg += 1 * credit[i];
				break;
			default:
				break;
		}
	}
	gpa = (double)sumg / sumc;
}

void ResultList::showResult() {
	for (int i = 0; i < number; i++) {
		cout << "科目名:" << course[i];
		cout << "\t単位数:" << credit[i];
		cout << "\t評価:" << grade[i] << "\n";
	}
}

void ResultList::del(char *title) {
	int i, j, sumc = 0, sumg = 0;
	for (i = 0; i < number; i++) {
	   if (strcmp(course[i], title) == 0) {
// 以下は登録されている科目の順番を変えないように処理している.順番を変えてもよいならもっと簡単
		for (j = i; j < number; j++) {
			strcpy(course[j], course[j+1]);
			credit[j] = credit[j+1];
			grade[j] = grade[j+1];
		}
		number--;
		for (j = 0; j < number; j++) {
			sumc += credit[j];
			switch (grade[j]) {
				case 'S':
					sumg += 4 * credit[j];
					break;
				case 'A':
					sumg += 3 * credit[j];
					break;
				case 'B':
					sumg += 2 * credit[j];
					break;
				case 'C':
					sumg += 1 * credit[j];
					break;
				default:
					break;
			}
		}
		gpa = (double)sumg / sumc;
		break;
	   }
	}
}
//以下はmainの参考。
int main() {
	ResultList rlist[10];
	int i, j, n;
	char str[50];
	char c;
	//学生ダミーデータ:レポートでそのまま使用した場合はカンニングとみなします :-p
	rlist[0].set("高坂穂乃果", 1123005, 3);
	rlist[1].set("絢瀬絵里", 1023003, 4);
	rlist[2].set("南ことり", 1123008, 3);
	rlist[3].set("園田海未", 1123039, 3);
	rlist[4].set("星空凛", 1023010, 4);
	rlist[5].set("西木野真姫", 1223014, 2);
	rlist[6].set("東條希", 1023007, 4);
	rlist[7].set("小泉花陽", 1223008, 2);
	rlist[8].set("矢澤にこ", 1023015, 4);
	rlist[9].set("アルパカ", 1323013, 1);
	while (1) {
		cout << "学生一覧\n";
		for (i = 0; i < 10; i++) {
			cout << i+1 << "\t";
			rlist[i].show();
		}
		// 以下では入力値の検証を行っていない.本当は入力値の検証を行った方がよい
		cout << "何番の学生のデータを処理しますか?";
		cin >> i;
		cout << "成績を入力するには1を、削除するには2を入力してください:";
		cin >> j;
		cout << "入力を終了するには科目名にendと入力してください。\n";
		if (j == 1) {
			while (1) {
				cout << "科目名:";	cin >> str;
				if (strcmp(str, "end") == 0) break;
				cout << "単位数:";	cin >> n;
				cout << "評価:";	cin >> c;
				rlist[i-1].regist(str, n, c);
			}
		} else {
			while (1) {
				cout << "科目名:";	cin >> str;
				if (strcmp(str, "end") == 0) break;
				rlist[i-1].del(str);
			}
		}
		rlist[i-1].show();
		cout << "この学生のデータを入力しました。\n\n";
		cout << "入力を終了しますか?\n";
		cout << "終了するなら1を、続けるなら0を入力してください:";
		cin >> n;
		if (n == 1) break;
	}
	for (i = 0; i < 10; i++) {
		rlist[i].show();
		rlist[i].showResult();
		cout << "GPA:" << rlist[i].get_gpa() << "\n\n";
	}
	return 0;
}

実行結果のスクリーンショットはうまく、登録や削除を説明できるように複数撮りましょうね!
たとえば、このスクリーンショットだけでは何が何だかわかりませんよね?

0521q3

第7回に続きます。

C++のフレンド関数

2013/5/14の「応用プログラミングA(C++)」の講義ふりかえり.

Q1は,独習C++の3章までの復習として関数とオブジェクト.
クラスに属していないメイン関数を作って,先に現れているクラスCoordを引数や戻り値に指定している.

#include
#include
using namespace std;
//クラスCoordの宣言
class Coord {
	double x,y,z;
public:
	void set_x(double u) {x=u;}
	void set_y(double v) {y=v;}
	void set_z(double w) {z=w;}
	double get_x() {return x;}
	double get_y() {return y;}
	double get_z() {return z;}
	void Show();
};
void Coord::Show() {
	cout << "(" << x << "," << y << "," << z << ")";
}

//Coordオブジェクトを返す、中点を求める関数
Coord mid_Coord(Coord ob1, Coord ob2);
//Coordオブジェクトを返す、距離を求める関数
double dist_Coord(Coord ob1, Coord ob2);

int main() {
	Coord p1,p2,p3;
	//p1,p2に3次元座標をセットしていく
	p1.set_x(1.0f);		p1.set_y(6.5f);		p1.set_z(-10.0f);
	p2.set_x(-1.0f);	p2.set_y(1.5f);		p2.set_z(4.0f);

	cout << "点A";	p1.Show(); cout << endl;
	cout << "点B";	p2.Show(); cout << endl;
	//中点p3を取得
	p3 = mid_Coord(p1,p2);
	cout <<"ABの中点";	p3.Show();	cout << endl;
	//距離を求める,値を返すだけなのでリダイレクトで出力できる
	cout <<"AB間の距離" << dist_Coord(p1,p2) << endl;
	return 0;
}
//中点を求める関数の実装
Coord mid_Coord(Coord ob1, Coord ob2) {
	Coord ob;
	ob.set_x( (ob1.get_x() + ob2.get_x()) / 2.0f );
	ob.set_y( (ob1.get_y() + ob2.get_y()) / 2.0f );
	ob.set_z( (ob1.get_z() + ob2.get_z()) / 2.0f );
	return ob;
}
//距離を求める関数の実装,1行で実装してみる
double dist_Coord(Coord ob1, Coord ob2) {
	return sqrt(
		( ob2.get_x() - ob1.get_x() ) * ( ob2.get_x() - ob1.get_x() ) +
		( ob2.get_y() - ob1.get_y() ) * ( ob2.get_y() - ob1.get_y() ) +
		( ob2.get_z() - ob1.get_z() ) * ( ob2.get_z() - ob1.get_z() )
		);
}

Q2はQ1の復習に引き続き,「フレンド関数」を使った実装方法を学ぶ.
色名と色の値を扱うクラスCNameを引数として,円クラスCircleのオブジェクトに対して,「色が一致しているか?」を判定するisSame(CName col)を宣言・実装する必要が有るため friend を名乗る必要がある.

#include <iostream>
#include <cstring>
using namespace std;
class CName;//ここはクラス名だけ宣言してみた
class Circle {
	double x,y,radius;	int r,g,b;
public:
	void set_xyr(double s, double t, double r) {	x = s; y = t; radius = r;	}
	void set_color(int u, int v, int w) {			r = u; g = v; b = w;	}
	void Show();
	bool isSame(CName col);
};
class CName {
	char name[50];	int r,g,b;
public:
	CName (char* str, int u, int v, int w);
	char* get_name() {		return name;	}
	void Show();
	friend bool Circle::isSame(CName col);
};
//friend関数isSameの実装
bool Circle::isSame(CName col) {
	if (r == col.r && g == col.g && b == col.b ) {
		return true;
	} else {
		return false;
	}
}
//CName(色名,RGB値)のコンストラクタ
CName::CName(char* str, int u, int v, int w) {
	strcpy(name, str);
	r = u; g = v; b = w;
}
void CName::Show() {
	cout << name << ":(" << r << "," << g << "," << b << ")\n";
}

int main() {
	Circle c;
	CName co1("Red",255,0,0); 	CName co2("Green",0,255,0); 	CName co3("Blue",0,0,255);
	c.set_xyr(2.0f,3.0f,5.0f);
	c.set_color(255,0,0); //赤
	cout << "円の情報を表示\n"; c.Show();
	cout << "色1の情報を表示\n"; co1.Show();
	cout << "色2の情報を表示\n"; co2.Show();
	cout << "色3の情報を表示\n"; co3.Show();
	cout << "この円の色は" << co1.get_name();
	if (c.isSame(co1)) {
		cout << "です" << endl;
	} else {
		cout << "ではありません" << endl;
	}
	cout << "この円の色は" << co2.get_name();
	if (c.isSame(co2)) {
		cout << "です" << endl;
	} else {
		cout << "ではありません" << endl;
	}
	cout << "この円の色は" << co3.get_name();
	if (c.isSame(co3)) {
		cout << "です" << endl;
	} else {
		cout << "ではありません" << endl;
	}

	return 0;
}
//void Show()の実装
void Circle::Show() {
	cout << "座標("<< x << ","<< y <<") 半径=" << radius << endl;
	cout << "RGB=("<< r <<","<< g <<","<< b << ")" << endl;
}

Q3はQ2の配列による拡張.

まだ課題提出締め切り前なので,main文以下だけ掲示しておきます.→全文掲載しました

#include
#include
using namespace std;

class CName;

class Circle {
	double x, y;
	double radius;
	int r, g, b;
public:
	void set_xyr(double s, double t, double r) {
		x = s;
		y = t;
		radius = r;
	}
	void set_color(int u, int v, int w) {
		r = u;
		g = v;
		b = w;
	}
	void show();
	bool isSame(CName col);
};

class CName {
	char name[50];
	int r, g, b;
public:
	CName(char* str, int u, int v, int w);
	char* get_name() {
		return name;
	}
	void show();
	friend bool Circle::isSame(CName col);
};

void Circle::show() {
	cout << "座標:(" << x << "," << y << ")\n";
	cout << "半径:" << radius << "\n";
	cout << "RGB:(" << r << "," << g << "," << b << ")\n";
}

bool Circle::isSame(CName col) {
	if (r == col.r && g == col.g && b == col.b)
		return true;
	else
		return false;
}

CName::CName(char* str, int u, int v, int w) {
	strcpy(name, str);
	r = u;
	g = v;
	b = w;
}

void CName::show() {
	cout << name << ":(" << r << "," << g << "," << b << ")\n";
}

int main() {
	Circle ob[3];
	CName co[8] = { CName("White", 255, 255, 255),
					CName("Black", 0, 0, 0),
					CName("Red", 255, 0, 0),
					CName("Green", 0, 255, 0),
					CName("Blue", 0, 0, 255),
					CName("Cyan", 0, 255, 255),
					CName("Magenta", 255, 0, 255),
					CName("Yellow", 255, 255, 0) };
	int i, j, flag;

	ob[0].set_xyr(2.0, 3.0, 5.0);
	ob[0].set_color(255, 0, 0);
	ob[1].set_xyr(4.0, 5.0, 6.5);
	ob[1].set_color(0, 255, 0);
	ob[2].set_xyr(1.5, 1.5, 2.0);
	ob[2].set_color(150, 150, 150);

	for (i = 0; i < 3; i++) {
		cout << "円" << i+1 << "の情報を表示\n";
		ob[i].show();
	}

	cout << "\n登録してある色一覧\n";
	for (i = 0; i < 8; i++) {
		co[i].show();
	}
	cout << "\n";

	for (i = 0; i < 3; i++){
		flag = 0;
		for (j = 0; j < 5; j++) {
			if (ob[i].isSame(co[j])) {
				cout << "円" << i+1 << "の色は" << co[j].get_name() << "です\n";
				flag = 1;
				break;
			}
		}
		if (!flag) {
			cout << "円" << i+1 << "の色は登録されている色にありません\n";
		}
	}

	return 0;
}

【実行結果】

半径:5
GB:(255,0,0)
円2の情報を表示
座標:(4,5)
半径:6.5
GB:(0,255,0)
円3の情報を表示
座標:(1.5,1.5)
半径:2
GB:(150,150,150)

登録してある色一覧
hite:(255,255,255)
lack:(0,0,0)
ed:(255,0,0)
reen:(0,255,0)
lue:(0,0,255)
yan:(0,255,255)
agenta:(255,0,255)
ellow:(255,255,0)

円1の色はRedです
円2の色はGreenです
円3の色は登録されている色にありません

次回は「C++でのポインタと配列の利用」です。