前回は新しいシリーズネタ【TurtleGraphics】の構想(↓)

 

(1)先ずは指示通りにVisual Studioで使ってみる。

(2)次にWindows 11標準装備のC#5(.NET Framework 4.8)で使えるかどうか、調査してみる。

(3)可能であれば、「誰でも使えるサンプル」から始め、

(4)様々なタートルグラフィックスを試すことができるアプリに挑戦してみる。

 

を書きました。今回はこの中の「(1)先ずは指示通りにVisual Studioで使ってみる。」を取り上げます。

 

1.ソリューションとプロジェクト

Visual Studioで新規にソリューション(名前は"TurtleGraphics"としました)とプロジェクト(名前は"TurtleGraphics01"としました)を作成しますが、最終的に「Windows 11標準装備のC#5(.NET Framework 4.8)」に落とす積りなので「WinForms(.NETFrame work)」で新規作成します。

 

2.Formの作成

前回紹介したダウンロードサイトのNakov.TuttleGraphicsのサンプルを適当につまんで表示できるようにしたいので、こんなプログラムウィンドウ(Form-名前は"TurtleGraphics01"としました)を考えました。(

 

:ご参考までに、Visual Studio"TurtleGraphics"ソリューション内に、"TurtleGraphics01"という「WinForms(.NETFrame work)」のプロジェクトを新規作成すると、

 

(1) プログラム(Application)を実行するエントリーポイントのある"Program.cs"、

(2) ↑のように("TurtleGraphics01 [Design]"というタブで)WYSWYGでFormをデザインするとそのForm(およびコントロール)を作る処理をコード化した"TurtleGraphics01.Designer.cs"、

(3) Formのサイズを変えたり、そのボタンコントロールを押したりするときに発生する「割り込み」イベントの処理を記述する"TurtleGraphics01.cs"

 

という3つのプログラム(*.cs)ファイルが作られます。

 

3.NuGet ManagerでNakov.TuttleGraphicsパッケージを導入

「器(WinFormsのForm)」を作ったら、次は(こっちを先にやってもいいんだけどね)NakovさんのTurtleGraphicsのダイナミックライブラリー(Navok.TurtleGraphics.dll)のパッケージをこのプロジェクトで使えるようにインストールします。「ツール」-「Nugetパッケージの管理」で以下のタブを開き、更に「参照」タブの検索欄に"Navok.TurtleGraphics"と打ち込むと(全部打ち込まなくても)出てきますので、これをクリックして選択し、右側の「インストール」で導入します。(

 

:実際にどのようなファイルがインストールされるのか確認するにはプロジェクトフォールダー(今回は"TurtleGraphics01")の中をご覧ください。結構な数のシステム用のファイルの他に、必ず"Navok.TurtleGraphics.dll"があるはずです。

 

4.プログラムアイコンとウィンドウアイコンの作成

プロジェクトを作った直後の上記1.のFormデザイン画面では既定の(面白くもなんともない)ウィンドウアイコン

 

 

がついています。

 

しかし、

 

こだわりの強い私としては矢張りプログラムアイコンと共に「」に統一したいと考えました。この場合、先ず何でもよいので「フリーの亀画像(結構サイズの大きいものが多い)」をwebから選び、

 

 

それを基に(64x64、)48 x 48、32 x 32、16 x 16と「ペイント」でよいので画像縮小して再編集し、それぞれビットマップファイル(*.bmp)に落としておきましょう。

 

次にプロジェクト(今回は"TurtleGraphics01")を右クリックし、「追加」-「新しい項目

 

 

を選択します。すると「新しい項目の選択」ダイアログが現れますので、「アイコンファイル」を選択します。

 

 

すると(恐らく手を抜いて20世紀から変わり映えしないUIの)アイコンエディターが登場するので、

 

 

規定値の「16 x 16、4ビット」と「32 x 32、4ビット」のサンプルを削除し、別途「16 x 16、24ビット」、「32 x 32、24ビット」と「48 x 48、24ビット」(更に「64 x 64、24ビット」を加えてもよいけど...)を追加して予め作っておいた同サイズの「」画像を開き、コピーしてこのエディターの編集欄に張り付けるだけで結構です。最後にきちんと「保存」しておいてください。

 

5.ビルド結果

その後は「割り込み」イベントの処理を記述する"TurtleGraphics01.cs"にボタンClick時の処理をサンプルから貼り付ければ基本的に完了です。(この「ボタンClick時の処理」については、後日別途項を変えて説明する予定です。)

これでプログラムは基本的に完了したので、(「Debug」でも​​​​​​よいのですが、Debugファイルは色々と余計なものが入っていてサイズが大きいので)「Release」でビルドすると​プロジェクトフォールダーの「bin(binaryの意味)」の「Release」フォールダーの中にこれらのファイルが生成されます。

 

 

システムが使う".config"ファイル、".pdb"ファイルの他、実行ファイルである "TurtleGraphics01.exe" が出来て、 "Navok.TurtleGraphics.dll" ファイル注意:これがないとプログラムは動きませんのでご注意を!)があることを確認してくださいね。

 

6.起動とサンプルの実行

では、実際に"TurtleGraphics01.exe"を起動してみましょう。このようなウィンドウが表示されます。

 

 

次に、「描画1」-「描画2」-「描画1」-「描画2」-「描画3」の順番にボタンを押してみましょう。描画を開始すると「」さんが登場して線を引き始めますね。「描画1」は青い三角形と棒、「描画2」は緑の三角形、「描画3」は赤い渦巻き状の線を描画します。


 

表示」ボタンは交互にを消したり、表示したりするトグル動作をします。「リセット」は画像や描画システムを初期化します。

 

以上のようにVisual Studioを使ってNakovさんのTurtleGraphicsを使った簡単なサンプルを作ってみました。余り「Visual Studio歴」がない私でも結構簡単にここまで作ることができました。(

:Visual Studioで面倒なのは、

①.NET Framework、.NET_Core、.NETxxなどのバージョンの違いで互換性がなかったりするので注意を要するのと、

②Visual Studioが勝手につけてくる名前(例えば今回もソリューション名はプロジェクト名と同じでWinFormsProject01、FormはForm01、ボタンコントロールはbutton01~04とかに勝手に名付けられていました)の一括変更が面倒

でした。そして今回四苦八苦したのは「アイコン作り」。正直これなら自作のEZImageとIconViewerの方が簡単じゃないかと思いました。(大体今時カラー深度4 bit-8色のことです-なんてアイコン、使わないでしょう?また、サイズの違う画像を拡大縮小したり、反転やシフトする機能は欲しいですよね。まぁ、そこは上手にあるアプリを使って「員数合わせ」をするのが私の強みなんですが。)

 

次回は(最終目的である、Visual Studio等の開発環境がなくとも、Windows 11に標準のC#5を使ってタートルグラフィックを愉しめるように)(2)次にWindows 11標準装備のC#5(.NET Framework 4.8)で使えるかどうか、調査してみる。」をやってみましょう。

 

では、次亀!

 

亀センニン、と言ってもこれ(亀仙人)ではありません。亀を選任して、シリーズ物を始める、ということです。でも、

 

亀ってなに?

 

となるのですが、ここで登場いただく亀さんは

 

タートルグラフィックス

 

です。でも「タートルグラフィックス(Turtle Graphics)」って何でしょう?それはこういうこと()です。

 

1967年、教育(特に構成主義および構築主義(英語版)学習)のために開発された ... LOGO(ロゴ)は、教育向けとして設計されたマルチパラダイムのコンピュータプログラミング言語である。しばしば簡易言語だと誤解されていることもあるが、再帰なども扱える言語としての機能、リストなどのデータ構造や、I/O・ファイルなどの一般的な機能を持ったライブラリなど、簡易言語ではなく、十分な能力を持ったプログラミング言語である。特徴的な機能としては『タートルグラフィック』がある。...

LOGO最大の特徴はタートルであり、画面上のカーソルで表され(タートルと呼ばれるようになったのは、先述の亀のロボットから)、それに動きと線描を命令することができ、プログラムに基づいて線で描かれたグラフィックスを生成できる。三角形または亀の形で表されることが多い(実際にはどんなアイコンでもよい)。シーモア・パパートがLOGOにタートルグラフィックスを追加したのは1960年代末ごろで、パパート自身が開発した亀ロボットに上げ下げ可能なペンを装着させて描画できるようにしたことからである。」(出典:wiki

 

私自身はLOGOもタートルグラフィックスも縁がなく、昔購入したSONYのHitbit MSX(主記憶64KBのHB-75 \69,800)の兄弟にSMC-777というPCソニー 松田聖子 関連CM集 1983 - 1984年)があり、それについていたDr. LOGOというプログラミング言語を思い出すぐらいです。そんな、

 

何だっけ?

 

が結果的には奏功し、WEB調査の結果「Pythonとか、Rubyとか」()では記事があるのですが、C#はなさそうなので「一丁LOGOを調べて、C#で簡易版でもやってみようか?」と考えたのが始まり。

:「turtle --- タートルグラフィックス」、「タートルグラフィックス

 

ところが、

 

更に調べるとこんな板に出くわし、そこにあったリンクからNakovさんが既にC#用のライブラリー()を公表しているとのこと。

:Nakov.TurtleGraphicsを取得できるサイト。以下の内容はほぼ同じです。

TurtleGraphics(C#)NuGet
TurtleGraphics(C#)GitHub
TurtleGraphics(C#)Nakov.TurtleGraphics library URL
TurtleGraphics(C#)Lab: Turtle Graphics GUI Application
 

まぁ、私も歳だし、

 

ここは(私自身LOGO命令文やタートルグラフィックスに素人だし)先人のライブラリーを使った

 

「タートルグラフィックス学習兼アプリ作成記」

 

にしようか、と方針転換しました。

 

今後は、

 

(1)先ずは指示通りにVisual Studioで使ってみる。

(2)次にWindows 11標準装備のC#5(.NET Framework 4.8)で使えるかどうか、調査してみる。

(3)可能であれば、「誰でも使えるサンプル」から始め、

(4)様々なタートルグラフィックスを試すことができるアプリに挑戦してみる。

 

という筋書きを考えています。

 

果たしてそんなにうまくゆくものか?

Stay tuned!

 

もう、午後6時!

 

になっていた。

 

Amazon Primeも観ず、晩酌も忘れて

 

何をしていたかというと、

 

次のネタ、ハッケーーーン!!!

 

して、その内容は?

 

なーーんだ?

 

乞うご期待!

 

ps.  投稿した後、「アッ」とおもったので追記します。「次ネタ発見」はエイプリルフールではゴザンセン!

 

皆さま、"Dementia_Pre"はお試しされたでしょうか?(やっていてわかったのですが、デフォルトのウィンドウサイズよりも小さくして、プッシュボタンを文字大にすると一覧性が増して、入力反応が向上するようです。)

 

当然のことながら、次のお題はまだ決まっていません。(笑)

 

ということで、つなぎはいつもの「食い物話」で。

 

皆さんは「焼きパスタ)」という言葉をご存じでしょうか?ウェブで見ていると「スパゲッティを茹で具材と炒める」のも「焼きパスタ」と書いている記事がありますが、それは余りに恥ずかしいのでやめましょう。私の場合、話は仄聞していましたが、見たのはYouTube()が初めてでした。

:ご参考

【暗殺者のパスタ1】

【暗殺者のパスタ2】

 

今回の話はこの「焼きパスタ」に果敢にチャレンジしよう、...という訳では(実は)なく、前日買ってきたレタスの内側が腐っていて、朝のサラダ作る際に患部を切除するあまり、切り取った葉の良性の部分が多くなり、二つ作ってしまったことに始まります。

 

朝食に一つ、昼飯にも同じサラダをもう一つ食べるとなると、何を一緒に食べようか?と食糧庫を眺め、

 

(1)「早茹で」のペンネが少し残っていたこと

(2)ニンニク、鷹の爪、バージンオリーブオイルの他、挽肉、玉葱、ピーマン、ソーセージという具材がそろっていたこと

(3)矢張り"Bloody Mary"用に買っていたトマトジュースが少し残っていたこと

(4)そして最後に↑の「暗殺者のパスタ(spaghetti all'assassina、Assassin's Spaghetti)」を覚えていたこと

 

から「何事も実験から」という気持ちが芽生えて作ってみました。

 

先ず

 

(1)多めの潰しニンニクでアーリオオーリオを作り、

(2)具材(挽肉、玉葱、ピーマン、ソーセージ)を軽く炒め、

(3)早茹でペンネ(45gしかなかったので嵩を増すためにモヤシも)をトマトジュースと共に投入

(4)「3分」の標準茹で時間よりやや長めに炒める

 

と、トマトジュースはソースとなって出来上がりです。(ムキになって焦げるまで炒める、という程、私は尖がっていません。)

 

出来上がりは、見た目が普通にアラビアータなんですが、食感は茹でたパスタよりも無骨な感じで、茹で時間よりも長めに炒めた割に所謂アルデンテな感じがしました。

 

(写真は左から、コンソメスープ、penne all'assassinaと「二つ目のサラダ」)

 

今度は本格的な「焦がしスパゲッティ」もやってみようかと思います。

 

このブログでも何度か取り上げた生成AIのユーザー対応の問題ですが、オープンAIの「GPT5」やグーグルの「ジェミニ」など11種類のモデルについて、米スタンフォード大等のチームが2026年03月26日付の米科学誌サイエンスに発表した研究についてこんな記事が出ていますね。

 

ポイントは以下の通り。

 

1.結論として研究は「おべっかは安全性に関わる問題で、規制や監視が必要だ」とし、

2.その理由として、他人への嫌がらせ、うそをついた話などに対して、生成AIは人間よりも平均49%も多く「あなたは悪くない」等ユーザーを肯定することにより「自分は正しい」と思う度合いは25~62%強まり、相手に謝るなど関係を改善しようとする意欲は10~28%減ったことから、「ユーザーの自己正当化傾向を強めたり、人間関係を改善する意欲を削ぐ」影響が考えられるとしています。

3.この「ユーザーに対するおべっか」により、「ユーザーが高く評価し、また使いたいと思う」傾向も見られたとのこと。

 

でも、これって人間の性じゃね?

 

昔から政権、企業から学校の小学校のクラスまで

 

「権力者はお友達グループを形成する」

 

のは人間性の経験則であり、

 

人がするのは見逃して、生成AIがするのは規制が必要

 

というのもなんかな、と思います。むしろ「人間教育」が必要でしょう。でもト〇〇プや安〇、高〇なんかが居る世界ですからね。ダメか?)

 

もう一つ。

 

実は生成AIは対応態度を設定で変えられるんですよね。私も前からChat-GPTやCopilotのデフォルトの「ヨイショッ!」対応が鼻についたので、「プロフェッショナル風味」に変えたのですが、「こんなこともわからんのか?君は馬鹿か?」的「上から目線の塩対応」に腹を立てて、設定を基に戻してしまいました。

 

偉そうなことを言って、お前も同類だろう?

 

というのが、自戒の言葉です。

 

さて、前回で最終仕様も決まって使えるようになったので、プログラムコードを末尾に掲載します。

 

(1)このプログラムは、検査履歴データを読み込んでMS Chartコントロールで棒グラフを表示するDemPreChartクラス(ウィンドウ)と、36のボタン入力で検査するDemAppクラス、およびエントリーポイントだけのLauncherクラスで構成されています。

 

(2)プログラムの流れは、

 

 (a)LauncherクラスインスタンスがDemAppクラスインスタンスを実行してプログラムが開始され、

 (b)DemAppウィンドウ生成時、DemPreChartウィンドウを生成し履歴グラフが表示されます。

 (c)DemPreChartウィンドウを終了すると、DemAppウィンドウが表示されて

 

前々回の流れで進みます。

 

(3)ユーザーの目から見ると、起動時(初回は「ログファイルを読み込めない」というエラーが出ますが、次回から)検査履歴の棒グラフを表示するので、それを確認の上、棒グラフのウィンドウを終了させると、出題ダイアログが出て、8文字入力すると正解不正解判定ダイアログが出て、次の出題に移ります。どの段階でもシステムボタン「X」または'Q'ボタンでプログラムを中止することができ、既に完了した検査結果はログに追加されます。

 

(4)Windows 11が動くPCなら、どなたでもこのプログラムを愉しむことができます。先ず、末尾のプログラムコードをテキストエディターに張り付け、"Dementia_Pre.cs"というファイル名で保存します。次にBCCForn and BCCSkeltonのサンプル、MSCompAssを使うか、または)次(↓)の"Dementia_Pre.bat"というバッチファイルを"Dementia_Pre.cs"と同じフォールダーに入れて、ダブルクリックすることでコンパイルができます。尚、以下のバッチファイルではプログラムアイコンやウィンドウアイコンがデフォルトのままですので、何か気に入ったアイコンBCCForn and BCCSkeltonのツール、EZImageとIconViewerで簡単に作れますよ)を"Icon.ico"というファイル名で同じフォールダーに入れておき、Dementia_Pre.batのピンク色の行の"/t:winexe"の後に、" (半角スペース)/win32icon:".\Icon.ico" (半角スペース)"をいれてコンパイルするとプログラムアイコン、ウィンドウアイコンが設定されます。

 

【Dementia_Pre.bat】→これをテキストエディターに貼って"Dementia_Pre.bat"で保存してください。

@ECHO OFF
ECHO ----------------------------------
ECHO  Dementia_Pre.bat
ECHO  Copyright (c) 2026 by Ysama
ECHO ----------------------------------

C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /t:winexe  /reference:"C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Windows.Forms.DataVisualization\v4.0_4.0.0.0__31bf3856ad364e35\System.Windows.Forms.DataVisualization.dll" /warn:4 ".\Dementia_Pre.cs"
pause
 

注意!:Webのテキストをエディターに張り付けるとUTF-8型式になると思いますが、csc.exeはShift-JIS、UTF-8何れもコンパイルできます。但しエディターによっては、または読み込み時にUTF-8をShift-JISとして読み込み、変換できず'?'が多発する場合もありますのでご注意ください。尚、BCCForn and BCCSkeltonの"SampleBCCSkelton\MSCompass\Debug\Sample\Dementia_Pre"フォールダーにあるソースファイルはShift-JISとなっています。

 

では、Enjoy!

 

【Dementia_Pre.cs】

////////////////////
//Dementia_Pre.cs
////////////////////

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;        //Assemblyを使う為
using System.Diagnostics;        //Stopwatchを使う為
using System.IO;                 //StreamReader/Writerを使用するのに必要
using System.Text;                 //Encoding.GetEncodingを使用するのに必要
using System.Windows.Forms.DataVisualization.Charting;    //MS Chartを使用するのに必要

namespace Dementia_Pre
{
    //アプリケーションクラス(解説:DemAppを動かすだけのクラス)
    public class Launcher
    {
        [STAThread]
        public static void Main()
        {
            DemApp da = new DemApp();
            Application.Run(da);
        }
    }

    /////////////////////////////
    //Demntia_Preクラス(DemApp)
    /////////////////////////////

    public class DemApp : Form
    {
        
        //クラスフィールド
        Button[] Btns = new Button[36];                    //36個のボタン(解説:表示する数字は変わります)
        string[] txtStr =  {"0", "1", "2", "3", "4",    //ボタン表示用文字列(解説:乱数でシャッフルします)
                            "5", "6", "7", "8", "9",
                            "A", "B", "C", "D", "E",
                            "F", "G", "H", "I", "J",
                            "K", "L", "M", "N", "O",
                            "P", "Q", "R", "S", "T", 
                            "U", "V", "W", "X", "Y",
                            "Z"};
        string question, answer;                        //問題と答え(解説:文字列です)
        Stopwatch stw = new Stopwatch();                //ストップウオッチ(解説:所要時間を図ります)
        string Dem_Pre_Data;                            //Dementia_Preの履歴データ(解説:CSVファイルなので、Excelなどで読めますよ)

        //コンストラクター
        public DemApp()
        {
            //プログラムアイコンをフォームにつける
            Assembly myOwn = Assembly.GetEntryAssembly();
            this.Icon = Icon.ExtractAssociatedIcon(myOwn.Location);
            this.Size = new Size(640, 480);
            this.MinimumSize = new Size(320, 190);
            this.Text = "Dementia Prevention";
            this.Load += Initialize;
        }

        //初期化処理
        private void Initialize(object sender, EventArgs e)
        {
            //ボタン x 36
            int w = ClientSize.Width / 6;
            int h = ClientSize.Height / 6;
            for(int y = 0; y < 6; y++)    //解説:縦
            {
                for(int x = 0; x < 6; x++)    //解説:
                {
                    int i = y * 6 + x;
                    Btns[i] = new Button();
                    Btns[i].Size = new Size(w, h);
                    Btns[i].Location = new Point(x * w, y * h);
                    Btns[i].Text = txtStr[i];
                    Btns[i].Click += Buttons_Click;
                    this.Controls.Add(Btns[i]);
                }
            }
            if(LogRead())    //履歴ログを読む(解説:読めたらTrue、不可ならFalse)
            {
                //過去履歴データをグラフ表示
                DemPreChart dpc = new DemPreChart();
                dpc.ShowDialog();
                dpc.Dispose();
            }
            //新しいゲームの開始
            MakeNewQuestion();
        }

        //サイズ変更処理
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            //ボタン配置更新
            int w = ClientSize.Width / 6;
            int h = ClientSize.Height / 6;
            for(int y = 0; y < 6; y++)    //解説:縦
            {
                for(int x = 0; x < 6; x++)    //解説:横
                {
                    int i = y * 6 + x;
                    if(Btns[i] != null)
                    {    //解説:サイズと位置を変更
                        Btns[i].Size = new Size(w, h);
                        Btns[i].Location = new Point(x * w, y * h);
                    }
                }
            }
        }

        //終了処理
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            DialogResult dr = MessageBox.Show("終了しますか?", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if(dr == DialogResult.No)
                e.Cancel = true;
            else
                LogWrite();            //履歴ログを書く
        }

        //すべてのボタンが押された時の処理
        private void Buttons_Click(object sender, EventArgs e)
        {
            //終了処理("Q"ボタンが押された時に確認してくる)
            if(((Button)sender).Text == "Q")
            {
                Close();
            }
            //答えを生成する
            answer += ((Button)sender).Text;
            //クリックされたボタンのNameを表示する
            MessageBox.Show(answer, "現在の答え", MessageBoxButtons.OK, MessageBoxIcon.Information);
            //完了確認(解説:8文字入力されるまではスキップします)
            if(answer.Length == 8)
            {
                stw.Stop();    //解説:ストップウオッチを止めます
                TimeSpan ts = stw.Elapsed;    //分ts.Minutes, 秒ts.Seconds
                string erapsed_time = "所要時間: " + ts.Minutes + "分" + ts.Seconds + "秒";
                string msg, title;
                if(answer == question)
                {
                    msg = "正解しました!";
                    title = "正解";
                }
                else
                {
                    msg = "不正解でした!";
                    title = "不正解";
                }
                msg += System.Environment.NewLine + "question: " + question + System.Environment.NewLine + "answer  : " + answer + System.Environment.NewLine + erapsed_time;
                MessageBox.Show(msg, title, MessageBoxButtons.OK, MessageBoxIcon.Information);
                Dem_Pre_Data += question + "," + answer + "," + (answer == question).ToString() + "," + ts.TotalMinutes.ToString() + System.Environment.NewLine;
                question = answer = string.Empty;
                MakeNewQuestion();
            }
            //新しいボタン表示文字の設定
            ShuffletxtStr();
        }

        //txtStr配列をシャッフルし、ボタン表示文字列も変更する
        private void ShuffletxtStr()
        {
            //乱数の初期化
            Random rand = new Random((int) DateTime.Now.Ticks & 0x0000FFFF);
            for(int i = 35; i >= 0; i--)
            {    //解説:36のアルファベット大文字、数字の配列をシャッフルしています
                int n = rand.Next(i);
                string temp = txtStr[i];
                Btns[i].Text = txtStr[i] = txtStr[n];
                txtStr[n] = temp;
            }
        }

        //新しいquesionを作成する
        private void MakeNewQuestion()
        {
            //乱数の初期化
            Random rand = new Random((int) DateTime.Now.Ticks & 0x0000FFFF);
            for(int i = 0; i < 8; i++)    //解説:乱数で8文字の出題を作成します
            {
                question += txtStr[rand.Next(36)];
            }
            MessageBox.Show("以下の文字列をよく覚えてOKボタンを押してください。" + System.Environment.NewLine + question,
                            "ゲーム開始", MessageBoxButtons.OK, MessageBoxIcon.Information);
            //ストップウォッチを初期化して開始する
            stw.Reset();
            stw.Start();
        }

        ///////////////////
        //ログファイル処理
        ///////////////////

        private bool LogRead()
        {
            try    //解説:エラー処理の為
            {
                using (StreamReader file = new StreamReader(".\\Dem_Pre.log", Encoding.UTF8, false))
                {
                    //ファイルを読む
                    Dem_Pre_Data = file.ReadToEnd();
                    // ファイルを閉じる
                    file.Close();
                    return true;
                }
            }
            catch(FileNotFoundException e)    //FileNotFoundException用
            {
                MessageBox.Show("Dem_Pre.logファイルを読み込みで、エラーが発生しましたが続行します。\r\n" + e.Message , "Logファイル読込エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            catch (Exception e)                //FileNotFoundException以外用
            {
                MessageBox.Show("エラーが発生しましたが続行します。\r\n" + e.Message , "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        private void LogWrite()
        {
            //累計を今回のデータで更新する
            using (StreamWriter file = new StreamWriter(".\\Dem_Pre.log", false, Encoding.UTF8))
            {
                //ファイルを書く
                file.Write(Dem_Pre_Data);
                // ファイルを閉じる
                file.Close();
            }
        }
    }

    ////////////////////
    //DemPreChartクラス
    ////////////////////

    public class DemPreChart : Form
    {
        //クラスコントロール
        Chart chart;        //MS Chartコントロール
        Button extBtn;        //終了ボタン
        //クラスフィールド
        double[] dat;    //解説:履歴の所要時間を記録するdouble配列です
        //コンストラクター
        public DemPreChart()
        {
            //プログラムアイコンをフォームにつける
            Assembly myOwn = Assembly.GetEntryAssembly();
            this.Icon = Icon.ExtractAssociatedIcon(myOwn.Location);
            //フォームの設定
            this.Size = new Size(640, 480);
            this.MinimumSize = new Size(320, 190);
            this.Text = "Dementia Prevention Log Chart";
            this.Load += Initialize;
        }

        //初期設定
        private void Initialize(object sender, EventArgs e)
        {
            //MS Chart
            chart = new Chart();
            chart.Location = new Point(10, 10);
            chart.Size = new Size(ClientSize.Width - 20, ClientSize.Height - 60);
            chart.Anchor = (AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom | AnchorStyles.Left);
//            chart.Legends.Add("Legend1");    //Addしないと「凡例」が表示されない
            this.Controls.Add(chart);

            //終了ボタン
            extBtn = new Button();
            extBtn.Location = new Point((ClientSize.Width - extBtn.Width) /2, ClientSize.Height - extBtn.Height - 10);
            extBtn.Text = "終了";
            extBtn.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
            extBtn.Click += exitButton_Click;
            this.Controls.Add(extBtn);

            if(IniChart())        //データを読み込む
                ShowChart();    //MS Chartを表示する
        }

        //終了ボタンが押された時の処理
        private void exitButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        //Dem_Pre.logファイル読み込み
        private bool IniChart()
        {
            string data = "";
            //ファイル(UTF-8:Encoding.UTF8)を読む
            try
            {
                using(StreamReader file = new StreamReader("Dem_Pre.log", Encoding.UTF8))
                {
                    data = file.ReadToEnd();
                    // ファイルを閉じる
                    file.Close();
                }
            }
            catch(FileNotFoundException e)    //FileNotFoundException用
            {
                MessageBox.Show("Dem_Pre.logファイルを読み込めなかったので、履歴グラフを表示できません。このウィンドウを終了させてください。\r\nエラーコード:" + e.Message, "Logファイル読み込みエラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            catch(Exception e)    //FileNotFoundException以外用
            {
                MessageBox.Show("このウィンドウを終了させてください。\r\nエラーコード:" + e.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            //文字列の行分割
            string[] lines = data.Split(new[]{"\r\n","\n","\r"}, StringSplitOptions.None);
            //行の語分割と実数配列の作成
            dat = new double[lines.Length - 1];                //最終行は空行の為
            for(int ln = 0; ln < lines.Length - 1; ln++)    //最終行は空行の為
            {
                string[] dt = lines[ln].Split(',');
                bool flag;    //検査結果
                double sec;    //所要時間(秒)
                if(!bool.TryParse(dt[2], out flag))
                    return false;
                if(!double.TryParse(dt[3], out sec))
                    return false;
                dat[ln] = flag ? sec : -sec;    //解説:正解は正(青)、不正解は負(赤)
            }
            return true;
        }

        //MS Chartを表示する
        private void ShowChart()
        {
            //MS Chartの初期化
            chart.Series.Clear();
            chart.ChartAreas.Clear();
            chart.Titles.Clear();
            //タイトル設定
            Title title = new Title("過去の検査履歴(「不正解」はマイナス表示)");
            Title title1 = new Title("所要時間(分)");
            //チャートエリア作成
            ChartArea chartAria = new ChartArea("Area1");
            chartAria.AxisX.Title = "回数";
            chartAria.AxisY.Title = "分";
            //系列の作成
            Series series = new Series();
            series.Color = Color.Transparent;
            series.ChartType = SeriesChartType.Column;    //系列の種類を棒グラフに設定
//            series.LegendText = "凡例:所要時間(分)";    //系列の凡例を設置
            series.BorderWidth = 2;                        //系列の境界線太さ
            series.MarkerStyle = MarkerStyle.None;        //系列のポイントマークの形状
             //読み込んだデータでデータポイントを作成
            for (int i = 0; i < dat.Length; i++)
            {
                DataPoint dp = new DataPoint(i + 1, dat[i]);
                //値によって色を変更(解説:正解は正(青)、不正解は負(赤))
                if(dat[i] >= 0)
                    dp.Color = Color.Blue;
                else
                    dp.Color = Color.Red;
                series.Points.Add(dp);
            }
            //チャート設定
            chart.Titles.Add(title);
            chart.Titles.Add(title1);
            chart.ChartAreas.Add(chartAria);
            chart.Series.Add(series);
            chart.ChartAreas["Area1"].BackColor = Color.WhiteSmoke;    //背景色を変更
        }
    }
}

 

ネタ切れでたどり着いた、このブログの最終目的「ボケ防止(Dementia Prevention)」()。

:参考サイト

記憶障害 - 09. 脳、脊髄、末梢神経の病気

認知症による記憶障害とは?その種類やチェック方法

認知症を疑った際に受ける「MMSE」とは?評価法や注意点

 

前回はそのさわりというか、見た目を紹介しました。

 

単に

 

(1)アルファベット大文字(26文字)と数字(10文字)からランダムに8文字の文字列を出題し、

(2)アルファベット大文字と数字、36文字のプッシュボタンの配列をランダムに変更させながらウィンドウを表示させ、

(3)出題文字列を記憶を頼りに入力してゆく

 

だけのプログラムですが、

 

これが結構ムズイ!何故か?

 

それは単なるアルファベットと数字8文字であっても、

 

(1)「意味のない(意味記憶ではない)文字の羅列」であること(作業記憶)

(2)最初の暗記時にそれらを暗唱して記憶すると思いますが、

(3)その後36文字の文字盤がランダムに変更され、盤上の文字を探しているうちに最初の暗記記憶が揮発(もしくは音や形状の似た他の文字列に変わっ)

 

不正解になるのではないかと思っています。(

:出典:新日本速読研究会

  • 視覚情報処理(後頭葉): 目から入った文字の形、線、位置情報を認識します。
  • ターゲットの特定と注意(頭頂葉): 膨大な情報の中から、あらかじめ目的としている文字(ターゲット)に意識的な「注意」を向けます。特に「空間認知」を司る部位が、文字の位置関係を把握します。
  • 脳内文字との照合(文字中枢・側頭葉): 脳内にある「脳内文字(記憶している文字の形)」と、目の前の文字を高速で照合します。
  • ワーキングメモリの活用(前頭前皮質): 探すべき文字を一時的に記憶(保持)しながら、文字を一つずつ確認する作業を行います。この際、前頭前皮質が活発に働きます。

 

最初は↑だけの記憶機能検査アプリでしたが、それらの処理に加え、毎回の結果をcsvファイルでログに録り、それを毎回起動時に過去の検査履歴として表示させると、

 

目を覆いたくなるような結果

:正の青棒グラフは正解の所要時間(従って短いほうが良い)、負の赤棒グラフはは「不正解」(矢張り長いほうが問題がありそうです)の所要時間になっています。

 

になります。ログを見ると

 

M3W3GGBF,M3W3GGBF,True,0.507834276666667
O926COKU,0926COQU,False,0.998608723333333
ZJU8PW79,ZI98EIQU,False,0.803857298333333
QIWLMD5H,QIWLMD5H,True,0.54092779
826BEAFO,826BELFO,False,0.744082726666667
GZY1I4QA,GYZ114QA,False,0.821337365
PZVXVQSZ,PZEUV2FZ,False,0.700327895
WSW5XH55,WSW5XH55,True,1.37099263333333
KN674MEA,KL674MEA,False,0.556191486666667
7R96PW4D,7R96PW4D,True,1.00059348166667
VA1IPNGB,VAPIGNTV,False,0.678592161666667
7B6FJ3SS,7B6FT76B,False,0.93899073
EK26Q2BP,EK26Q2VP,False,1.28993001333333
6Q4Q5ML4,6Q4Q5ML4,True,0.791656033333333
C2SKH2VZ,C2SKV2SZ,False,0.960329316666667
580MG8JM,580MJ8GL,False,0.898066496666667
XI36S5FV,XI36SVJM,False,1.29078560333333
 

ボタン押し間違い('I'と'1')は分かりますが、後は①音が近いアルファベット(K-Q、A-L、N-L etc)に書き換え、または②混乱して完全に異なる文字列になっていることがわかります。いずれにしても、

 

 

あ"~、俺もそろそろホントに終わりだなぁ~

 

という気持ちにさせてくれます。(若い人がやっても結構ムズイと思いますよ、意味のない文字羅列を記憶するのは結構難しいので。)

 

次は一応プログラムコードを紹介しましょうね。なお、これは特別な開発環境がなくてもWindows 11さえあれば動くようにできます。

 

色々と愚痴を重ねてきましたが、熟慮黙考の上、

 

なーんとか新しいアプリのアイデア

 

を得ることができました。その名も、

 

「ボケ防止」

 

一応、日本語はやめようと思い、英語のDementia(痴呆)Prevention(防止)から"Dementia_Pre"(sounds like "Dementia App(lication)")としました。

 

どんなものかと言うと、ダブルクリックして起動すると(実は起動直後の処理をちょっといじくる予定ですが)、

 

 

というメッセージボックスが出るので、その文字列をよく覚えます。OKボタンを押すと、

 

 

という(0 - 9とA - Zで36文字の)文字盤()が出ますので、出題された8文字の文字列を1文字ずつ入力してゆきます。8文字になり、

:↑のイメージは初期値で、毎回ボタンを押す度にランダムに配列が変更され、目当ての文字を一所懸命探す必要があります。

 

 

OKボタンを押すと、

 

 

または「不正解」の表示が出され、所要した時間も教えてくれます。(「1分41秒」も私が実際にやった、本当の値です。)

 

これによって、記憶力、検索の際の認知力、適切なボタンを押す運動神経の結果およびその反応スピードが試されます。結果の発表後は再度はじめからゲームが進行し、終了するには"Q"ボタンを押す()か、ウィンドウのシステムボタン(「X」)を押します。

:答えに"Q"を入力する場合、「終了しますか?」のダイアログが出た際に「いいえ」を選んでください。終了せずに"Q"が入力されます。

 

こんな簡単なものですが、結構古希過ぎの老人には難しく(恐らくあなたにも難しく)余り良い成績を残せません。

 

記憶は短期記憶から傷んでくる

 

ということを実証するソフトです。

 

本ブログの最終目的をリビューしていて、新しいネタを思いつきました。

 

決して医学的に意味があるかどうかわかりませんが...

 

プログラミング的にも面白くはないかと思いますが...

 

(対象外の若い方であっても)結果を見て、楽しくなくなるかもしれませんが...

 

少なくとも、

 

所謂、ひとつのプログラミングネタ

 

にはなるかと思います。その名も、

 

Dementia_Pre!

 

乞御期待!

 

2020年に完全リタイアし、ボケ防止に再開した「趣味としてのプログラミング」。

 

定年時に一応Visual Studio(VS)2019とか、Embarcadero C++ Builder(ECB)とかの無料版で肩慣らしをしましたが、VSはUIの相性が悪く、ECBは「フリーライセンスが一年だけ」の上にメモリーエラーが多発し、

 

それなら

 

と20数年前に開発したBorland C++用の自作プログラミングツール、ライブラリー等("BCCFormand BCC Skelton")でプログラミングを再開し、2021年に始めたのがこのブログ。

 

その後、

  • 20余年間の技術的発展(C++11~、Unicord化、64bit CPU化、OpenGL 3~)対応、
  • 自作ツール等(ECCSkelton、EZImage、IconViewer、BCFEditor etc)のUpdate、
  • COM(DirectShow、SAPI、Shell etc)のサンプル作成、
  • 他言語学習(C#、Python)、
  • C++やC#でのゲーム造り(Menace、Nim、LightCycle、Chinchirorin、Maze、Othello、8Puzzle、Cell etc)、
  • 同ツール造り(Dump、DirectShow、IDList、Album、Renamer、ResWriter/Reader、Replacer、Resizer、CardboardBox etc)、
  • 同デモプログラム造り(TextToSpeech、Tower Of Hanoi、Glut_BCC、Biorythm)

等々で5年間を何とか凌ぎ(足りないネタは【無駄話】、【食い物話】、【お酒の話】、精神心理学の【Psycho】等で補完)、最終的に(前にも何度か触れたことはありましたが)最新バージョンのVS(VS 2026)の味見(【Visual Studio探検記】)までやり、Unityにも触れ(アレルギーが出たので中止)ましたが、

 

はたと、自分の現在位置について黙考

 

し、現在のハードルとこのブログの行く末について具体的に纏め、次の結論とならざるを得ないと考えています。

 

(1)プログラミング環境はIDE、コード補完ツール等が充実して既に自分自身でコードを書く量は半減しています。

(2)コードも生成AIの助けのみならず、作成依頼により、(その基礎となるハードウェア、ソフトウェアの基礎知識やリソース等周辺知見を含み)プログラミングを理解していなくて作れてしまいます。

(3)それ以前の問題として、ツールやゲームはフリーソフトが溢れていて、「作るべき(意味のある)もの、作るべき何か」が絶滅しているといっても過言ではありません。

(4)従って、今まで「個人生活上必要で見落としているツールや、余り見かけない類の(オートマタ的)ゲーム」を追求してきましたが、それすらも枯渇し、

 

趣味として行うプログラミングの存続する余地はほぼ無い

 

と言い切れる状態になりました。

 

これからどうしようか?

 

取り敢えず、広い意味の花鳥風月に "touched" した際に駄文を載せることになりそうです。(プログラミングは、そのテーマの"one of them"として扱いましょう。)