Unified
Split
Showing
with
95 additions
and 11 deletions.
- +7 −1 src/Grid.cpp
- +86 −9 src/Random.cpp
- +2 −1 src/Random.h
| @@ -75,9 +75,15 @@ void Grid::Random(int8 minMoves) | ||
| for (int8 index = 0; index < numButtons; index++) | ||
| buttonIndices[index] = index; | ||
|
|
||
| const int8 begin = ChooseRandom(buttonIndices, numButtons, minMoves); | ||
| int8 begin; | ||
| const int8 n = fDimension; | ||
|
|
||
| if (n == 5) { | ||
| ChooseRandom5x5(buttonIndices, minMoves); | ||
| begin = 0; | ||
| } else | ||
| begin = ChooseRandom(buttonIndices, numButtons, minMoves); | ||
|
|
||
| for (int8 i = 0; i < minMoves; i++) { | ||
| const int8 index = buttonIndices[begin + i]; | ||
|
|
||
| @@ -10,23 +10,34 @@ | ||
|
|
||
| //#define NDEBUG | ||
| #include <assert.h> // assert | ||
|
|
||
| #include <stdlib.h> // random | ||
|
|
||
|
|
||
| static void | ||
| Swap(int& a, int& b) | ||
| { | ||
| assert (a != b); | ||
| if (a == b) | ||
| return; | ||
|
|
||
| const int tmp = a; | ||
| a = b; | ||
| b = tmp; | ||
| } | ||
|
|
||
|
|
||
| // array size >= n | ||
| int ChooseRandom(int array[], int n, int k) | ||
| static bool | ||
| find(int m, int array[], int size) | ||
| { | ||
| for (int index = 0; index < size; index++) | ||
| if (m == array[index]) | ||
| return true; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
|
|
||
| int | ||
| ChooseRandom(int array[], int n, int k) // array size >= n | ||
| { | ||
| assert(k > 0 && k < n); | ||
|
|
||
| @@ -35,12 +46,78 @@ int ChooseRandom(int array[], int n, int k) | ||
| if (chooseComplement) | ||
| k = n - k; | ||
|
|
||
| for (int i = 0; i < k; i++) { | ||
| const int offset = random() % (n - i); | ||
|
|
||
| if (offset > 0) | ||
| Swap(array[i], array[i + offset]); | ||
| for (int index = 0; index < k; index++) { | ||
| assert(n - index > 1); | ||
| Swap(array[index], array[index + random() % (n - index)]); | ||
| } | ||
|
|
||
| return chooseComplement ? k : 0; | ||
| } | ||
|
|
||
|
|
||
| void | ||
| ChooseRandom5x5(int array[], int k) // array size >= 25 | ||
| { | ||
| assert(k > 0 && k <= 15); | ||
|
|
||
| // partition the 5x5 grid | ||
| int c[] = { 0, 4, 20, 24 }; // corners | ||
| int h[] = { 1, 3, 10, 11, 13, 14, 21, 23 }; // horizontal | ||
| int v[] = { 2, 5, 7, 9, 15, 17, 19, 22 }; // vertical | ||
| // int d[] = { 6, 8, 12, 16, 18 }; // diagonals | ||
|
|
||
| // initialize the corresponding counters | ||
| int C = 0; | ||
| int H = 0; | ||
| int V = 0; | ||
|
|
||
| // set the upper limits of the counters | ||
| int CMax, HMax, VMax; | ||
| switch (k) { | ||
| case 14: | ||
| CMax = 3; | ||
| HMax = VMax = 5; | ||
| break; | ||
| case 15: | ||
| CMax = 2; | ||
| HMax = VMax = 4; | ||
| break; | ||
| default: | ||
| CMax = 4; | ||
| HMax = VMax = 8; | ||
| } | ||
|
|
||
| int n = 25; // 5x5 | ||
|
|
||
| for (int index = 0; index < k;) { | ||
| assert(n - index > 0); | ||
|
|
||
| int nextIndex = index; | ||
| if (n - index > 1) | ||
| nextIndex += random() % (n - index); | ||
|
|
||
| const int m = array[nextIndex]; | ||
| bool skip = false; | ||
|
|
||
| if (find(m, c, 4)) | ||
| if (C == CMax || C + H == 6 || C + V == 6) | ||
| skip = true; | ||
| else | ||
| C++; | ||
| else if (find(m, h, 8)) | ||
| if (H == HMax || C + H == 6 || H + V == 8) | ||
| skip = true; | ||
| else | ||
| H++; | ||
| else if (find(m, v, 8)) | ||
| if (V == VMax || C + V == 6 || H + V == 8) | ||
| skip = true; | ||
| else | ||
| V++; | ||
|
|
||
| if (skip) | ||
| array[nextIndex] = array[--n]; | ||
| else | ||
| Swap(array[index++], array[nextIndex]); | ||
| } | ||
| } | ||
| @@ -1,6 +1,7 @@ | ||
| #ifndef RANDOM_H | ||
| #define RANDOM_H | ||
|
|
||
| int ChooseRandom(int array[], int n, int k); | ||
| int ChooseRandom(int array[], int n, int k); | ||
| void ChooseRandom5x5(int array[], int k); | ||
|
|
||
| #endif |