LoginSignup
19
4

More than 1 year has passed since last update.

原初

原初、混沌があった。
混沌は凝り固まり…うんこになった!
世界は💩に覆われようとしていた。
その時!🚽が現れた。
💩の世界に現れた🚽は、次の規則に縛られていた。

  • 誕生
    💩に隣接する🚽が3つあれば、次の世代🚽が誕生する。

  • 生存

  • 🚽に隣接する🚽が2つか3つならば、次の世代でも生存する。

  • 過疎
    🚽に隣接する🚽が1つ以下ならば、💩にまみれて死滅する。

  • 過密
    🚽に隣接する🚽が4つ以上ならば、過剰により死滅する。

そう!たんなるライフゲーム!

Delphi

一昨年は、Windows, macOS 向けアプリを、昨年は、iOS, Android 向けアプリを作ったので、今年は!CUI のアプリケーションも作れちゃうんだ是!ってところを見せつけたいと思います。

では、ご覧ください!
Windows

macOS

Linux (Ubuntu 18.04)

Qiita に載せるためフレームレートを落としたのでガックガクですが、本当はもっと綺麗に動きます(いつも言う)
中でも macOS がガックガクなのは僕のスキル不足です(スクリーンキャプチャした mov ファイルから アニメーション gif にする最適解が解らなかった)

苦労したところ

プログラムは一瞬で組めたけど、作業時間の95割は各コンソールで💩の絵文字を表示するところ!

Windows
cmd.exe ではかなり頑張ったものの絵文字が表示できなかったので、Windows Terminal + PowerShell にして chcp 65001 したらあっさり表示された!

macOS
君は優秀!何もしなくて絵文字出た!
でも zsh はエスケープシーケンスが特殊なのでイーブン!

Linux
WSL でインストールされる Ubuntu を普通に動かすと cmd.exe ベースで動くので絵文字が出ない!
Windows Terminal を使うと無事絵文字が出た
…Windows Terminal が優秀なのでは??

ソース

短いので全文載せちゃう

program LifeGameConsole;

uses
  System.SysUtils;

const
  // 盤面の大きさ
  N = 32 - 1;

  // 生死の文字
  STATE: array [Boolean] of String = ('💩', '🚽');

type
  // 盤面の状態を表す2次元配列
  TBoard = array [0.. N, 0.. N] of Boolean;

// 円環型座標取得
function GetPos(const iPos: Integer): Integer;
begin
  Result := iPos;
  if Result < 0 then
    Result := N;
  if Result > N then
    Result := 0;
end;

// 全画面消去
procedure Clear; inline;
begin
  {$IFDEF OSX}
  Writeln('%{'#$1b'[2J%}');
  {$ELSE}
  Writeln(#$1b'c');
  {$ENDIF}
end;

// 原点移動
procedure MoveOrg; inline;
begin
  {$IFDEF OSX}
  Writeln('%{'#$1b'[0;0H%}');
  {$ELSE}
  Writeln(#$1b'[0;0H');
  {$ENDIF}
end;

begin
  var Gen := 0;      // 世代
  var Board: TBoard; // 盤面
  var Next: TBoard;  // 次世代の盤面

  // ランダムで初期化
  Randomize;
  for var Y := 0 to N do
    for var X := 0 to N do
      Board[X, Y] := Random(2) > 0;

  // 画面クリア
  Clear;

  // メイン: 終了は Ctrl + C
  while True do
  begin
    // 原点に移動
    MoveOrg;

    // 世代表示
    Writeln(('Gen: ' + Gen.ToString + StringOfChar(' ', N)).Substring(0, N));
    Inc(Gen);

    // 盤面の表示と次世代判断
    for var Y := 0 to N do
    begin
      for var X := 0 to N do
      begin
        // 盤面表示
        Write(STATE[Board[X, Y]]);

        // 次世代の生死判断
        var C := 0;
        for var Q := Y - 1 to Y + 1 do
        begin
          var V := GetPos(Q);
          for var P := X - 1 to X + 1 do
            Inc(C, Ord(Board[GetPos(P), V]));
        end;

        Next[X, Y] := (C = 3) or ((C = 4) and Board[X, Y]);
      end;

      Writeln;
    end;

    // 世代交代
    Board := Next;

    Sleep(16);
  end;
end.

個人的に気に入っているのは次世代の生死判断のところです!
よろしくお願いいたします!

さいごに

クソアプリアドベントカレンダーなのに、ゲームを作ってしまった!!!

19
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
4