Я создаю алгоритм для решения судоку с использованием распространения ограничений и локального поиска (аналогично Norvig). Для этого я отслеживаю списки возможных значений для каждого из квадратов в судоку. Для каждой попытки присвоить новое значение квадрату я клонирую массив и рекурсивно передаю его методу поиска алгоритма. Однако каким-то образом этот список все еще изменяется. Речь идет о методе:
List<int>[,] search(List<int>[,] vals)
{
if (vals == null)
return null;
if (isSolved(vals))
return vals;
//get square with lowest amt of possible values
int min = Int32.MaxValue;
Point minP = new Point();
for (int y = 0; y < n * n; y++)
{
for (int x = 0; x < n * n; x++)
{
if (vals[y, x].Count < min && vals[y, x].Count > 1)
{
min = vals[y, x].Count;
minP = new Point(x, y);
}
}
}
for(int i=vals[minP.Y, minP.X].Count-1; i >= 0; i--)
{
//<Here> The list vals[minP.Y, minP.X] is altered within this for loop somehow, even though the only thing done with it is it being cloned and passed to the assign method for another (altered) search afterwards
Console.WriteLine(vals[minP.Y, minP.X].Count + "-" + min);
int v = vals[minP.Y, minP.X][i];
List<int>[,] newVals = (List<int>[,])vals.Clone();
List<int>[,] l = search(assign(minP, v, newVals));
if (l != null)
return l;
}
return null;
}
Список vals[minP.Y, minP.X] каким-то образом изменяется внутри цикла for, из-за чего он в конечном итоге пытается передать методу assign квадраты, имеющие 1 (или даже 0) возможных значений. Оператор Console.Writeline показывает, что vals[minP.Y, minP.X].Count в конечном итоге будет отличаться от переменной 'min' (которая определена как то же самое над циклом for).
Если бы кто-нибудь мог помочь мне в том, как список изменяется в этом цикле for и как это исправить, я был бы очень признателен!
С наилучшими пожеланиями.
РЕДАКТИРОВАТЬ: методы, в которых редактируются эти списки (однако в клонированной версии):
List<int>[,] assign(Point p, int v, List<int>[,] vals)
{
int y = p.Y, x = p.X;
for (int i = vals[y, x].Count - 1; i >= 0; i--)
{
int v_ = vals[y, x][i];
if (v_ != v && !eliminate(p, v_, vals))
return null;
}
return vals;
}
bool eliminate(Point p, int v, List<int>[,] vals)
{
if (!vals[p.Y, p.X].Remove(v))
return true; //al ge-elimineerd
// Update peers when only 1 possible value left
if (vals[p.Y, p.X].Count == 1)
foreach (Point peer in peers[p.Y, p.X])
if(!eliminate(peer, vals[p.Y, p.X][0], vals))
return false;
else if (vals[p.Y, p.X].Count == 0)
return false;
// Update units
List<Point> vplaces = new List<Point>();
foreach (Point unit in units[p.Y, p.X])
{
if (vals[unit.Y, unit.X].Contains(v))
{
vplaces.Add(unit);
if (vplaces.Count > 1)
continue;
}
}
if (vplaces.Count == 0)
return false;
else if (vplaces.Count == 1)
{
Console.WriteLine("test");
if (assign(vplaces[0], v, vals) == null)
return false;
}
return true;
}