我目前正在尝试编写一个程序,将能够找到解决方案的游戏佩格纸牌使用回溯。
我的程序接收一个包含启动板的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
}
我能理解理解回溯算法的困难。然而,一旦你理解了几个关键点,一切都会变得清晰起来。回溯是在备份之前尽可能深入的过程。回溯是解决四皇后问题和迷宫的常见解决方法。下面是一些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.编码快乐!
出于某种原因,您的解算
只会尝试按特定顺序对单元格进行排序。
解决方案
最好具有以下结构(高级伪代码):
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
我目前正在编程一个递归算法解决一个佩格纸牌游戏。 算法需要使用“回溯”的方法来求解棋盘。我想我已经设法得到了一个非常接近正确的解决方案。看来我的代码正确地为所有可解板解板。它似乎也能正确地确定板何时不可解,但只有当钉住的数量不太高时。 有什么想法吗?