Skip to main content
Code Review

Return to Answer

Add links to what I consider beautiful implementations of Game of Life in Java and Kotlin
Source Link

Your program is actually NOT an implementation of Game of Life, because your universe is finite. The universe size is limited to ×ばつ20, which is very tiny. A good implementation of Game of Life would feature a Universe of size ×ばつ232 which is still finite but feels infinite for practical purposes. Think of a differendifferent data structure. Instead of managing the entire space-time continuum of the Game of Life universe, manage only the matter. Stop caring about dead cells, care about life cells only.

@Test
public void testBlinker() {
 final Universe blinkerFrame1 = Universe.parse(".*\n.*\n.*");
 final Universe blinkerFrame2 = Universe.pasreparse("...\n***");
 assertEquals(blinkerFrame2, blinkerFrame1.iterate());
 assertEquals(blinkerFrame1, blinkerFrame2.iterate());
}

Use braces as an opportunity to extract.

Links

Here's what I consider beautiful implementations of Game of Life:

Your program is actually NOT an implementation of Game of Life, because your universe is finite. The universe size is limited to ×ばつ20, which is very tiny. A good implementation of Game of Life would feature a Universe of size ×ばつ232 which is still finite but feels infinite for practical purposes. Think of a differen data structure. Instead of managing the entire space-time continuum of the Game of Life universe, manage only the matter. Stop caring about dead cells, care about life cells only.

@Test
public void testBlinker() {
 final Universe blinkerFrame1 = Universe.parse(".*\n.*\n.*");
 final Universe blinkerFrame2 = Universe.pasre("...\n***");
 assertEquals(blinkerFrame2, blinkerFrame1.iterate());
 assertEquals(blinkerFrame1, blinkerFrame2.iterate());
}

Use braces as an opportunity to extract.

Your program is actually NOT an implementation of Game of Life, because your universe is finite. The universe size is limited to ×ばつ20, which is very tiny. A good implementation of Game of Life would feature a Universe of size ×ばつ232 which is still finite but feels infinite for practical purposes. Think of a different data structure. Instead of managing the entire space-time continuum of the Game of Life universe, manage only the matter. Stop caring about dead cells, care about life cells only.

@Test
public void testBlinker() {
 final Universe blinkerFrame1 = Universe.parse(".*\n.*\n.*");
 final Universe blinkerFrame2 = Universe.parse("...\n***");
 assertEquals(blinkerFrame2, blinkerFrame1.iterate());
 assertEquals(blinkerFrame1, blinkerFrame2.iterate());
}

Use braces as an opportunity to extract.

Links

Here's what I consider beautiful implementations of Game of Life:

Source Link

Unicode - nice

I see you directly use Unicode. I like that.

Incorrect solution

Your program is actually NOT an implementation of Game of Life, because your universe is finite. The universe size is limited to ×ばつ20, which is very tiny. A good implementation of Game of Life would feature a Universe of size ×ばつ232 which is still finite but feels infinite for practical purposes. Think of a differen data structure. Instead of managing the entire space-time continuum of the Game of Life universe, manage only the matter. Stop caring about dead cells, care about life cells only.

Test

Your program lacks testing, which I can see from the next point.

Do not use static for mutable fields

You have static variables which are not final, which means that your program has only one shared mutable state. Holding mutable state is one of the things for which OO languages like Java provide objects.

Use the power of enum

enums aren't mere enumarations of constants. In other languages they are. In Java, enums are special classes, which describe a predefined, finite, immutable set of objects (as opposed to a normal class which describes a set of objects which is not predefined, infinite and mutable). In this case you could give enum Cell a toString() method which would return the cell symbol. Then you would not need a switch in printBoard().

In general, switch statements (and if statements that are switch statements in disguise) indicate a lack of OO-design. Often, they can be replaced with polymorphism.

You could even create an abstract method in Cell which generates the next cell based on the number of life neighbors and implemented it differently for alive and dead cells.

Separate the construction of output from the actual output

Method printBoard() is doing two things and thus difficult to test (and a bit inefficient):

  • It constructs the output.
  • It prints the output.

Consider separating these two things. Create one method which constructs the output, maybe using a StringBuilder. And the other method would only print the output. It will give you two benefits:

  • The program will be faster (which probably is no concern here).
  • The program will be easier to test.

Use the same format for input as for output

Currently, you use coordinates for input and a Unicode-Art representation of the universe for output. That means the program's output cannot be fed into the program as input again. Imagine how a test could look like if the output can be fed back to the program as input.

JUnit Example

@Test
public void testBlinker() {
 final Universe blinkerFrame1 = Universe.parse(".*\n.*\n.*");
 final Universe blinkerFrame2 = Universe.pasre("...\n***");
 assertEquals(blinkerFrame2, blinkerFrame1.iterate());
 assertEquals(blinkerFrame1, blinkerFrame2.iterate());
}

Gherkin / Cucumber Example

Given the following Universe:
 """
 .*.
 .*.
 .*.
 """
When iterating it once,
Then it MUST be equal to this:
 """
 ...
 ***
 ...
 """

Long main() method

The main() method is quite long. You could split it into a method that reads the Universe from the input, and a method which loops for the generations. The method which loops for the generations should then also be split.

Use braces as an opportunity to extract.

lang-java

AltStyle によって変換されたページ (->オリジナル) /