前回予告しました「TGEditクラス」「TGListクラス」「TGSet クラス」のコードを「ご参考」として掲載します。
コードの大部分はコメントだけで分かると思いますが、TGSetクラスのDoThis()(命令の実行)だけは解説:を入れます。
尚、ダイアログ部分は本編の解説が終わってからとなります。
///////////////////////////////////////////////////////////////////////////////
// TGEライブラリー (TGE.dll)
// Copyright (c) 2026 by Ysama
//
// 【概要】
//LOGOベースの描画命令を纏めた「命令セット(TGSet)」、その一覧である「命令リス
//ト(TGList)」、「命令リスト」から指定した命令セットで、繰り返しを含め実行順を
//定める「実行リスト(TGList)」及び編集ダイアログをまとめたNakov.TurtleGraphics
//の命令編集ライブラリー
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.Collections.Generic; //Listを使う為
using System.IO; //FIle関係
using System.Text; //Encoding.GetEncoding を使用するのに必要
using Nakov.TurtleGraphics; //TurtleGraphicsを使う為
namespace TGE
{
/////////////////////////////////////////////
//TurtleGraphics命令を編集するラッパークラス
/////////////////////////////////////////////
public class TGEdit
{
//クラスフィールド
public TGSet CmdSet; //命令セット({コマンド番号, 引数}の整数配列 )
public TGList CmdList; //命令リスト(命令セットの一覧)
public TGList ExeList; //実行リスト(指定する命令セットの実行順リスト)
//コンストラクター
public TGEdit(Form form = null)
{
if(form == null)
Turtle.Init();
else
Turtle.Init(form);
CmdSet = new TGSet();
CmdList = new TGList();
ExeList = new TGList();
}
//TurtleGraphicsのDispose/Reset
public void Reset()
{
Turtle.Reset();
}
//亀の表示/非表示を確認する
public bool IsTurtleShown()
{
return Turtle.ShowTurtle;
}
//亀を表示/非表示する
public void ShowTurtle(bool flag)
{
Turtle.ShowTurtle = flag;
}
}
///////////////////////////////////////////
//命令リストクラス-命令セットの集合クラス
///////////////////////////////////////////
public class TGList
{
//クラスメンバー
List<TGSet> CmdList;
public string FileName {get; set;} //ファイル入出力名
//コンストラクター
public TGList()
{
CmdList = new List<TGSet>();
FileName = String.Empty;
}
//コピーコンストラクター
public TGList(TGList tgl)
{
CmdList = new List<TGSet>(tgl.CmdList);
FileName = tgl.FileName;
}
//TGListの初期化
public void Clear()
{
CmdList.Clear();
FileName = String.Empty;
}
//TGListの命令セット数
public int CountSets()
{
return CmdList.Count;
}
//n番目の命令セットを取得
public TGSet GetSet(int n)
{
if(n < 0 || n > CmdList.Count - 1)
return new TGSet(); //空のTGSetを返す
return CmdList[n];
}
//TGListへのTGSetの追加
public void AddSet(TGSet tgs)
{
CmdList.Add(new TGSet(tgs)); //Deep copy
}
//n番目の命令セットの削除
public bool RemoveAt(int n)
{
if(n < 0 || n > CmdList.Count - 1)
return false;
else
CmdList.RemoveAt(n);
return true;
}
//n番目に命令セットを挿入
public bool InsertSet(int n, TGSet tgs)
{
if(n < 0 || n > CmdList.Count - 1) //最後尾に追加するにはAddを使う
return false;
else
CmdList.Insert(n, tgs);
return true;
}
//CmdListへTGSetを介して命令セット入力
public bool ReadList(string data)
{
//入力用TGSet
TGSet tgs = new TGSet();
//文字列の行分割
string[] lines = data.Split(new[]{"\r\n","\n","\r"}, StringSplitOptions.None);
//行の語分割と整数配列の作成
bool Is1stTime = true; //最初の命令セットの’-1'か否かのフラグ
foreach(string line in lines)
{
if(line == String.Empty) //(有る筈のない)空行に遭遇したら中止する
break;
string[] dt = line.Split(',');
if(dt[0] == "Name:") //命令セットデータの最終行は"Name:,(Name),(Description)"とする
{
tgs.Name = dt[1];
tgs.Description = dt[2];
continue; //次行へスキップ
}
int cmd = 0, arg1 = 0, arg2 = 0, arg3 = 0; //入力結果
if(!int.TryParse(dt[0], out cmd))
return false;
else
{
if(cmd == -1) //命令'-1'はセット開始(先行セット終了、セットの区切り)
{
if(!Is1stTime) //最初の-1で先行セットがなければAddSet()は不要
AddSet(tgs); //CmdListに今迄の命令セットを登録
else
Is1stTime = false;
tgs.Clear(); //次の命令セットの為に入力用tgsを初期化する
}
}
if(!int.TryParse(dt[1], out arg1))
return false;
if(!int.TryParse(dt[2], out arg2))
return false;
if(!int.TryParse(dt[3], out arg3))
return false;
tgs.AddCmd(cmd, arg1, arg2, arg3);
}
AddSet(tgs); //最後の命令セットを登録
return true;
}
//CmdListの命令セットの一覧出力
public string WriteList()
{
string str = String.Empty;
foreach(TGSet tgs in CmdList)
{
str += tgs.WriteSet();
}
return str;
}
//CmdListの命令セットの実行
public void DoSet()
{
foreach(TGSet tgs in CmdList)
{
tgs.DoThis();
}
}
///////////////////////////////////////////////////////////////////////////////////////
// >>> "*.tge"のファイルについて <<<
//(1) LOGOベースのTurtleGraphicsの命令に対応した命令番号と引数一つのテキストcsvファイル
//(2) 命令'-1'はセット開始(先行セット終了、セットの区切り)で引数は繰り返し回数
//(3) 命令セットデータの最終行は"Name:,(Name),(Description)"とする
///////////////////////////////////////////////////////////////////////////////////////
//tgdファイル書き込み(UTF-8:Encoding.UTF8)
public bool WriteFile()
{
if(FileName == String.Empty)
return false;
using(StreamWriter file = new StreamWriter(FileName, false, Encoding.UTF8))
{
//ファイルを書く
file.Write(WriteList());
//ファイルを閉じる
file.Close();
}
return true;
}
//tgdファイル読み込み(UTF-8:Encoding.UTF8)
public bool ReadFile()
{
if(FileName == String.Empty)
return false;
string data = String.Empty;
try
{
using(StreamReader file = new StreamReader(FileName, Encoding.UTF8))
{
data = file.ReadToEnd();
// ファイルを閉じる
file.Close();
}
}
catch(Exception e) //FileNotFoundException e
{
//Debug用
//MessageBox.Show("エラーコード:" + e.ToString(), "初期化ファイル読み込みエラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBox.Show("ファイルを読み込めませんでした。\r\n。エラーコード:" + e.ToString(), "確認", MessageBoxButtons.OK, MessageBoxIcon.Information);
return false;
}
return ReadList(data);
}
}
/////////////////////////////////////////////////
//命令セットクラス(名称と説明付きの命令セット)
/////////////////////////////////////////////////
public class TGSet
{ //クラスメンバー
List<int[]> CmdSet; //命令配列
public string Name {get; set;} //命令セット名
public string Description {get; set;} //説明
//コンストラクター1
public TGSet()
{
CmdSet = new List<int[]>();
Name = String.Empty;
Description = String.Empty;
}
//コンストラクター1
public TGSet(string name, string description)
{
CmdSet = new List<int[]>();
Name = name; //再設定自由
Description = description; //再設定自由
}
//コピーコンストラクター
public TGSet(TGSet copy)
{
CmdSet = new List<int[]>(copy.CmdSet);
Name = copy.Name;
Description = copy.Description;
}
//初期化
public void Clear()
{
CmdSet.Clear();
Name = String.Empty;
Description = String.Empty;
}
//命令セットの命令数
public int Count()
{
return CmdSet.Count;
}
//命令セットの設定(1)
public void Set(TGSet tgs)
{
CmdSet.Clear();
CmdSet = new List<int[]>(tgs.CmdSet);
Name = tgs.Name;
Description = tgs.Description;
}
//命令セットの設定(2)
public void Set(List<int[]> list, string name, string description)
{
CmdSet.Clear();
CmdSet = new List<int[]>(list);
Name = name;
Description = description;
}
//n番目の命令取得
public int[] GetCmd(int n)
{
if(n < 0 || n > CmdSet.Count - 1)
return new int[] {-1, -1, -1, -1}; //エラー
else
return CmdSet[n];
}
//n番目の命令設定(1)(命令番号cmdは必須、定数引数arg1は重要、arg2とarg3はオプション扱い)
public bool SetCmd(int n, int cmd, int arg1, int arg2 = 0, int arg3 = 0)
{
if(n < 0 || n > CmdSet.Count - 1)
return false;
CmdSet[n] = new int[] {cmd, arg1, arg2, arg3}; //Deep copy
return true;
}
//n番目の命令設定(2)
public bool SetCmd(int n, int[] cmd)
{
if(n < 0 || n > CmdSet.Count - 1 || cmd.Length != 4)
return false;
CmdSet[n] = cmd;
return true;
}
//命令の追加(命令番号cmdは必須、定数引数arg1は重要、arg2とarg3はオプション扱い)
public void AddCmd(int cmd, int arg1, int arg2 = 0, int arg3 = 0)
{
CmdSet.Add(new int[] {cmd, arg1, arg2, arg3}); //Deep copy
}
//命令の追加(配列渡し)
public bool AddCmd(int[] cmdarr)
{
if(cmdarr.Length != 4)
return false;
else
{
CmdSet.Add((int[])cmdarr.Clone()); //Deep copy
return true;
}
}
//命令の削除
public bool RemoveAt(int n)
{
if(n < 0 || n > CmdSet.Count - 1)
return false;
else
CmdSet.RemoveAt(n);
return true;
}
//n番目に命令を挿入(命令番号cmdは必須、定数引数arg1は重要、arg2とarg3はオプション扱い)
public bool Insert(int n, int cmd, int arg1, int arg2 = 0, int arg3 = 0)
{
if(n < 0 || n > CmdSet.Count - 1) //最後尾に追加するにはAddを使う
return false;
else
CmdSet.Insert(n, new int[] {cmd, arg1, arg2, arg3});
return true;
}
//n番目に命令を挿入(配列渡し)
public bool Insert(int n, int[] cmdarr)
{
if(n < 0 || n > CmdSet.Count - 1) //最後尾に追加するにはAddを使う
return false;
else
CmdSet.Insert(n, (int[])cmdarr.Clone());
return true;
}
//命令の一覧出力
public string WriteSet()
{
string str = String.Empty;
foreach(int[] array in CmdSet)
{
//str += array[0].ToString() + "," + array[1].ToString() + ","
// + array[2].ToString() + "," + array[3].ToString() + Environment.NewLine;
str += string.Join(",", array) + Environment.NewLine;
}
str += "Name:" + "," + Name + "," + Description + Environment.NewLine;
return str;
}
//命令(int[4]-コマンド番号、引数1、引数2、引数3)の実行
public void DoThis() //解説:TurtleGraphicsの命令処理を行います。
{
int times = 1; //解説:繰り返し回数です。既定値は「1回」です。
for(int i = 0; i < times; i++) //最低でも規定値1回は実行
{ //cmdは命令(cmd[0])と引数(cmd[1~3])の整数配列
foreach(int[] cmd in CmdSet)
{ //引数cmd[1]は定数、cmd[2]は回数の倍数、cmd[3]は回数による分数(ともに規定値は0)
switch(cmd[0]) //引数cmd[0]は命令番号
{
case -1: //命令セット開始(解説:これはTurtleGraphicsの命令ではなく、TGSet独自命令です。)
times = cmd[1]; //引数は繰り返し回数(解説:1回以上の場合、timesのループ回数が更新されます。)
cmd[0] = 0; //繰り返しの為にNOPにする(解説:2回目からはNOPで「何もしません」。)
break;
case 0: //NOP - No OPeration(解説:-1命令はループ中はNOPになります。)
break;
case 1: //Forward(arg)(解説:基本的に引数は以下の式になります。)
Turtle.Forward(cmd[1] + cmd[2] * i + cmd[3] / (times - i));
break;
case 2: //Backward(arg)
Turtle.Backward(cmd[1] + cmd[2] * i + cmd[3] / (times - i));
break;
case 3: //MoveTo(arg1, arg2)(解説:引数の使い方が例外となります。)
int x = cmd[1] + cmd[3] * i; //arg1(cmd[3]のループ倍数が加算)
int y = cmd[2] + cmd[3] * i; //arg2(cmd[3]のループ倍数が加算)
Turtle.MoveTo(x, y);
break;
case 4: //Rotate(arg)
Turtle.Rotate(cmd[1] + cmd[2] * i + cmd[3] / (times - i));
break;
case 5: //RotateTo(arg)
Turtle.RotateTo(cmd[1] + cmd[2] * i + cmd[3] / (times - i));
break;
case 6: //PenUp()
Turtle.PenUp();
break;
case 7: //PenDown()
Turtle.PenDown();
break;
case 8: //X
Turtle.X = cmd[1] + cmd[2] * i + cmd[3] / (times - i);
break;
case 9: //Y
Turtle.Y = cmd[1] + cmd[2] * i + cmd[3] / (times - i);
break;
case 10: //Angle
Turtle.Angle = cmd[1] + cmd[2] * i + cmd[3] / (times - i);
break;
case 11: //PenColor(Color構造体←整数の変換-解説:Colorのメソッドです。)
Turtle.PenColor = Color.FromArgb(cmd[1] + cmd[2] * i + cmd[3] / (times - i)); //2026年04月22日変更
break;
case 12: //PenSize
Turtle.PenSize = cmd[1];
break;
case 13: //PenVisible (1 - true, 0 - false)
Turtle.PenVisible = (cmd[1] == 1);
break;
case 14: //Delay
Turtle.Delay = cmd[1];
break;
default:
break;
}
}
}
CmdSet[0][0] = -1; //配列は参照引き渡しの為、値-1に復旧する
}
}













