# C# で書かれたライフゲームを Delphi に移植してみる --- tags: Delphi programming ライフゲーム embarcadero objectpascal created_at: 2019-06-26 updated_at: 2020-05-09 --- # はじめに 特に目的はないのですが、@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 := 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 にしたくらいでほぼベタ移植です。 ## ソースコード (その2) コンソール 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 := 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](./e2796788c65c2cda1de5.md) に移植しようとしたら文字列がないのでそこそこ大変なのでやめました (w なお、VCL や FireMonkey を使ったライフゲームは DocWiki にサンプルがありますので、こちらも試してみてください。 ![image.png](./images/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)