///////////////////////////////
// LifeGamePlus.cs (LifeGame+)
// Copyright August 2023
// by Y-Sama
///////////////////////////////
using System;
namespace LifeGamePlus
{ ///////////////
//生命体クラス
///////////////
public class Livant
{ //プロパティ
public bool Alive //生存状態フラグ
{
get; set;
}
public int Age //年齢(0→最高年齢(暫定的に64))
{
get; set;
} //SOGIE:性的指向(Sexual Orientation)、性自認(Gender Identity)、性表現(Gender Expression)を組み合わせた用語
public int Sogie //異性愛女性 = 0(40%)、異性愛男性 = 1(50%)、同性愛 = -1(10%)に設定
{
get; set;
}
public string Name //個体的ID(固有名で子が出来た場合のみ付与する)
{ //生殖による出生時に「世界」から与えられる
get; set;
}
public string Tribe //社会的ID(集団の固有名-同一であれば共生、異なれば敵対)
{ //出生時に「世界」から与えられる
get; set;
} //メソッド
public Livant() //コンストラクター
{
this.Alive = true; //誕生したので生きている
this.Age = 0; //誕生したので0歳
this.Sogie = GivenGender(); //乱数でジェンダーを決定する
}
/* public ~Livant() //デストラクター(https://ufcpp.net/study/csharp/resource/rm_destructor/)
{
//delete this; this = null; //危険な処理
} */
private int GivenGender() //誕生時の性別の決定
{
Random rnd = new System.Random();
switch(rnd.Next(0, 9))
{
case 0: //10%の同性愛グループ
return -1;
case 1: //1 - 4の40%は女性異性愛グループ
case 2:
case 3:
case 4:
return 0;
default: //5 - 9の50%は男性異性愛グループ
return 1;
}
}
}
/////////////////////////////////////
//世界クラス(生命体の存在する世界)
/////////////////////////////////////
public class World
{ //プロパティ
public int Width //世界の幅
{
get; set;
}
public int Height //世界の高さ
{
get; set;
} //メソッド
}
////////////////
// For Testing
////////////////
public class Application
{
public static void Main()
{
}
}
ということで、早速そのコードをECC(Embarcadero C++ Compiler-"*.c"ファイルのコンパイルは面倒なので、"*.cpp"のC++プログラム)用に若干手直ししてコンパイルし、一応動くのを確かめました。(尤も、未だにボードが〇✖で埋まってもまだ手を指すように求めてくるので、未だ完動してはいませんが... 。)
namespace TestArray //解説基本的にアッセンブリー(実行ファイル名)の名前空間を使う。なお、ECCでは
//名前空間内にエントリ^ポイント(main関数)を入れると「ソースファイルが見当たらない」エラーになる。
{
public class Sample //C++ではclassキーワードにアクセス指定子をつけない。
{
public int[] a; //C++では配列を宣言する場合、配列へのポインターを宣言する。
public string[] b; //C++では文字列配列を宣言する場合、char配列の配列へのポインターを宣言する。
public Sample() //C++ではコンストラクターにアクセス指定子をつけない。
{
a = new int[5] {1, 2, 3, 4, 5};
b = new string[3] {"ABC", "DEF", "GHI"};
}
} //C++ではクラス定義の最後に";"が必要。 //デストラクターで明示的にメモリーを開放しなくても、C#はGarbage Collectorがやってくれる。
public class App //C++ではclassキーワードにアクセス指定子をつけない
{
static public void Main()
{ //クラスオブジェクト単体の場合
Sample sample = new Sample(); //C++では宣言しただけでインスタンスが生成される。("=new..."は不要)
for(int i = 0; i < sample.a.Length; i++) //C++では配列にLengthメンバーなんてない。
Console.Write(sample.a[i].ToString() + " ");
Console.Write("\r\n");
for(int i = 0; i < sample.b.Length; i++)
if(i < sample.b.Length - 1)
Console.Write(sample.b[i] + ", ");
else
Console.Write(sample.b[i]);
Console.Write("\r\n"); //クラスオブジェクト配列の場合
Sample[] sampleArr = new Sample[5]; //C++ではポインター宣言と共にインスタンスが生成される。(個別のSampleに関わるnewは不要)
for(int j = 0; j < 5; j++)
{ //解説:↓の行がないと私が嵌った「オブジェクト参照がオブジェクトインスタンスに設定されていません」というSystemNullReferenceExceptionエラーとなる。(sampleArrはnullの配列を指しているだけ。)
//sampleArr[j] = new Sample(); //まずSampleのインスタンスを個別に生成してやる必要がある。(超面倒!)
for(int i = 0; i < sampleArr[j].a.Length; i++)
Console.Write(sampleArr[j].a[i].ToString() + " ");
Console.Write("\r\n");
for(int i = 0; i < sampleArr[j].b.Length; i++)
if(i < sampleArr[j].b.Length - 1)
Console.Write(sampleArr[j].b[i] + ", ");
else
Console.Write(sampleArr[j].b[i]);
Console.Write("\r\n");
}
Console.Read(); //C++のgetch()と同じ目的。
}
}
}
メモリーリーク: Form クラスは、ウィンドウやコントロールなどのネイティブリソースを使用します。Dispose() を呼び出さない場合、これらのリソースが正しく解放されず、メモリーリークが発生する可能性があります。特に長期間にわたって多数のフォームを開いて閉じた場合、メモリ使用量が増加し続ける可能性があります。
///////////////////
// CardboardBox.cs
///////////////////
using System;
using System.Collections;
using System.Collections.Generic; //List使用の為(解説:本体でのデータ管理はListを使います。)
using System.Windows.Forms;
using System.Drawing;
using System.Resources;
using System.IO; //Fileクラス使用の為
using csFileList; //FileLIstクラス使用の為(解説:これが作成したcsFileList.dllの読み込みです。)
namespace CardboardBox
{ ///////////////////////////
//エントリーポイントクラス
///////////////////////////
class MainApp
{
[STAThread]
public static void Main()
{ //解説:起動時のコマンドラインを取得します。