您的位置:首页 > 编程语言 > C语言/C++

华容道游戏破解C++版(MFC)

2018-03-14 13:57 204 查看
参见下面的文章,华容道用C#写出破解后,感觉程序实在是简单,于是尝试移植到其他语言上http://blog.csdn.net/robinspada/article/details/79354500仅仅是简单移植,没有特别优化,运行时间如下


这个版本是所有版本里面移植起来最麻烦的一个,主要是C++好久没有使用了,在指针和字符串编码上花了大量时间指针:当时从C++到java的时候,没有绝对指针有什么不好,反而觉得指针效率高,自己能够完全掌控指针。这次移植就被指针坑了,花了大半天时间,而其他的移植也就2,3个小时。类库使用MFC,当年觉得MFC博大精深,现在看来确实比.net差好多CMapStringToString只支持UNICODE的字符串,当时没有明白,老是无法正确检索
唯一的欣慰就是C++写出来的程序运行时间最短,大约是C#的一半。郁闷的是,网上有文章说c语言的程序,最快可以达到十几毫秒,而且机器比我的差很多,不知是真是假现在的程序中,动态分配内存和字符内码转换比较花时间,不过改成静态就能达到十几毫秒吗?不知道

#include "stdafx.h"
class Node
{
public:
char map[21];
int parent;
Node() {
}
Node(const char* map, int parent)
{
memcpy(this->map, map, 21);
this->parent = parent;
}
};
class Huarongdao
{
protected:
//已经走过地图类型(去重复用)
CMapStringToString history;
//每一步的所有走法(走到终点回溯上一步用,如果只求步数则可以不要)
CArray<CArray<Node>*> allNodes;
//下一步各种走法节点
CArray<Node> *nextList=NULL;

int index;
enum Direct {
Left = -1,
Right = 1,
Up = -4,
Down = 4
};
public:
Huarongdao() {
history.InitHashTable(20011);
}
~Huarongdao() {
//需要释放allNodes,nextList的指针
for (int i = 0; i < allNodes.GetCount(); i++) {
delete allNodes[i];
}
if (nextList) delete nextList;
}
void Move(Direct dir, const char* map, char ch, bool first = true) {
char work[21];
memcpy(work, map,21);
for (int k = 0; k < 20; k++)
{
if (work[k] == ch) work[k] = ' ';
}

for (int i = 0; i < 20; i++)
{
if (map[i] == ch)
{
int pos = i + (int)dir;
int x = i % 4;

if (dir == Direct::Left && x == 0 ||
dir == Direct::Right && x == 3 ||
pos < 0 || pos >= 20) return;

if (work[pos] != ' ') return;
work[pos] = ch;
}
}

//重复检查
if (IsDuplicate(work)) return;
//加入下一步,记录父节点
nextList->Add(Node(work, index));
if (first)
{
//试着走第二步,但不能退回
if (dir != Direct::Right) Move(Direct::Left, work, ch, false);
if (dir != Direct::Left) Move(Direct::Right, work, ch, false);
if (dir != Direct::Down) Move(Direct::Up, work, ch, false);
if (dir != Direct::Up) Move(Direct::Down, work, ch, false);
}
}
bool IsDuplicate(const char* map)
{
char layout[21];
memcpy(layout, map,21);
//相似的形状统一成一种,去重复
for (int k = 0; k < 20; k++)
{
switch (layout[k]) {
case '3':
case '4':
case '6':
layout[k] = '1';
break;
case '7':
case '8':
case '9':
layout[k] = '0';
break;
}
}
LPCTSTR result;
CString key;
if (history.LookupKey((LPCTSTR)(key= layout), result)) return true;

//左右镜像(大约节约1/2时间),去重复
char reverse[21];
memcpy(reverse, layout,21);

for (int k = 0; k < 20; k++)
{
int x = 3 - (k % 4);
int y = k / 4;
reverse[y * 4 + x] = layout[k];
}
if (history.LookupKey((LPCTSTR)(key = reverse), result)) return true;
history[(LPCTSTR)(key = layout)]= _T("1");

return false;
}
void Print(int index)
{
CArray<char*> outList;
int parent = index;
for (int level = allNodes.GetCount() - 1; level >= 0; level--)
{
char* outMap = allNodes[level]->GetAt(parent).map;
parent = allNodes[level]->GetAt(parent).parent;
outList.Add(outMap);
}
int cnt = 0;
for (int j = outList.GetCount() - 1; j >= 0; j--)
{
printf("--------------------------%d\n", cnt++);
char* work = outList[j];
for (int y = 0; y < 5; y++)
{
char row[5];
row[4] = 0;
memcpy(row,work+ y * 4,4);
printf("%s\n", row);
}
}
}
void Scan()
{
char* initMap =
"1223"
"1223"
"4556"
"4786"
"9 0";
CArray<Node> *curList = new CArray<Node>();
curList->Add(Node(initMap, 0));

long t1=GetTickCount();
//迭代直到无路可走
while (nextList=NULL,allNodes.Add(curList),curList->GetCount()>0)
{
//记录每一步
//allNodes.Add(curList);

nextList = new CArray<Node>();
nextList->SetSize(0,1000);

for (index = 0; index < curList->GetCount(); index++)
{
char* map = (*curList)[index].map;
//到达终点的判断
if (map[4 * 4 + 1] == '2' && map[4 * 4 + 2] == '2')
{
printf("time:%d\n" , (GetTickCount() - t1));
Print(index);
return;
}
//穷举各种可能性,去重复,加入到下一步的节点
for (char ch = '0'; ch <= '9'; ch++)
{
Move(Direct::Left, map, ch);
Move(Direct::Right, map, ch);
Move(Direct::Up, map, ch);
Move(Direct::Down, map, ch);
}
}

//迭代
curList = nextList;
}
wprintf(_T("无解"));
}

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: