2013-11-25 3 views
-1

나는 단순한 삶의 게임을 만들었습니다.생명의 게임 -이 알고리즘은 무엇입니까

//should return true if there were any changes to any "living" state 
bool Algorithm.runOver(Cell target) 
{ 
    if (target.Occupied && !target.excluded) 
    { 
     target.Right.populate(); 
     target.Left.populate(); 
     target.Top.populate(); 
     target.Bot.populate(); 

     target.Right.excluded = true; 
     target.Left.excluded = true; 
     target.Top.excluded = true; 
     target.Bot.excluded = true; 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

제외하고 이미 알고리즘은 모든 실행이 완료 거짓 매번에 resetted되어 실행 여기에

class Cell 
{ 
    public Cell(MainWindow correspondingMainWindow){ 
     this.mainWindow = correspondingMainWindow; 
    } 

    public bool excluded; 

    public Boolean Occupied { get; set; } 

    public Control correspondingPanel; 

    private int[] coordinates; 

    private MainWindow mainWindow; 

    public int[] Coordinates 
    { 
     get { return this.coordinates; } 
     set { 
      if(value.Length != 2) 
      { 
       throw new ArgumentException(); 
      } 
      else if(value[0] < 0 || value [1] < 0 
        || value[0] > Settings.FIELDWIDTH 
        || value[1] > Settings.FIELDHEIGHT) 
      { 
       throw new ArgumentException(); 
      } 
      else{ 
       correspondingPanel = mainWindow.FieldArea.Controls 
         .Find(String.Format("panel{0}_{1}", value[0], value[1]), true) 
         .FirstOrDefault(); 
       this.coordinates = value; 
      } 
     } 

    } 

    //Surrounding Cells in the 3x3 around the current cell 
    //this is to speed up the updating as soon as the algorithm runs on many cells 
    public Cell Top { get; set; } 
    public Cell TopRight { get; set; } 
    public Cell Right { get; set; } 
    public Cell BotRight { get; set; } 
    public Cell Bot { get; set; } 
    public Cell BotLeft { get; set; } 
    public Cell Left { get; set; } 
    public Cell TopLeft { get; set; } 

    public void die() 
    { 
     this.Occupied = false; 
     this.correspondingPanel.BackColor = Color.Beige; 
    } 

    public void populate() 
    { 
     this.Occupied = true; 
     this.correspondingPanel.BackColor = Color.DarkRed; 
    } 
} 

문제의 알고리즘 : 실제 물건 일 경우

이 내 세포입니다 한 번 세포. 이것은 walkUver()의 호출을이 워크에서 업데이트 된 Cell에서 막는 것입니다.

지금 내 필드의 왼쪽 상단 모서리 (간단한 뱀 필드와 같은)에서 셀을 가져 와서 표시하고 알고리즘을 실행하면 첫 번째 실행 후 변경이 중지됩니다.

실제로 설계된 방식으로 셀을 업데이트하지만 그 다음에 중지됩니다.

나는 내 셀을 프로그램의 정적 목록에 저장한다. (나는 올바르게해야 작동 할 때까지 가장 쉬운 방법이다). 셀에는 일치시킬 패널이 있습니다. 이러한 패널은 FieldArea라는 GroupBox에 있습니다. 그들은 몇 가지 정적 상수 설정 (좌표에 대한 집합 유효성 검사에서 볼 수 있음)을 기반으로 동적으로 생성됩니다.

세포가 패널에 정확하게 일치한다고 확신합니다. 이 문제는 왼쪽 상단 (0,0)에서 오른쪽 아래까지 FieldArea를 통해 대각선에서 발생하는 것으로 보입니다. 다른 시작점이 올바르게 작동합니다. 어떻게 든 더 많은 양의 세포가 "꼭대기"에서 왔을 때 세포는 필드의 상단과 좌측 가장자리에 경계선을 형성합니다.

지금 질문 : 내가 뭘 잘못하고 있니? 내 필드가 올바르게 작동하지 않는 이유는 무엇입니까?

답변

4

"세계"를 2 부 보존해야하며, 규칙을 적용하는 동안 변경되지 않아야합니다. 규칙을 하나의 세계에만 적용하면 일부 셀은 이전 상태로, 다른 셀은 이미 새 상태로 유지되는 혼합 구성이됩니다.

private Cell[,] activeWorld = new Cell[w,h]; 
private Cell[,] hiddenWorld = new Cell[w,h]; 

Populate(activeWorld); 
while (true) { 
    Display(activeWorld); 
    ApplyRules(activeWorld, hiddenWorld); 

    // Swap worlds 
    var temp = activeWorld; 
    activeWorld = hiddenWorld; 
    hiddenWorld = temp; 
} 

방법 ApplyRules은 'activeWorld'에서 세포를 읽고 hiddenWorld에 결과를 작성해야합니다 :

따라서 이런 일을한다.


업데이트 : 실제 디자인은 지나치게 설계되었습니다. 셀이 채워 졌는지 여부를 알려주는 간단한 2-d 부울 배열이 충분해야합니다. 최적화로 시작하지 마십시오. 이것은 아마도 복잡하고 읽기 쉽고 오류가있는 코드가 될 것입니다. 대신 알고리즘과 좋은 코드 구조에주의를 기울이십시오. 나중에 성능 문제가 발생하면 문제를 분석하고 적절한 최적화를 적용하십시오. 이 경우의 95 % 이상에서 문제는 코딩 세부 사항 및 알고리즘과 관련이 없으며 I/O와 관련됩니다. 이 게임의 경우 셀을 표시하는 데 규칙 적용보다 훨씬 많은 시간이 걸릴 것입니다. 어쨌든 너무 빨라서 게임 루프에 일시 중지 기능을 추가해야합니다.

주변 셀의 색인을 가져 오는 논리를 최적화하지 마십시오. 그것은 고통의 가치가 없습니다.

한계 셀 문제를 해결하는 좋은 방법 중 하나는 세상을 감싸는 것입니다. 오른쪽에 보이지 않는 것들이 왼쪽에 다시 나타나게합니다.이를 위해 모듈러스 연산 (%)을 사용하십시오. x % N은 항상 0 ... N-1 범위의 값을 산출합니다. 당신은 X와 Y가 주어과 같이 3 × 3 셀의 좌표 좌표를 얻을 수 있습니다 :

for (int dx = -1; dx <= +1; dx++) { 
    int i = (x + dx + Width) % Width; 
    for (int dy = -1; dy <= +1; dy++) { 
     int j = (y + dy + Height) % Height; 
     bool occupied = world[i, j]; 
     ... 
    } 
} 
+ Width

+ Height 우리는 항상 양의 값을 가지고 있는지 확인하십시오.

는 위에서 언급 한 알고리즘이

불행하게도 내가 제외 된 세포

, 즉 변경되지 않았습니다 "결함"이었다

1

좋아, 여기에 약속 한대로 내 개인 윈 -의 - 주입니다. "왼쪽 상단"에서 목록을 빠져 나와 오류가 나타났습니다.

나는 제외를 die() 및 populate() 함수로 옮겼습니다. "chosing"셀이 제외되면서

public Algorithm.walkOver(Cell target) 
{ 
    if (target.Occupied && !target.excluded) 
    { 
     bool b = true; 

    //if there could no changes be made, we also have to return there were no changes... 
    //else the while loop continues forever and we lose the process :(
     if (target.Right.Occupied && target.Left.Occupied 
      && target.Bot.Occupied && target.Top.Occupied) 
     b = false; 

     if(!target.Right.Occupied) 
      target.Right.populate(); 

     if (!target.Left.Occupied) 
      target.Left.populate(); 

     if (!target.Top.Occupied) 
      target.Top.populate(); 

     if (!target.Bot.Occupied) 
      target.Bot.populate(); 

     return b; 
    } 
    else 
    { 
     return false; 
    } 
} 

가 나는 또한 while 루프의 시작으로 다시 이동 :

public void die(){ 
    this.Occupied = false; 
    this.correspondingPanel.BackColor = Color.Beige; 
    this.excluded = true; 
} 

는 또한 루프가 제대로 상처 입는 확인했다.

+0

문제가 해결되지 않으면 제 의견을 잊어주십시오. –

관련 문제