Как обновить мировой порядок, чтобы получить следующую итерацию ячеек DEAD / ALIVE - PullRequest
1 голос
/ 08 июня 2019

Я пишу код для игры жизни. С небольшим прогрессом.

Проблема не очень очевидна для меня, но у меня есть подозрение, почему я не могу повторить свой мир.

Описание того, что должен делать мой код:

В моей основной функции я объявил размеры для моего массива / мира.

массив символов field, где я могу хранить каждый элемент как DEAD или ALIVE.

объявленный массив counts, который передается функции PrintWorld, где массив хранит количество соседей, которое имеет каждая ячейка.

функция intitField(rows,cols,field), которая инициализирует мой массив field.

Наконец, у меня есть функция printWorld(rows,cols,field,counts), которая должна выполнять необходимые операции для обновления моего мира.

Краткое описание того, что printWorld делает и как оно взаимодействует с другими функциями:

Что printWorld делает:

печатает текущее используемое поле. В то время как пользователь нажимает ввод, это обеспечивается циклом while.

внутри цикла while есть функция evolve, которая должна обновлять мир каждый раз, когда пользователь нажимает ввод.

Внутри функции evolve мы найдем функцию CellNeighbour.

CellNeighbour использует массив, объявленный в моей основной функции counts[rows][cols].

Внутри CellNeighbour мы храним количество живых соседей, которые каждая ячейка имеет внутри массива counts.

Когда все живые соседи сохранены в counts, мы продолжаем с остальными evolve.

Теперь я могу использовать этот факт для того, чтобы проверить условия, налагаемые игрой жизни.

Как видно из evolve, следующая итерация ячейки готовится путем проверки условий.

Затем определяем, должна ли следующая клетка быть МЕРТВОЙ или ЖИВОЙ.

Когда все ячейки для следующего поколения определены, мы продолжаем с функцией evolve.

Теперь перейдем к функции updateWorld.

Все, что updateWorld делает, это берет все вновь сохраненные ячейки для следующего поколения и сохраняет их в массиве символов field[rows][cols].current

Таким образом, когда мы вернемся к функции printWorld, я должен получить новые значения для field[i][j].current внутри цикла while. И новое поколение клеток должно быть напечатано.

К сожалению, я не могу найти, что я делаю неправильно. Однако я подозреваю, что при вызове функций некоторые массивы теряют сохраненную информацию. Но я не могу это подтвердить.

Вы можете найти мой код ниже:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/* Constants, representation of states */
#define ALIVE 'X'
#define DEAD '.'

/* Declaration of data structure */
typedef struct{
  char current;
  char next;
} cell;

/* Declaration of functions */
void initField(const int rows, const int cols, cell field[rows][cols]);
void loadGlider(const int rows, const int cols, cell field[rows][cols]);
void loadSemaphore(const int rows, const int cols, cell field[rows][cols]);
void printWorld(const int rows, const int cols, cell field[rows][cols],int counts[rows][cols]);
void CellNeighbour(const int rows, const int cols, cell field[rows][cols], int counts[rows][cols]);
void evolve(const int rows,const int cols,cell field[rows][cols], int counts[rows][cols]);
void updateWorld(int const rows, int const cols, cell field[rows][cols]);



/* Function:    main
* Description: Start and run games, interact with the user.
* Input:       About what initial structure and whether to step or exit.
* Output:      Information to the user, and the game field in each step.
*/

int main(void) {

  const int rows = 20;
  const int cols = 20;
  cell field[rows][cols];
  int counts[rows][cols];

  initField(rows,cols, field);
  printWorld(rows,cols,field,counts);
  //CellNeighbour(rows,cols,field,counts);//test


  /*Used for testing*/
  for (int i = 0; i < rows; i++){
    for (int j = 0; j < cols; j++){
      printf("%d ", counts[i][j]);// updated in CellNeighbour
    }
    printf("\n");
  }




  return 0;
}


/* Function:    initField
* Description: Initialize all the cells to dead, then asks the user about
*              which structure to load, and finally load the structure.
* Input:       The field array and its size.
* Output:      The field array is updated.
*/

void initField(const int rows, const int cols, cell field[rows][cols]) {

  for (int r = 0 ; r < rows ; r++) {
    for (int c = 0 ; c < cols ; c++) {
      field[r][c].current = DEAD;
    }
  }

  printf("Select field spec to load ([G]lider, [S]emaphore)");


  int ch = getchar();

  /* Ignore following newline */
  if (ch != '\n') {
    getchar();
  }

  switch (ch) {
    case 'g':
    case 'G':
    loadGlider(rows, cols, field);
    break;
    case 's':
    case 'S':
    loadSemaphore(rows, cols, field);
  }
}


/* Function:    loadGlider
* Description: Inserts a glider into the field.
* Input:       The field array and its size.
* Output:      The field array is updated.
*/

void loadGlider(const int rows, const int cols, cell field[rows][cols]) {

  field[0][1].current = ALIVE;
  field[1][2].current = ALIVE;
  field[2][0].current = ALIVE;
  field[2][1].current = ALIVE;
  field[2][2].current = ALIVE;
}


/* Function:    loadSemaphore
* Description: Inserts a semaphore into the field.
* Input:       The field array and its size.
* Output:      The field array is updated.
*/

void loadSemaphore(const int rows, const int cols, cell field[rows][cols]) {

  field[8][1].current = ALIVE;
  field[8][2].current = ALIVE;
  field[8][3].current = ALIVE;
}




/* Function:    printWorld
* Description: Prints the current field
* Input:       The field array and its size.
* Output:      The field array is updated.
*/


void printWorld(const int rows, const int cols, cell field[rows][cols], int counts[rows][cols]){

  char c = '\n';

  while(c == '\n'){
    for (int i = 0; i < rows; i++) {
      for (int j = 0; j < cols; j++) {
        printf("%c ", field[i][j].current);
      }
      printf("\n");
    }
    evolve(rows,cols,field,counts);

    printf("EXIT PROGRAM PRESS ANY CHARACTERS\n");
    printf("TO GET NEXT ITERATION PRESS ENTER\n");
    c = getchar();

    if(c != '\n'){ //exits the loop
      break;
    }

  }
}

void evolve(const int rows,const int cols,cell field[rows][cols], int counts[rows][cols]){

  CellNeighbour(rows, cols,field,counts);

  for(int i = 0;i<rows;i++){
    for(int j =0;j<cols;j++){
        if (field[i][j].current == ALIVE && counts[i][j] == 2){
    field[i][j].next = ALIVE;
  }
  else if (counts[i][j] == 3){
    field[i][j].next = ALIVE;
  }
  else{
    field[i][j].next = DEAD;
  }
}


    //Updating the next iteration, below:

    updateWorld(rows, cols, field);

  }
}



  void CellNeighbour(const int rows, const int cols, cell field[rows][cols], int counts[rows][cols]){

    int i,j;


    for(i = 0;i<rows;i++){
      for(j =0;j<cols;j++){
        counts[i][j] =0;
      }
    }

    for( i =0;i<rows;i++){
      for( j = 0;j<cols;j++){
        if(i>0 && j>0){
          if(field[i-1][j-1].current == ALIVE){
            counts[i][j]++;
          }
        }
        if(j>0){
          if(field[i][j-1].current == ALIVE){
            counts[i][j]++;
          }
        }
        if(j>0){
          if(field[i+1][j-1].current == ALIVE){
            counts[i][j]++;
          }
        }
        if(i<rows-1){
          if(field[i+1][j].current == ALIVE){
            counts[i][j]++;
          }
        }
        if(i <rows-1 && j <cols-1){
          if(field[i+1][j+1].current == ALIVE){
            counts[i][j]++;
          }
        }
        if(j<cols-1){
          if(field[i][j+1].current == ALIVE){
            counts[i][j]++;
          }
        }
        if(i>0 && j<cols-1){
          if(field[i-1][j+1].current == ALIVE){
            counts[i][j]++;
          }
        }
        if(i>0){
          if(field[i-1][j].current == ALIVE){
            counts[i][j]++;
          }
        }
      }
    }
  }

  void updateWorld(int const rows, int const cols, cell field[rows][cols]){

    for(int i = 0;i<rows;i++){
      for(int j =0;j<cols;j++){
        field[i][j].current = field[i][j].next;
      }
    }
  }

Когда printworld печатает начальное поле. Скажем, мы выбрали поле спецификации Glider, которое инициализирует поле с координатами:

  field[0][1].current = ALIVE;
  field[1][2].current = ALIVE;
  field[2][0].current = ALIVE;
  field[2][1].current = ALIVE;
  field[2][2].current = ALIVE;

Я получаю:

. X . . . . . . . . . . . . . . . . . .
. . X . . . . . . . . . . . . . . . . .
X X X . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .

Итак, после того, как клетки эволюционировали (обновились), я должен получить:

. . x . . . . . . . . . . . . . . . . . .
X . X . . . . . . . . . . . . . . . . .
. X X . . . . . . . . . . . . . . . . .
. X . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .

Вот видео, которое я получаю, когда инициализирую поле со спецификацией планера:

https://streamable.com/rvbzw

Однако он должен «скользить» из верхнего левого угла экрана в нижний правый угол.

Есть идеи, почему это происходит?

...