I’m looking for some help on a problem that I vaguely inquired about before, which is solving 15-peg solitaire recursively. I keep getting strange errors when I compile and run it, most of them say “stack overflow” or that I’m getting a seg fault. This is what I have so far, where “board[15]” represents the 15 peg board, and “moves[36]” represents all of the possible moves that can be made. The recursion is supposed to spot when there is only one peg left.
#include <iostream>
using namespace std;
void solveGame(int a[15], int b[36][3], int c[15][4]);
void chooseMove (int a[15], int b[36][3], int openSpace, int c[15][4]);
int findEmpty (int a[15]);
int pegCount (int a[15]);
bool isPeg (int peg, int a[15]);
int usedVals[15] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
int d = 0;
int index = 0;
int main ()
{
int openSpace = 5;
int board[15]= {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
board[openSpace] = 0;
int alreadyMoved[15][4];
int moves[36][3] = {{0, 1, 3},
{0, 2, 5},
{1, 3, 6},
{1, 4, 8},
{2, 4, 7},
{2, 5, 9},
{3, 6, 10},
{3, 7, 12},
{3, 1, 0},
{3, 4, 5},
{4, 7, 11},
{4, 8, 13},
{5, 9, 14},
{5, 8, 12},
{5, 2, 0},
{5, 4, 3},
{6, 3, 1},
{6, 7, 8},
{7, 4, 2},
{7, 8, 9},
{8, 4, 1},
{8, 7, 6},
{9, 5, 2},
{9, 8, 7},
{10, 6, 3},
{10, 11, 12},
{11, 7, 4},
{11, 12, 13},
{12, 7, 3},
{12, 8, 5},
{12, 11, 10},
{12, 13, 14},
{13, 8, 4},
{13, 12, 11},
{14, 9, 5},
{14, 13, 12}};
solveGame(board, moves, alreadyMoved);
for (int i = 0; i < 13; i++)
cout << alreadyMoved[i][0] << " " << alreadyMoved[i][1] << " " < <alreadyMoved[i][2] << endl;
return 0;
}
// main recursive function
void solveGame (int a[15], int b[36][3], int c[15][4]
{
int empSpace;
int moveIndex;
if (pegCount(a) < 2) {
cout<<"game over"<<endl;
} else {
empSpace = findEmpty(a);
chooseMove(a, b, empSpace, c);
solveGame(a, b, c);
}
}
// supposed to pick a move that is applicable to the board otherwise it find a new move
void chooseMove (int a[15], int b[36][3], int openSpace, int c[15][4])
{
int i = 0;
while (1) {
if (i < 36 && b[i][2] == openSpace && isPeg(b[i][0],a) && isPeg(b[i][1],a)) {
a[b[i][0]] = 0;
a[b[i][1]] = 0;
a[b[i][2]] = 1;
c[d][0] = b[i][0];
c[d][1] = b[i][1];
c[d][2] = b[i][2];
c[d][3] = i;
d++;
index = 0;
for (int v = 0; v < 15; v++)
usedVals[v] = -1;
break;
} else if (i > 35) {
a[b[c[d-1][3]][0]] = 1;
a[b[c[d-1][3]][1]] = 1;
a[b[c[d-1][3]][2]] = 0;
c[d-1][0] = 0;
c[d-1][1] = 0;
c[d-1][2] = 0;
c[d-1][3] = 0;
usedVals[index] = openSpace;
index++;
int newOpen = findEmpty(a);
chooseMove(a, b, newOpen, c);
}
i++;
}
}
// counts the pegs on the board in order to cancel recursion
int pegCount (int a[15])
{
int count = 0;
for (int i = 0; i < 15; i++)
if (a[i] == 1)
count++;
return count;
}
// finds an empty space that hasn't already been found faulty
int findEmpty (int a[15])
{
for (int i = 0; i < 15; i++) {
for(int j = 0; j < 15; j++) {
if(a[i] == 0 && i != usedVals[j] && usedVals[j] > -1)
return i;
}
}
}
// tests if current index is a peg
bool isPeg (int peg, int a[15])
{
return a[peg] == 1;
}
A quick glance shows a lot of potential problems, but I think it probably boils down to the way you are passing arrays. Arrays are passed by reference and not by value, so the recursive function is working with a single copy of the array, which I don’t think is what you want. Therefore you are never finding the ending move, which will get you a stackoverflow from unlimited recursion.
Try allocating a new copy of the arrays at each level of recursion. Some people will want you to use
newormallocfor this, because they feel an introduction to C++ should be a trial by fire where you have to master memory management to do anything useful. Instead, I would advise you not to use arrays at all; use a collection class that will work properly when passed by value (I think std::vector of POD will do this) and the collection class will create copies of your arrays the way your code seems to expect.You may also be having a problem of doing a depth-first search in chooseMove, when you really want a breadth-first search.