private void UpdateBest(List<int> xs, List<int> ys, List<int> values) { Board board2 = new Board(sizey, sizex); board2.Apply(xs, ys, values); textBox4.Lines = DrawBoard(board2); }
private void Search() { Generator g = new DancingGenerator(sizex, sizey, new Random(), 1); g.EnsureDiff = false; int loop = 0; while (true) { loop++; g.Generate(); List<int> xs = g.Xs; List<int> ys = g.Ys; List<int> values = g.Values; Board board2 = new Board(sizey, sizex); board2.MaxLookahead = 2; board2.Apply(xs, ys, values); SolveState result2 = board2.SolveWithRating(); string name = ""; if (board2.LastLookaheadUsed != 1) name = board2.LastLookaheadUsed.ToString(); else name = board2.LastLookaheadUsed.ToString() + "." + board2.Score.ToString() + "." + board2.HighTuples.ToString(); if (result2 != SolveState.Solved) { name = "Failed to solve."; } else { bool highest = true; string[] nameSplits = name.Split('.'); foreach (string key in frequency.Keys) { string[] splits = key.Split('.'); if (int.Parse(splits[0]) > int.Parse(nameSplits[0])) { highest = false; break; } else if (int.Parse(splits[0]) < int.Parse(nameSplits[0])) { continue; } else { if (splits.Length == 1) { highest = false; break; } if (int.Parse(splits[1]) > int.Parse(nameSplits[1])) { highest = false; break; } else if (int.Parse(splits[1]) < int.Parse(nameSplits[1])) { continue; } else { if (int.Parse(splits[2]) > int.Parse(nameSplits[2])) { highest = false; break; } else if (int.Parse(splits[2]) < int.Parse(nameSplits[2])) { continue; } else { highest = false; break; } } } } if (highest) { this.Invoke(new UpdateBestDelegate(UpdateBest), xs, ys, values); } } Board board = new Board(sizey, sizex); board.Apply(xs, ys, values); if (frequency.ContainsKey(name)) { frequency[name] = frequency[name] + 1; if (sample[name].Count < 100) sample[name].Add(board); } else { frequency[name] = 1; sample[name] = new List<Board>(); sample[name].Add(board); } name = "Count: " + xs.Count; if (frequency2.ContainsKey(name)) { frequency2[name] = frequency2[name] + 1; if (sample2[name].Count < 100) sample2[name].Add(board); } else { frequency2[name] = 1; sample2[name] = new List<Board>(); sample2[name].Add(board); } if ((loop & 0xF) == 0) { string result = ""; foreach (KeyValuePair<string, int> de in frequency) { result += de.Key + ":" + de.Value.ToString() + "\n"; } foreach (KeyValuePair<string, int> de in frequency2) { result += de.Key + ":" + de.Value.ToString() + "\n"; } this.Invoke(new UpdateStringDelegate(UpdateString), result); } } }
public override void Generate() { xs = new List<int>(); ys = new List<int>(); values = new List<int>(); int lastLookaheadUsed = 0; SolveState result = SolveState.MultipleSolutions; int width = sizex * sizey; int loops = 0; Board workingBoard = null; int possibilityCount = 0; List<List<int>> a = new List<List<int>>(); while (result != SolveState.Solved) { if (result == SolveState.MultipleSolutions) { if (workingBoard != null) { int rndnum = rnd.Next(possibilityCount); int i2 = a[rndnum][0]; int j2 = a[rndnum][1]; int k2 = a[rndnum][2]; bool hasOpp = width % 2 == 0 || (i2 != width / 2 || j2 != width / 2); xs.Add(i2); ys.Add(j2); values.Add(k2 + 1); if (hasOpp) { int rnd2 = rnd.Next(a[rndnum].Count - 3) + 3; int l2 = a[rndnum][rnd2]; xs.Add(width - 1 - i2); ys.Add(width - 1 - j2); values.Add(l2 + 1); } } else { int x = rnd.Next(width); int y = rnd.Next(width); int v = rnd.Next(width) + 1; xs.Add(x); ys.Add(y); values.Add(v); bool hasOpp = width % 2 == 0 || (x != width / 2 || y != width / 2); if (hasOpp) { xs.Add(width - 1 - x); ys.Add(width - 1 - y); values.Add(rnd.Next(width) + 1); } } Board board = new Board(sizey, sizex); // This line used to generate harder games. board.MaxLookahead = maxLookahead; board.Apply(xs, ys, values); result = board.Solve(); if (result == SolveState.MultipleSolutions) { workingBoard = board; a = new List<List<int>>(); possibilityCount = 0; for (int i = 0; i < width; i++) { for (int j = 0; j < width; j++) { if (workingBoard.Get(i, j) == 0) { if (workingBoard.Get(width - 1 - i, width - 1 - j) == 0) { for (int k = 0; k < width; k++) { if (workingBoard.CheckPossible(i, j, k + 1)) { List<int> aInner = new List<int>(); aInner.Add(i); aInner.Add(j); aInner.Add(k); for (int l = 0; l < width; l++) { if (workingBoard.CheckPossible(width - 1 - i, width - 1 - j, l + 1)) { aInner.Add(l); } } if (aInner.Count >= 4) { a.Add(aInner); possibilityCount++; } } } } } } } if (possibilityCount == 0) { a = new List<List<int>>(); possibilityCount = 0; for (int i = 0; i < width; i++) { for (int j = 0; j < width; j++) { if (workingBoard.Get(i, j) == 0) { for (int k = 0; k < width; k++) { if (workingBoard.CheckPossible(i, j, k + 1)) { List<int> aInner = new List<int>(); aInner.Add(i); aInner.Add(j); aInner.Add(k); for (int l = 0; l < width; l++) { if (workingBoard.CheckPossible(width - 1 - i, width - 1 - j, l + 1)) { aInner.Add(l); } } if (aInner.Count >= 4) { a.Add(aInner); possibilityCount++; } } } } } } if (possibilityCount == 0) { // Deadend, try again. Faster then walking backwards? Generate(); return; } } } lastLookaheadUsed = board.LastLookaheadUsed; } else if (result == SolveState.Unsolvable) { if (width % 2 == 0 || (xs[xs.Count - 1] != width / 2 || ys[ys.Count - 1] != width / 2)) { xs.RemoveAt(xs.Count - 1); ys.RemoveAt(ys.Count - 1); values.RemoveAt(values.Count - 1); } xs.RemoveAt(xs.Count - 1); ys.RemoveAt(ys.Count - 1); values.RemoveAt(values.Count - 1); result = SolveState.MultipleSolutions; } loops++; // if we go for a long time, try again. if (loops > width * width * width) { Generate(); return; } } if (ensureDiff && lastLookaheadUsed != maxLookahead) { Generate(); return; } }
private void Generate(int maxLookahead, Random rnd) { Generator g = new DancingGenerator(sizex, sizey, rnd, maxLookahead); g.Generate(); xs = g.Xs; ys = g.Ys; values = g.Values; /* reduction phase, takes a long time right now and for no real gain. int width = boxes.Count; for (int i = 0; i < xs.Count; i++) { List<int> xs2 = new List<int>(xs); List<int> ys2 = new List<int>(ys); List<int> values2 = new List<int>(values); if (width % 2 == 0 || (xs2[i] != width / 2 || ys2[i] != width / 2)) { if (i > 0) { if (xs2[i - 1] == width - 1 - xs2[i] && ys2[i - 1] == width - 1 - ys2[i]) { continue; } } if (i < xs.Count - 1) { if (xs2[i + 1] == width - 1 - xs2[i] && ys2[i + 1] == width - 1 - ys2[i]) { xs2.RemoveAt(i); xs2.RemoveAt(i); ys2.RemoveAt(i); ys2.RemoveAt(i); values2.RemoveAt(i); values2.RemoveAt(i); } } } else { xs2.RemoveAt(i); ys2.RemoveAt(i); values2.RemoveAt(i); } Board board = new Board(sizey, sizex); board.MaxLookahead = maxLookahead; for (int j = 0; j < xs2.Count; j++) { board.Set(xs2[j], ys2[j], values2[j]); } SolveState result = board.Solve(); if (result == SolveState.Solved) { xs = xs2; ys = ys2; values = values2; i--; } } */ // We have what we are looking for, output it and rate it. for (int i = 0; i < boxes.Count; i++) { for (int j = 0; j < boxes[i].Count; j++) { boxes[i][j].Text = string.Empty; } } for (int i = 0; i < xs.Count; i++) { boxes[xs[i]][ys[i]].Text = values[i].ToString(); } Board board2 = new Board(sizey, sizex); board2.MaxLookahead = maxLookahead; board2.Apply(xs, ys, values); textBox4.Lines = DrawBoard(board2); ; SolveState result2 = board2.SolveWithRating(); if (board2.LastLookaheadUsed != 1) textBox2.Text = board2.LastLookaheadUsed.ToString(); else textBox2.Text = board2.LastLookaheadUsed.ToString() + "." + board2.Score.ToString() + "." + board2.HighTuples.ToString(); }
public override void Generate() { xs = new List<int>(); ys = new List<int>(); values = new List<int>(); int width = sizex * sizey; int lastLookaheadUsed = 0; int loops = 0; SudokuDancingLinks dl = new SudokuDancingLinks(sizey, sizex); while (true) { int x = 0; int y = 0; bool match = true; while (match) { x = rnd.Next(width); y = rnd.Next(width); match = false; for (int i = 0; i < xs.Count; i++) { if (xs[i] == x && ys[i] == y) { match = true; break; } } } int v = rnd.Next(width) + 1; xs.Add(x); ys.Add(y); values.Add(v); bool hasOpp = width % 2 == 0 || (x != width / 2 || y != width / 2); if (hasOpp) { xs.Add(width - 1 - x); ys.Add(width - 1 - y); values.Add(rnd.Next(width) + 1); } dl.Clear(); for (int i = 0; i < xs.Count; i++) { dl.Grid[ys[i], xs[i]] = values[i]; } dl.Solve(); if (dl.Count <= 0) { if (width % 2 == 0 || (xs[xs.Count - 1] != width / 2 || ys[ys.Count - 1] != width / 2)) { xs.RemoveAt(xs.Count - 1); ys.RemoveAt(ys.Count - 1); values.RemoveAt(values.Count - 1); } xs.RemoveAt(xs.Count - 1); ys.RemoveAt(ys.Count - 1); values.RemoveAt(values.Count - 1); } else if (dl.Count == 1) { break; } loops++; // if we go for a long time, try again. if (loops > width * width * width) { Generate(); return; } } List<int> xs2 = new List<int>(xs); List<int> ys2 = new List<int>(ys); List<int> values2 = new List<int>(values); xs = new List<int>(); ys = new List<int>(); values = new List<int>(); while (xs2.Count > 0) { int choice = rnd.Next(xs2.Count); int x = xs2[choice]; int y = ys2[choice]; int v = values2[choice]; int x2 = -1; int y2 = -1; int v2 = -1; if (choice > 0 && xs2[choice - 1] == width - 1 - x && ys2[choice - 1] == width - 1 - y) { x2 = width - 1 - x; y2 = width - 1 - y; v2 = values2[choice - 1]; xs2.RemoveAt(choice - 1); xs2.RemoveAt(choice - 1); ys2.RemoveAt(choice - 1); ys2.RemoveAt(choice - 1); values2.RemoveAt(choice - 1); values2.RemoveAt(choice - 1); } else if (choice < xs2.Count - 1 && xs2[choice + 1] == width - 1 - x && ys2[choice + 1] == width - 1 - y) { x2 = width - 1 - x; y2 = width - 1 - y; v2 = values2[choice + 1]; xs2.RemoveAt(choice); xs2.RemoveAt(choice); ys2.RemoveAt(choice); ys2.RemoveAt(choice); values2.RemoveAt(choice); values2.RemoveAt(choice); } else { xs2.RemoveAt(choice); ys2.RemoveAt(choice); values2.RemoveAt(choice); } dl.Clear(); for (int i = 0; i < xs.Count; i++) { dl.Grid[ys[i], xs[i]] = values[i]; } for (int i = 0; i < xs2.Count; i++) { dl.Grid[ys2[i], xs2[i]] = values2[i]; } dl.Solve(); if (dl.Count != 1) { xs.Add(x); ys.Add(y); values.Add(v); if (x2 != -1) { xs.Add(x2); ys.Add(y2); values.Add(v2); } } } if (ensureDiff) { Board b = new Board(sizey, sizex); b.MaxLookahead = maxLookahead; b.Apply(xs, ys, values); SolveState result = b.Solve(); if (result != SolveState.Solved) { Generate(); return; } lastLookaheadUsed = b.LastLookaheadUsed; if (lastLookaheadUsed != maxLookahead) { Generate(); return; } } }