数据结构

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace 拼图
  8. {
  9.  
  10. /// <summary>
  11. /// 空格移动的方向
  12. /// </summary>
  13. enum Direction
  14. {
  15. None,
  16. Up,
  17. Left,
  18. Right,
  19. Down
  20. }
  21.  
  22. /// <summary>
  23. /// 解答
  24. /// </summary>
  25. enum Answer
  26. {
  27. /// <summary>
  28. /// 不存在解答
  29. /// </summary>
  30. NotExist,
  31. /// <summary>
  32. /// 存在解答
  33. /// </summary>
  34. Exist,
  35. /// <summary>
  36. /// 在当前指定的搜索深度内不存在解答(需要扩大深度)
  37. /// </summary>
  38. NotExistInDepth
  39. }
  40.  
  41. /// <summary>
  42. /// 局面状态信息
  43. /// </summary>
  44. class StateMsg
  45. {
  46. private int depth;
  47. private Direction dir;
  48. public int Depth
  49. {
  50. get { return depth; }
  51. }
  52. public Direction Dir
  53. {
  54. get { return dir; }
  55. }
  56.  
  57. public StateMsg(int depth, Direction dir)
  58. {
  59. this.depth = depth;
  60. this.dir = dir;
  61. }
  62. }
  63.  
  64. /// <summary>
  65. /// 局面状态
  66. /// </summary>
  67. class State : StateMsg
  68. {
  69. private long code;
  70.  
  71. /// <summary>
  72. /// 棋盘的编码
  73. /// </summary>
  74. public long Code
  75. {
  76. get { return code; }
  77. set { code = value; }
  78. }
  79.  
  80. public State(long code, int depth, Direction dir)
  81. : base(depth, dir)
  82. {
  83. this.code = code;
  84. }
  85. }
  86. }

Astar类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace 拼图
  8. {
  9. class AStar
  10. {
  11.  
  12. /// <summary>
  13. /// ten[i]代表10的i次方
  14. /// </summary>
  15. private static readonly long[] tens = { , , , , , , , , , };
  16.  
  17. /// <summary>
  18. /// 不是合理的编码
  19. /// </summary>
  20. private const int OutOfCode = -;
  21.  
  22. /// <summary>
  23. /// 标志是否找到目标状态的编码
  24. /// </summary>
  25. public const int WinnerCode = ;
  26.  
  27. private Direction[][] dirs;
  28.  
  29. private int startBoard;
  30. private static int endBoard;
  31. private static int[] endBoardArray;
  32.  
  33. private int MaxDepth;
  34.  
  35. private SortedList<long, StateMsg> openList;
  36. private Dictionary<long, StateMsg> boardtable;
  37.  
  38. private const long maxNodes = ; //至多搜索的结点数=最大局面状态数量:(9!)=362880;
  39.  
  40. private long nodes;
  41. private int same;
  42. private float time;
  43. private Direction[] result;
  44.  
  45. /// <summary>
  46. /// 已经访问的结点数量
  47. /// </summary>
  48. public long Nodes
  49. {
  50. get { return nodes; }
  51. }
  52.  
  53. /// <summary>
  54. /// 重复访问相同结点的数量
  55. /// </summary>
  56. public int Same
  57. {
  58. get { return same; }
  59. }
  60.  
  61. public float Time
  62. {
  63. get { return time; }
  64. }
  65.  
  66. public static int N;
  67.  
  68. /// <summary>
  69. /// 最终结果
  70. /// </summary>
  71. public Direction[] Result
  72. {
  73. get { return result; }
  74. }
  75.  
  76. public AStar(int n)
  77. {
  78. N = n;
  79. dirs = new Direction[n*n][];
  80. if(n==)
  81. {
  82. dirs[] = new Direction[] { Direction.Right, Direction.Down };
  83. dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Down };
  84. dirs[] = new Direction[] { Direction.Left, Direction.Down };
  85. dirs[] = new Direction[] { Direction.Up, Direction.Right, Direction.Down };
  86. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
  87. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Down };
  88. dirs[] = new Direction[] { Direction.Up, Direction.Right };
  89. dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Up };
  90. dirs[] = new Direction[] { Direction.Up, Direction.Left };
  91. }
  92. else
  93. {
  94. dirs[] = new Direction[] { Direction.Right, Direction.Down };
  95. dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Down };
  96. dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Down };
  97. dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Down };
  98. dirs[] = new Direction[] { Direction.Left, Direction.Down };
  99. dirs[] = new Direction[] { Direction.Up, Direction.Right, Direction.Down };
  100.  
  101. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
  102. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
  103. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
  104.  
  105. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Down };
  106. dirs[] = new Direction[] { Direction.Up, Direction.Right, Direction.Down };
  107.  
  108. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
  109. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
  110. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
  111.  
  112. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Down };
  113. dirs[] = new Direction[] { Direction.Up, Direction.Right, Direction.Down };
  114.  
  115. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
  116. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
  117. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
  118.  
  119. dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Down };
  120. dirs[] = new Direction[] { Direction.Up, Direction.Right };
  121. dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Up };
  122. dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Up };
  123. dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Up };
  124. dirs[] = new Direction[] { Direction.Up, Direction.Left };
  125. }
  126.  
  127. }
  128.  
  129. /// <summary>
  130. /// 求与目标位置不同的个数(不计空格,因此返回值0~8)
  131. /// </summary>
  132. /// <param name="curboard"></param>
  133. /// <returns></returns>
  134. public static int Different(int curboard)
  135. {
  136. int t_start = curboard;
  137. int emp_start = curboard % ;
  138. int ev = ;
  139. //写2个for是为了减少9个if
  140. for (int i = N*N; i > emp_start; i--)
  141. {
  142. t_start /= ;
  143. if (t_start % != endBoardArray[i])
  144. ev++;
  145. }
  146. for (int i = emp_start - ; i >= ; i--)
  147. {
  148. t_start /= ;
  149. if (t_start % != endBoardArray[i])
  150. ev++;
  151. }
  152. return ev;
  153. }
  154.  
  155. public static int getBoard(long code)
  156. {
  157. return (int)(code % tens[]);
  158. }
  159.  
  160. private static int getEval(long code)
  161. {
  162. return (int)(code / tens[]);
  163. }
  164.  
  165. private static int getEmpIndex(long code)
  166. {
  167. return (int)(code % );
  168. }
  169.  
  170. private static long combinCode(int board, int eval)
  171. {
  172. long codehead = eval * tens[];
  173. return codehead + board;
  174. }
  175.  
  176. /// <summary>
  177. /// 改变局面(移动空格)
  178. /// </summary>
  179. /// <param name="code"></param>
  180. /// <param name="dir"></param>
  181. public static long change(long code, Direction dir)
  182. {
  183. int newboard;
  184. int eval;
  185. int num;
  186. int t0;
  187. long t1;
  188. long t2;
  189. switch (dir)
  190. {
  191. case Direction.Left:
  192. newboard = getBoard(code) - ;
  193. if (newboard == endBoard)
  194. return WinnerCode;
  195. eval = Different(newboard);
  196. return combinCode(newboard, eval);
  197. case Direction.Right:
  198. newboard = getBoard(code) + ;
  199. if (newboard == endBoard)
  200. return WinnerCode;
  201. eval = Different(newboard);
  202. return combinCode(newboard, eval);
  203. case Direction.Up:
  204. num = getBoard(code);
  205. t0 = N*N - num % + ;
  206. t1 = num / tens[t0];
  207. t2 = t1 % ;
  208. t1 = t1 - t2 + (t2 % ) * + t2 / ;
  209. t1 *= tens[t0];
  210. newboard = (int)(t1 + ((num % tens[t0]) - N));
  211. if (newboard == endBoard)
  212. return WinnerCode;
  213. eval = Different(newboard);
  214. return combinCode(newboard, eval);
  215. case Direction.Down:
  216. num = getBoard(code);
  217. t0 = N*N - num % + - N;//跟Up不同的地方
  218. t1 = num / tens[t0];
  219. t2 = t1 % ;
  220. t1 = t1 - t2 + (t2 % ) * + t2 / ;//跟Up不同的地方
  221. t1 *= tens[t0];
  222. newboard = (int)(t1 + ((num % tens[t0]) + N));//跟Up不同的地方
  223. if (newboard == endBoard)
  224. return WinnerCode;
  225. eval = Different(newboard);
  226. return combinCode(newboard, eval);
  227. }
  228. return OutOfCode;
  229. }
  230.  
  231. /// <summary>
  232. /// 恢复上一步的局面
  233. /// </summary>
  234. /// <param name="code"></param>
  235. /// <param name="dir"></param>
  236. public long unchange(long code, Direction dir)
  237. {
  238. return change(code, (Direction)( - dir));
  239. }
  240.  
  241. /// <summary>
  242. /// 当找到目标时,从哈希表里找原来的路径
  243. /// </summary>
  244. /// <param name="endCode"></param>
  245. /// <param name="depth"></param>
  246. private void setResult(long endCode, Direction curDir, Direction lastDir, int depth)
  247. {
  248. long lastCode = endCode;
  249. result = new Direction[depth];
  250. result[depth - ] = curDir;
  251. for (int i = depth - ; i >= ; i--)
  252. {
  253. if (boardtable.ContainsKey(lastCode))
  254. {
  255. result[i] = boardtable[lastCode].Dir;
  256. lastCode = unchange(lastCode, result[i]);
  257. }
  258. else
  259. return;
  260. }
  261. }
  262.  
  263. //本算法的核心部分
  264. #region 带Open表和HashTable的最好优先搜索(每次扩展Open表后都对Open表排序)
  265.  
  266. /// <summary>
  267. /// 扩展Open表
  268. /// </summary>
  269. /// <param name="board"></param>
  270. /// <param name="depth"></param>
  271. private bool extentOpenList(long code, Direction lastDir, int depth)
  272. {
  273. int empIndex = (int)(code % - );
  274. int len_moves = dirs[empIndex].Length;
  275. long newcode;
  276. Direction dir = - lastDir;
  277. for (int i = ; i < len_moves; i++)
  278. if (dirs[empIndex][i] != dir)
  279. {
  280. newcode = change(code, dirs[empIndex][i]);
  281.  
  282. //跟目标匹配,结束
  283. if (newcode == WinnerCode)
  284. {
  285. setResult(code, dirs[empIndex][i], lastDir, depth);
  286. return true;
  287. }
  288. if (newcode <= tens[])
  289. throw new Exception("棋盘码修改错误! ");
  290. if (newcode != OutOfCode)
  291. {
  292. if (!openList.ContainsKey(newcode))
  293. {
  294. if (!boardtable.ContainsKey(newcode))
  295. openList.Add(newcode, new StateMsg(depth, dirs[empIndex][i]));
  296. else
  297. {
  298. same++;
  299. if (depth < boardtable[newcode].Depth)
  300. {
  301. boardtable.Remove(newcode);
  302. openList.Add(newcode, new StateMsg(depth, dirs[empIndex][i]));
  303. }
  304. }
  305. }
  306. else
  307. {
  308. same++;
  309. if (depth < openList[newcode].Depth)
  310. openList[newcode] = new StateMsg(depth, dirs[empIndex][i]);
  311. }
  312. }
  313. }
  314. return false;
  315. }
  316.  
  317. /// <summary>
  318. /// 带Open表和HashTable的最好优先搜索(每次扩展Open表后都对Open表排序)
  319. /// </summary>
  320. /// <returns></returns>
  321. private int BestFirstSearch()
  322. {
  323. int depth = ;
  324. Direction[] moves;
  325. int board;
  326. long newCode = combinCode(this.startBoard, );
  327. int empIndex = getEmpIndex(newCode);
  328.  
  329. moves = dirs[empIndex - ];
  330. StateMsg data;
  331. if (extentOpenList(newCode, Direction.None, depth))
  332. return WinnerCode;
  333. while (openList.Count > )
  334. {
  335. lock (this)
  336. {
  337. nodes++;
  338. if (nodes >= maxNodes)
  339. return -;
  340. newCode = openList.Keys[];
  341. board = getBoard(newCode);
  342. data = openList[newCode];
  343. if (data.Depth != )
  344. {
  345. depth = data.Depth;
  346. if (board == endBoard)
  347. {
  348. return WinnerCode;
  349. }
  350. boardtable.Add(newCode, new StateMsg(depth, data.Dir));
  351. openList.RemoveAt();
  352. if (depth < MaxDepth)
  353. if (extentOpenList(newCode, data.Dir, depth + ))
  354. return WinnerCode;
  355. }
  356. }
  357. }
  358. return -;
  359. }
  360.  
  361. #endregion
  362.  
  363. /// <summary>
  364. /// 把一维数组的局面编码成一个整数的表示形式
  365. /// </summary>
  366. /// <param name="genBoard"></param>
  367. /// <returns></returns>
  368. public int ToIntBoard(int[] genBoard)
  369. {
  370. int board = ;
  371. int emp = ;
  372. for (int i = ; i < genBoard.Length; i++)
  373. {
  374. if (genBoard[i] != )
  375. board = * board + genBoard[i];
  376. else
  377. emp = i + ;
  378. }
  379. return * board + emp;
  380. }
  381.  
  382. /// <summary>
  383. /// 判断是否可以从初始状态到达目标状态(计算两个状态的逆序列,奇偶性相同的返回true)
  384. /// </summary>
  385. /// <param name="start"></param>
  386. /// <param name="end"></param>
  387. /// <returns></returns>
  388. private bool ExistAns(int[] start, int[] end)
  389. {
  390. int sequence_start = , sequence_end = ;
  391. for (int i = ; i < start.Length; i++)
  392. {
  393. if (start[i] != )
  394. for (int j = i + ; j < start.Length; j++)
  395. {
  396. if (start[j] != && start[j] < start[i])
  397. sequence_start++;
  398. }
  399. if (end[i] != )
  400. for (int j = i + ; j < start.Length; j++)
  401. {
  402. if (end[j] != && end[j] < end[i])
  403. sequence_end++;
  404. }
  405. }
  406. return (sequence_start + sequence_end) % == ;
  407. }
  408.  
  409. /// <summary>
  410. /// 初始化求解
  411. /// </summary>
  412. /// <param name="start"></param>
  413. /// <param name="end"></param>
  414. /// <param name="maxDepth"></param>
  415. private void InitComp(int[] start, int[] end, int maxDepth)
  416. {
  417. nodes = ;
  418. same = ;
  419. MaxDepth = maxDepth;
  420. result = null;
  421. boardtable = new Dictionary<long, StateMsg>();
  422. openList = new SortedList<long, StateMsg>();
  423. //openStack = new Stack<State>();
  424. //openQueue = new Queue<State>();
  425.  
  426. this.startBoard = ToIntBoard(start);
  427. endBoard = ToIntBoard(end);
  428. int t_end = endBoard;
  429. int emp_end = endBoard % ;
  430. endBoardArray = new int[N*N+];
  431. endBoardArray[] = emp_end;
  432. endBoardArray[emp_end] = ;
  433. for (int i = N*N; i > emp_end; i--)
  434. {
  435. t_end /= ;
  436. endBoardArray[i] = t_end % ;
  437. }
  438. for (int i = emp_end - ; i >= ; i--)
  439. {
  440. t_end /= ;
  441. endBoardArray[i] = t_end % ;
  442. }
  443. }
  444.  
  445. /// <summary>
  446. /// 求解8数码问题
  447. /// </summary>
  448. /// <param name="start"></param>
  449. /// <param name="end"></param>
  450. /// <param name="maxDepth"></param>
  451. /// <returns></returns>
  452. public Answer Compute(int[] start, int[] end, int maxDepth)
  453. {
  454. if (!ExistAns(start, end))
  455. return Answer.NotExist;
  456. InitComp(start, end, maxDepth);
  457. if (startBoard == endBoard)
  458. return Answer.Exist;
  459. long oldtime = System.DateTime.Now.Ticks;
  460. int eval = ;
  461. eval = BestFirstSearch();
  462. time = (System.DateTime.Now.Ticks - oldtime) / 10000000.0f;
  463. if (eval == WinnerCode)
  464. return Answer.Exist;
  465. return Answer.NotExistInDepth;
  466. }
  467.  
  468. }
  469. }

A*算法【拼图游戏】的更多相关文章

  1. 基于unity3d和leap motion的拼图游戏

    近期用unity3d引擎做了一个拼图游戏,会分几次写完,以此作为总结. 本文基本查找了网上能查到的全部资料作为參考.也算是大家节省了时间. 眼下仅仅完毕了拼图部分,leap motion手势控制部分会 ...

  2. 程序设计 之 C#实现《拼图游戏》 (下) 原理篇

    前言:在 http://www.cnblogs.com/labixiaohei/p/6698887.html 程序设计 之 C#实现<拼图游戏>(上),上传了各模块代码,而在本文中将详细剖 ...

  3. [Android]自己动手做个拼图游戏

    目标 在做这个游戏之前,我们先定一些小目标列出来,一个一个的解决,这样,一个小游戏就不知不觉的完成啦.我们的目标如下: 游戏全屏,将图片拉伸成屏幕大小,并将其切成若干块. 将拼图块随机打乱,并保证其能 ...

  4. 拼图游戏js

    实现算法: 1. JavaScript动态生成拼图:通过生成16个div,且除最后一个div不使用背景图片以外,其他div都设置拼图图片为背景.然后通过调整background-position来实现 ...

  5. iOS 滑块拼图游戏(Puzzle8)

    代码地址如下:http://www.demodashi.com/demo/11505.html 一.准备工作 先了解一个定义和定理 定义:在一个1,2,...,n的排列中,如果一对数的前后位置与大小顺 ...

  6. C#实现拼图游戏

    C#实现<拼图游戏> (下) 原理篇   前言:在 http://www.cnblogs.com/labixiaohei/p/6698887.html 程序设计 之 C#实现<拼图游 ...

  7. 利用Vue.js实现拼图游戏

    之前写过一篇<基于Vue.js的表格分页组件>的文章,主要介绍了Vue组件的编写方法,有兴趣的可以访问这里进行阅读:http://www.cnblogs.com/luozhihao/p/5 ...

  8. JavaScript拼图游戏

    今天是2016年最后一天上班了.最近几天都比较休闲,有时间空闲下来写写文档之类的. 2016过得真是快.感觉没做什么就过去了.想到之前想坚持每个月写一写博客都没坚持到.希望2017年可以吧. 无聊之余 ...

  9. SDL制作拼图游戏

    看完教程第三集后,好像自己能用这个来写一个简单的拼图游戏,第一次写出个带界面的游戏,好有成就感. 图片是自己慢慢截左上部分8个脸. #include <stdio.h> #include ...

  10. 拼图游戏(js,C#,java三种语言)

    <html> <head> <meta charset="utf-8"> <style type="text/css" ...

随机推荐

  1. cogs1619. [HEOI2012]采花 x

    1619. [HEOI2012]采花 ★★☆   输入文件:1flower.in   输出文件:1flower.out   简单对比时间限制:5 s   内存限制:128 MB [题目描述] 萧薰儿是 ...

  2. Redis总结 C#中如何使用redis

    转载自:https://www.cnblogs.com/zhangweizhong/p/4972348.html 本篇着重讲解.NET中如何使用redis和C#. Redis官网提供了很多开源的C#客 ...

  3. JavaWeb_EL表达式存储数据及获得项目路径

    菜鸟教程 传送门 EL表达式[百度百科]:EL(Expression Language) 是为了使JSP写起来更加简单.表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供 ...

  4. Feature Engineering and Feature Selection

    首先,弄清楚三个相似但是不同的任务: feature extraction and feature engineering: 将原始数据转换为特征,以适合建模. feature transformat ...

  5. 高并发通信模型NIO

    一.NIO和BIO的对比 BIO通信模型 2.配置 BIO tomcat server.xml NIO 3.NIO

  6. Spring Boot使用阿里云证书启用HTTPS

    1.到阿里云下载证书页面下载证书 2.根据页面内容,可以使用2种证书:PFX JKS 把对应证书放到src/main/resources目录下 在application.properties文件中加入 ...

  7. 20175215 2018-2019-2 第四周Java课程学习总结

    第五章学习内容 1.子类的继承性 (1)子类和父类在同一包中的继承性 如果子类和父类在同一个包中,那么,子类自然地继承了其父类中不是private的成员变量作为自己的成员变量,并且也自然地继承了父类中 ...

  8. 循环链表C语言实现

    按照单链表的设计,稍加改动.和单向链表不一样的地方,头节点不指向NULL,而是指向自己head 循环链表的判满 1)判断next是不是头结点,2)判断size /* * CycleLinkList.h ...

  9. Linux修改环境变量的4种方法

    转载 查看PATH:echo $PATH以添加mongodb server为列修改方法一:export PATH=/usr/local/mongodb/bin:$PATH//配置完后可以通过echo ...

  10. Java: Integer用==比较时127相等128不相等的原因

    直接看问题吧 for (int i = 0; i < 150; i++) { Integer a = i; Integer b = i; System.out.println(i + " ...