C# で書かれたライフゲームを Delphi に移植してみる

# はじめに
特に目的はないのですが、@yoship1639 さんの [【C#】26行でライフゲームを書いてみる（コンソール表示可能）](https://qiita.com/yoship1639/items/e7d7b7206002934e85ab) という記事中のライフゲームを Delphi に移植してみようと思いました。

使用した Delphi は 10.3 Rio です。無償版の [Community Edition](https://www.embarcadero.com/jp/products/delphi/starter) でももちろん動作します。

# ライフゲームを書く
操作はオリジナルと同じです。

 - コンソール表示可能
 - [Enter]で次世代に移行
 - X　Yでフィールド[Y, X]にセルの設置
 - qで終了

## ソースコード
基本的な機能しか使っていないので Windows, macOS, Linux のいずれでも動作すると思います。オリジナルの C# のソースコードと見比べてみるのも楽しいと思います。

```pascal:LifeGame.pas
program LifeGame;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

const
  W = 10; // ヨコ
  H = 10; // タテ
  CELLSTR: array [Boolean] of string = (' .', ' o');

var
  f, pf: array [0..Pred(H), 0..Pred(W)] of Boolean; // フィールド

begin
  repeat
    var buf: string;
    Readln(buf);
    var sc: TArray<string> := buf.Split([' ']);
    if Length(sc) = 0 then
    begin
      Writeln;
      for var y:= 0 to Pred(H) do
      begin
        WriteLn;
        for var x := 0 to Pred(W) do
        begin
          var c := 0;
          for var yy := Pred(y) to Succ(y) do
            for var xx := Pred(x) to Succ(x) do
            begin
              if (yy < 0) or (yy >= H) or (xx < 0) or (xx >= W) or ((x = xx) and (y = yy)) then
                Continue;
              Inc(c, Ord(pf[yy, xx]));
            end;
          f[y, x] := ((c = 2) and pf[y, x]) or (c = 3);
          Write(CELLSTR[f[y, x]]);
        end;
      end;
      pf := f;
    end
    else if Length(sc) >= 2 then
      pf[sc[1].ToInteger, sc[0].ToInteger] := True
    else if sc[0] = 'q' then
      Break;
  until False;
end.
```

48 行でしたね。空行とか削ればもう少し短くなりますが、読みやすさ優先で。フィールドの型を Boolean にしたくらいでほぼベタ移植です。

## ソースコード (その２)
コンソール API を使ってみました。

```pascal:LifeGame.pas
program LifeGame;

{$APPTYPE CONSOLE}

{$IFDEF MSWINDOWS}
  {$DEFINE USECONSOLEAPI}
{$ENDIF}

uses
  {$IFDEF USECONSOLEAPI}
  Winapi.Windows,
  {$ENDIF}
  System.SysUtils;

const
  W = 10; // ヨコ
  H = 10; // タテ
  CELLSTR: array [Boolean] of string = (' .', ' o');

var
  f, pf: array [0..Pred(H), 0..Pred(W)] of Boolean; // フィールド

begin
  {$IFDEF USECONSOLEAPI}
  var stdout := GetStdHandle(STD_OUTPUT_HANDLE);
  var cd: TCoord := Default(TCoord); // (X:0; Y:0)
  {$ENDIF}
  repeat
    var buf: string;
    Readln(buf);
    var sc: TArray<string> := buf.Split([' ']);
    if Length(sc) = 0 then
    begin
      {$IFDEF USECONSOLEAPI}
      SetConsoleCursorPosition(stdout, cd);
      {$ELSE}
      Writeln;
      {$ENDIF}
      for var y:= 0 to Pred(H) do
      begin
        WriteLn;
        for var x := 0 to Pred(W) do
        begin
          var c := 0;
          for var yy := Pred(y) to Succ(y) do
            for var xx := Pred(x) to Succ(x) do
            begin
              if (yy < 0) or (yy >= H) or (xx < 0) or (xx >= W) or ((x = xx) and (y = yy)) then
                Continue;
              Inc(c, Ord(pf[yy, xx]));
            end;
          f[y, x] := ((c = 2) and pf[y, x]) or (c = 3);
          Write(CELLSTR[f[y, x]]);
        end;
      end;
      {$IFDEF USECONSOLEAPI}
      SetConsoleCursorPosition(stdout, cd);
      Write(StringOfChar(' ', W));
      SetConsoleCursorPosition(stdout, cd);
      {$ELSE}
      Writeln;
      {$ENDIF}
      pf := f;
    end
    else if Length(sc) >= 2 then
      pf[sc[1].ToInteger, sc[0].ToInteger] := True
    else if sc[0] = 'q' then
      Break;
  until False;
end.
```

フィールドが同じ位置に描画されるので変化を確認しやすいと思います。

# おわりに
実はライフゲーム(Conway's Game of Life) も Pascal も 1970 年生まれなんですよね。
上記コードをさらに [標準 Pascal](https://qiita.com/ht_deko/items/e2796788c65c2cda1de5) に移植しようとしたら文字列がないのでそこそこ大変なのでやめました (w

なお、VCL や FireMonkey を使ったライフゲームは DocWiki にサンプルがありますので、こちらも試してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/bf077bcd-b7a3-a74b-6791-8fb2972ffdae.png)

 - [Conway's Life VCL サンプル (DocWiki)](http://docwiki.embarcadero.com/CodeExamples/en/RTL.ConwaysLifeVCL_Sample)
 - [Conway's Life FMX サンプル (DocWiki)](http://docwiki.embarcadero.com/CodeExamples/en/RTL.ConwaysLifeFMX_Sample)

**See also:**

 - [ライフゲーム (Wikipedia)](https://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B2%E3%83%BC%E3%83%A0)
 - [ジョン・ホートン・コンウェイ (Wikipedia)](https://ja.wikipedia.org/wiki/%E3%82%B8%E3%83%A7%E3%83%B3%E3%83%BB%E3%83%9B%E3%83%BC%E3%83%88%E3%83%B3%E3%83%BB%E3%82%B3%E3%83%B3%E3%82%A6%E3%82%A7%E3%82%A4)
 - [ライフゲームの世界 (ニコニコ動画)](https://www.nicovideo.jp/mylist/34610498)