| C:\upload\java\Life\source\java\RepeatPattern.java |
/******************************************************************* This class, *RepeatPattern*, has a routine < DoesThePatternRepeat > which compares the present board with the boards of as far as NUMBER_OF_OLDBOARDS generations ago to see if they are the same. If so, it returns true, otherwise false. This class has two routines: one to determine if we are in a repeating pattern, and another to set up the graphics telling the user that we are in a repeating pattern. ******************************************************************** */ import java.awt.Graphics; import java.awt.*; import java.awt.event.*; final class RepeatPattern implements Constants, Strings { private Vars vars; private int period; /* When a repeating pattern is found, this will hold the period of the pattern. */ private PopupWindow error; // For exceptions. /******************************************************************* Constructor follows: ******************************************************************** */ RepeatPattern(Frame parentFrame, Objects objects) { String errorString = ((parentFrame != null) && (objects != null)) ? NULL_STRING : "parentFrame = " + parentFrame + " objects = " + objects; if (!errorString.equals(NULL_STRING)) { System.out.println("Error, null pointer, RepeatPattern " + errorString); return; } this.vars = vars; error = new PopupWindow(parentFrame, objects.GetScreenLocations(), ERROR_WINDOW_NAME); period = PATTERN_DOES_NOT_REPEAT; // If used, it will change. } /******************************************************************* The next boolean function, < DoesThePatternRepeat >, compares the present board with the boards of as far as NUMBER_OF_OLDBOARDS generations ago to see if they are the same. If so, it returns a "true"; if not, a "false." Because of the modular arithmetic, this is one of the harder-to-understand routines. Read carefully. ******************************************************************** */ protected final boolean DoesThePatternRepeat(int [][][] oldBoards, int [][] currentBoard, int generation, int rows, int columns) { period = PATTERN_DOES_NOT_REPEAT; // If used, will change. int i, j, k; /* Loop variables. We need three of them, as < k > will loop through old boards stored in the array < oldboards >, and the others will loop through < currentBoard > comparing it to the current old board under consideration. */ i = j = k = 0; /* Avoid "not initialized" hassles with the below try-catch clause. */ boolean repeat = true; /* What we ultimately return. Avoid "not initialized" hassles with the below try-catch clause. */ /* We loop on kIndex (see k) through all the old boards stored in the 3-D array */ int kIndex = 0; /* The loop really goes from 1 -- 99, then 0. See below note. */ try // We are referencing several arrays. Be careful. { // Note below test! // || // || // \/ kLoop: for (k = 1; k <= oldBoards.length; k++)// See next comment. /* Note loop goes to oldboards.length. This seemingly obvious "Programming 101" error is no error at all: we do not use k for oldboard's index; we use < kIndex > and oldboards.length will become kIndex = 0 (zero) (see next line). */ { kIndex = k % oldBoards.length;/* See above comment on the "Programming 101" error. */ repeat = true; // Assume the pattern repeats. Set // false if no match // in oldboards[k][][]. iLoop: for (i = 1; i <= rows; i++) // Loop starts at 1. { for (j = 1; j <= columns; j++) // Loop starts at 1. { if (oldBoards[kIndex][i][j] != currentBoard[i][j])// Difference? { repeat = false; /* We initially assume the pattern repeating. We have found a difference. */ break iLoop; /* Doesn't repeat. Don't waste CPU time going further. */ } // End "if (there is a difference)" clause. } // End j-loop } // End i-loop if (repeat) // The last pattern was found repeating. { break kLoop; // Get out. The pattern repeats. } } // End k-loop } // End try clause catch (ArrayIndexOutOfBoundsException e) // Array index out of // bounds!? { String errorStr = e.getMessage(); errorStr = errorStr + ARRAY_BOUNDS_EXCEPTION + ", routine " + "DoesThePatternRepeat: " + ROWS + " = " + rows + ", " + COLUMNS + " = " + columns + ", i = " + i + ", " + AND + " j = " + j; error.ShowMessage(errorStr, OK); } if (repeat) /* If the result is false, then the current pattern at least hasn't been found to be repeating and the next block is not executed; otherwise it repeats. */ { /* If we execute this code we know the pattern to be repeating, and it's the kIndex-th board of array *oldboards*. However, we have to determine the period of the pattern. */ /* Now to document what's happening in the next line. We do the example of < oldBoards.length = 5 >. Spit out some generation numbers followed by their remainders mod 5 (the boards where those generations are held): Assume a pattern repeats every three boards. generation: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ... kIndex, and rem. (mod 5): 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 ... Assume we are on the 4th board. The last the repetition was board 1. We set < period > = 4 - 1 = 3. If we are on the 15th board, the last repetition was the 12th. This means that it is stored in *oldboards*[2][][]; see above numbers; < kIndex > = 2. Thus 15%5 = 0; 12 + 3 = 15. If we are on the 11th board, the last repetition was on the 8th board (kIndex = 3). Think about it. All other examples are similar. */ int count; for (count = 1; count <= oldBoards.length; count++) { if ((kIndex + count)%oldBoards.length == generation%oldBoards.length) { break; } } if (count == oldBoards.length + 1) { error.ShowMessage(UNRECOVERABLE_ERROR + " in " + " < RepeatPattern DoesThePatternRepeat() >: " + PERIOD_NOT_PROPERLY_SET, OK); } else { period = count; } /* Parameter < period > is returned to caller in routine < GetPeriod() > below. */ } return repeat; // Does the pattern repeat? Tell caller. } // End of the routine < DoesThePatternRepeat >. /******************************************************************* The next routine, < getPeriod >, tells the caller the period of a repeating pattern. ******************************************************************** */ protected final int GetPeriod() { return period; } } // End class < RepeatPattern >