采用回溯的Peg Solitaire解决方案

时间:2014-03-22 22:58:51

标签: c++ algorithm recursion backtracking

我目前正在尝试编写一个能够使用反向跟踪找到游戏挂钩纸牌解决方案的程序。

我的程序接收包含起始板的txt文件。除了包含实际后跟踪部分的solve()函数之外,一切都已完成,这在概念上证明对我来说真的很难。我已经在一张纸上工作了一段时间,但我认为我没有取得多大进展。任何帮助将不胜感激。下面的示例txt文件,* = peg,. =未结头寸,2 =行3 =列

2 3

 .**

 **.

头文件

 #pragma once
 #include <string>
 #include <fstream>
 #include <iostream>
 #include <sstream>
 #include <exception>
 using namespace std;
 typedef unsigned char PegType;

class PegBoard
 {

 private:
 int numRows;
 int numCols;
 char ** pegBoard;
 enum  Direction{UP,DOWN,LEFT,RIGHT};
 PegType peg;
 PegType EMPTY;
 PegType openPosition;

public:
//constructor
PegBoard(istream &input);

//deconstructor
 ~PegBoard();

//toString
 void toString() ;

//solve
 bool solve(int x, int y);
private:
//isSolved
bool isSolved();

//canJump
bool canJump(int frmRow, int frmCol, Direction whichWay);

//jump
void jump(int frmRow, int frmCol, Direction whichWay);

//unjump
void unjump(int frmRow, int frmCol, Direction whichWay);

 };

实施档案

 #include "PegBoard.h"

//constructor
PegBoard::PegBoard(istream &input){
 string dummyLine;
 numCols = 0;
 numRows = 0;
 peg = '*';
 EMPTY = ' ';
 openPosition = '.';

 //get rows and cols
 getline(input,dummyLine);
 numRows = dummyLine[0] - '0';
 numCols = dummyLine[2] - '0';
 pegBoard = new char* [numRows];

 //generate starting board from txt file
    while(!input.eof()){
        for(int r=0; r<numRows; r++){  
            getline(input,dummyLine);
            pegBoard[r] = new char[numCols];
            for(int c=0; c<numCols; c++){
                if(dummyLine[c] == peg || dummyLine[c] == EMPTY || dummyLine[c] == openPosition)
                    pegBoard[r][c] = dummyLine[c];
                else
                    throw out_of_range("Invalid Board Configuration");
            }//end [r][c]
        }// end [r]
    }// end file
}//end constructor

//deconstructor
PegBoard::~PegBoard(){
    for (int i=0; i < numRows; i++)
        delete [] pegBoard[i];
        delete [] pegBoard;
}//end deconstructor

//solve function the one I still need to complete
bool PegBoard::solve(int x, int y){
    //base case
    if(isSolved())
        return true;
    else{
        //attempt a jump at every direction
        for(int i=0; i < 4; i++){
        switch (i){
        case 0: jump(x,y,UP);
                break;
        case 1: jump(x,y,DOWN);
                break;
        case 2: jump(x,y,LEFT);
                break;
        case 3: jump(x,y,RIGHT);
                break;
        default: 
                break;
            }//end switch
        }//end for
    }//end else
        solve(x+1,y);
        return false;
}//end solve()

//isSolved
bool PegBoard::isSolved(){
int counter =0;
//travser through board and check to see if only one * remains. 
   for(int r=0; r<numRows; r++){
        for(int c=0; c<numCols; c++){
            if(pegBoard[r][c] == '*'){
                counter ++;
            }//end check
    }//end [r][c] 
}//end [r]
if(counter == 1)
        return true;
else
        return false;
}//end isSolved()

//canJump
bool PegBoard::canJump(int frmRow, int frmCol, Direction whichWay){
    //check inputed values are in bounds
    if(frmRow >= 0 && frmRow < numRows && frmCol >= 0 && frmCol < numCols){
        //check if inputed values contains a *
        if(pegBoard[frmRow][frmCol] == peg){
            switch (whichWay)
            {
            case PegBoard::UP:
                //check upward bounds
                if(frmRow-2 >= 0){
                    //check if next to peg and if avaiable position to jump to
                    if(pegBoard[frmRow-1][frmCol] == peg && pegBoard[frmRow-2][frmCol] == openPosition)
                        return true;
                    }
                break;
            case PegBoard::DOWN:
                //check downward bounds
                if(frmRow+2 < numRows){
                //check if next to peg and 2 spaces from open position
                    if(pegBoard[frmRow+1][frmCol] == peg && pegBoard[frmRow+2][frmCol] == openPosition)
                        return true;
                    }
                break;
            case PegBoard::LEFT:
                //check left bounds
                if(frmCol-2 >=0){
                    //check if next to peg and 2 spaces from open position
                    if(pegBoard[frmRow][frmCol-1] == peg && pegBoard[frmRow][frmCol-2] == openPosition)
                        return true;
                    }
                break;
            case PegBoard::RIGHT:
                if(frmCol+2 < numCols){
                    //check if next to peg and 2 spaces from open position
                    if(pegBoard[frmRow][frmCol+1] == peg && pegBoard[frmRow][frmCol+2] == openPosition)
                        return true;
                    }
                break;
            default: return false;
                break;
            }//end switch
        }//end peg check
    }//end starting bounds check
    return false;
}//end canJump

  //jump
void PegBoard::jump(int frmRow, int frmCol, Direction whichWay){
    /*
    *      **.
    *      ..* 
    */
    if(canJump(frmRow,frmCol,whichWay)){
    switch (whichWay)
    {
    case UP:
        // assign new position
        pegBoard[frmRow-2][frmCol] = peg;
        //delete starting position
        pegBoard[frmRow][frmCol] = openPosition;
        //delete jumped position
        pegBoard[frmRow-1][frmCol] = openPosition;
        break;
    case DOWN:
        // assign new position
        pegBoard[frmRow+2][frmCol] = peg;
        //delete starting position
        pegBoard[frmRow][frmCol] = openPosition;
        //delete jumped position
        pegBoard[frmRow+1][frmCol] = openPosition;
        break;
    case LEFT:
        // assign new position
        pegBoard[frmRow][frmCol-2] = peg;
        //delete starting position
        pegBoard[frmRow][frmCol] = openPosition;
        //delete jumped position
        pegBoard[frmRow][frmCol-1] = openPosition;
        break;
    case RIGHT:
        // assign new position
        pegBoard[frmRow][frmCol+2] = peg;
        //delete starting position
        pegBoard[frmRow][frmCol] = openPosition;
        //delete jumped position
        pegBoard[frmRow][frmCol+1] = openPosition;
        break;
    default: 
        break;
    }//end switch
    }//end canJump
}//end jump

//unjump
void PegBoard::unjump(int frmRow, int frmCol, Direction whichWay){
    //still need to do
    switch (whichWay)
    {
    case UP:
        // assign new position
        pegBoard[frmRow-2][frmCol] = openPosition;
        //delete starting position
        pegBoard[frmRow][frmCol] = peg;
        //delete jumped position
        pegBoard[frmRow-1][frmCol] = peg;
        break;
    case DOWN:
        // assign new position
        pegBoard[frmRow+2][frmCol] = openPosition;
        //delete starting position
        pegBoard[frmRow][frmCol] = peg;
        //delete jumped position
        pegBoard[frmRow+1][frmCol] = peg;
        break;
    case LEFT:
        // assign new position
        pegBoard[frmRow][frmCol-2] = openPosition;
        //delete starting position
        pegBoard[frmRow][frmCol] = peg;
        //delete jumped position
        pegBoard[frmRow][frmCol-1] = peg;
        break;
    case RIGHT:
        // assign new position
        pegBoard[frmRow][frmCol+2] = openPosition;
        //delete starting position
        pegBoard[frmRow][frmCol] = peg;
        //delete jumped position
        pegBoard[frmRow][frmCol+1] = peg;
        break;
    default: 
        break;
    }//end switch
}

1 个答案:

答案 0 :(得分:4)

出于某种原因,您的solve仅按特定顺序尝试单元格。

solve最好具有以下结构(更高级别的伪代码):

check if we already won
for all x:
    for all y:
        for all directions dir:
            if jump from (x, y) in direction dir is possible:
                (1) do that jump
                (2) recursively call solve
                (3) undo that jump

到目前为止,你所缺少的是for all x: for all y:部分和跳跃撤消。