あ"~、なーんでこんなテーマにしたんだろう?」と嘆く日々、は大袈裟ですが、大体特殊な生まれや環境の人でない限り、

 

そんなに外国と接点があるわけはないっ!!!

 

のが普通だった時代なので、前回のような

 

洋行

前回書き忘れましたが、「酒」に味を占めて、又トラベラーズチェックが余ったので、帰りにお土産を買うことにしました。当時は「洋行帰りのお土産」と言えば、所謂「免税枠」のお酒(これは国内で手に入りづらい「ジョニ黒」が定番で、私は更にその上のJohnny WalkerSwing3本と洋モク(外国製の煙草のことですが、既に死語ですよね?)2カートンが定番だったのでその通り買ったのですが、「未成年者に免税枠は適用されない」ということで、吃驚するくらいの関税を払った記憶があります。

 

自体が稀だったのです。

 

ということで、

 

今の人のようにサマースクールやインターン的に海外に出向いて勉強したり、働いたりする学生が稀だったので、大学時代にはこれ以上の外国との接点は「ロッキード事件」に興味を持って調べたくらいで、何もなかったですね。

 

大学を卒業して、社会人になった()後も、特筆するイベントはなく、

:簡単に書きますが、実は色々と山あり谷ありでした。しかし、テーマから外れるので省略します。

  • 入社二年目で部内の海外事業担当課の「黒電話()」にコレクトコールが入り、偶々通りかかった私がとって、"%#X#!?(Would you accept the collect call?だった筈)"と英語で聞かれ、「誰か助けて~!」と叫んだ歴史
  • 会社内の内線電話は国際通話ができない仕組みだったので、本当に当時は「ジーコンの黒電話」が海外直通用にありました。
  • (それまで275円/ドル位であった相場が1978年10月に175円となる急激な円高だったので)矢張り入社二年目で行った3泊4日位のグアム旅行

位しか「外国との接点」的イベントは思いつきません。

 

従ってこのまま行けば「外国とは縁のない私の人生」が待ち受けているはずだったのに、その後の私のキャリアを大きく変える潜在的なイベントが実は潜行していたのでした。それは、

 

神様との出会い注)

刑事コロンボでよく言われた「いやぁ、ウチのカミさんがね」の丁寧語です。

 

でした。

 

前回書いた通り、当時の普通の中学生、高校生として(要すれば、外国には縁のない)過ごしてきた私は、これまた当たり前のように大学受験を迎え、エンターテインメントが減少し、「外国もの」との接点も少なくなりますが、一方上の兄(注1)の強い勧めがあり、受験勉強は「旺文社大学受験講座」だけしかやらず、同時に深夜放送で洋楽も聴いていました。(注2

注1:余談ですが、彼は当時の所謂ツッパリで、高2で悪ガキどもと停学を食らい、高3で高1の私に英語を教わっていたのですが、現役で(担任教師によれば「これしか受からない」という)1校合格後、5日で退学し、その後浪人して猛勉強の上、早稲田、慶応 x 2、東京理科、上智の5校全制覇という快挙を上げました。

注2:当時忘れられない曲には以下などがあります。

Leon Russell - Tite Rope, Song for you

Helen Reddy - Angie Baby

Roberta Flack - Killing Me Softly With His Song

 

テーマからそれるので結果だけ記せば、自信満々のマークシート試験で「滑り止めの早稲田」を落ち、落ち込んで受け「だめだっ!」と思った志望校の国立大に受かりました。

 

Lucky Me (How lucky I am)

 

もっと喜んだのは親父で、彼は経済的事情から大学にゆけなかったため「教育こそ本当の遺産(相続財産)」という考えをもっており、(上の兄は数十万円かかったのに)入学金、年間受験料ともに36,000円注1)しかかからなかった私が「可哀想だ」ということで、(何処で仕入れてきたのかわかりませんが)突然勝手に(予告なく)UNICEF主催の青少年の国際理解教育の為のツアー(注2)を予約してきました。(驚!

注1:1973年の平均初任給62,300円、物価ではカローラが約53万円〜70万円14インチカラーテレビが約9万円台、一戸建て家屋が概ね1,000万円強程度でした。

注2:確か取引先の信用金庫からの情報で、覚えているのは「学生一人50万円かかる、15日間でイギリス・ロンドン~フランス・パリ~西ドイツ(当時)・フランクフルト~オーストリア・ウィーン~イタリア・ローマ(ミラノから太陽道路で、ローマはバチカン市国も訪問)までのツアー」で、確認の為にネットで調べてみましたが、当時日本ユニセフ協会は国際理解教育活動を行っていたこと以外は具体的な情報は得られませんでした。

 

えっ、外国!(嬉しさよりも、不安と惧れ)

 

というのが、当時の偽らざる心情でした。又、一般人が海外旅行ができるようになってからまだ9年目、ということもあり、渡航手続きは煩瑣を極めます。

  • 旅券-パスポートは単次旅券で、確か5,000円程したと記憶してます。数次旅券は「(1万円位して高い!し)もう行かないだろう」ということで単次旅券になりました。
  • 査証-ビサですが、当時はすべての国のビサ(1ヶ国3,000円位)が必要でした。
  • 予防接種-如何に高度成長期の1973年で日本のGNP(国民総生産)が西ドイツを抜き、アメリカに次ぐ西側第2位になったとはいえ、まだまだアジアからの渡航ですからコレラ、天然痘、チフス、ペスト等に係る国際予防接種証明書(イエローカード)が入国条件でした。
  • 旅行小切手-サイン+カウンターサインが必要なトラベラーズチェック(現在は死語?2014年から発行されていないらしい)のことで、限度額いっぱいの$500-当時は「360円/US$」なので18万円-をThomas Cookのもので用意したと記憶しています。

18歳になって、生まれて初めてのパーマをかけ、まだ冬が明けない欧州なのでこんな風Maxiのトレンチコートを着て、上の兄に唯一の国際空港である羽田まで車で送ってもらったことを覚えています。

 

当時英語は受験英語で、「読み、書き」はできても「しゃべり、聴き」は覚束なく、その他の国の言葉は挨拶(e.g. "Bon jour" in French)と「いくら? e.g. "Combien?" in French」位を旅行本で調べました。(欧州国の歴史等は世界史の授業程度しか知識がなく、文化等は全くの無知でした。)

 

 

で、

 

少しは「外国」と接することができたのかというと、

 

そんなことは全くなく

 

ただただ(今の言葉でいえば)

 

訳分かんなかったけど、スンゲー

 

ということだけで、旅行後の印象(と言うか、私にとっての事実)は、

  • イギリスは食事が本当に不味い(悪食の18歳男子でも、食べられたのがモーニングロールと紅茶だけ)
  • フランスは水がなく、風呂が使えない(小さなバスタブに、紐を引いて如雨露のお湯を垂らす感じ-なお、飲料水もないので、ビールとワインばっかり飲んでいました)
  • 西ドイツはビールがうまいが、食事はジャガイモと豚肉だけ(フランスから酒浸りになりました!)
  • イタリアは文句なく何でも美味い、生まれて初めて食べたドラッグストアのピザに感激(勿論イタリアワインやビールも)
ということで、(高尚な社会と文化等はお留守で)結局は
 
「飯と酒」
 
の記憶しかないです。(爆)
 
ps. 因みにこの旅行は「沈まぬ太陽」にも出てくる、地獄|恐怖の「JAL南回り欧州便(所要28時間)」で、バンコク、ドバイに立ち寄り、数えきれないくらい矢鱈機内食を食べ腰が痛く(事実、反対向きに搭乗席に正対して寝ていました)閉所恐怖に陥り、飛行機から飛び出したくなったのをよく覚えています。改めてこの便(どうもロンドン行きのJL462便らしい)の中継地は、
  • 羽田空港(東京) 【出発】
  • 啓徳(カイタック)空港(香港)
  • ドンムアン空港(バンコク/タイ)
  • 国際空港(ドバイ/アラブ首長国連邦)
  • ヘリニコン(エリンニコン)空港(アテネ/ギリシャ)
  • フランクフルト空港(当時の西ドイツ)
  • ヒースロー空港(ロンドン/イギリス) 【到着】
であったようです。
 

前回も触れましたが、小学校高学年から中学へ進学する(従って、私も色気づく)頃になると、「外国もの」ソースには「映画」や「音楽」も加わります。(

:自戒と注意喚起までにですが、思春期の記事を書いていると「私にとっての外国」というテーマから逸脱し、「私のエンターテインメント史」になってしまうので、何度か書き直しましたが、矢張りその「」が拭えません。割り引いて読んでください。

 

(1)「映画」

親が結構映画が好きだったので、家で「Screen」(注1)という映画雑誌を取っていました。従って数々の外国俳優を知っていましたし、その映画も(TVの洋画劇場ものですが...)観ました。今は(Amazon Prime等でも)ハリウッドに代表される米国映画が主流ですが、当時は映画と言えば中心はマルチェロ マストロヤンニ、ソフィア ローレン等イタリア、アラン ドロン、ジャン ポール ベルモンド等フランスで、米国映画は追随者、という感じでした。中学に入り思春期になると特に「太陽がいっぱい」とか「鉄道員注2)」とか結構見ていましたね。

注1:現在もあるんですね、この雑誌

注2:役者で監督のピエトロ ジェルミに嵌っていました。他に「わらの男」、「刑事 」とかもTVでやりましたね。

 

(2)「音楽」

兄が二人いたのでガキの頃からませていて、小学生の頃から外国のポップミュージックを聞いていたことは前回も書きました。更に「小学生のくせに髪を伸ばしてエレキギターなどを弾いていた」()ので、

:小学校の担任から「不良」といわれましたが、何か?大体当時「長髪」といっても耳が全部出ていたんですよね。

 

The Ventures

:小学校の時代には、加山雄三は勿論、寺内タケシとかコピーするのが流行り、「勝ち抜きエレキ合戦」なんて言う番組もありました。

 

から

 

The Beatles

 

等を聞いていて、中学になると矢張り今度はお定まりのポップス、ロック、ブルース、ジャズ等へ傾倒してゆきます。ポップスはThe SupremesDiana Ross)、Jacjson 5Michael Jackson)等モータウン系、ロックは(矢張りギター系で)

Jimi Hendrix

CreamEric Claption

ブルースは当時のThree KingsB.B.KingAlbert KingFreddie King)、ジャズは(当時曲を聴いたことがないと馬鹿にされた)

Miles Davis

等を聞いていたように思います。(が、どういう訳か、この後子供の頃に始めたバイオリンを再開し、クラシック音楽へ回帰するするということもありました。)単発ですが「アートロック」の流れでVanilla Fudgeの" Keep me hangin’on"()が大流行したのもこのころでしたか。

:オリジナルはThe Supremesの"You Keep me hangin’on"です。

 

いずれにせよ、ニキビ面の中坊はカッコよさを求めて「洋楽」一辺倒でしたね。

 

(3)「TV番組」

日本のTV界も国産コンテンツが増え、小学校の時のような「海外ものばかり」ということはありませんが、それでもまだ輸入TVドラマは結構ありました。米国だけでもこんなにあります。

矢張り男の子であったので、

ミステリーゾーン

アウター・リミッツ

TimeTunnel(1967年 NHK)

宇宙家族ロビンソン

等のSFものとか、

バットマン 
0011ナポレオン・ソロ

バークにまかせろ

Prisoner No. 6(1969年 NHK)

等のアクション、スパイもの等に興味を持っていましたね。

 

そんなことで「海外旅行は自由化」()され、(主に欧米白人社会でしたが)外国に関するソースはあれど、矢張り

今こんなことを言うと若い人はびっくりしますが、1964年(昭和39年)4月1日、日本で観光目的の海外旅行が自由化され、一般市民でもパスポートを取得し、外貨(当初は1人500ドルまで)を持ち出して自由に海外へ渡航できるようになりました。1964年の出国者数は約13万人でしたが、1969年には観光目的が業務目的を初めて上回り、出国者数も49万人(男性8割、女性2割)を超えました。

 

1ドル360円の固定相場制

 

の壁は大きく、厚く、ほとんどの日本人にとって「実際に外国に往く」という可能性は皆無でした。(私の場合、ガキだったので当たり前と言えばそうなんですが。)

 

2026年07月11日のお昼は、この間トライした韓国冷麺風ビーフベースのスープ(ビーフコンソメが好きなので)ソーメンを作ってみました。具は

水菜、

オニオンスライス

錦糸卵、そして

キムチ

です。スープを最後まで飲み干しました。
 

 

最近間違ってケチャップを買い過ぎたので、消費の為にナポリタン等を作っていましたが、2026年07月14日のお昼は久々のケチャップライス(所謂「チキンライス」)にしてみました。「ケチャップライス?」とバカにしていましたが、食べると懐かしくもあり、美味しかったです。(グラウンドポーク、玉葱微塵切り、少量の人参、モヤシ(?)を入れてみました。お供はビープメンチカツです。)

 

2026年07月15日のお昼は、「マツコの知らない世界」でツナ缶から冷や汁を作る調理法が出ていたので、自分なりにアレンジしてみました。
ツナ缶はオイル漬けではなく、ノンオイル(野菜スープ)ベースで、
油揚げ長ネギの煮びたし、
錦糸卵
豆腐
玉葱微塵切り
大葉茗荷七味唐辛子
で纏めました。元々味噌汁冷や汁が大好きなので、とてもおいしくいただきました。

 

既に終了した本シリーズですが、ゲームのパフォーマンスについては書いていませんでしたので、私の神様に説明したように説明してみます。

 

.これはオリジナルがJavaScriptというインターネットブラウザー向けに書かれた「鳥の群生行動」を分離(Separation)、整列(Alignemnt)及び結合(Cohesion)からシミュレートするプログラムを、私自身の"Cell/Cells"という「人間的」生態シミュレーションゲームで抜けていた「群れを成す」「群れから離反する」という行動の関心の為に、自分なりに 組みなおしたプログラムで、

 

.オリジナルとちがうのは「群れを成す」Flocker種の他に、群れから離反したがるIntrovert種(全体の5%程)と、協調行動を無視して群れへ向かってゆく攻撃的なSociopath種(全体の3%程)を加えて、全体(社会)の推移を観察するゲームにしている。

 

実際のゲームの推移のサンプルとして、

 

 

というパラメーターで朝の7時から

 

 

 

11時まで4時間動かしてみたところ、("Cell/Cells"のように交尾による再生産が行われないので当たり前と言えば当たり前なのですが)次のようになりました。

 

 

一人Sociopathが空しく(己が滅ぼした「群れ」を求めて)飛び続けています。

 

何か

 

第47代米国連邦合衆国大統領を彷彿

 

させる情景ではあります。

 

前回書いたように、本ブログのテーマであるプログラミングから少し張られて、【無駄話】のノリで、「今は昔...」を物語ってみようかなと思います。

 

今回取り上げようと思うのは、

 

外国の話

 

です。(

:現在のインターネット環境と国際化の現代では「外国」という言葉すらunfamiliarな感じですが、これからお話しする時代は、諸外国の情報(地理、社会、風土、文化、歴史 etc)が「紙媒体」でも簡単には手の入らなかったような、(今から思えば)incredibleな時代であることを念頭においてください。

 

(昭和31年、1956年の『経済白書』で日本が高度経済成長期へ移行したことを告げる有名なフレーズ「もはや戦後ではない」からすれば )私が生まれた戦後9年目の1954年は、「外国」といえば、まだ「進駐軍(実際近所にはまだ米軍将校の白い家がありましたよ)の記憶が生々しかった時代でした。

 

子供の頃からませていた私は、学齢前から船の絵などを描く際、船腹にアルファベットなどを書き、お袋を喜ばせていました。というのは、新しもの好きの親父が「観音開きののついた、木製フレームの6チャンネルしかないテレビ

 

Angled Side View of Retro TV with Antenna and Faux Wood Finish, Transparent PNG

(解説:これに扉がついていましたね。そんな写真はもうないみたいです。)

(解説:↑の写真は結構新しいので、この写真の方が近いかも。出典

 

を買い、当時多くの民放番組が「米国からの輸入もの」であったことから、自然と覚えたのかもしれません。

 

思いつくままに記せば、

 

・1956年(昭和31年)から日本テレビ系列でスタートした「名犬リンチンチンRin Tin Tin)」

・1958年(昭和33年)から日本テレビ系列でスタートした「ディズニーランド」(ミッキーマウスドナルドダック

・1959年(昭和34年)からTBSテレビ系列でスタートした「ポパイ

・1960年(昭和35年)からNETテレビ系列でスタートした「ララミー牧場

・1962年(昭和37年)からTBSテレビ系列でスタートした「コンバット

・1963年(昭和38年)からフジテレビ系列でスタートした「突撃!マッキーバー

・1965年(昭和40年)からNETテレビ系列でスタートした「ローハイド

・1966年(昭和41年)からTBSテレビ系列でスタートした「奥さまは魔女

・1966年(昭和41年)からNETテレビ系列でスタートした「かわいい魔女ジニー

・1966年(昭和41年)からTBSテレビ系列でスタートした「宇宙家族ロビンソン

etc、etc

 

と幼少期から小学校まで「輸入もの」はメィジャーなコンテンツでした。(他にもたくさんあるのですが、切りがないのでここでやめます。)

 

小学校高学年になると(私には兄が二人いるのでその影響で)外国との接点は、映画や音楽()にも広がりました。

:これも思いつく順に挙げれば、

砂に消えた涙

アカプルコの海

ワシントン広場の世は更けて

(初期の)The Beatles

Sean Connery時代の007Dr. NoGold FingerThunderball

...これもきりがないのでやめます。

 

いずれにしても子供の頃は(文字情報以外では主に)テレビ番組が「外国(当時は「海外」とは言わず)」に触れる主たる機会、ソースでした。そしてそれは、(当時のほとんどの日本人にとっても)

 

自分が行くことなど、到底叶わない、想像すらできない

手の届かない世界

 

にすぎませんでした。そうです。1960年代の日本

 

米ソ冷戦時代冷戦はなぜ始まったのか? 歴史は繰り返されるのか?

1ドル360円の固定為替相場時代(主たる国際空港は羽田しかありませんでした。注1

平均初任給1~2万円の時代注2

注1:1964年まで、外貨の持ち出し制限(1人年間500ドル)がありました。

注2:当時はまだ少ない大卒で約2万1,000円〜2万2,000円、主流の高卒が約1万8,000円前後、そして中卒が約1万5,000円前後。

 

というような時代でした。

 

今でも覚えているのは、TVのポパイの友人、Wimpy

 

J. Wellington Wimpy | Popeye the Sailorpedia | Fandom の画像

参照先:https://popeye.fandom.com/wiki/J._Wellington_Wimpy

 

が食べる

 

ハンバーガー

 

という食べ物を

 

何としてもいつか一度は食べてみたい!

 

と強く思ったことですかね?(今、古希を超えて、ハンバーガーなんぞ見る気にもなりませんが...)

 

もっといろいろと書こうかなと思っていた【Boids】

ですが、脳みそが疲れたこともあり、前回で終了させました。

 

問題は、次に何するか?

 

です。かなり前にこんなことを書きました。

 

「一旦別のテーマで昔話)を展開するのも

:前に「実は【今は昔...】シリーズで私の海外経験を振り返ってみようかと思ったのですが、結構スタートで長引いたので、このネタは温存することにしました。」と書いたこともありましたし...

 

アリ

 

かと考えます。」

 

勿論【今は昔...】というのは今昔物語のイントロフレーズですが、結局今年年男の老人には

 

昔語り

 

しかできないし、又それが今の方には何かの役に立つこともあるのでしょう。

 

ということで...【今昔物語】

 

シリーズを始めようかと思います。その第一回目は「日本人のパスポート保有率は20%未満)」という現実から、戦後の「(私の目から見た)島国、日本の国際化」を取り上げてみます。

:このような記事がありました。「保有率が上昇」とありますが、発行数は減少です。記事を読んでいても増加要因が感じられず「率」という言葉に気が付きました。分子(パスポート数)が減少しても、分母(人口}がより減少しているので「率」が増加しているのでしょう。The title looks like misleading, isn't it? そういえば最近矢鱈(昔は「円高、デフレ(物価安)」が悪いことだとして自民党が経済成長の為に誘導した)「円安、インフレ(物価高)と騒ぎますが、これも金融取引のみならず、主要財を輸入する(その代金で為替が変動する)日本では為替相場と経済状況が密接に関連することに心しなければならないことだと思います。

 

まぁ、【無駄話】の延長で【今昔物語】シリーズを愉しんでください。

 

最後のつもりで書いた前回の記事、Sociopath殺害メソッド(!)の為に作ったIDが使われていなかったことが分かったり(登録には使っていたので、csc.exeの警告も出ていなかったので...)、プログラムについて考えながらブログを書いていたら、

 

アッ!

 

と天啓が下りてきました。オリジナルのブラウザーベース版(最初はこれだけで感動モノでしたが...)

 

 

やオリジナルを移植し、Flockerの他、IntrovertSociopathを加えたC#版(Version 2.0)

 

 

は勿論目を楽しませてくれますが、如何せん

 

背景が無粋

 

であることも真実。恰も

 

本当に鳥が群れを成して飛んでいるような雰囲気

 

を演出できないかと思い、

 

「そーだ、Windowsの風景イメージがいっぱいあるじゃん!」

 

ということから気に入った(そしてBoidsと親和性のある)イメージ()を持ってきて背景にできるようにし、この変更からVersion 2.1にしました。

:Win32のGDI+で使えるイメージファイル(png, jpeg/jpg, bmp, gif-tiffはあまり見ないのでやめました)であればなんでも大丈夫です。但し、PCの物理的なディスプレー画素サイズ以上の大きさがあった方がよいでしょう。

 

(1)最初は「描画の際の背景クリア」の代わりに、「予め外部ファイルから読み込んだ(私のPCの物理的なディスプレーサイズの)イメージオブジェクトを貼り付け」てから描画することで思い通りの画面になったので、

 

(2)気にもせずリソースファイルに背景画面を入れて使おうと考えたところ、「待てよ。PCによって(最大)画面サイズがことなるし、人によっては背景画なしで動作を見たい、という方もいるかも。どうする?」と考えるに至り、

 

(3)であれば、「設定」で背景を付けるか否か確認し、

 

 

つけるなら「ファイルを開くダイアログ」で背景画像を選択し、

 

 

そうでなければ、単純に背景を消去

 

 

するようにしました。

 

(4)プログラム的には「背景の有無」をbool フィールドで持ち、背景イメージをファイルから読み込むことにしました...が、後に「「背景の有無」」は背景イメージ(Image bkImageという画像メモリーへのポインター)にメモリーが割り当てられているか否か(bkImageがnullか否か)で判断するようにしました。

 

 

 

 

どーですか?いー感じでしょ?

 

【Task3】として完了と言って恥ずかしくない出来栄えだと思います。

 

【変更箇所】

1.Boids_for_CS.cs

(1)

    /////////////////////////////////////////////////
    //Boids(個体群)クラス定義(Boidsコントロール)
    /////////////////////////////////////////////////
    public class Boids : Control            //種の群れ
    {
        //フィールド定義

(略)

        private Image bkImage;                //背景画像(nullか否かで背景の有無を判断)

(略)

 

(2)

        //終了時リソース開放処理
        protected override void Dispose(bool disposing)
        {
            if(disposing)
            {

(略)

                if(bkImage != null)
                    bkImage.Dispose();        //背景画像の廃棄

            }

(略)

 

(3)

        //描画Canvas初期化・再設定
        private void InitCanvas()
        {

(略)

            //背景描画
            if(bkImage != null)
                gHandle.DrawImage(bkImage, 0, 0);

        }

 

(4)

        //Boidsの描画(Timer割り込み処理)
        private void DrawBoids(object sender, EventArgs e)
        {
            if(bkImage != null)            //背景描画
                gHandle.DrawImage(bkImage, 0, 0);
            else 
                       //描画面を消去(解説:Version 2.0はこれだけ)
                gHandle.Clear(this.BackColor);

(略)

 

(5)<メソッドの追加>

        //背景の設定(ユーザーがPCディスプレイのサイズに合わせた画像を自由に設定する)
        public void SetBackGround(bool flag)
        {
            if(!flag)
            {
                MessageBox.Show("背景を無効にします。", "キャンセル", MessageBoxButtons.OK, MessageBoxIcon.Information);
                if(bkImage != null)        
//元々nullであれば何もしない
                {
                    bkImage.Dispose();
                    bkImage = null;
                }
            }
            else
            {
                
//OpenFileDialogオブジェクトの生成
                OpenFileDialog openDlg = new OpenFileDialog();    //usingを使うと最後のDispose処理が不要になる
                openDlg.Filter = "イメージファイル(png, jpeg/jpg, bmp, gif)|*.png;*.jpeg;*.jpg;*.bmp;*.gif";
                DialogResult result = openDlg.ShowDialog();
                if(result == DialogResult.OK)
                {
                    if(bkImage != null)    
//既に背景が設定されていた場合、一旦廃棄する
                    {
                        bkImage.Dispose();
                        bkImage = null;
                    }
                    bkImage = Image.FromFile(openDlg.FileName);
                }
                else if(result == DialogResult.Cancel)
                    MessageBox.Show("キャンセルされました。", "キャンセル", MessageBoxButtons.OK, MessageBoxIcon.Information);
                
//オブジェクトを破棄する
                openDlg.Dispose();
            }
        }

 

2.Boids.cs

(1)

        //「設定」処理
        private void OnSetUp_Click(object sender, EventArgs e)
        {
            SetUpDlg suDlg = new SetUpDlg();
            suDlg.ShowDialog(this);
            NoOfBoids = suDlg.NoOfBoids;
            Introvert = suDlg.Introvert;
            Sociopath = suDlg.Sociopath;
            boids.SetBackGround(suDlg.Background);    //解説:選択しようとしまいと背景設定を実施する
            suDlg.Dispose();
        }
 

(2)

    //////////////////////
    //Boids設定ダイアログ
    //////////////////////
    class SetUpDlg : Form
    {
        //ダイアログのフィールド

(略)

        public bool Background;

(略)

        public SetUpDlg()
        {
            //ダイアログの属性設定
            this.Text = "Boidsの環境設定";
            this.ClientSize = new Size(140, 170);

 

(3)

        //OnLoad処理
        private void Form_Load(object sender, EventArgs e)
        {

(略)

            BkCheck = new CheckBox();
            BkCheck.TextAlign = ContentAlignment.MiddleLeft;
            BkCheck.Location = new Point((ClientSize.Width - BkCheck.Width) / 2, 100);
            BkCheck.Size = new Size(160, 24);
            BkCheck.Text = "背景を付加";
            this.Controls.Add(BkCheck);

        }
 

(4)

        //OKボタン処理
        protected void OnOK_Click(object sender, EventArgs e)
        {

(略)

                Background = BkCheck.Checked;
                Close();
            }
        }

 

ダウンロードパッケージも併せてVersion 2.1へ更新しておきましょう。

 

今度こそ本当に【Boids】を終了いたします。皆さん、ありがとうございました。

 

さて、前回は器をやったので、今回は真打のBoids_for_CS.cs)をやりましょう。

:Boidsウィンドウコントロールのはいったdllのソースコードです。

 

【Boids_for_CS.cs】

///////////////////////////////////////////////
//    Boids_for_CS.cs
//    Copyright (c) 2026 by Y-sama
//    C#プログラム及び日本語コメント文責:Y-sama
//    Original program Copyright by Ben Eater
//    https://eater.net/boids
///////////////////////////////////////////////

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;        //Graphicsクラス(アンチエイリアス)使用の為
using System.Collections.Generic;    //List使用の為

namespace Boids_for_CS
{
    //グローバル定数(↓こいつらについてはここを参照してください。)
    public enum BoidType    //Boidの種を行動特性別に以下4種とする
    {
        Flocker,            //0 - "Birds of a feather flock together"
        Introvert,            //1 - Harmless "Lone wolf" but tends to get away from a flock
        Sociopath,            //2 - Dangerous, often times kills others
        Dead                //3 - a dead body
        //https://gigazine.net/news/20240921-difference-between-psychopath-sociopath/
    }

    /////////////////////////////////////////////////////////
    //Boid(個体)クラス定義
    //注意:Boidタイプが「死骸(BoidType.Dead)」の場合、
    //(1)呼び出し側でメソッド呼び出しを制限することが原則
    //(2)気になる人は
    //        "if(bType == BoidType.Dead)    return;
    //        を行動メソッドの冒頭に追加してください
    /////////////////////////////////////////////////////////

    public class Boid                        //個体
    {
        //定数
        const int VisualRange = 75;    //視野
        //プロパティ
        public int ID {private set; get;}    //BoidのID(読み取り専用)ー解説:Ver2.0で追加しました。(末尾参照

        //フィールド定義
        public BoidType bType;                //生物学的種のID(ユーザー指定可)-解説:これが↑のやつです。
        public int X;                        //x座標
        public int Y;                        //y座標
        public double dx;                    //x移動距離(-5.0~5.0-左右へ5.0)
        public double dy;                    //y移動距離(-5.0~5.0-上下へ5.0)
        public Queue<Point> History;        //履歴(x、y座標の履歴配列)

        //コンストラクター
        public Boid(int id)    //解説:Ver2.0で引数を追加しました。
        {
            ID = id;                //IDを指定して生成する
            History = new Queue<Point>();
        }

        //擬鳥間の距離計算(√(x軸距離 ^ 2 + y軸距離 ^ 2))
        public int DistanceFrom(Boid other)
        {
            return (int)Math.Sqrt((other.X - this.X) * (other.X - this.X) +
                                (other.Y - this.Y) * (other.Y - this.Y));
        }

        //擬鳥の移動と飛行跡記録
        //特記:Sociopathの場合、他のBoidに追いつけば殺害する

        public void Move(List<Boid> boids)
        {
            //x軸方向へdx、y軸方向へdy移動する(MidpointRounding.AwayFromZero→例「-2.5→-3.0」)
            this.X += (int)Math.Round(this.dx, MidpointRounding.AwayFromZero);
            this.Y += (int)Math.Round(this.dy, MidpointRounding.AwayFromZero);
            //50個までの要素数でキューを管理
            History.Enqueue(new Point(this.X, this.Y));    //Queueに飛行跡データを追加する
            if(History.Count > 50)                        //Queueの数が50を超えたら
                History.Dequeue();                        //一番古いものを削除する
            //BoidType.Sociopathの殺害行為(解説:Ver2.0で追加しました。-ここでIDを使う予定が使いませんでした。)
            if(bType == BoidType.Sociopath)    //自分がSociopath
            {
                foreach(Boid otherBoid in boids)
                {
                    //自分以外他のBoidに追いついたならば
                    if(otherBoid != this && DistanceFrom(otherBoid) == 0)
                    {
                        //そのBoidを殺害する
                        otherBoid.bType = BoidType.Dead;
                    }
                }
            }
        }

        //擬鳥を描画領域内に止め、境界に接近すると反対方向へ向かわせる(dx、dyは移動方向・距離)
        //特記:全BoidType共通

        public void KeepWithinBounds(int width, int height)
        {
            const int margin = 200;        //余白(調整対象)
            if(X < margin)                //x軸左方向
                dx++;                    //右方向(加算)
            if(X > width - margin)        //x軸右方向
                dx--;                    //左方向(減算)
            if(Y < margin)                //y軸上方向
                dy++;                    //下方向(加算)
            if(Y > height - margin)        //y軸下方向
                dy--;                    //上方向(減算)
        }

        //擬鳥の集団への対応(向かう|離れる)速度を少し調節する
        //特記:FlockerとSociopathは擬鳥集団の中央へ向かうが、Introvertは離れる

        public void FlyTowardsCenter(List<Boid> boids)
        {
            const double centeringFactor = 0.005;        //速度変更係数
            int centerX = 0, centerY = 0, numNeighbors = 0;
            foreach(Boid otherBoid in boids)
            {
                //視野内の擬鳥のx、y座標とその数を加算
                if(otherBoid != this)
                {
                    if(DistanceFrom(otherBoid) < VisualRange)
                    {
                        centerX += otherBoid.X;
                        centerY += otherBoid.Y;
                        numNeighbors++;
                    }
                }
            }
            if(numNeighbors > 0)
            {
                //視野内の擬鳥のx、y座標の平均を求め、dx、dyを速度変更係数を乗じて調整する
                double sign = (bType != BoidType.Introvert) ? 1.0 : -1.0;    //死骸対応はしていない
                dx += (Math.Round((double)centerX / numNeighbors, MidpointRounding.AwayFromZero) - X) * centeringFactor * sign;
                dy += (Math.Round((double)centerY / numNeighbors, MidpointRounding.AwayFromZero) - Y) * centeringFactor * sign;
            }
        }

        //衝突しそうな近くの擬鳥から離れる
        //特記:FlockerとIntrovertは離れるが、Sociopathは逆に近づく

        public void AvoidOthers(List<Boid> boids)
        {
            const int minDistance = 20;                    //離反する境界距離
            const double avoidFactor = 0.05;            //速度変更係数
            double moveX = 0.0, moveY = 0.0;
            foreach(Boid otherBoid in boids)
            {
                if(otherBoid != this)
                {
                    //境界距離以内の擬鳥との離反(マイナス)座標を累計する
                    if(DistanceFrom(otherBoid) < minDistance)
                    {
                        //Sociopathでない自分が
                        if(bType != BoidType.Sociopath)
                        {    //Sociopathと遭遇した場合
                            if(otherBoid.bType == BoidType.Sociopath)
                            {    //必死に(通常の倍の加速で)逃げようとする(解説:パニック状態です。)
                                dx += (X - otherBoid.X) * avoidFactor * 2;
                                dy += (Y - otherBoid.Y) * avoidFactor * 2;
                                return;
                            }
                            //相手がSociopathでなければ避けようとする
                            else
                            {
                                moveX += X - otherBoid.X;    //-(otherBoid.X - X)
                                moveY += Y - otherBoid.Y;    //-(otherBoid.Y - Y)
                            }
                        }
                        //自分がSociopathなら
                        else
                        {    //相手に近づこうとする
                            moveX += otherBoid.X - X;
                            moveY += otherBoid.Y - Y;
                        }
                    }
                }
            }
            //自分の方向、速度(dx、dy)に離反・接近速度(速度変更係数を乗じたもの)を反映
            dx += moveX * avoidFactor;
            dy += moveY * avoidFactor;
        }

        //他の擬鳥の速さ(速度と方向)を求め、それへ自分を調整する
        //特記:FlockerとIntrovertは離れるが、Sociopathは逆に近づく

        public void MatchVelocity(List<Boid> boids)
        {
            //Flockerは群れに歩調を合わせるが、IntrovertとSociopathは無視する
            if(bType != BoidType.Flocker)
                return;
            const double matchingFactor = 0.05;            //速度変更係数
            double avgDX = 0.0, avgDY = 0.0;
            int numNeighbors = 0;
            foreach(Boid otherBoid in boids)
            {
                if(otherBoid != this)
                {
                    //視野内の擬鳥のx、y移動距離を加算し、その数を記録
                    if(DistanceFrom(otherBoid) < VisualRange)
                    {
                        avgDX += otherBoid.dx;
                        avgDY += otherBoid.dy;
                        numNeighbors++;
                    }
                }
            }
            //移動距離の合計を総数で除算して平均を求め、自分の移動距離との差に速度変更係数を乗じたもので調整する
            if(numNeighbors > 0)
            {
                avgDX = avgDX / numNeighbors;
                avgDY = avgDY / numNeighbors;
                dx += (avgDX - dx) * matchingFactor;
                dy += (avgDY - dy) * matchingFactor;
            }
        }

        //速度(dx、dyのベクトル値)は変化するが15を超えない
        public void LimitSpeed()
        {
            const double speedLimit = 15.0;            //限界速度
            //x、y軸の移動距離から求められる速度(speed)が
            double speed = Math.Sqrt(dx * dx + dy * dy);
            //限界速度を超えたならば、x、y軸の移動距離を限界速度で頭打ちにする
            if(speed > speedLimit)
            {
                dx = speedLimit / speed * dx;
                dy = speedLimit / speed * dy;
            }
        }

        //擬鳥の描画
        public void Draw(Graphics gHandle, bool draw_trail = false)
        {
            if(bType == BoidType.Dead)    return;            //死骸は(明示的に)描画しない
            //Boidの描画色
            Color[] BoidCol = new Color [3] {Color.Blue, Color.Green, Color.Red};
            //飛行跡のPen色
            Pen[] BoidTrail = new Pen[3] {Pens.SkyBlue, Pens.LightGreen, Pens.Tomato};
            //半直線(0, 0)-(x, y)と正のx軸の平面上の角度(ラジアン単位)
            //float angle = (float)Math.Atan2(dy, dx);

            float angle = (float)(Math.Atan2(dy, dx) * 180.0 / Math.PI);
            //三角形の3つの頂点(原点(0,0)周辺に定義)
            PointF[] points = {
                new PointF(8, 0),    // 上の頂点
                new PointF(-8, -4),    // 左下の頂点
                new PointF(-8, +4)    // 右下の頂点
            };
            //原点の移動と回転
            gHandle.TranslateTransform(X, Y);            //描画位置(X, Y)へ移動
            gHandle.RotateTransform(angle);
            //塗りつぶし実行
            using(Brush brush = new SolidBrush(BoidCol[(int)bType]))
            {
                gHandle.FillPolygon(brush, points);
            }
            //Graphicsの状態をリセット
            gHandle.ResetTransform();
            //飛行跡が真であれば一定の長さの飛行痕(糸のような線)を残す
            if(draw_trail)
            {
                //飛行跡(Point)配列をDrawCurve(DrawLineよりもよさげ)で描く
                Point[] trail = this.History.ToArray();
                if(trail.Length > 1)
                {
                    //gHandle.DrawLines(Pens.SkyBlue, trail);
                    gHandle.DrawCurve(BoidTrail[(int)bType], trail);
                }
            }
        }
    }

    /////////////////////////////////////////////////
    //Boids(個体群)クラス定義(Boidsコントロール)
    /////////////////////////////////////////////////

    public class Boids : Control            //種の群れ
    {
        //フィールド定義
        private static Random rand;            //乱数
        List <Boid> boids;                    //擬鳥配列
        //描画関係プロパティ
        private Bitmap Canvas {set; get;}    //仮想画面ビットマップ
        private Graphics gHandle {set; get;}//仮想画面のグラフィック
        private Timer DrawTimer;            //描画用タイマー
        private bool Draw_Trail = false;    //飛行跡許可フラグ

        public Boids()
        {
            //乱数の初期化
            rand = new Random((int)DateTime.Now.Ticks);
            //擬鳥配列の生成
            boids = new List<Boid>();
            //タイマー初期設定
            DrawTimer = new Timer();
            DrawTimer.Interval = 15;        //設定値15/1000秒(最小値は事実上15程度)
            DrawTimer.Tick += DrawBoids;
            //コントロール生成時処理
            //ちらつき防止(解説:これは全く知らず、ちらつきが出ていましたが、Chat-GPTに教えてもらいました。)

            SetStyle(
                ControlStyles.UserPaint |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.OptimizedDoubleBuffer,
                true
            );
            UpdateStyles();
        }

        //終了時リソース開放処理)(解説:ここもFormとはちょっと異なります。コントロールの場合の定番メソッドとしてChat-GPTに指導してもらいました。)
        protected override void Dispose(bool disposing)
        {
            if(disposing)
            {
                if(DrawTimer != null)
                    DrawTimer.Dispose();    //タイマーの廃棄
                if(gHandle != null)
                    gHandle.Dispose();        //描画ハンドルの廃棄
                if(Canvas != null)
                    Canvas.Dispose();        //仮想画面の廃棄
            }
            base.Dispose(disposing);
        }

        //Resizeイベント処理
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            //描画Canvas(再)設定
            InitCanvas();
        }

        //Paintイベント処理
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            //Canvas描画処理
            if(Canvas != null)    //仮想画面がnullの場合はスキップ
                e.Graphics.DrawImage(Canvas, 0, 0);
        }

        //描画Canvas初期化・再設定
        private void InitCanvas()
        {
            //コントロール生成中のエラー対策
            if(this.ClientSize.Width < 1 || this.ClientSize.Height < 1)
                return;
            //既存の仮想画面、グラフィックハンドルがあれば廃棄する

            //解説:ここも私は誤解しておりましたが、Dispose()はメモリーを開放しますが、"= null"はメモリーアドレス参照を明示的に解消します。
            if(gHandle != null)
            {
                gHandle.Dispose();    //解説:メモリーを開放
                gHandle = null;    //解説:メモリーアドレス参照を解消
            }
            if(Canvas != null)
            {
                Canvas.Dispose();    //解説:Ditto
                Canvas = null;    //解説:Ditto
            }
            //ビットマップ仮想画面の作成
            Canvas = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            //Graphicsクラス(アンチエイリアス)
            gHandle = Graphics.FromImage(Canvas);
            gHandle.SmoothingMode = SmoothingMode.AntiAlias;
            gHandle.PixelOffsetMode = PixelOffsetMode.HighQuality;
        }

        //Boidsの描画(Timer割り込み処理)
        private void DrawBoids(object sender, EventArgs e)
        {
            //描画面を消去
            gHandle.Clear(this.BackColor);
            foreach(Boid boid in boids)
            {
                if(boid.bType == BoidType.Dead)
                    continue;                    //死骸は何もしない
                //速さをそれぞれの規則に基づいて更新
                boid.FlyTowardsCenter(boids);    //群れへの参集
                boid.AvoidOthers(boids);        //近すぎる擬鳥からの離反
                boid.MatchVelocity(boids);        //速度調整
                boid.LimitSpeed();                //限界速度制限
                //Boidsコントロールの枠内にとどめる
                boid.KeepWithinBounds(this.ClientSize.Width, this.ClientSize.Height);
                //現在の速さに基づき位置(x、y座標)を更新し、飛行跡を追加
                boid.Move(boids);
                //Boidsの描画
                boid.Draw(gHandle, Draw_Trail);    //Draw_Trail-飛行跡の描画指定
            }
            //Canvasを表示
            this.Invalidate();
        }

        //解説:以下から公開(public)めそっどになります。
        //擬鳥の生成(擬鳥配列の初期化)
        public string CreateBoids(int count, bool lonewolf = false, bool sociopath = false)
        {
            //コントロール生成中のエラー対策(エラーは空文字を返す)
            if(this.ClientSize.Width < 1 || this.ClientSize.Height < 1)
                return String.Empty;
            //一旦boids(List)を空にする
            boids.Clear();
            //戻り値文字列
            string ResMsg = "Boidsの総数:" + count.ToString();
            //擬鳥配列の初期化
            for(int i = 0; i < count; i++)
            {
                //擬鳥初期化
                Boid bd = new Boid(i);            //iがIDとなる
                bd.bType = BoidType.Flocker;    //一種だけなので暫定的にFlockerとする
                bd.X = rand.Next(this.ClientSize.Width);    //0~Width - 1
                bd.Y = rand.Next(this.ClientSize.Height);    //0~Height - 1 ;
                bd.dx = rand.Next(-5, 6);        //-5.0~5.0-左右へ5.0
                bd.dy = rand.Next(-5, 6);        //-5.0~5.0-上下へ5.0
                bd.History.Enqueue(new Point(bd.X, bd.Y));    //最初の位置を記録(解説:オリジナルにはなかったけど...)
                boids.Add(bd);
            }
            //Introvert(総数の5%程度)を付加する
            int numInt = 0;
            if(lonewolf)
            {
                int num = rand.Next(1, (int)(count * 0.05) + 1);    //1~Count x 5%までの乱数値
                numInt = num;
                while(num > 0)    //総数に対して選択数が小さいのでシャッフル方式は採らない
                {
                    int n = rand.Next(count);
                    if(boids[n].bType == BoidType.Flocker)
                    {
                        boids[n].bType = BoidType.Introvert;
                        num--;
                    }
                }
            }
            //Sociopath(総数の3%程度)を付加する
            int numSocio = 0;
            if(sociopath)        //総数に対して選択数が小さいのでシャッフル方式は採らない
            {
                int num = rand.Next(1, (int)(count * 0.03) + 1);    //1~Count x 3%までの乱数値
                numSocio = num;
                while(num > 0)    //総数に対して選択数が小さいのでシャッフル方式は採らない
                {
                    int n = rand.Next(count);
                    if(boids[n].bType == BoidType.Flocker)
                    {
                        boids[n].bType = BoidType.Sociopath;
                        num--;
                    }
                }
            }
            ResMsg += "(Flocker:" + (count - numInt - numSocio).ToString() + "、Introvert:" + numInt.ToString() + "、Sociopath:" + numSocio.ToString() + ")";
            return ResMsg;
        }

        //Boids開始
        public bool Start()
        {
            //擬鳥未生成の場合のエラートラップ
            if(boids.Count == 0)
            {
                MessageBox.Show("まだ擬鳥が生成されていません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            //描画不可状態でのエラートラップ
            if(Canvas == null || gHandle == null)
            {
                MessageBox.Show("Graphics not ready.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            DrawTimer.Start();                //タイマー割り込み開始
            return true;
        }

        //Boids停止
        public void Stop()
        {
            DrawTimer.Stop();                //タイマー割り込み停止
        }

        //飛行跡描画可否
        public void DrawTrail(bool flag)
        {
            Draw_Trail = flag;                //飛行跡描画指定
        }

        //Boids結果表示(解説:Ver2.0で追加しました。停止した時のBoidsの状況を文字列で返そうと思いました。)
        public void Result()
        {
            string ResMsg = "Boidsの総数:" + boids.Count.ToString();
            int numFlock = 0,  numInt = 0,  numSocio = 0;
            foreach(Boid boid in boids)
            {
                switch((int)boid.bType)
                {
                    case 0:        //Flocker
                        numFlock++;
                        break;
                    case 1:        //Introvert
                        numInt++;
                        break;
                    case 2:        //Sociopath
                        numSocio++;
                        break;
                    default:    //Dead
                        break;
                }
            }
            ResMsg += "(Flocker:" + numFlock.ToString() + "、Introvert:" + numInt.ToString() + "、Sociopath:" + numSocio.ToString() + "、Dead:" + (boids.Count - numFlock - numInt - numSocio).ToString() + ")";
            MessageBox.Show(ResMsg, "Boidsの結果", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}

 

【末尾参照】Boid(個体)クラスにIDを入れてますが、これはSociopathが他のBoidに追いついた際にこれを殺害する処理を「Listのディープコピーを自分との距離を基にソートし、自分以外のものがいれば」で考えていたために、オリジナルList配列の何番目になるのかを知るために追加したものでした。でも結局↑のように、「自分がSociopathで、自分自身ではなく、且つ距離が0」という条件でクリアしたので、使いませんでした(これを書いていて気が付きました-笑;)後日の拡張の為に残しておきましょう。

 

如何だったでしょうか?

 

これにてBoids、一件落着ぅ~!

 

として終わりにしようと思いましたが、

 

本日、ひらめき

があり、

 

後もう一回だけ、↑の変更点を解説しますね。

 

「字数制限エラー」による残りです。

 

    /////////////////////
    //Version ダイアログ
    /////////////////////

    class VersionDlg : Form
    {
        public VersionDlg(Icon ico)
        {
            //ダイアログの属性設定
            this.Text = "バーション情報";
            this.ClientSize = new Size(320, 100);
            this.MaximizeBox = false;        // 最大化ボタン
            this.MinimizeBox = false;        // 最小化ボタン
            this.ShowInTaskbar = false;        //タスクバー上表示
            this.FormBorderStyle = FormBorderStyle.FixedDialog;        // 境界のスタイル
            this.StartPosition = FormStartPosition.CenterParent;    // 親フォームの中央に配置
            //コントロールの属性設定
            Button btnOK = new Button();
            btnOK.Size = new Size(40, 28);
            btnOK.Location = new Point(ClientSize.Width - btnOK.Width - 10, (ClientSize.Height - btnOK.Height) / 2);
            btnOK.Text = "OK";
            btnOK.Click += new EventHandler(OnOK_Click);
            Label imglabel = new Label();
            imglabel.Size = new Size(40, 40);
            imglabel.Location = new Point(10, (ClientSize.Height - imglabel.Height) / 2);
            imglabel.BorderStyle = BorderStyle.Fixed3D;
            imglabel.Image = ico.ToBitmap();                        //親のシステムアイコン
            Label label = new Label();
            label.Size = new Size(ClientSize.Width - imglabel.Width - btnOK.Width - 40, ClientSize.Height- 20);
            label.Location = new Point(imglabel.Width + 20, (ClientSize.Height - label.Height) / 2);
            label.BorderStyle = BorderStyle.Fixed3D;
            label.Text = Title.Ver + "\r\nCopyright (c) 2026 by Ysama\r\n(written in Microsoft C#)";    //解説:Title.Verを使っています。
            label.TextAlign = ContentAlignment.MiddleCenter;
            label.Font = new Font("Times New Roman", 10, FontStyle.Bold);
            this.Controls.Add(btnOK);
            this.Controls.Add(imglabel);
            this.Controls.Add(label);
        }

        private void OnOK_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}

 

次回はとうとう真打のBoids_for_CS.dllcs)の登場です。