/Demos/C#/NQueens/Board.cs

http://swingamesdk.googlecode.com/ · C# · 328 lines · 239 code · 72 blank · 17 comment · 37 complexity · 36a9ec7823ecd7d693798e5241fecb3c MD5 · raw file

  1. using System;
  2. using System.Text;
  3. using System.Drawing;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using SwinGame;
  7. using Graphics = SwinGame.Graphics;
  8. using Bitmap = SwinGame.Bitmap;
  9. using Font = SwinGame.Font;
  10. using FontStyle = SwinGame.FontStyle;
  11. using Event = SwinGame.Event;
  12. using CollisionSide = SwinGame.CollisionSide;
  13. using Sprite = SwinGame.Sprite;
  14. using Queen = GameProject.Queen;
  15. using GameResources;
  16. namespace GameProject
  17. {
  18. public class Board : IEnumerable<Queen>
  19. {
  20. public readonly Random Rand = new Random();
  21. public readonly int NumQueens;
  22. public readonly Queen[] Queens;
  23. public readonly Color QueenColor;
  24. public readonly Diagonal[][] Diagonals;
  25. public readonly DateTime Start;
  26. public int CurrentConflicts;
  27. public Board(int n)
  28. {
  29. Start = DateTime.Now;
  30. QueenColor = Core.GetColor(255, 255, 255, 120);
  31. Queens = new Queen[n];
  32. NumQueens = n;
  33. jIdx = NumQueens;
  34. rowsChecked = new bool[NumQueens];
  35. Diagonals = new Diagonal[2][];
  36. for(int i = 0; i < 2; i++)
  37. {
  38. Diagonals[i] = new Diagonal[2 * NumQueens - 1];
  39. for(int j = 0; j < 2 * NumQueens - 1; j++)
  40. {
  41. Diagonals[i][j] = new Diagonal();
  42. Diagonals[i][j].Queens = 0;
  43. }
  44. }
  45. int[] rows = new int[NumQueens];
  46. for(int i = 0; i < NumQueens; i++)
  47. {
  48. rows[i] = i;
  49. }
  50. for(int i = 0; i < NumQueens; i++)
  51. {
  52. int j = Rand.Next(NumQueens);
  53. int temp = rows[j];
  54. rows[j] = rows[i];
  55. rows[i] = temp;
  56. }
  57. for(int i = 0; i < NumQueens; i++)
  58. {
  59. Queens[i] = new Queen(this, i, rows[i]);
  60. if(i % 100 == 0)
  61. {
  62. Graphics.ClearScreen();
  63. Text.DrawText("" + (int)(i / (float)NumQueens * 100) + "% Loaded", Color.White, Resources.GameFont("Courier"), 10, 400);
  64. Core.RefreshScreen();
  65. Core.ProcessEvents();
  66. if(Core.WindowCloseRequested()) return;
  67. }
  68. }
  69. CurrentConflicts = TotalConflicts;
  70. }
  71. public Diagonal[] PositiveDiagonal
  72. {
  73. get { return Diagonals[0]; }
  74. }
  75. public Diagonal[] NegativeDiagonal
  76. {
  77. get { return Diagonals[1]; }
  78. }
  79. public IEnumerator<Queen> GetEnumerator()
  80. {
  81. foreach(GameProject.Queen q in Queens) yield return q;
  82. }
  83. IEnumerator IEnumerable.GetEnumerator()
  84. {
  85. foreach(GameProject.Queen q in Queens) yield return q;
  86. }
  87. public Queen this[int idx]
  88. {
  89. get
  90. {
  91. return Queens[idx];
  92. }
  93. }
  94. public void Draw()
  95. {
  96. Graphics.ClearScreen();
  97. foreach(Queen q in this)
  98. {
  99. int conflicts = q.Conflicts;
  100. int x, y;
  101. x = (int)((q.Column / (float)NumQueens) * 800);
  102. y = (int)((q.Row / (float)NumQueens) * 800);
  103. switch(conflicts)
  104. {
  105. case 0: Graphics.DrawPixel(QueenColor, x, y); break;
  106. case 1: Graphics.DrawPixel(Color.Yellow, x, y); break;
  107. case 2: Graphics.DrawPixel(Color.Green, x, y); break;
  108. case 3: Graphics.DrawPixel(Color.Purple, x, y); break;
  109. default: Graphics.DrawPixel(Color.Red, x, y); break;
  110. }
  111. }
  112. }
  113. private int AtQueen = -1; //will do ++ before first check
  114. private int jIdx;
  115. private int steps = 0;
  116. private Queen NextQueen()
  117. {
  118. jIdx++;
  119. if (jIdx % 1000 == 0) Console.Write(".");
  120. if(jIdx >= NumQueens)
  121. {
  122. steps++;
  123. AtQueen = (AtQueen + 1) % (NumQueens - 1);
  124. jIdx = AtQueen + 1;
  125. Console.WriteLine("\nStep {0}", steps);
  126. }
  127. return Queens[AtQueen];
  128. }
  129. private Queen NextConflictingQueen()
  130. {
  131. if(CurrentConflicts <= 0) return null;
  132. AtQueen = (AtQueen + 1) % NumQueens;
  133. //Console.WriteLine("Conflicts = {0} == {1}", CurrentConflicts, TotalConflicts);
  134. while(Queens[AtQueen].Conflicts == 0)
  135. {
  136. AtQueen = (AtQueen + 1) % NumQueens;
  137. }
  138. steps++;
  139. if(steps % 100 == 0)
  140. Console.Write(".");
  141. return Queens[AtQueen];
  142. }
  143. private Queen NextQueen2()
  144. {
  145. if(CurrentConflicts <= 0) return null;
  146. if (AtQueen > -1) return Queens[AtQueen];
  147. //Console.WriteLine("Conflicts = {0} == {1}", CurrentConflicts, TotalConflicts);
  148. ResetRowsChecked();
  149. FindMostConflicts();
  150. AtQueen = 0;
  151. while(Queens[AtQueen].Conflicts == 0)
  152. {
  153. AtQueen = (AtQueen + 1);
  154. }
  155. steps++;
  156. Console.Write(".");
  157. return Queens[AtQueen];
  158. }
  159. private bool[] rowsChecked;
  160. private void ResetRowsChecked()
  161. {
  162. for(int r = 0; r < NumQueens; r++) rowsChecked[r] = false;
  163. }
  164. public void StepToSolution()
  165. {
  166. if(CurrentConflicts == 0) return;
  167. Queen q = NextQueen2();
  168. int rowToSwap = q.BestRowToMoveTo(rowsChecked, out AtQueen);
  169. int otherIdx = -1;
  170. int startConflicts = q.Conflicts;
  171. /* for(int r = 0; r < NumQueens; r++)
  172. {
  173. if (r == AtQueen) continue;
  174. if (Queens[r].Row == rowToSwap)
  175. {
  176. otherIdx = r;
  177. break;
  178. }
  179. }
  180. */
  181. q.RemoveQueen();
  182. q.PutQueenBackAt(rowToSwap);
  183. rowsChecked[rowToSwap] = true;
  184. //AtQueen = otherIdx;
  185. CurrentConflicts -= (startConflicts - q.Conflicts) * 2;
  186. if(CurrentConflicts == 0)
  187. {
  188. Console.WriteLine("At solution in {0} seconds", DateTime.Now.Subtract(Start).TotalSeconds);
  189. }
  190. }
  191. public void StepToSolutionBestSwap()
  192. {
  193. if(CurrentConflicts == 0) return;
  194. Queen qi = NextConflictingQueen();
  195. qi.DoBestSwap();
  196. if(CurrentConflicts == 0)
  197. {
  198. Console.WriteLine("At solution in {0} seconds", DateTime.Now.Subtract(Start).TotalSeconds);
  199. }
  200. }
  201. public void StepToSolutionGradient()
  202. {
  203. if(CurrentConflicts == 0) return;
  204. int start, current;
  205. Queen qi = NextQueen();
  206. Queen qj = Queens[jIdx];
  207. if(qi.Conflicts > 0 || qj.Conflicts > 0)
  208. {
  209. start = qi.Conflicts + qj.Conflicts;
  210. qi.SwapWith(qj);
  211. current = qi.Conflicts + qj.Conflicts;
  212. if(start <= current)
  213. {
  214. //Not a good swap
  215. qi.SwapWith(qj); //reverse swap
  216. }
  217. else
  218. {
  219. //Get new conflicts
  220. CurrentConflicts -= (start - current) * 2;
  221. //Console.WriteLine("Conflicts = {0} == {1}", CurrentConflicts, TotalConflicts);
  222. //Console.WriteLine("Start = {0} Current = {1}", start, current);
  223. }
  224. }
  225. }
  226. public int TotalConflicts
  227. {
  228. get
  229. {
  230. int result = 0;
  231. foreach(Queen q in this) result += q.Conflicts;
  232. return result;
  233. }
  234. }
  235. public int QueenAtRow(int r)
  236. {
  237. for(int i = 0; i < NumQueens; i++) if (Queens[i].Row == r) return i;
  238. return -1;
  239. }
  240. private int FindMostConflicts()
  241. {
  242. int max = 0;
  243. Queen result = Queens[0];
  244. int ret = -1;
  245. for(int i = 1; i < NumQueens; i++)
  246. {
  247. if (Queens[i].Conflicts > max)
  248. {
  249. ret = i;
  250. max = Queens[i].Conflicts;
  251. }
  252. }
  253. return ret;
  254. }
  255. }
  256. }