Neverending cycle happening only sometimes

时间:2015-12-14 18:13:42

标签: c# unity3d cycle

So, the problem that this program solves is filling a square matrix following some set rules. In this case, the rules are that numbers must be less than 10 and that the sum of each column or row must be equal to a certain number.

It works well on 5x5 and 6x6 matrices with target sums being 25 and 30 respectively, but, for example, at 8x8 - 40 it fails 50% of the time. The //DEBUG BREAK debug line shows that it goes infinite after successfully adding almost all (318 out of 320 or somewhere around that amount) 1s at //DEBUG FINISH.

Every iteration it takes a random row and column and, if it passes the check, adds 1 to the cell, while also checking if the row or column has been filled to the target sum and excludes the row/column from the random selection set.

The counter 'k' counts all the cycle iterations and testing shows that the program either ends up with k being only 5-10 iterations more over theoretical minimum, which is the total sum of all numbers, and that is a great result. It shows that the "excluding from selection set" part works, which, in theory, should ensure that infinite bad-luck series never happen.

SumRow just summs a specified row or column, depending on the bool value.

void Regenerate()
    {
        board = new int[boardSize, boardSize];
        int x, y;
        int i, imax = boardSize * sum;
        System.Collections.Generic.List<int> 
        hor = new System.Collections.Generic.List<int>(),
        ver = new System.Collections.Generic.List<int>();
        for (i = 0; i < boardSize; i++)
        {
            hor.Add(i);
            ver.Add(i);
        }

        i = 0;
        bool b;
        int k = 0;
        while (i < imax)
        {
            k++;
            b = true;
            x = hor[Random.Range(0, hor.Count)];
            y = ver[Random.Range(0, ver.Count)];

            if (SumRow(y, false) >= sum) { ver.Remove(y); b = false; }
            if (SumRow(x, true) >= sum) { hor.Remove(x); b = false; }
            if (b && (board[x, y] != 9))
            {
                board[x, y]++;
                i++;
            }
            if (k > 5 * i)
            {
                Debug.Log("break at " + i.ToString()); //DEBUG BREAK
                break;
            }
        }
        Debug.Log(string.Format("{0}/{1}", k, imax)); //DEBUG FINISH

        }

0 个答案:

没有答案