数据结构

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*算法【拼图游戏】的更多相关文章

  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. Protocol Buffers 开发者指南

    欢迎来到 protocol buffers 的开发者指南.protocol buffers 是一个语言中立,平台中立针对通讯协议,数据存储和其他领域中对结构化数据进行序列化的扩展方法. 本文档主要针对 ...

  2. AcWing:106. 动态中位数(对顶堆)

    依次读入一个整数序列,每当已经读入的整数个数为奇数时,输出已读入的整数构成的序列的中位数. 输入格式 第一行输入一个整数PP,代表后面数据集的个数,接下来若干行输入各个数据集. 每个数据集的第一行首先 ...

  3. Apicloud_(模板)登陆注册功能模板

    项目已托管到Github上 传送门 不需要使用任何图片资源,需要用到SHA1.js库文件, Apicloud_(接口验证)用户注册头部信息X-APICloud-AppKey生成 传送门 项目全代码放到 ...

  4. JS框架_(JQuery.js)绚丽的3D星空动画

    百度云盘: 传送门 密码:8ft8 绚丽的3D星空动画效果(纯CSS) (3D星空动画可以用作网页背景,Gary为文本文字) <!doctype html> <html lang=& ...

  5. RedisTemplate 用法

      Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串).List(列表).Set(集合).Hash(散列)和 Zset(有 ...

  6. 分布式-信息方式-ActiveMQ的集群

    ActiveMQ的集群Queue consumer clusters              ActiveMQ支持 Consumer对消息高可靠性的负载平衡消费,如果一个 Consumer死掉,该消 ...

  7. JavaBean,EJB,POJO,Spring Bean 的演进历程

    JavaBean Sun公司对类提出的规范:1,类是public的2,有一个无参构造方法3,属性修饰要用private,通过get set操作4,实现Serializable接口5,对事件使用Swin ...

  8. mongo 是什么

    一.概述1.MongoDB是什么?用一句话总结MongoDB是一款为web应用程序和互联网基础设施设计的数据库管理系统.没错MongoDB就是数据库,是NoSQL类型的数据库 2.为什么要使用Mong ...

  9. Miniui 表单验证

    自定义表单验证: input输入框的表单验证可通过vtype和onvalidation事件两种方式实现 可编辑列表(例如div)的表单验证只能通过vtye来实现表单验证 (1)vtype方式: jsp ...

  10. 第九周学习总结&实验报告(7)

    完成火车站售票程序的模拟. 要求: (1)总票数1000张; (2)10个窗口同时开始卖票; (3) 卖票过程延时1秒钟; (4)不能出现一票多卖或卖出负数号票的情 况 实验代码: package y ...