当前位置: 首页 > 知识库问答 >
问题:

带有回溯功能的Peg接龙解决方案

鲁城
2023-03-14

我目前正在尝试编写一个程序,将能够找到解决方案的游戏佩格纸牌使用回溯。

我的程序接收一个包含启动板的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
}

共有2个答案

章德惠
2023-03-14

我能理解理解回溯算法的困难。然而,一旦你理解了几个关键点,一切都会变得清晰起来。回溯是在备份之前尽可能深入的过程。回溯是解决四皇后问题和迷宫的常见解决方法。下面是一些psedo代码来表示回溯算法。

FUNCTION backtraking(node):
    IF reject(node) THEN return False
    IF accept(node) THEN return True
    FOR child IN children(node):
     backtraking(child)

在回溯过程中,你会尽可能地沿着解决方案的路径前进,直到你到达一个解决方案或一个死胡同。然后后退一步,尝试另一条路。拒绝函数实际上是回溯算法效率的关键。“拒绝”功能允许您拒绝已探索或满足条件的节点。此条件说明节点是否没有作为解决方案的子体。此外,了解回溯函数是一个递归函数也很重要,这意味着它是一个调用自身的函数。在最内部的回溯调用完成之前,FOR循环不会继续。一旦你理解了上面的基本原理,然后试着重写你的算法。如果你陷入困境,那么在这里再问一个问题,或者回顾一下我写的回溯算法,以找到peg游戏问题的解决方案:http://peggamesolutions.com/programming.html.编码快乐!

呼延衡
2023-03-14

出于某种原因,您的解算只会尝试按特定顺序对单元格进行排序。

解决方案最好具有以下结构(高级伪代码):

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:部分,以及跳转撤销。

 类似资料:
  • 我正在为Java中的Peg纸牌游戏开发一个解决方案。然而,我的解决方案似乎无法解决游戏。 我正在使用“标准”版本,所以董事会看起来像: 0为空,1为钉,2为空 所需的电路板状态为 我的Solutions()方法是这样工作的: 沿

  • 谁能帮帮我吗?

  • 我正在用java制作一个带回溯功能的peg纸牌解析器。 我就是这么做的: 问题是我找不到解决办法。以下是代码的输出:http://pastebin.com/raw.php?i=BhkLu3qr.如您所见,解决方案阵列不完整。 谢谢

  • 我正在做一个小的个人数独游戏,并试图扩展它。 到目前为止,我使用递归回溯方法使“Solve”部分正常工作,每当它设法解决递归时,就会返回true。 现在我正在尝试构建一个独特的解决方案板生成器,我在网上找到了很多关于如何实现它的信息。 然而,我在第一步很挣扎,这是我的布尔递归回溯算法变成一个递归算法,它保留了一个可能解决方案的计数。这对于检查我生成的板是否是唯一的至关重要。 更重要的是,我意识到我

  • 问题内容: 据我了解 不应该匹配。实际上,甚至拒绝编译它,而的也是如此。模块似乎有不同的看法: 结果: 任何人都可以对此行为提供合理的解释吗? 更新资料 这种行为似乎是限制了在re模块。替代regex模块似乎可以正确处理断言中的组: 请注意,与有所不同pcre,regex它还允许可变宽度的查找: 最终,regex将被包含在标准库中,如PEP 411中所述。 问题答案: 这看起来确实像是Python

  • 我目前正在编程一个递归算法解决一个佩格纸牌游戏。 算法需要使用“回溯”的方法来求解棋盘。我想我已经设法得到了一个非常接近正确的解决方案。看来我的代码正确地为所有可解板解板。它似乎也能正确地确定板何时不可解,但只有当钉住的数量不太高时。 有什么想法吗?