2011-07-28 4 views
2

최근 Perl에 쓴 Conway의 Game of Life의 C++ 코드를 복사하기 시작했습니다. 그리고 나는 그것을 거의 한 마디로 복사했습니다. 그러나 C++ 코드의 출력은 Perl과 크게 다릅니다. C++ 코드는 완벽하게 실행되지만 Perl 코드는 이상한 동작을합니다. 지금까지 생명의 게임을 본 사람이라면이 게임의 다음과 같은 상태가 이상한 것을 볼 수 있어야합니다Perl에서의 Game of Life - 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 네, 방금 시도했습니다. 나는 왼쪽 상단 모서리에 외로운 글라이더를 씌우고 단지 하나의 반복이 끝나면 모양을 바꾸어 (글라이더가 아닌 형태로) 끝까지 놓고 머물렀다. –

+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]을 변경

은 (는 0에서 $rows-1 대신 $rows$columns$columns-1를 반복하고 있습니다. 있도록 또한, 당신은 아마 당신의 루프를 수정하려는) $current_state[$i]과 동일한 참조를 포함합니다.

두 번째 배열은 실제로 배열 배열이거나 배열에 대한 참조 배열임을 잊지 마십시오.

얕은 복사본 대신 전체 복사본을 만들어야합니다.

#!/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 - 당신이 가장자리 주위 엿해야한다고 생각하지 않습니다

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

전체 프로그램

일부를 정리.

+2

@Artem Mavrin, 또 다른 해결책은'$ state [$ i] [$ j]'대신'$ state [$ i * $ cols + $ j]'를 사용하는 것입니다. – ikegami

4

아하, 찾았습니다.

2 차원 배열은 실제로 배열을 참조하는 배열입니다. @current_state = @next_state을 수행하면 바깥 쪽 배열의 얕은 사본 만 만들어 지므로 두 배열 모두 같은 행 배열에 대한 참조를 포함하게됩니다.

경우에 따라 수정 사항은 간단합니다. 루프 시작 부분에 @next_state =()을 설정하면됩니다. 그렇게하면 perl은 새로운 행 집합을 자동으로 초기화합니다. 또한 $current_state[$i][$j] 때문에 $next_state[$i]을 변경하는 첫 번째 반복 후