Help us understand the problem. What is going on with this article?

サクラエディタでライフゲーム

環境

サクラエディタ Ver.2.2.0.1
Windows 10

ライフゲームマクロ

サクラエディタの可能性を試すために
なんとなく動かしたくなり昔作ったコードを移植。

業務でライフゲームを動かす必要に迫られた場合にどうぞ。
※一応言っておくと私は業務時間中にライフゲームを動かしたりはしていない。

function simpleMethod(  board, width, height ){
    var next_isLiving = new Array( width * height );
    for (var x = 0; x < width; x++) {
        for (var y = 0; y < height; y++) {
            var isLiving_around = 0;
            var ym  = y - 1;
            var yp  = y + 1;
            var xm  = x - 1;
            var xp  = x + 1;

            if (x > 0 &&      y > 0 &&      board[ym * width + xm] === 1) isLiving_around++;
            if (x > 0 &&                    board[y  * width + xm] === 1) isLiving_around++;
            if (x > 0 &&      y < height && board[yp * width + xm] === 1) isLiving_around++;
            if (              y < height && board[yp * width + x ] === 1) isLiving_around++;
            if (x < width &&  y < height && board[yp * width + xp] === 1) isLiving_around++;
            if (x < width &&                board[y  * width + xp] === 1) isLiving_around++;
            if (x < width &&  y > 0 &&      board[ym * width + xp] === 1) isLiving_around++;
            if (              y > 0 &&      board[ym * width + x ] === 1) isLiving_around++;

            if ( 1 === board[y * width + x] ) { // 生きセル
                if (isLiving_around <= 1) {
                    next_isLiving[y * width + x] = 0; // 孤独死
                }
                else if (isLiving_around >= 4) {
                    next_isLiving[y * width + x] = 0; // 過密死
                }
                else { //次のフレームでも生きてる場合
                    next_isLiving[y * width + x] = 1; // 生存維持
                }
            }
            else {
                if (isLiving_around === 3) next_isLiving[y * width + x] = 1; //繁殖
                else {
                    next_isLiving[y * width + x] = 0;
                }
            }
        }
    }
    return next_isLiving;
}

function nextStep(board, width, height){
  var nextLiving = simpleMethod( board, width, height );

  return nextLiving;
}

function boardToString(board, width, height){
  var outText = "";
  for(var i = 0; i < height; ++i){
    for(var j = 0; j < width; ++j){
      if( 1 === nextBoard[ i * width + j ] ){
        outText += "*";
      }
      else{
        outText += " ";
      }
    }
    outText += "\n";
  }
  return outText;
}

// ここからエディタマクロ

var nStep = 10;
var text = Editor.GetSelectedString(0);
lines = text.split("\n");

var arr = new Array(30 * 30);
for( var i = 0; i < 30 * 30; ++i){
  arr[i] = 0;
}

for( var i = 0; i < lines.length && i < 30; ++i ) {
  for( var j = 0; j < lines[i].length && j < 30; ++j ) {
    var num = parseInt(lines[i].charAt(j));
    if( " " === lines[i].charAt(j) ){
      arr[ i * 30 + j ] = 0;
    }
    else if( "*" === lines[i].charAt(j) ){
      arr[ i * 30 + j ] = 1;
    }
  }
}

Editor.Sleep(100);

var nextBoard = nextStep( arr, 30, 30 );
var outText = boardToString( nextBoard, 30, 30 );
Editor.InsText( outText );

Editor.Sleep(100);

for(var step = 0; step < nStep; ++step){
  Editor.SelectLine(0);
  for(var i = 0; i < 30; ++i){
    Editor.Up_Sel();
  }

  nextBoard = nextStep( nextBoard, 30, 30 );
  outText = boardToString( nextBoard, 30, 30 );

  Editor.InsText( outText );
  Editor.Sleep(100);
}

実用

入力は30x30に固定している(それ以下でも入力できるが、描画開始すると30x30になる)
"*"を入れた個所が生存マスになる。

以下の形式で入力を行い、実行前に全体を文字列選択しておく。

※Qiitaの仕様なのか空白のみの行が空行になっているが、動かない場合直してほしい

入力例
   *               *       
    *              *       
  ***              *       








    ** ******              
    ** ******              
    **                     
    **     **              
    **     **              
    **     **              
           **        *     
    ****** **        *     
    ****** **        *     
                     *     
                     *     



image.png

マクロ実行。(「共通設定」→「マクロ」から登録でも良い)

変な入力でマクロが暴走しても責任持てないので実行は自己責任で

image.png

test.gif

マクロ動作なので若干ぎこちない気がするものの、動いた。

気になる点

マクロの実行時間が一定時間(3秒程度?)を超えるとサクラエディタ自体に制御が戻らないせいか、画面の描画が死ぬ。

なので、描画周期としているEditor.Sleep()の待ち時間を長めにすると、
最初の数ステップ描画後にウインドウが固まってしまい、後の動きが見れない。
逆に待ち時間を短めにすると勢いよく動いてすぐ終わってしまう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした