A*算法【拼图游戏】
数据结构
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace 拼图
- {
- /// <summary>
- /// 空格移动的方向
- /// </summary>
- enum Direction
- {
- None,
- Up,
- Left,
- Right,
- Down
- }
- /// <summary>
- /// 解答
- /// </summary>
- enum Answer
- {
- /// <summary>
- /// 不存在解答
- /// </summary>
- NotExist,
- /// <summary>
- /// 存在解答
- /// </summary>
- Exist,
- /// <summary>
- /// 在当前指定的搜索深度内不存在解答(需要扩大深度)
- /// </summary>
- NotExistInDepth
- }
- /// <summary>
- /// 局面状态信息
- /// </summary>
- class StateMsg
- {
- private int depth;
- private Direction dir;
- public int Depth
- {
- get { return depth; }
- }
- public Direction Dir
- {
- get { return dir; }
- }
- public StateMsg(int depth, Direction dir)
- {
- this.depth = depth;
- this.dir = dir;
- }
- }
- /// <summary>
- /// 局面状态
- /// </summary>
- class State : StateMsg
- {
- private long code;
- /// <summary>
- /// 棋盘的编码
- /// </summary>
- public long Code
- {
- get { return code; }
- set { code = value; }
- }
- public State(long code, int depth, Direction dir)
- : base(depth, dir)
- {
- this.code = code;
- }
- }
- }
Astar类
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace 拼图
- {
- class AStar
- {
- /// <summary>
- /// ten[i]代表10的i次方
- /// </summary>
- private static readonly long[] tens = { , , , , , , , , , };
- /// <summary>
- /// 不是合理的编码
- /// </summary>
- private const int OutOfCode = -;
- /// <summary>
- /// 标志是否找到目标状态的编码
- /// </summary>
- public const int WinnerCode = ;
- private Direction[][] dirs;
- private int startBoard;
- private static int endBoard;
- private static int[] endBoardArray;
- private int MaxDepth;
- private SortedList<long, StateMsg> openList;
- private Dictionary<long, StateMsg> boardtable;
- private const long maxNodes = ; //至多搜索的结点数=最大局面状态数量:(9!)=362880;
- private long nodes;
- private int same;
- private float time;
- private Direction[] result;
- /// <summary>
- /// 已经访问的结点数量
- /// </summary>
- public long Nodes
- {
- get { return nodes; }
- }
- /// <summary>
- /// 重复访问相同结点的数量
- /// </summary>
- public int Same
- {
- get { return same; }
- }
- public float Time
- {
- get { return time; }
- }
- public static int N;
- /// <summary>
- /// 最终结果
- /// </summary>
- public Direction[] Result
- {
- get { return result; }
- }
- public AStar(int n)
- {
- N = n;
- dirs = new Direction[n*n][];
- if(n==)
- {
- dirs[] = new Direction[] { Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Left, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Right };
- dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Up };
- dirs[] = new Direction[] { Direction.Up, Direction.Left };
- }
- else
- {
- dirs[] = new Direction[] { Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Left, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Right, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Left, Direction.Down };
- dirs[] = new Direction[] { Direction.Up, Direction.Right };
- dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Up };
- dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Up };
- dirs[] = new Direction[] { Direction.Left, Direction.Right, Direction.Up };
- dirs[] = new Direction[] { Direction.Up, Direction.Left };
- }
- }
- /// <summary>
- /// 求与目标位置不同的个数(不计空格,因此返回值0~8)
- /// </summary>
- /// <param name="curboard"></param>
- /// <returns></returns>
- public static int Different(int curboard)
- {
- int t_start = curboard;
- int emp_start = curboard % ;
- int ev = ;
- //写2个for是为了减少9个if
- for (int i = N*N; i > emp_start; i--)
- {
- t_start /= ;
- if (t_start % != endBoardArray[i])
- ev++;
- }
- for (int i = emp_start - ; i >= ; i--)
- {
- t_start /= ;
- if (t_start % != endBoardArray[i])
- ev++;
- }
- return ev;
- }
- public static int getBoard(long code)
- {
- return (int)(code % tens[]);
- }
- private static int getEval(long code)
- {
- return (int)(code / tens[]);
- }
- private static int getEmpIndex(long code)
- {
- return (int)(code % );
- }
- private static long combinCode(int board, int eval)
- {
- long codehead = eval * tens[];
- return codehead + board;
- }
- /// <summary>
- /// 改变局面(移动空格)
- /// </summary>
- /// <param name="code"></param>
- /// <param name="dir"></param>
- public static long change(long code, Direction dir)
- {
- int newboard;
- int eval;
- int num;
- int t0;
- long t1;
- long t2;
- switch (dir)
- {
- case Direction.Left:
- newboard = getBoard(code) - ;
- if (newboard == endBoard)
- return WinnerCode;
- eval = Different(newboard);
- return combinCode(newboard, eval);
- case Direction.Right:
- newboard = getBoard(code) + ;
- if (newboard == endBoard)
- return WinnerCode;
- eval = Different(newboard);
- return combinCode(newboard, eval);
- case Direction.Up:
- num = getBoard(code);
- t0 = N*N - num % + ;
- t1 = num / tens[t0];
- t2 = t1 % ;
- t1 = t1 - t2 + (t2 % ) * + t2 / ;
- t1 *= tens[t0];
- newboard = (int)(t1 + ((num % tens[t0]) - N));
- if (newboard == endBoard)
- return WinnerCode;
- eval = Different(newboard);
- return combinCode(newboard, eval);
- case Direction.Down:
- num = getBoard(code);
- t0 = N*N - num % + - N;//跟Up不同的地方
- t1 = num / tens[t0];
- t2 = t1 % ;
- t1 = t1 - t2 + (t2 % ) * + t2 / ;//跟Up不同的地方
- t1 *= tens[t0];
- newboard = (int)(t1 + ((num % tens[t0]) + N));//跟Up不同的地方
- if (newboard == endBoard)
- return WinnerCode;
- eval = Different(newboard);
- return combinCode(newboard, eval);
- }
- return OutOfCode;
- }
- /// <summary>
- /// 恢复上一步的局面
- /// </summary>
- /// <param name="code"></param>
- /// <param name="dir"></param>
- public long unchange(long code, Direction dir)
- {
- return change(code, (Direction)( - dir));
- }
- /// <summary>
- /// 当找到目标时,从哈希表里找原来的路径
- /// </summary>
- /// <param name="endCode"></param>
- /// <param name="depth"></param>
- private void setResult(long endCode, Direction curDir, Direction lastDir, int depth)
- {
- long lastCode = endCode;
- result = new Direction[depth];
- result[depth - ] = curDir;
- for (int i = depth - ; i >= ; i--)
- {
- if (boardtable.ContainsKey(lastCode))
- {
- result[i] = boardtable[lastCode].Dir;
- lastCode = unchange(lastCode, result[i]);
- }
- else
- return;
- }
- }
- //本算法的核心部分
- #region 带Open表和HashTable的最好优先搜索(每次扩展Open表后都对Open表排序)
- /// <summary>
- /// 扩展Open表
- /// </summary>
- /// <param name="board"></param>
- /// <param name="depth"></param>
- private bool extentOpenList(long code, Direction lastDir, int depth)
- {
- int empIndex = (int)(code % - );
- int len_moves = dirs[empIndex].Length;
- long newcode;
- Direction dir = - lastDir;
- for (int i = ; i < len_moves; i++)
- if (dirs[empIndex][i] != dir)
- {
- newcode = change(code, dirs[empIndex][i]);
- //跟目标匹配,结束
- if (newcode == WinnerCode)
- {
- setResult(code, dirs[empIndex][i], lastDir, depth);
- return true;
- }
- if (newcode <= tens[])
- throw new Exception("棋盘码修改错误! ");
- if (newcode != OutOfCode)
- {
- if (!openList.ContainsKey(newcode))
- {
- if (!boardtable.ContainsKey(newcode))
- openList.Add(newcode, new StateMsg(depth, dirs[empIndex][i]));
- else
- {
- same++;
- if (depth < boardtable[newcode].Depth)
- {
- boardtable.Remove(newcode);
- openList.Add(newcode, new StateMsg(depth, dirs[empIndex][i]));
- }
- }
- }
- else
- {
- same++;
- if (depth < openList[newcode].Depth)
- openList[newcode] = new StateMsg(depth, dirs[empIndex][i]);
- }
- }
- }
- return false;
- }
- /// <summary>
- /// 带Open表和HashTable的最好优先搜索(每次扩展Open表后都对Open表排序)
- /// </summary>
- /// <returns></returns>
- private int BestFirstSearch()
- {
- int depth = ;
- Direction[] moves;
- int board;
- long newCode = combinCode(this.startBoard, );
- int empIndex = getEmpIndex(newCode);
- moves = dirs[empIndex - ];
- StateMsg data;
- if (extentOpenList(newCode, Direction.None, depth))
- return WinnerCode;
- while (openList.Count > )
- {
- lock (this)
- {
- nodes++;
- if (nodes >= maxNodes)
- return -;
- newCode = openList.Keys[];
- board = getBoard(newCode);
- data = openList[newCode];
- if (data.Depth != )
- {
- depth = data.Depth;
- if (board == endBoard)
- {
- return WinnerCode;
- }
- boardtable.Add(newCode, new StateMsg(depth, data.Dir));
- openList.RemoveAt();
- if (depth < MaxDepth)
- if (extentOpenList(newCode, data.Dir, depth + ))
- return WinnerCode;
- }
- }
- }
- return -;
- }
- #endregion
- /// <summary>
- /// 把一维数组的局面编码成一个整数的表示形式
- /// </summary>
- /// <param name="genBoard"></param>
- /// <returns></returns>
- public int ToIntBoard(int[] genBoard)
- {
- int board = ;
- int emp = ;
- for (int i = ; i < genBoard.Length; i++)
- {
- if (genBoard[i] != )
- board = * board + genBoard[i];
- else
- emp = i + ;
- }
- return * board + emp;
- }
- /// <summary>
- /// 判断是否可以从初始状态到达目标状态(计算两个状态的逆序列,奇偶性相同的返回true)
- /// </summary>
- /// <param name="start"></param>
- /// <param name="end"></param>
- /// <returns></returns>
- private bool ExistAns(int[] start, int[] end)
- {
- int sequence_start = , sequence_end = ;
- for (int i = ; i < start.Length; i++)
- {
- if (start[i] != )
- for (int j = i + ; j < start.Length; j++)
- {
- if (start[j] != && start[j] < start[i])
- sequence_start++;
- }
- if (end[i] != )
- for (int j = i + ; j < start.Length; j++)
- {
- if (end[j] != && end[j] < end[i])
- sequence_end++;
- }
- }
- return (sequence_start + sequence_end) % == ;
- }
- /// <summary>
- /// 初始化求解
- /// </summary>
- /// <param name="start"></param>
- /// <param name="end"></param>
- /// <param name="maxDepth"></param>
- private void InitComp(int[] start, int[] end, int maxDepth)
- {
- nodes = ;
- same = ;
- MaxDepth = maxDepth;
- result = null;
- boardtable = new Dictionary<long, StateMsg>();
- openList = new SortedList<long, StateMsg>();
- //openStack = new Stack<State>();
- //openQueue = new Queue<State>();
- this.startBoard = ToIntBoard(start);
- endBoard = ToIntBoard(end);
- int t_end = endBoard;
- int emp_end = endBoard % ;
- endBoardArray = new int[N*N+];
- endBoardArray[] = emp_end;
- endBoardArray[emp_end] = ;
- for (int i = N*N; i > emp_end; i--)
- {
- t_end /= ;
- endBoardArray[i] = t_end % ;
- }
- for (int i = emp_end - ; i >= ; i--)
- {
- t_end /= ;
- endBoardArray[i] = t_end % ;
- }
- }
- /// <summary>
- /// 求解8数码问题
- /// </summary>
- /// <param name="start"></param>
- /// <param name="end"></param>
- /// <param name="maxDepth"></param>
- /// <returns></returns>
- public Answer Compute(int[] start, int[] end, int maxDepth)
- {
- if (!ExistAns(start, end))
- return Answer.NotExist;
- InitComp(start, end, maxDepth);
- if (startBoard == endBoard)
- return Answer.Exist;
- long oldtime = System.DateTime.Now.Ticks;
- int eval = ;
- eval = BestFirstSearch();
- time = (System.DateTime.Now.Ticks - oldtime) / 10000000.0f;
- if (eval == WinnerCode)
- return Answer.Exist;
- return Answer.NotExistInDepth;
- }
- }
- }
A*算法【拼图游戏】的更多相关文章
- 基于unity3d和leap motion的拼图游戏
近期用unity3d引擎做了一个拼图游戏,会分几次写完,以此作为总结. 本文基本查找了网上能查到的全部资料作为參考.也算是大家节省了时间. 眼下仅仅完毕了拼图部分,leap motion手势控制部分会 ...
- 程序设计 之 C#实现《拼图游戏》 (下) 原理篇
前言:在 http://www.cnblogs.com/labixiaohei/p/6698887.html 程序设计 之 C#实现<拼图游戏>(上),上传了各模块代码,而在本文中将详细剖 ...
- [Android]自己动手做个拼图游戏
目标 在做这个游戏之前,我们先定一些小目标列出来,一个一个的解决,这样,一个小游戏就不知不觉的完成啦.我们的目标如下: 游戏全屏,将图片拉伸成屏幕大小,并将其切成若干块. 将拼图块随机打乱,并保证其能 ...
- 拼图游戏js
实现算法: 1. JavaScript动态生成拼图:通过生成16个div,且除最后一个div不使用背景图片以外,其他div都设置拼图图片为背景.然后通过调整background-position来实现 ...
- iOS 滑块拼图游戏(Puzzle8)
代码地址如下:http://www.demodashi.com/demo/11505.html 一.准备工作 先了解一个定义和定理 定义:在一个1,2,...,n的排列中,如果一对数的前后位置与大小顺 ...
- C#实现拼图游戏
C#实现<拼图游戏> (下) 原理篇 前言:在 http://www.cnblogs.com/labixiaohei/p/6698887.html 程序设计 之 C#实现<拼图游 ...
- 利用Vue.js实现拼图游戏
之前写过一篇<基于Vue.js的表格分页组件>的文章,主要介绍了Vue组件的编写方法,有兴趣的可以访问这里进行阅读:http://www.cnblogs.com/luozhihao/p/5 ...
- JavaScript拼图游戏
今天是2016年最后一天上班了.最近几天都比较休闲,有时间空闲下来写写文档之类的. 2016过得真是快.感觉没做什么就过去了.想到之前想坚持每个月写一写博客都没坚持到.希望2017年可以吧. 无聊之余 ...
- SDL制作拼图游戏
看完教程第三集后,好像自己能用这个来写一个简单的拼图游戏,第一次写出个带界面的游戏,好有成就感. 图片是自己慢慢截左上部分8个脸. #include <stdio.h> #include ...
- 拼图游戏(js,C#,java三种语言)
<html> <head> <meta charset="utf-8"> <style type="text/css" ...
随机推荐
- cogs1619. [HEOI2012]采花 x
1619. [HEOI2012]采花 ★★☆ 输入文件:1flower.in 输出文件:1flower.out 简单对比时间限制:5 s 内存限制:128 MB [题目描述] 萧薰儿是 ...
- Redis总结 C#中如何使用redis
转载自:https://www.cnblogs.com/zhangweizhong/p/4972348.html 本篇着重讲解.NET中如何使用redis和C#. Redis官网提供了很多开源的C#客 ...
- JavaWeb_EL表达式存储数据及获得项目路径
菜鸟教程 传送门 EL表达式[百度百科]:EL(Expression Language) 是为了使JSP写起来更加简单.表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供 ...
- Feature Engineering and Feature Selection
首先,弄清楚三个相似但是不同的任务: feature extraction and feature engineering: 将原始数据转换为特征,以适合建模. feature transformat ...
- 高并发通信模型NIO
一.NIO和BIO的对比 BIO通信模型 2.配置 BIO tomcat server.xml NIO 3.NIO
- Spring Boot使用阿里云证书启用HTTPS
1.到阿里云下载证书页面下载证书 2.根据页面内容,可以使用2种证书:PFX JKS 把对应证书放到src/main/resources目录下 在application.properties文件中加入 ...
- 20175215 2018-2019-2 第四周Java课程学习总结
第五章学习内容 1.子类的继承性 (1)子类和父类在同一包中的继承性 如果子类和父类在同一个包中,那么,子类自然地继承了其父类中不是private的成员变量作为自己的成员变量,并且也自然地继承了父类中 ...
- 循环链表C语言实现
按照单链表的设计,稍加改动.和单向链表不一样的地方,头节点不指向NULL,而是指向自己head 循环链表的判满 1)判断next是不是头结点,2)判断size /* * CycleLinkList.h ...
- Linux修改环境变量的4种方法
转载 查看PATH:echo $PATH以添加mongodb server为列修改方法一:export PATH=/usr/local/mongodb/bin:$PATH//配置完后可以通过echo ...
- Java: Integer用==比较时127相等128不相等的原因
直接看问题吧 for (int i = 0; i < 150; i++) { Integer a = i; Integer b = i; System.out.println(i + " ...