推箱子源程序v1

前面文章中贴出的代码比较零乱,这里把完整的代码贴出来,方便大家参考。

共分三个文件: 


// SokoState_v1.h -- SokoState类的头文件,第一版

#ifndef _SOKOSTATE_H
#define _SOKOSTATE_H

#include <iostream>
#include <vector>
#include <stack>

using std::vector;
using std::stack;
using std::ostream;
using std::istream;

const int MIN_ROWS = 4;
const int MAX_ROWS = 16;
const int MIN_COLS = 4;
const int MAX_COLS = 16;

class SokoState
{
public:
    SokoState() : rows_(0), cols_(0) {}
    void nextStep(vector<SokoState>&) const;
    bool isTarget() const;
    bool operator< (const SokoState& other) const;
    friend ostream& operator<< (ostream& os, const SokoState& s);
    friend istream& operator>> (istream& is, SokoState& s);
    void printAnswer(ostream& os) const;

private:
    struct Point
    {
        int x_, y_;
        Point(int x, int y) : x_(x), y_(y) {}
        Point up() const { return Point(x_-1, y_); }
        Point down() const { return Point(x_+1, y_); }
        Point left() const { return Point(x_, y_-1); }
        Point right() const { return Point(x_, y_+1); }
    };

    enum MapChar {
        CharWall = 'W',         // Wall障碍物
        CharBox = 'B',          // Box箱子,不在目的地
        CharSpace = 'S',        // Space空地,没有任何东西
        CharDest = 'D',         // Dest目的地
        CharInDest = 'I',       // 已放在目的地上的箱子
        CharSoko = 'K',         // Soko推箱子的人,不在目的地
        CharSokoInDest = 'O',   // Soko推箱子的人,恰好在目的地
        CharError = 'E'         // 错误状态
    };

    enum MapFlag {
            FlagWall = 0x01,    // 是否障碍物
            FlagBox = 0x02,     // 是否有箱子
            FlagDest = 0x04,    // 是否目的地
            FlagSoko = 0x08     // 是否有人
    };

    bool isWall(Point p) const
        { return (map_[p.x_][p.y_] & FlagWall) != 0; }
    bool isBox(Point p) const
        { return (map_[p.x_][p.y_] & FlagBox) != 0; }
    bool isDest(Point p) const
        { return (map_[p.x_][p.y_] & FlagDest) != 0; }
    bool isSoko(Point p) const
        { return (map_[p.x_][p.y_] & FlagSoko) != 0; }
    bool isSpace(Point p) const
        { return !isWall(p) && !isBox(p); }
    bool isPureSpace(Point p) const
        { return isSpace(p) && !isSoko (p); }
    unsigned char mapChar(Point p) const;
    bool moveBox(SokoState& r, Point box, Point soko, Point nBox,
        char d) const;
    void checkSoko(stack<Point>& ps, Point p);
    void stateEq();

    struct SokoStep  //用于记录每一步箱子的移动
    {
        int x_;
        int y_;
        char d_;  // direction: R,L,U,D
        SokoStep(int x, int y , char d) : x_(x), y_(y), d_(d) {}
        friend ostream& operator<< (ostream& os, const SokoStep& s)
        {
            os << "[" << s.x_ << ", " << s.y_ << ", " << s.d_ << "]";
            return os;
        }
    };

    int rows_, cols_;
    unsigned char map_[MAX_ROWS][MAX_COLS];
    vector<SokoStep> steps_;
};

#endif
 

 


 

  // SokoState_v1.cpp -- SokoState类的实现文件,第一版

 

#include <iterator>
#include <string>
#include <memory>
#include <stdexcept>
#include "SokoState_v1.h"

 

using namespace std;

 

inline unsigned char SokoState::mapChar(Point p) const
{
    if (isWall(p))
        return CharWall;
    else if (isBox(p))
        return isDest(p) ? CharInDest : CharBox;
    else if (isSoko(p))
        return isDest(p) ? CharSokoInDest : CharSoko;
    else if (isDest(p))
        return CharDest;
    else
        return CharSpace;
}

 

void SokoState::checkSoko(stack<Point>& ps, Point p)
{
    if (isPureSpace(p))
    {
        map_[p.x_][p.y_] |= FlagSoko;
        ps.push(p);
    }
}

 

void SokoState::stateEq()
{
    int i, j;
    for (i = 1; i < rows_-1; i++)
    {
        for (j = 1; j < cols_-1; j++)
        {
            if (isSoko(Point(i, j))) break;
        }
        if (j < cols_-1) break;
    }
   
    stack<Point> points;
    Point p(i, j);
    points.push(p);

 

    while (!points.empty())
    {
        p = points.top();
        points.pop();
        checkSoko(points, p.up());
        checkSoko(points, p.down());
        checkSoko(points, p.left());
        checkSoko(points, p.right());
    }
}

 

bool SokoState::moveBox(SokoState& r, Point box, Point soko, Point nBox,
    char d) const
{
    if (!isSoko(soko) || !isSpace(nBox))
        return false;

 

    r = *this;
    for (int i = 0; i < r.rows_; i++)  //清除soko标志
    {
        for (int j = 0; j < r.cols_; j++)
        {
            r.map_[i][j] &= ~FlagSoko;
        }
    }
    r.map_[box.x_][box.y_] &= ~FlagBox;  //移动箱子
    r.map_[box.x_][box.y_] |= FlagSoko;
    r.map_[nBox.x_][nBox.y_] |= FlagBox;
    r.stateEq();
    r.steps_.push_back(SokoStep(box.x_, box.y_, d));
    return true;
}

 

void SokoState::nextStep(vector<SokoState>& vs) const
{
    SokoState newState;
    for (int i = 1; i < rows_-1; i++)
    {
        for (int j = 1; j < cols_-1; j++)
        {
            Point p(i, j);
            if (!isBox(p))
                continue;
            if (moveBox(newState, p, p.down(), p.up(), 'U'))
                vs.push_back(newState);
            if (moveBox(newState, p, p.up(), p.down(), 'D'))
                vs.push_back(newState);
            if (moveBox(newState, p, p.right(), p.left(), 'L'))
                vs.push_back(newState);
            if (moveBox(newState, p, p.left(), p.right(), 'R'))
                vs.push_back(newState);
        }
    }
}

 

bool SokoState::isTarget() const
{
    for (int i = 1; i < rows_-1; i++)
    {
        for (int j = 1; j < cols_-1; j++)
        {
            Point p(i, j);
            if (isDest(p) != isBox(p))
                return false;
        }
    }
    return true;
}

 

void SokoState::printAnswer(ostream& os) const
{
    copy(steps_.begin(), steps_.end(), ostream_iterator<SokoStep>(os, " "));
}

 

bool SokoState::operator< (const SokoState& other) const
{
    if (rows_ < other.rows_)
        return true;
    if (rows_ > other.rows_)
        return false;
    if (cols_ < other.cols_)
        return true;
    if (cols_ > other.cols_)
        return false;
    for (int i = 0; i < rows_; i++)
    {
        for (int j = 0; j < cols_; j++)
        {
            if (map_[i][j] < other.map_[i][j])
                return true;
            if (map_[i][j] > other.map_[i][j])
                return false;
        }
    }
    return false;
}

 

ostream& operator<< (ostream& os, const SokoState& s)
{
    for (int i = 0; i < s.rows_; i++)
    {
        for (int j = 0; j < s.cols_; j++)
        {
            os << s.mapChar(SokoState::Point(i, j));
        }
        os << "/n";
    }
    os << "------------------------" << endl;
    return os;
}

 

istream& operator>> (istream& is, SokoState& s)
{
    is >> s.rows_;
    if (s.rows_ < MIN_ROWS || s.rows_ > MAX_ROWS)
    {
        throw invalid_argument("rows of soko game error.");
    }
    is >> s.cols_;
    if (s.cols_ < MIN_COLS || s.cols_ > MAX_COLS)
    {
        throw invalid_argument("cols of soko game error.");
    }

 

    string str;
    getline(is, str);  // 滤过第一行的换行
    for (int i = 0; i < s.rows_; i++)
    {
        getline(is, str);
        for (int j = 0; j < s.cols_; j++)
        {
            s.map_[i][j] = 0;
            switch (str[j]) {
                case SokoState::CharBox :
                    s.map_[i][j] |= SokoState::FlagBox;
                    break;
                case SokoState::CharWall :
                    s.map_[i][j] |= SokoState::FlagWall;
                    break;
                case SokoState::CharSpace :
                    break;
                case SokoState::CharDest :
                    s.map_[i][j] |= SokoState::FlagDest;
                    break;
                case SokoState::CharInDest :
                    s.map_[i][j] |= SokoState::FlagDest | SokoState::FlagBox;
                    break;
                case SokoState::CharSoko :
                    s.map_[i][j] |= SokoState::FlagSoko;
                    break;
                case SokoState::CharSokoInDest :
                    s.map_[i][j] |= SokoState::FlagSoko | SokoState::FlagDest;
                    break;
                default :
                    throw invalid_argument(
                        string("char of soko game error: ") + str );
            }
        }
    }
    s.stateEq();
    return is;
}

 

 


 

// soko.cpp -- 推箱子主程序

#include <iostream>
#include "BreadthFirstSearch.hpp"
#include "SokoState_v1.h"

using namespace std;

bool printAnswer(const SokoState& s)
{
    s.printAnswer(cout);
    cout << endl;
    return true;
}

int main(int argc, char *argv[])
{
    SokoState initState;
    cin >> initState;
    cout << initState;
    OrderCheckDup<SokoState> checkDup;
    int n = BreadthFirstSearch(initState, printAnswer, checkDup);
    if (n == 0)
    {
        cout << "No answer." << endl;
    }
 
    return 0;
}

 


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值