2011-07-28 18 views
2

私は最近、Perlに書いたConwayのGame of LifeのC++コードをコピーしようとしました。しかし、C++コードの出力はPerlの出力と大きく異なります。 C++コードは完璧に動作しますが、Perlコードは奇妙な動作をします。今まで人生のゲームを見ています誰もがゲームの以下の状態が奇妙であることを確認する必要がありますPerlでのゲームのゲーム - 問題をC++から翻訳する

[][] [] [] [] [][][] [] []    [] [] [] [] [][]  [] 
    [] [] [] [] []  [] [] [][] [] [] [][] []   [] [] 
    [] [][] [] [] []   [] []  [][][][] [] [] [][][][][] [] [] 
    []  [][] [] []  [] [][][][] [] [] []  []  [][] [] 
[] [][]  [] [] [][][] []  []   []  [] [][] [] [] 
[] [] [][][][][] [] [] [][] [][] []   [][] []  [][][] [] 
[] []     [] [][][] [][] [][][]   [][][] [] [] 
    [] [] [][][][][][][][][][]      [][][][][]  []  [] 
[][] []      [][][][][][][] [][][]  [][]  [][] [] 
    [] []  [][][][]  [] [] [] [] [][][] [] 
    [][] [] []  []     [] [] [][] [] [][] 
    [] [] [][]  [] [][][][] [][] []  [] 
     [][] [] [][][][][] [][][]   [][][][][][][][] [][] 
    []  [] [] []   []  [][][][]     [][] 
[][]  [] [] [] [] [] [] [][][]   [][][][][][][][] 
     [][] [] []  [] [] [] [] [][][][] []   [][]  [][] 
[]   [][] [] [][] []   []   [][][][] [][][] 
[]  [][][][] [] []  [] [] []  [] [] [] [] [] []  [] 
       [][][] [][][]  [] [][]  [][] []  [] []  [] 
    []    [][][] [] [][] [][]   [] []  [] [][] [] 
    [][]   []  []  [][][][][][]  [][] [] [] [] 
     []   [] [][][][][][][][][]   [] [] [] [] [][][] 
    [][] [][][] [] []     [][] []  [] [] [][] [] [] [] 
    [] []  []  [][] [][][][][][][] [] [][] [] [] []  [] 

[]は、生きた細胞を表し、任意の二つの白いスペースは死細胞を表しています。奇妙な部分は、コードを実行する多くの試みを通して存在する水平線と垂直線です。私はまだ予想される行動(グライダー、オシレーターなど)を見てきました。

私のコードは以下の通りです。私は助け/明確化を感謝します。前もって感謝します!

#!/usr/bin/perl 

use warnings; 
use strict; 
use Curses; 
use Time::HiRes 'usleep'; 

my $iterations = 100; 
$iterations = $ARGV[0] if @ARGV; 

initscr; 
getmaxyx(my $rows, my $columns); 
$columns = int($columns/2); 
my ($i, $j); 
my @initial_state; 
foreach $i (0 .. $rows) { 
     foreach $j (0 .. $columns) { 
       $initial_state[$i][$j] = int rand(2); 
     } 
} 

my @current_state = @initial_state; 
my @next_state; 
my $iteration; 
my ($up, $down, $right, $left); 
my $adjacent_cells; 

foreach $iteration (0 .. $iterations) { 
     foreach $i (0 .. $rows) { 
       foreach $j (0 .. $columns) { 
         $up  = ($i + 1) % $rows; 
         $down = ($i - 1) % $rows; 
         $right = ($j + 1) % $columns; 
         $left = ($j - 1) % $columns; 
         $adjacent_cells = $current_state[$i][$right] 
             + $current_state[$i][$left] 
             + $current_state[$up][$right] 
             + $current_state[$up][$left] 
             + $current_state[$down][$right] 
             + $current_state[$down][$left] 
             + $current_state[$up][$j] 
             + $current_state[$down][$j]; 
         if ($current_state[$i][$j]) { 
           $next_state[$i][$j] = $adjacent_cells == 2 || $adjacent_cells == 3 ? 1 : 0; 
           addstr($i, 2*$j, '[]'); 
         } 
         else { 
           $next_state[$i][$j] = $adjacent_cells == 3 ? 1 : 0; 
           addstr($i, 2*$j, ' '); 
         } 
       } 
     } 
     @current_state = @next_state unless $iteration == $iterations; 
     usleep 10000; 
     refresh(); 
} 

getch(); 
endwin(); 
+0

空のスペースに囲まれたグライダーの初期状態を構築しようとしましたか?または同様に簡単な何か?それは何をするためのものか? – spraff

+0

@spraffはい、私はそれを試しました。私は左上の孤独なグライダーを置き、ちょうど1回の反復の後に形を変えて(非グライダーの形に)、最後まで置いていました。 –

+0

それdef。あなたの実際の質問に対する答えではありませんが、あなたはConways Game of Lifeの[Threaded PDL](http://pdl.perl.org/?docs=Threading&title=PDL::Threading#threaded_pdl_implementation)実装を見たことがありますか? –

答えて

3

$next_state[$i][$j]を変更することも$current_state[$i][$j]$next_state[$i]ために変更$current_state[$i]と同じ参照が含まれています。

2次元配列は本当に配列の配列であるか、具体的には配列への参照の配列であることを忘れないでください。

浅いコピーの代わりにディープコピーを作成する必要があります。

@current_state = map { [ @$_ ] } @next_state; 

一部をクリーンアッププログラム全体、:

#!/usr/bin/perl 

use strict; 
use warnings; 

use Curses; 
use Time::HiRes qw(usleep); 
use List::Util qw(sum); 

my $iterations = $ARGV[0] || 100; 

initscr; 
getmaxyx(my $rows, my $cols); 
$cols = int($cols/2); 
my @initial_state; 
for my $i (0 .. $rows-1) { 
     for my $j (0 .. $cols-1) { 
       $initial_state[$i][$j] = int rand(2); 
     } 
} 

my @current_state = map { [ @$_ ] } @initial_state; 
my @next_state; 
my $iteration = 0; 
for (;;) { 
     for my $i (0 .. $rows-1) { 
       for my $j (0 .. $cols-1) { 
         addstr($i, 2*$j, $current_state[$i][$j] ? '[]' : ' '); 
       } 
     } 

     last if ++$iteration == $iterations; 

     for my $i (0 .. $rows-1) { 
       for my $j (0 .. $cols-1) { 
         my $up  = ($i + 1) % $rows; 
         my $down = ($i - 1) % $rows; 
         my $right = ($j + 1) % $cols; 
         my $left = ($j - 1) % $cols; 
         my $adjacent_cells = sum 
           $current_state[$i][$right], 
           $current_state[$i][$left], 
           $current_state[$up][$right], 
           $current_state[$up][$left], 
           $current_state[$down][$right], 
           $current_state[$down][$left], 
           $current_state[$up][$j], 
           $current_state[$down][$j]; 

         if ($current_state[$i][$j]) { 
           $next_state[$i][$j] = ($adjacent_cells == 2 || $adjacent_cells == 3) ? 1 : 0; 
         } 
         else { 
           $next_state[$i][$j] = $adjacent_cells == 3 ? 1 : 0; 
         } 
       } 
     } 

     @current_state = map { [ @$_ ] } @next_state; 

     usleep 100000; 
     refresh(); 
} 

getch(); 
endwin(); 

PS - 私はあなたがエッジの周り覗き見されなければならないとは思いません。

+2

@Artem Mavrinもう一つの解決策は '$ state [$ i] [$ j]'の代わりに '$ state [$ i * $ cols + $ j]'を使うことです。 – ikegami

4

Aha、見つかりました。

2次元配列は、実際には配列への参照の配列です。 @current_state = @next_stateを実行すると、外部配列のシャローコピーのみが作成されるため、両方の配列は同じ行配列への参照を含むことになります。

あなたの場合、修正は簡単です:ループの先頭に@next_state =()と設定してください。そうすることで、perlは新しい配列セットを自動化します。最初の反復の後

(また、あなたはおそらく、あなたが0から$rows-1$columns-1に代わりの$rows$columnsに反復しているように、あなたのループを修正したいと思います。)

関連する問題