华容道算法和使用广度搜索的一些单人游戏求解框架

      最新无聊在玩华容道,结果玩的时候,有些关不知道怎么过,就自己想着写程序来求最小还原步数。经过一番搜索和思考,写出来下面的代码,其中借鉴了别人的红黑树的代码,还有就是使用广度搜索来求解的思想。

      在写算法的过程中,突然想到还有其他的单人游戏也是可以用广度搜索来求解的,因此,就针对这类游戏写了一个框架,适用于状态数不会太变态的游戏,例如华容道,Unblock me(移动木块)之类的游戏。3阶以上的魔方就不能用这个框架,状态数太多,使用广度搜索的话内存完全不够用。

file: OnePlayerMap

#ifndef ONEPLAYERMAP_H_
#define ONEPLAYERMAP_H_

#include <stdlib.h>

struct OnePlayerMap
{
        OnePlayerMap()
        :mLastMap(NULL)
        ,mNext(NULL)
        ,mStep(0)
        {count++;};
        virtual ~OnePlayerMap()
        {count--;}
        static int count;
        virtual bool less_equal(const OnePlayerMap* status) = 0;
        // 判断是否是结局或目标状态
        virtual bool isEnd() = 0;
        // 返回由这一个状态能转变到的所有状态的链表, 即广度搜索
        virtual OnePlayerMap* getNextStatuses() = 0;
        // 显示或打印这个状态
        virtual void print() = 0;

        OnePlayerMap* mLastMap;
        OnePlayerMap* mNext;
        int mStep;
};

#endif /* ONEPLAYERMAP_H_ */

游戏状态的基类,派生类必须实现那几个纯虚函数。

bool isEnd() 是判断当前状态是否是目标状态,例如曹操是否移到出口。

bool less_equal(const OnePlayerMap* status) 是判断当前状态是否小于等于status的状态,这个方法是用来在插入红黑树时使用的。

OnePlayerMap* getNextStatuses() 是返回一个链表,这个链表的内容是由当前状态衍生出来的下一步的所有状态。

void print()是显示或打印当前的状态,这个可以根据需要自己定义打印的格式。

file:RBTree.h

#include <stdlib.h>
#include <string>
#include <iostream>
#include <functional>

template <typename T, typename Comp = std::less_equal<T> >
class RedBlackTree
{
        typedef bool RB_TREE_COLOR;
        const static RB_TREE_COLOR BLACK = false;
        const static RB_TREE_COLOR RED = true;
    struct Node{
                T       key;
                bool    color;
                Node*   parent;
                Node*   left;
                Node*   right;
                Node(T data_, bool  color_, Node* p, Node* l, Node* r)
                        :key(data_),color(color_),parent(p),left(l),right(r){}
                ~Node(){}
    };
        Node* NIL;
        Node* root;
        Comp compare;
        bool isUnique;// is all data unique

public:

    RedBlackTree(bool unique=true, Node* p=NULL, Node* q=NULL, Node* e=NULL)
    :isUnique(unique)
    {
                NIL =  new Node(0, BLACK, NIL, NIL, NIL);//哨兵结点
                root = NIL;
    }
    ~RedBlackTree()
    {
                DeleteTree(root);
                delete NIL;
    }

        void  LeftRotate(Node* x);
        void  RightRotate(Node* y);
        bool  RBInsert(T data); // true: insert success, false: has equals data.
        void  RBInsertFixup(Node* z);
        void  RBDelete(T data);
        void  RBDeleteFixUp(Node* x);
        Node* TreeSearchNumber(Node* x, T k);
        Node* TreeSuccessor(Node* x);
        void  DeleteTree(Node* x);
        void  PrintTree(Node* x);
        Node* GetNode(void);
        Node* TreeMinIMUM(Node* x );
};


template<typename T, typename Comp>
typename RedBlackTree<T, Comp>::Node* RedBlackTree<T, Comp>::TreeMinIMUM(Node* x) {
        while (x->left != NIL)
                x = x->left;
        return x;
}
template<typename T, typename Comp>
typename RedBlackTree<T, Comp>::Node* RedBlackTree<T, Comp>::GetNode(void) {
        return root;
}

template<typename T, typename Comp>
void RedBlackTree<T, Comp>::PrintTree(Node* x) {
        if (NIL != x) {
                //std::cout << x->key << std::endl;
                x->key->print();
                if (NIL != x->left) {
                        PrintTree(x->left);
                }
                if (NIL != x->right) {
                        PrintTree(x->right);
                }
        }
}

template<typename T, typename Comp>
void RedBlackTree<T, Comp>::DeleteTree(Node* x) {
        if (x != NIL) {
                if (NIL != x->left) {
                        DeleteTree(x->left);
                }
                if (NIL != x->right) {
                        DeleteTree(x->right);
                }
                delete x;
                x = NULL;
        }
}

template<typename T, typename Comp>
typename RedBlackTree<T, Comp>::Node* RedBlackTree<T, Comp>::TreeSearchNumber(Node* x, T k) {
        if (x == NIL || k == x->key)
                return x;
        if (compare(x->key, k))
                return TreeSearchNumber(x->left, k);
        else
                return TreeSearchNumber(x->right, k);
}

template<typename T, typename Comp>
typename RedBlackTree<T, Comp>::Node* RedBlackTree<T, Comp>::TreeSuccessor(Node* x) //存在两种情况:
{
        if (x->right != NIL) //如果结点x的右子树非空,则x的后继即右子树中的最左的结点。
                return TreeMinIMUM(x->right);
        Node* y = x->parent; //如果结点x的右子树为空,且x有一个后继y,则y是x的最低祖先结点,
        while ((y != NIL) && (x == x->right)) //且y的左儿子也是x的祖先票篇 p154,p155《算法导论》
        {
                x = y;
                y = y->parent;
        }
        return y;
}

template<typename T, typename Comp>
void RedBlackTree<T, Comp>::LeftRotate(Node* x) {
        Node* y = x->right; //y是x的右结点
        if (NIL == y)
                return;
        x->right = y->left; //让x的右指针指向y的左结点。
        if (NIL != y->left) //y的左结点不是哨兵
                y->left->parent = x; //让y的左结点的parent指向x
        y->parent = x->parent; //让y的父子针指向x的父结点
        if (x->parent == NIL) //x为根结点
        {
                root = y; //让y成为根结点
        } else if (x == x->parent->left) //如果x为左子女
        {
                x->parent->left = y; //y便代替x成为左子女
        } else
                x->parent->right = y; //否则代替x成为右子女

        y->left = x; //x成为y的左子女
        x->parent = y; //y成为x的父结点
}

template<typename T, typename Comp>
void RedBlackTree<T, Comp>::RightRotate(Node* y) {
        Node* x = y->left;
        if (NIL == x)
                return;
        y->left = x->right;
        if (x->right != NIL)
                x->right->parent = y;
        x->parent = y->parent;
        if (y->parent == NIL) {
                root = x;
        } else if (y == y->parent->right) {
                y->parent->right = x;
        } else {
                y->parent->left = x;
        }

        x->right = y;
        y->parent = x;
}

template<typename T, typename Comp>
bool RedBlackTree<T, Comp>::RBInsert(T data) {
        Node* x = root;
        Node* y = NIL;

        while (x != NIL) {
                y = x;
                if (compare(data, x->key)) // 如果data <= x->key
                {
                        if (isUnique && compare(x->key, data))
                        {// 如果a<=b同时b<=a,那么a=b.
                         // 找到相同的节点,如果不允许相同节点,则返回
                                return false;
                        }
                        if (x->left != NIL) {
                                x = x->left;
                        } else {
                                break;
                        }
                } else {
                        if (x->right != NIL) {
                                x = x->right;
                        } else {
                                break;
                        }
                }
        }

        Node* z = new Node(data, RED, y, NIL, NIL); //将要插入的结点
        if (y == NIL)
                root = z;
        else if (compare(data, y->key))
                y->left = z;
        else
                y->right = z;

        RBInsertFixup(z);
        return true;
}
//在调用RBInsertFixup(),那些红黑树的性质可能会被破坏呢?性质1和性质3当然继续成立,
//因为新插入的结点的子女都是哨兵NIL。性质5即从一个制定结点开始的每条路径上黑结点的个数
//都是相等的,也会成立,因为结点z本身就是具有哨兵子女的红结点。因此,可能被破坏的就是根节点2,
//以及一个红结点不能有红子女的性质4。这两个可能的破坏是因为z被着为红色。如果z是根结点则破坏了性质2,
//如果z的父结点是红色就破坏了性质4.

template<typename T, typename Comp>
void RedBlackTree<T, Comp>::RBInsertFixup(Node* z) {
        Node* y = NIL;
        while (root != z && z->parent->color == RED) {
                if (z->parent == z->parent->parent->left) {
                        y = z->parent->parent->right;
                        if (y != NIL && y->color == RED) {
                                z->parent->color = BLACK;
                                y->color = BLACK;
                                z->parent->parent->color = RED;
                                z = z->parent->parent;
                        } else {
                                if (z == z->parent->right) {
                                        z = z->parent;
                                        LeftRotate(z);
                                }

                                z->parent->color = BLACK;
                                z->parent->parent->color = RED; //还没旋转
                                RightRotate(z->parent->parent);
                        }
                }
                else {
                        y = z->parent->parent->left;
                        if (y != NIL && y->color == RED) {
                                z->parent->color = BLACK;
                                y->color = BLACK;
                                z->parent->parent->color = RED;
                                z = z->parent->parent;
                        } else {
                                if (z == z->parent->left) {
                                        z = z->parent;
                                        RightRotate(z);
                                }

                                z->parent->color = BLACK;
                                z->parent->parent->color = RED;
                                LeftRotate(z->parent->parent);
                        }
                }
        } //while

        root->color = BLACK;
}

template<typename T, typename Comp>
void RedBlackTree<T, Comp>::RBDelete(T data) {
        Node* x = NIL;
        Node* y = NIL;
        //查找看有没有值和同结点指示的一样
        Node* z = TreeSearchNumber(root, data); //找到此结点
        if ((z->left == NIL) || (z->right == NIL)) {
                y = z;
        } else {
                y = TreeSuccessor(z);
        }
        if (y->left != NIL) {
                x = y->left;
        } else {
                x = y->right;
        }
        x->parent = y->parent;
        if (y->parent == NIL)
                root = x;
        else if (y == y->parent->left)
                y->parent->left = x;
        else
                y->parent->right = x;

        if (y != z)
                z->key = y->key;

        if (y->color == BLACK && NIL != x)
                RBDeleteFixUp(x);

        delete y;
}

template<typename T, typename Comp>
void RedBlackTree<T, Comp>::RBDeleteFixUp(Node* x) {
        Node* w = NIL;
        while (x != root && BLACK == x->color) {
                if (x == x->parent->left) {
                        w = x->parent->right;
                        if (NIL == w)
                                continue;
                        if (w->color == RED) {
                                w->color = BLACK;
                                x->parent->color = RED;
                                LeftRotate(x->parent);
                                w = x->parent->right;
                        }
                        if (NIL != w->left && BLACK == w->left->color && NIL != w->right
                                        && BLACK == w->right->color) {
                                w->color = RED;
                                x = x->parent;
                        } else {
                                if (NIL != w->right && BLACK == w->right->color) {
                                        w->left->color = BLACK;
                                        w->color = RED;
                                        RightRotate(w);
                                        w = x->parent->right;
                                }
                                w->color = x->parent->color;
                                x->parent->color = BLACK;
                                w->right->color = BLACK;
                                LeftRotate(x->parent);
                                x = root;
                        }
                }
                else {
                        w = x->parent->left;
                        if (NIL == w)
                                continue;
                        if (RED == w->color) {
                                w->color = BLACK;
                                x->parent->color = RED;
                                RightRotate(x->parent);
                        }
                        if (NIL != w->left && BLACK == w->left->color && NIL != w->right
                                        && BLACK == w->right->color) {
                                w->color = RED;
                                x = x->parent;
                        } else {
                                if (NIL != w->left && w->left->color == BLACK) {
                                        w->right->color = BLACK;
                                        w->color = RED;
                                        LeftRotate(w);
                                        w = x->parent->left;
                                }

                                w->color = w->parent->color;
                                w->parent->color = BLACK;
                                w->left->color = BLACK;
                                RightRotate(w->parent);
                                x = root;
                        }

                }
        }
        x->color = BLACK;
}
这个是红黑树的实现代码,是从别人那拷贝过来,根据我的需要增加了一个仿函数的模板参数.这里就不详细介绍了。


file:OnePlayerGame.h

#ifndef ONEPLAYERGAME_H_
#define ONEPLAYERGAME_H_

#include <functional>
#include "RBTree.h"
#include "OnePlayerMap.h"

using namespace std;
//仿函数,用来对两个指针类型的对象调用其less_euqal(T)函数
template <class T>
struct less_euqal_pointer: public binary_function<T, T, bool> {
        bool operator()(const T&x, const T& y) const
        {
                return (*x).less_equal(y);
        }
};

class OnePlayerGame
{
public:
        OnePlayerGame(OnePlayerMap* state)
        :mStartState(state)
        ,mEndState(NULL)
        ,mHasSolution(false)
        {
                mStartState->mNext = mStartState;
        }

        virtual ~OnePlayerGame()
        {
                clear();
        }
        bool startFindSolution(int maxStep = 10000); // 缺省最大寻找10000步数, 查找步数大于maxStep时报失败,广度搜索
        bool hasSolution() {return mHasSolution;}
        void printSolution();

protected:
        void clear();//清除占用的内存

        OnePlayerMap* mStartState;
        OnePlayerMap* mEndState;
        bool mHasSolution;
        RedBlackTree<OnePlayerMap*, less_euqal_pointer<OnePlayerMap*> > mRedBlackTree;
};

#endif /* ONEPLAYERGAME_H_ */
调用步骤是,构造时传入初始状态,然后调用startFindSolution(maxStep), 找到solution返回true,否则返回false,maxStep是尝试的最大步数,超过这个步数则失败。

bool hasSolution()返回调用startFindSolution是否找到solution的结果

printSolution()如果有找到solution,则调用此方法将每一步打印出来,从上到下是从最终结果往初始状态一步一步显示出来,以后可以考虑反过来显示。

file:OnePlayerGame.cpp

#include <stdio.h>
#include "OnePlayerGame.h"

int OnePlayerMap::count = 0;
bool OnePlayerGame::startFindSolution(int maxStep)
{
        OnePlayerMap* p = mStartState;
        OnePlayerMap* tail = mStartState->mNext;
        mHasSolution = false;
        while(p != NULL && p->mStep < maxStep)
        {
                if (p->isEnd()) {
                        mHasSolution = true;
                        mEndState = p;
                        break;
                }

                OnePlayerMap* nextStatus = p->getNextStatuses();//返回环形链表,最后一个元素的mNext是nextStatus。
                tail->mNext = nextStatus;
                while(tail->mNext != NULL)
                {
                        if (mRedBlackTree.RBInsert(tail->mNext))
                        {//插入成功,没有重复
                                tail->mNext->mStep = p->mStep + 1;
                                tail = tail->mNext;
                        } else {
                         // 已经有重复的状态了,删除该状态
                                OnePlayerMap* temp = tail->mNext;
                                tail->mNext = tail->mNext->mNext;
                                delete temp;
                        }
                }

                p = p->mNext;
        }

        return mHasSolution;
}

void OnePlayerGame::printSolution()
{
        if (mHasSolution)
        {
                //printf("total states:%d\n", state->count);
                int count = 0;
                OnePlayerMap* p = mEndState;
                while(p != NULL)
                {
                        p->print();
                        p = p->mLastMap;
                        count++;
                }

                printf("total steps:%d\n", count);
        }
        else
        {
                printf("can't found solution\n");
        }
}

void OnePlayerGame::clear()
{
        OnePlayerMap* p = mStartState->mNext;
        while (p != NULL)
        {
                OnePlayerMap* temp = p;
                p=p->mNext;
                delete temp;
        }
}

file:HuaRongDaoMap.h

#ifndef HUARONGDAOMAP_H_
#define HUARONGDAOMAP_H_

#include <stdlib.h>
#include "OnePlayerMap.h"

class HuaRongDaoMap : public OnePlayerMap
{
public:
        HuaRongDaoMap()
        :mCao(0)
        ,mShujiang(0)
        ,mHengjiang(0)
        ,mBing(0)
        ,mKongge(0)
        {}
        HuaRongDaoMap(const char chessNumber, const char chess[]);
        HuaRongDaoMap(const HuaRongDaoMap& status)
        :mCao(status.mCao)
        ,mShujiang(status.mShujiang)
        ,mHengjiang(status.mHengjiang)
        ,mBing(status.mBing)
        ,mKongge(status.mKongge)
        {
        }

        bool less_equal(const OnePlayerMap* status);
        virtual bool isEnd(){return (mCao == 10);}
        virtual OnePlayerMap* getNextStatuses();

        // 交换一个数中两个部分的位值
        // value: 被交换的数
        // source, target :要交换的位的起始位置
        // length: 要交换的位数
        int switchbits(int value, int source, int target, int length)
        {
            int x = ((value >> source) ^ (value >> target)) & ((1U << length) - 1); // XOR temporary
                return value ^ ((x << source) | (x << target));
        }

        virtual void print();

        char mCao;// possible value 0 - 11,
        int mShujiang;
        int mHengjiang;
        int mBing;
        int mKongge;
};

#endif /* HUARONGDAOMAP_H_ */

file:HuaRongDao.cpp

#include <stdio.h>
#include <assert.h>
#include "HuaRongDaoMap.h"

HuaRongDaoMap::HuaRongDaoMap(const char chessNumber, const char chess[])
:mShujiang(0)
,mHengjiang(0)
,mBing(0)
,mKongge(0)
{
        int bMap = 0;
        int position = 0;
        int squalNumber = 0;
        for (int i = 0; i < chessNumber; i++)
        {
                switch(chess[i])
                {
                case 'k':// kongge
                        squalNumber++;
                        mKongge |= (1 << position);
                        bMap |= (1 << position);
                        break;
                case 'b':// bing
                        squalNumber++;
                        mBing |= (1 << position);
                        bMap |= (1 << position);
                        break;
                case 's':// shujiang
                        squalNumber += 2;
                        mShujiang |= (1 << position);
                        bMap |= (1 << position);
                        bMap |= (1 << (position + 4));
                        break;
                case 'h':// hengjiang
                {
                        squalNumber += 2;
                        int x = position & 0x3;
                        int y = position >> 2;
                        mHengjiang |= (1 << (y * 3 + x));
                        bMap |= (3 << position);
                }
                        break;
                case 'c':// cao
                {
                        squalNumber += 4;
                        int x = position & 0x3;
                        int y = position >> 2;
                        mCao = y * 3 + x;
                        bMap |= (3 << position);
                        bMap |= (3 << (position + 4));
                }
                        break;
                }

                while(bMap >> position & 1)
                {
                        position++;
                }
        }

        assert(squalNumber == 20);
}

OnePlayerMap* HuaRongDaoMap::getNextStatuses()
{
        HuaRongDaoMap head;
        OnePlayerMap* point = &head;
        // move cao
        int caoX = mCao % 3; // 7, x=1, y = 2
        int caoY = mCao / 3; // 2, x=2, y = 0
        if (caoX > 0) {
                int leftOne = (caoY << 2) + caoX - 1;
                if ((1 << leftOne & mKongge) &&
                   (1 << (leftOne + 4) & mKongge))
                {
                        // move left
                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                        state->mCao = mCao - 1;
                        state->mKongge = switchbits(state->mKongge, leftOne + 2, leftOne, 1);
                        state->mKongge = switchbits(state->mKongge, leftOne + 2 + 4, leftOne + 4, 1);
                        state->mLastMap = this;
                        point->mNext = state;
                        point = point->mNext;
                }
        }

        if (caoX < 2) {
                int rightOne = (caoY << 2) + caoX + 2;
                if ((1 << rightOne & mKongge) &&
                        (1 << (rightOne + 4) & mKongge))
                {
                        // move right
                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                        state->mCao = mCao + 1;
                        state->mKongge = switchbits(state->mKongge, rightOne - 2, rightOne, 1);
                        state->mKongge = switchbits(state->mKongge, rightOne - 2 + 4, rightOne + 4, 1);
                        state->mLastMap = this;
                        point->mNext = state;
                        point = point->mNext;
                }
        }

        if (caoY > 0) {
                int upOne = (caoY << 2) - 4 + caoX;
                if ((1 << upOne & mKongge) &&
                        (1 << (upOne + 1) & mKongge))
                {
                        // move up
                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                        state->mCao = mCao - 3;
                        state->mKongge = switchbits(state->mKongge, upOne + 8, upOne, 1);
                        state->mKongge = switchbits(state->mKongge, upOne + 8 + 1, upOne + 1, 1);
                        state->mLastMap = this;
                        point->mNext = state;
                        point = point->mNext;
                }
        }

        if (caoY < 3)
        {
                int downOne = (caoY << 2) + 8 + caoX ;// cao 的下面位置,用来判断是否是空格
                if ((1 << downOne & mKongge) &&
                        (1 << (downOne + 1) & mKongge))
                {
                        // move down
                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                        state->mCao = mCao + 3;
                        state->mKongge = switchbits(state->mKongge, downOne - 8, downOne, 1);
                        state->mKongge = switchbits(state->mKongge, downOne - 8 + 1, downOne + 1, 1);
                        state->mLastMap = this;
                        point->mNext = state;
                        point = point->mNext;
                }
        }

        // move heng jiang
        for (int i = 0; i < 15; i++)
        {
                if (mHengjiang >> i & 1)
                {
                        int hengX = i % 3;
                        int hengY = i / 3;
                        if (hengX > 0)
                        {
                                int leftOne = (hengY << 2) + hengX - 1;
                                if (1 << leftOne & mKongge)
                                {
                                        // move 1 left
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mHengjiang = switchbits(state->mHengjiang, i, i - 1, 1);
                                        state->mKongge = switchbits(state->mKongge, leftOne, leftOne + 2, 1);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;
                                        if ( hengX > 1 &&
                                                (1 << (leftOne - 1) & mKongge))
                                        {
                                                // move 2 left
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mHengjiang = switchbits(state->mHengjiang, i, i - 2, 1);
                                                state->mKongge = switchbits(state->mKongge, leftOne - 1, leftOne - 1 + 2, 2);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }
                                }
                        }

                        if (hengX < 2)
                        {
                                int rightOne = (hengY << 2) + hengX + 2;
                                if (1 << rightOne & mKongge)
                                {
                                        // move 1 right
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mHengjiang = switchbits(state->mHengjiang, i, i + 1, 1);
                                        state->mKongge = switchbits(state->mKongge, rightOne, rightOne - 2, 1);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;
                                        if (hengX < 1 &&
                                                (1 << (rightOne + 1) & mKongge))
                                        {
                                                // move 2 right
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mHengjiang = switchbits(state->mHengjiang, i, i + 2, 1);
                                                state->mKongge = switchbits(state->mKongge, rightOne, rightOne - 2, 2);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }
                                }
                        }

                        if (hengY > 0)
                        {
                                int upOne = (hengY << 2) + hengX - 4;
                                if ((1 << upOne & mKongge) &&
                                        (1 << (upOne + 1) & mKongge))
                                {
                                        // move up
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mHengjiang = switchbits(state->mHengjiang, i, i - 3, 1);
                                        state->mKongge = switchbits(state->mKongge, upOne, upOne + 4, 2);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;
                                }
                        }

                        if (hengY < 4)
                        {
                                int downOne = (hengY << 2) + hengX + 4;
                                if ((1 << downOne & mKongge) &&
                                        (1 << (downOne + 1) & mKongge))
                                {
                                        // move down
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mHengjiang = switchbits(state->mHengjiang, i, i + 3, 1);
                                        state->mKongge = switchbits(state->mKongge, downOne, downOne - 4, 2);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;
                                }
                        }
                }
        }

        // move shu jiang
        for (int i = 0; i < 16; i++)
        {
                if (mShujiang >> i & 1)
                {
                        int shuX = i & 3;
                        int shuY = i >> 2;
                        if (shuX > 0)
                        {
                                int leftOne = i - 1;
                                if ((1 << leftOne & mKongge) &&
                                        (1 << (leftOne + 4) & mKongge))
                                {
                                        // move left
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mShujiang = switchbits(state->mShujiang, i, i - 1, 1);
                                        state->mKongge = switchbits(state->mKongge, leftOne, leftOne + 1, 1);
                                        state->mKongge = switchbits(state->mKongge, leftOne + 4, leftOne + 4 + 1, 1);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;
                                }
                        }

                        if (shuX < 3)
                        {
                                int rightOne = i + 1;
                                if ((1 << rightOne & mKongge) &&
                                        (1 << (rightOne + 4) & mKongge))
                                {
                                        // move right
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mShujiang = switchbits(state->mShujiang, i, i + 1, 1);
                                        state->mKongge = switchbits(state->mKongge, rightOne, rightOne - 1, 1);
                                        state->mKongge = switchbits(state->mKongge, rightOne + 4, rightOne + 4 - 1, 1);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;
                                }
                        }

                        if (shuY > 0)
                        {
                                int upOne = i - 4;
                                if (1 << upOne & mKongge)
                                {
                                        // move 1 up
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mShujiang = switchbits(state->mShujiang, i, i - 4, 1);
                                        state->mKongge = switchbits(state->mKongge, upOne, upOne + 8, 1);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;

                                        if (shuY > 1 &&
                                                (1 << (upOne - 4) & mKongge))
                                        {
                                                // move 2 up
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mShujiang = switchbits(state->mShujiang, i, i - 8, 1);
                                                state->mKongge = switchbits(state->mKongge, upOne, upOne + 8, 1);
                                                state->mKongge = switchbits(state->mKongge, upOne - 4, upOne + 4, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }
                                }
                        }

                        if (shuY < 3)
                        {
                                int downOne = i + 8;
                                if (1 << downOne & mKongge)
                                {
                                        // move 1 down
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mShujiang = switchbits(state->mShujiang, i, i + 4, 1);
                                        state->mKongge = switchbits(state->mKongge, downOne, downOne - 8, 1);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;
                                        if (shuY < 2 &&
                                                (1 << (downOne + 4) & mKongge))
                                        {
                                                // move 2 down
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mShujiang = switchbits(state->mShujiang, i, i + 8, 1);
                                                state->mKongge = switchbits(state->mKongge, downOne, downOne - 8, 1);
                                                state->mKongge = switchbits(state->mKongge, downOne + 4, downOne - 4, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }
                                }
                        }
                }
        }

        // move bing
        for (int i = 0; i < 20; i++)
        {
                if (mBing >> i & 1)
                {
                        int bingX = i & 3;
                        int bingY = i >> 2;
                        if (bingX > 0)
                        {
                                if (1 << (i - 1) & mKongge)
                                {
                                        // move l left
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mBing = switchbits(state->mBing, i, i - 1, 1);
                                        state->mKongge = switchbits(state->mKongge, i - 1, i, 1);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;

                                        if (bingX > 1 &&
                                                (1 << (i - 2) & mKongge))
                                        {
                                                // move 2 left
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i - 2, 1);
                                                state->mKongge = switchbits(state->mKongge, i - 2, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }

                                        if (bingY > 0 &&
                                                (1 << (i - 5) & mKongge))
                                        {
                                                // move left up
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i - 5, 1);
                                                state->mKongge = switchbits(state->mKongge, i - 5, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }

                                        if (bingY < 4 &&
                                                (1 << (i + 3) & mKongge))
                                        {
                                                // move left down
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i + 3, 1);
                                                state->mKongge = switchbits(state->mKongge, i + 3, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }
                                }
                        }

                        if (bingX < 3)
                        {
                                if (1 << (i + 1) & mKongge)
                                {
                                        // move 1 right
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mBing = switchbits(state->mBing, i, i + 1, 1);
                                        state->mKongge = switchbits(state->mKongge, i + 1, i, 1);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;
                                        if (bingX < 2 &&
                                                (1 << (i + 2) & mKongge))
                                        {
                                                // move 2 right
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i + 2, 1);
                                                state->mKongge = switchbits(state->mKongge, i + 2, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }

                                        if (bingY > 0 &&
                                                (1 << (i - 3) & mKongge))
                                        {
                                                // move right up
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i - 3, 1);
                                                state->mKongge = switchbits(state->mKongge, i - 3, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }

                                        if (bingY < 4 &&
                                                (1 << (i + 5) & mKongge))
                                        {
                                                // move right down
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i + 5, 1);
                                                state->mKongge = switchbits(state->mKongge, i + 5, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }
                                }
                        }

                        if (bingY > 0)
                        {
                                if (1 << (i - 4) & mKongge)
                                {
                                        // move 1 up
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mBing = switchbits(state->mBing, i, i - 4, 1);
                                        state->mKongge = switchbits(state->mKongge, i - 4, i, 1);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;
                                        if (bingY > 1 &&
                                                (1 << (i - 8) & mKongge))
                                        {
                                                // move 2 up
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i - 8, 1);
                                                state->mKongge = switchbits(state->mKongge, i - 8, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }

                                        if (bingX > 0 &&
                                                (1 << (i - 5) & mKongge))
                                        {
                                                // move up left
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i - 5, 1);
                                                state->mKongge = switchbits(state->mKongge, i - 5, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }

                                        if (bingX < 3 &&
                                                (1 << (i - 3) & mKongge))
                                        {
                                                // move up right
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i - 3, 1);
                                                state->mKongge = switchbits(state->mKongge, i - 3, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }
                                }
                        }

                        if (bingY < 4)
                        {
                                if (1 << (i + 4) & mKongge)
                                {
                                        // move 1 down
                                        HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                        state->mBing = switchbits(state->mBing, i, i + 4, 1);
                                        state->mKongge = switchbits(state->mKongge, i + 4, i, 1);
                                        state->mLastMap = this;
                                        point->mNext = state;
                                        point = point->mNext;
                                        if (bingY < 3 &&
                                                (1 << (i + 8) & mKongge))
                                        {
                                                // move 2 down
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i + 8, 1);
                                                state->mKongge = switchbits(state->mKongge, i + 8, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }

                                        if (bingX > 0 &&
                                                (1 << (i + 3) & mKongge))
                                        {
                                                // move down left
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i + 3, 1);
                                                state->mKongge = switchbits(state->mKongge, i + 3, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }

                                        if (bingX < 3 &&
                                                (1 << (i + 5) & mKongge))
                                        {
                                                // move down right
                                                HuaRongDaoMap* state = new HuaRongDaoMap(*this);
                                                state->mBing = switchbits(state->mBing, i, i + 5, 1);
                                                state->mKongge = switchbits(state->mKongge, i + 5, i, 1);
                                                state->mLastMap = this;
                                                point->mNext = state;
                                                point = point->mNext;
                                        }
                                }
                        }
                }
        }

        point->mNext = NULL;
        return head.mNext;
}

void HuaRongDaoMap::print()
{
        char map[4][5];
        int caoX = mCao % 3;
        int caoY = mCao / 3;
        map[caoX][caoY] = 5;
        map[caoX + 1][caoY] = 5;
        map[caoX][caoY + 1] = 5;
        map[caoX + 1][caoY + 1] = 5;

        for (int i = 0; i < 15; i++)
        {
                if (1 << i & mHengjiang)
                {
                        int hengX = i % 3;
                        int hengY = i / 3;
                        map[hengX][hengY] = 4;
                        map[hengX + 1][hengY] = 4;
                }
        }

        for (int i = 0; i < 16; i++)
        {
                if (1 << i & mShujiang)
                {
                        int shuX = i & 3;
                        int shuY = i >> 2;
                        map[shuX][shuY] = 3;
                        map[shuX][shuY + 1] = 3;
                }
        }

        for (int i = 0; i < 20; i++)
        {
                if (1 << i & mBing)
                {
                        map[i & 3][i >> 2] = 1;
                }
        }

        for (int i = 0; i < 20; i++)
        {
                if (1 << i & mKongge)
                {
                        map[i & 3][i >> 2] = 0;
                }
        }

        for (int i = 0; i < 5; i++)
        {
                for (int j = 0; j < 4; j++)
                {
                        printf("%d ", map[j][i]);
                }
                printf("\n");
        }
        printf("\n");
}

bool HuaRongDaoMap::less_equal(const OnePlayerMap* status)
{
        const HuaRongDaoMap* newData = dynamic_cast<const HuaRongDaoMap*>(status);
        assert(newData != NULL);
        int val = (mHengjiang << 16 | mShujiang);
        int newval = (newData->mHengjiang << 16 | newData->mShujiang);
        if (val != newval)
        {
                return val <= newval;
        }

        int val2 = ((mBing << 4) | mCao);
        int newval2 = (newData->mBing << 4) | newData->mCao;
        return val2 <= newval2;
} 

file:main.cpp

#include <stdio.h>
#include <sys/time.h>

#include "OnePlayerGame.h"
#include "HuaRongDaoMap.h"

int main() {
        {
                HuaRongDaoMap state(12,"kcksbhbbhsbh");

                printf("play game\n");
                OnePlayerGame oneGame(&state);
                struct timeval tpstart,tpend;
                gettimeofday(&tpstart,NULL); //获取时间

                oneGame.startFindSolution();
                gettimeofday(&tpend,NULL);

                printf("find solution time is %ld usecond\n",
                                1000000 * (tpend.tv_sec - tpstart.tv_sec) + tpend.tv_usec-tpstart.tv_usec);
                if (oneGame.hasSolution()) {
                        oneGame.printSolution();
                } else {
                        printf("can't find solution.\n");
                }
                printf("OnePlayerMap allocate Node Count:%d\n", OnePlayerMap::count);
        }
        printf("OnePlayerMap Node Count after release:%d\n", OnePlayerMap::count);
        return 0;
}
这个框架只用参照HuaRongDaoMap.h(.cpp),重新写一个派生类,实现那几个函数,就可以很简单的运行了。


你可能感兴趣的:(华容道算法和使用广度搜索的一些单人游戏求解框架)