华容道问题求解_详细设计(五)之hash值和回放功能

(续上文)

布局的hash 值计算

笔者也参考了之前的一些文章,很多文章提到了怎么节省存贮空间来查找最优解,这不是笔者的目的。笔者的目的比较单一,就是找到最优解就行了。因此并没有在存贮上面进行过多的优化,曾经尝试使用移位指令进行棋子的移动,然而并没有发现运行速度比使用庞大的对象速度更快。(或许是算法的问题)因此索性就使用了高级语言的高级方法,放弃了对存贮空间的限制和约束。基于前面的设计,每个布局保存在一个4*5的整数数组里面(保存的棋子的ID),因此为了简单起见笔者将这个20个整数构成一个字符串,然后利用C#提供的现有的字符串hash函数,就得到了这个布局的hash值。这个方法简单粗暴,并不美丽,但是解决问题就行了。
一个细节:在实际棋子的移动过程当中,我们关心的是棋子的形状而非棋子的名字,因此在棋子布局的时候,尽管每个棋子都赋予了名字,在进行查找的时候,是忽略了这些名字的。因此在使用DFS结合Dijkstra 算法查找时会出现名字改变的情况,这里笔者没有对名字进行一致处理,因为这种处理对解法其实没有什么帮助,只是界面看着更连贯些。(具体原因也不解释了,很简单)。在BFS的查找过程当中,不会有这个问题。
hash 函数如下:

      public int GetMyHashCode(GameState gameState){string val = string.Empty;for (int i = 1; i <= 4; i++){for (int j = 1; j <=5; j++){var pcs  = gameState.layoutOfObj[i, j];val += pcs.GetHrdType().ToString();}}return val.GetHashCode();}

注意上面只取了Type值进行hash处理。

回放功能

找到了解法,还要能进行回放,否则也看不到效果,也不能证明是否成功了,因此增加回放功能很有必要。
回放功能,就是记录每个布局的hash值和布局,然后根据hash值从布局记录中查找对应的布局,在映射到UI上就可以了。

最佳结果保存在如下定义的数据字典里

       // the shorest path will be stored in the following variable.// key:the hash code of the current layout, value.item1, the hashcode of the source layout , item2 the number of the shortest steps.Dictionary<int, (int,int)> hCodeAndShotShortPathDict = new Dictionary<int, (int,int)>();

hash值和布局快照保存在如下定义的数据字典中

// store the hash code and the layout shot , selpcs index,dstPcs.idx Dictionary<int, (Piece[],int,int)> hCodeAndShotDict = new Dictionary<int, (Piece[], int, int)>();
回放时,将这两个数据字典结合起来,就可以找到快照,将快照映射到界面上就可以了。

具体的保存过程

DFS中的用了Dijkstra 算法,算法本身就包括了最短路径的记录,因此这里不再赘述。
BFS算法中,找到的方法都是对应不同布局的最佳步骤,因此在尝试移动棋子的过程当中,记录当前的布局就可以了。
代码如下:
在AddEdgeToGraph 中的函数AdjustShortPath 就是用于记录解法的。
       private void AddEdgeToGraph(StateShot source, StateShot dest){var toHashCode = GetMyHashCode(dest);var frmHashCode = GetMyHashCode(source);AdjustShortPath(dest, toHashCode, frmHashCode);AddEdge(frmHashCode, toHashCode, 1);}private void PushState(StateS

AdjustShortPath 代码如下:

      private void AdjustShortPath(StateShot dest, int toHashCode, int frmHashCode){(int, int) lastItem;if (hCodeAndShotShortPathDict.TryGetValue(toHashCode, out lastItem)){if (lastItem.Item2 > dest.bestSteps){//这是笔者增加的视图记录最短路径的判断,DFS时,找到了比原来步骤少的方法,但是不是最优的。BFS时,这里执行不到。hCodeAndShotShortPathDict[toHashCode] = (frmHashCode, dest.bestSteps);}//hCodeAndShotShortPathDict.Add(toHashCode, (dest.basePcs, selPcs.idx, dstPcs.idx, frmHashCode, pathLen));}else{// 查找过程记录,BFS时,记录的就是最佳结果hCodeAndShotShortPathDict.Add(toHashCode, (frmHashCode, dest.bestSteps));}}

回放过程

程序先找到要回放的结果布局,然后将这个结果布局的对应的保存的所有过程布局,放到一个数组中,每执行一步,数组的索引加一,指向下一个过程布局。代码如下:

     private void MoveNext(){//allShortPath = allShortPath2;if (allShortPath == null){MessageBox.Show(string.Format("The shortest path is now being searched ,wait for a moment."), "Notice", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);return;}//solutionPcsIdx 布局数组索引//cbbSolutionIdx 保存在CBB 中的结果布局索引(hash 值)if (solutionPcsIdx >= 0 && solutionPcsIdx < allShortPath[cbbSolutionIdx].Count){if (solutionPcsIdx < allShortPath[cbbSolutionIdx].Count - 1)solutionPcsIdx++;var lastKey = allShortPath[cbbSolutionIdx][solutionPcsIdx - 1];//txt_Notice.Text = string.Format("Layout code:{0} Graph node info {1}\r\n{2}",lastKey, _hrdGame.adjacencyList[lastKey],txt_Notice.Text);var lastLayoutArr = _hrdGame.GetLayoutIdxArrByHashCode(lastKey);var key = allShortPath[cbbSolutionIdx][solutionPcsIdx];var layoutArr = _hrdGame.GetLayoutIdxArrByHashCode(key);//get the moving pieces by comparing the two layoutsvar movedPcs = GetMovedPieces(lastLayoutArr.Item1, layoutArr.Item1);var frmIdx = layoutArr.Item2;var toIdx = frmIdx;// layoutArr.Item3;var srcPcs = movedPcs.Item1;var dstPcs = movedPcs.Item2;var passPcs = movedPcs.Item3;// animation moving var selPos = srcPcs.GetHrdPos();var emptySpPos = dstPcs.GetHrdPos();var passPos = passPcs.GetHrdPos();// the following used to add animation effectvar srcPos = new HrdPoint(selPos.X, selPos.Y);var dstPos = new HrdPoint(emptySpPos.X, emptySpPos.Y);_hrdGame.gameState.pieces = layoutArr.Item1;_hrdGame.MovePcsWithAnimation(srcPcs, srcPos, dstPos, passPos, dstPcs, null);btn_ShowSteps.Text = string.Format("{0}/{1}", solutionPcsIdx, allShortPath[cbbSolutionIdx].Count - 1);//MessageBox.Show(string.Format("Click for next step, current step: {0}/{1}", i, allPath[0].Count));}}

函数中增加了 动画部分,因此做了相应的处理,这一部分将在后文赘述。

回放时,需要用户点击回放按钮。也支持了Undo功能,以方便用户观察棋子的移动过程。目前,执行Undo功能时没有做动画处理。

说明如下:
首先在下拉列表中选择一个布局的Hash值,例如第一个(就应该是最少步骤那个,BFS决定的)
在这里插入图片描述

点击[>>],棋子移动一步

在这里插入图片描述
点击[<<],恢复到上一步

在这里插入图片描述
(待续)
MaraSun BJFWDQ
2024-03-10

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/735303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

消息队列 MQ

文章目录 1. MQ 相关概念1.1 什么是 MQ1.2 为什么要用 MQ1.3 MQ 分类1.4 MQ 的选择 1. MQ 相关概念 1.1 什么是 MQ MQ(message queue)&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO 先入先出&#xff0c;只不过队列中存放的内容是 message 而已&#x…

阿里云DSW做AI绘画时的显卡选择A10?V100?

V100是Volta架构&#xff0c;A10是Ampere架构&#xff0c;架构上讲A10先进点&#xff0c;其实只是制程区别&#xff0c;用起来没区别。 V100是HBM的内存读取&#xff0c;带宽大&#xff0c;但是DDR5的。 二块卡都是全精度为主的算力卡&#xff0c;半精度优势不明显。 需要用…

FPN(Feature Pyramid Network)

参考&#xff1a; 【目标检测】FPN(Feature Pyramid Network) - 知乎 Feature pyramid network是CVPR2017年的一篇文章&#xff0c;它在目标检测中融入了特征金字塔&#xff0c;提高了目标检测的准确率&#xff0c;尤其体现在小物体的检测上。 1. 动机(Motivation) 识别不同…

【读书笔记】针对ICS的ATTCK矩阵详解(一)

Techniques - ICS | MITRE ATT&CKhttps://attack.mitre.org/techniques/ics/ 一、初始访问&#xff08;Initial Access&#xff09; 该阶段&#xff1a;攻击者正在尝试进入ICS环境。 初始访问包括攻击者可能用作入口向量&#xff0c;从而可以在 ICS 环境中获得初始立足点的…

pytorch实现分割模型TransUNet

TransUNet是一个非常经典的图像分割模型。该模型出现在Transformer引入图像领域的早期&#xff0c;所以结构比较简单&#xff0c;但是实际上效果却比很多后续花哨的模型更好。所以有必要捋一遍pytorch实现TransUNet的整体流程。 首先&#xff0c;按照惯例&#xff0c;先看一下…

逼疯快递员的送货上门,谁来背锅?

快递上门的问题近几年来一直争论不休。 最近&#xff0c;随着新修订的《快递市场管理办法》正式实施&#xff0c;这个话题又成为了焦点。 消费者希望快递能够送上门省去麻烦&#xff0c;快递员希望统一送到代收点提高效率。 是消费者要求太高&#xff1f;快递员太过怠慢&…

[金三银四] 系统调用相关

2.36 系统调用的详细流程 Linux 在x86上的系统调用通过 int 0x80 实现&#xff0c;用系统调用号来区分入口函数。操作系统实现系统调用的基本过程是&#xff1a; 应用程序调用库函数&#xff08;API&#xff09;&#xff1b;API 将系统调用号存入寄存器&#xff08;EAX&#…

CKA备考攻略:掌握Pod日志收集,事半功倍的秘诀!

往期精彩文章 : 提升CKA考试胜算&#xff1a;一文带你全面了解RBAC权限控制&#xff01;揭秘高效运维&#xff1a;如何用kubectl top命令实时监控K8s资源使用情况&#xff1f;CKA认证必备&#xff1a;掌握k8s网络策略的关键要点提高CKA认证成功率&#xff0c;CKA真题中的节点维…

2.JavaWebMySql基础

导语&#xff1a; 一、数据库基本概念 1.什么是数据库 2.关于MySql数据库 二、MySQL的安装与卸载 安装步骤&#xff1a; 卸载步骤&#xff1a; 三、MySQL服务操作 1.服务启动和关闭&#xff1a; 2.登录和退出MySQL&#xff1a; 3.服务自启动&#xff1a; 4.命令行登…

Python实现线性查找算法

Python实现线性查找算法 以下是使用 Python 实现线性查找算法的示例代码&#xff1a; def linear_search(arr, target):"""线性查找算法:param arr: 要搜索的数组:param target: 目标值:return: 如果找到目标值&#xff0c;返回其索引&#xff1b;否则返回 -1…

【玩转Linux】有关Linux权限

目录 一.Linux权限的概念 1. 权限的本质 2.Linux中的用户 3.Linux中的权限管理 (1)文件访问者的分类 (2)文件类型和访问权限&#xff08;事物属性&#xff09; ①文件基本权限 ②文件权限值的表示方法 (3)文件访问权限的相关设置方法 ① 用 户 表 示 符 / - 权 …

Vue3 快速上手从0到1,两小时学会【附源码】

小伙伴们好&#xff0c;欢迎关注&#xff0c;一起学习&#xff0c;无限进步 以下内容为vue3的学习笔记 项目需要使用到的依赖 npm install axios npm install nanoid vue-router npm install pinia npm install mitt 源码&#xff1a;Gitee 运行 npm install npm run dev需要运…

MacBook2024苹果免费mac电脑清理垃圾软件CleanMyMac X

CleanMyMac X是一款专业的Mac清理软件&#xff0c;具备多种强大功能。首先&#xff0c;它能够智能清理Mac磁盘上的垃圾文件和多余语言安装包&#xff0c;从而快速释放电脑内存。其次&#xff0c;CleanMyMac X可以轻松管理和升级Mac上的应用&#xff0c;同时强力卸载恶意软件并修…

windows使用pyenv

1、前言 虽然anaconda比pyenv相比有更好的python安装体验&#xff0c;但是有一个比较严重的问题的就是&#xff0c;他的python版本跨度不够大&#xff0c;一些老一些的项目的python版本找不到&#xff0c;比如py12306要求的python版本是3.6&#xff0c;在anaconda却找不到这个版…

查看pip当前关联python版本及位置

好久没用python了&#xff0c;把各种pip指向的环境忘光光啦&#xff0c;这里记录一下查看pip当前关联的python版本及位置的方法&#xff1a; pip -V结果&#xff1a; 我一般不用这个版本的python&#xff0c;去环境变量看了一下&#xff0c;原来是anaconda的Scripts自带pip&a…

gprof安装使用(CMake)说明

一、安装 1、gprof默认已安装&#xff0c;可安装相关图形处理 sudo apt-get install python graphviz sudo pip install gprof2dot 注意&#xff1a;在Debian中没有安装成功&#xff0c;报Python的版本不匹配 二、使用说明 1、使用CMake管理的工程&#xff1a; 重新配置CMa…

Elastic Stack--05--聚合、映射mapping

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.聚合(aggregations)基本概念桶&#xff08;bucket&#xff09;度量&#xff08;metrics&#xff09; 案例 11. 接下来按price字段进行分组&#xff1a;2. 若想对所…

LVS集群 ----------------(直接路由 )DR模式部署 (二)

一、LVS集群的三种工作模式 lvs-nat&#xff1a;修改请求报文的目标IP,多目标IP的DNAT lvs-dr&#xff1a;操纵封装新的MAC地址&#xff08;直接路由&#xff09; lvs-tun&#xff1a;隧道模式 lvs-dr 是 LVS集群的 默认工作模式 NAT通过网络地址转换实现的虚拟服务器&…

2024年【电工(初级)】考试内容及电工(初级)考试报名

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 电工&#xff08;初级&#xff09;考试内容根据新电工&#xff08;初级&#xff09;考试大纲要求&#xff0c;安全生产模拟考试一点通将电工&#xff08;初级&#xff09;模拟考试试题进行汇编&#xff0c;组成一套电…

Gitlab修改仓库权限为public、Internal、Private

Public&#xff08;公开&#xff09;&#xff1a;所有人都可以访问该仓库&#xff1b; Internal&#xff08;内部&#xff09;&#xff1a;同一个GitLab群组或实例内的所有用户都可以访问该仓库&#xff1b; Private&#xff08;私人&#xff09;&#xff1a;仅包括指定成员的用…