How do I make it go in diagonal directions? - c++

I have code that I already have four basic directions (Up, Down, Left, Right). However, I want to have them go in diagonal directions as well, so it will add up to eight directions. How would I do that? What I see from it, I basically have to have two directions change at the same time, but I don't know how to do that.
Code:
// problem with backtracking using stack
#include <cstring>
#include <iostream>
#include <stack>
using namespace std;
#define N 4
#define M 5
class node {
public:
int x, y;
int dir;
node(int i, int j)
{
x = i;
y = j;
// Initially direction
// set to 0
dir = 0;
}
};
// maze of n*m matrix
int n = N, m = M;
// Coordinates of food
int fx, fy;
bool visited[N][M];
bool isReachable(int maze[N][M])
{
// Initially starting at (0, 0).
int i = 0, j = 0;
cout << '[' << i << ':' << j << ']';
stack<node> s;
node temp(i, j);
s.push(temp);
while (!s.empty()) {
// Pop the top node and move to the
// left, right, top, down or retract
// back according the value of node's
// dir variable.
temp = s.top();
int d = temp.dir;
i = temp.x, j = temp.y;
// Increment the direction and
// push the node in the stack again.
temp.dir++;
s.pop();
s.push(temp);
// If we reach the Food coordinates
// return true
if (i == fx and j == fy) {
return true;
}
// Checking the Up direction.
if (d == 0) {
if (i - 1 >= 0 and maze[i - 1][j] == 1 and
!visited[i - 1][j]) {
cout <<'['<< i - 1 << ':'<<j << ']' ;
node temp1(i - 1, j);
visited[i - 1][j] = true;
s.push(temp1);
}
}
// Checking the left direction
else if (d == 1) {
if (j - 1 >= 0 and maze[i][j - 1] == 1 and
!visited[i][j - 1]) {
cout << '[' << i << ':' << j-1 << ']' ;
node temp1(i, j - 1);
visited[i][j - 1] = true;
s.push(temp1);
}
}
// Checking the down direction
else if (d == 2) {
if (i + 1 < n and maze[i + 1][j] == 1 and
!visited[i + 1][j]) {
cout << '[' << i + 1 << ':' << j << ']' ;
node temp1(i + 1, j);
visited[i + 1][j] = true;
s.push(temp1);
}
}
// Checking the right direction
else if (d == 3) {
if (j + 1 < m and maze[i][j + 1] == 1 and
!visited[i][j + 1]) {
cout << '[' << i << ':' << j + 1<< ']' ;
node temp1(i, j + 1);
visited[i][j + 1] = true;
s.push(temp1);
}
}
// If none of the direction can take
// the rat to the Food, retract back
// to the path where the rat came from.
else {
visited[temp.x][temp.y] = false;
s.pop();
}
//system("pause");
}
// If the stack is empty and
// no path is found return false.
return false;
}
// Driver code
int main()
{
// Initially setting the visited
// array to true (unvisited)
memset(visited, false, sizeof(visited));
// Maze matrix
int maze[N][M] = {
{ 1, 0, 1, 1, 0 },
{ 1, 1, 1, 0, 1 },
{ 0, 1, 0, 1, 1 },
{ 1, 1, 1, 1, 1 }
};
// Food coordinates
fx = 2;
fy = 3;
if (isReachable(maze)) {
cout << "Path Found!" << '\n';
}
else
cout << "No Path Found!" << '\n';
return 0;
}```

By combining the conditions you already have... You have the following for checking the second dimension:
if (j + 1 < m and maze[i][j + 1] == 1 and !visited[i][j + 1])
If you want to increment both at once you would do something like:
if (i + 1 < n and j + 1 < m and maze[i + 1][j + 1] == 1 and !visited[i + 1][j + 1])
Since you have 4 diagonals, you would do similar checkings for the other 3 diagonals. Be careful with copy and paste not to forget to increment/decrement both i and j.

Let's assume a board, with row 0 and column 0 in the upper left corner.
Also, assume the present position is at <row, column>.
There are 8 locations relative to the present position (unless you are near the edge of the board).
+---------------------+---------------------+--------------------+
| row - 1, column - 1 | row - 1, column + 0 | row - 1, column + 1|
+---------------------+---------------------+--------------------+
| row + 0, column - 1 | row, column | row + 0, column + 1|
+---------------------+---------------------+--------------------+
| row + 1, column - 1 | row + 1, column + 0 | row + 1, column + 1|
+---------------------+---------------------+--------------------+
Before making a move, check the validity of the next move.
The next move would be based on the above table.

Related

Get co-ordinates surrounding specific matrix

Given an arbitrary matrix, how do I find the co-ordinates that surrounds each city accurately?
E.g. City 1 has surrounding matrix of (0, 0), (0, 3), (1, 0), (1, 3), (2,0), (2, 1), (2, 2), (2, 3).
I have tried using a hardcoded method. Which is loop through each city's co-ordinate, however there are still inaccuracy in this method.
E.g. (0, 1) and from there check all 8 directions, up, down, left, right, upper left, upper right, bottom left, bottom right.
And if the char value is ' ', it is not a city which means it is part of a surrounding.
Is there any way which is much more efficient and more accurate in finding the surrounding?
void surroundings(int x, int y) {
// Initiate the first city struct information
citySummInfo.cityId = cityLocList[0].cityId;
citySummInfo.cityName = cityLocList[0].cityName;
citySummInfoList.push_back(citySummInfo);
// Add unique cityID & cityName into vector
for (size_t i = 0; i < cityLocList.size(); i++) {
for (size_t j = 0; j < citySummInfoList.size(); j++) {
if (cityLocList[i].cityId == citySummInfoList[j].cityId && cityLocList[i].cityName == citySummInfoList[j].cityName) {
break;
}
else if (j == citySummInfoList.size() - 1) {
citySummInfo.cityId = cityLocList[i].cityId;
citySummInfo.cityName = cityLocList[i].cityName;
citySummInfoList.push_back(citySummInfo);
}
}
}
// To populate the entire matrix with city ID
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
for (size_t k = 0; k < cityLocList.size(); k++) {
if (cityLocList[k].xGrid == i && cityLocList[k].yGrid == j)
mapPtr[j][i] = cityLocList[k].cityId + '0';
}
}
}
// Main process of getting the surrounding
for (size_t i = 0; i < citySummInfoList.size(); i++) {
for (size_t j = 0; j < cityLocList.size(); j++) {
if (citySummInfoList[i].cityId == cityLocList[j].cityId)
citySummInfoList[i].coOrdinates.push_back(to_string(cityLocList[j].xGrid) + "." + to_string(cityLocList[j].yGrid));
}
}
for (size_t i = 0; i < citySummInfoList.size(); i++) {
vector<string> temp;
for (size_t j = 0; j < citySummInfoList[i].coOrdinates.size(); j++) {
char cityId = citySummInfoList[i].cityId + '0';
char delim[] = { '.' };
vector<string> tempAxis = tokenizer(citySummInfoList[i].coOrdinates[j], delim, 1);
int xAxis = stoi(tempAxis[0]);
int yAxis = stoi(tempAxis[1]);
if (xAxis - 1 < 0 || yAxis - 1 < 0) {
continue;
}
if (mapPtr[xAxis - 1][yAxis + 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis - 1) + "." + to_string(yAxis + 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis - 1][yAxis] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis - 1) + "." + to_string(yAxis);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis - 1][yAxis - 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis - 1) + "." + to_string(yAxis - 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis][yAxis + 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis) + "." + to_string(yAxis + 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis][yAxis - 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis) + "." + to_string(yAxis - 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis + 1][yAxis + 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis + 1) + "." + to_string(yAxis + 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis + 1][yAxis] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis + 1) + "." + to_string(yAxis);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis + 1][yAxis - 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis + 1) + "." + to_string(yAxis - 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
}
citySummInfoList[i].coOrdinates.reserve(temp.size());
citySummInfoList[i].coOrdinates.insert(citySummInfoList[i].coOrdinates.end(), temp.begin(), temp.end());
}
}
Also, is there a possibility that my print function may cause such unreliability?
void print(int x, int y) {
for (int i = 0; i <= x + 2; i++) {
if (i == 0 || i >= x + 1) // Indentation for 1st and last row of non city locations
cout << setw(4) << " ";
for (int j = 0; j <= y + 2; j++) {
if ((i == 0 || i == x + 1) && j <= y + 1) { // Layout for first and last row
cout << "# ";
}
else if ((j == 0 && (i != 0 || i <= x))) { // Numbering for each row
if (x - i >= 0) {
cout << setw(3) << left << x - i << " ";
}
else {
cout << " "; // Indentation for last row of #s
}
}
else if (j == 1 && i < x + 2) { // Layout for first column
cout << "#";
}
else if (j == y + 2 && i != 0 && i < x + 1) { // Layout for last column
cout << " #";
}
else if (i == x + 2 && j < y + 1) { // Numbering for each column
cout << j - 1 << " ";
}
else if ((i != 0 && i != x + 2 && j != y + 2)) {
cout << " " << mapPtr[x - i][j - 2]; // Plot map value
}
}
cout << endl;
}
cout << endl;
}
This is an O(n) answer for your problem. The idea behind it is to find all points that are edges (a point is an edge if it is adjacent to anything which is not its own city).
After finding all edge points, loop through each of them and add all points adjacent to them which are whitespace characters.
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int, int> point;
string m[] = {
" ",
" 555 ",
" 555 ",
" 222 555 ",
" 222 ",
" 222 ",
" 222 ",
" ",
"11 33 ",
"11 44",
" 44"
};
//hash function for pairs
struct hash_pair {
template <class T1, class T2>
size_t operator()(const pair<T1, T2>& p) const {
auto hash1 = hash<T1>{}(p.first);
auto hash2 = hash<T2>{}(p.second);
return hash1 ^ hash2;
}
};
bool insideBounds(int x, int y, point &size){
if(x < 0 || x >= size.x || y < 0 || y >= size.y) return false;
return true;
}
bool isEdge(int x, int y, point &size){
for(int i = -1; i < 2; ++i){
for(int j = -1; j < 2; ++j){
if(!insideBounds(x + j, y + i, size)) return true;
if(m[y + i][x + j] == ' ') return true;
}
}
return false;
}
void FindSurrounding(int x, int y){
//size of map
point size = make_pair(11, 11);
//current city id
char city = m[y][x];
//finding a point in edge of the city
point edge = make_pair(x, y);
for(int i = x - 1; i >= 0; --i)
if(m[y][i] == city) edge = make_pair(i, y);
//find all edge points
unordered_set<point, hash_pair> visited;
stack<point> toVisit;
toVisit.push(edge);
while(toVisit.size()){
point current = toVisit.top();
visited.insert(current);
toVisit.pop();
for(int i = -1; i < 2; ++i){
for(int j = -1; j < 2; ++j){
point p = make_pair(current.x + j, current.y + i);
if(!insideBounds(p.x, p.y, size) || m[p.y][p.x] != city) continue;
if(visited.find(p) == visited.end() && isEdge(p.x, p.y, size)){
toVisit.push(p);
}
}
}
}
//find surrounding slots
unordered_set<point, hash_pair> surrounding;
for (const auto& p: visited) {
for(int i = -1; i < 2; ++i){
for(int j = -1; j < 2; ++j){
point curr = make_pair(p.x + j, p.y + i);
if(insideBounds(curr.x, curr.y, size) && m[curr.y][curr.x] == ' '){
surrounding.insert(curr);
}
}
}
}
//print answer
for (const auto& p: surrounding) {
cout<<"("<<p.x<<", "<<p.y<<"), ";
}
}
int main()
{
FindSurrounding(0, 8);
return 0;
}
OUTPUT: (2, 10), (1, 10), (2, 9), (0, 10), (2, 8), (2, 7), (1, 7), (0, 7),

Rat in maze problems, how to display coordinates where rat stepped in random generated matrix?

I started coding and searched a lot codes on internet but couldn't find the solution for my problem. I'm gonna paste there my current code. I already coded that if there is perfect path for rat or no (rat can only step on number one, "0" and "2" are walls.) But I cant display the coordinates of each "number one". For an example:
1,0,1,
1,2,2,
1,1,1,
Then the path is, (0,0) -> (1,0) -> (2,0) -> (1,2) -> (2,2)
if the matrix is
1,0,2,
0,2,1,
1,0,1,
Then no path for the rat.
Please edit my code and paste it there please or if you have already solved program for my problem please share it with me... I'm really new in c++.
// CPP program to solve Rat in a maze
// problem with backtracking using stack
#include <cstring>
#include <iostream>
#include <stack>
using namespace std;
#define N 4
#define M 5
void mtxkeres(int (&mat)[N][M]);
class node {
public:
int x, y;
int dir;
node(int i, int j)
{
x = i;
y = j;
// Initially direction
// set to 0
dir = 0;
}
};
// maze of n*m matrix
int n = N, m = M;
// Coordinates of food
int fx, fy;
bool visited[N][M];
bool isReachable(int maze[N][M])
{
// Initially starting at (0, 0).
int i = 0, j = 0;
stack<node> s;
node temp(i, j);
s.push(temp);
while (!s.empty()) {
// Pop the top node and move to the
// left, right, top, down or retract
// back according the value of node's
// dir variable.
temp = s.top();
int d = temp.dir;
i = temp.x, j = temp.y;
// Increment the direction and
// push the node in the stack again.
temp.dir++;
s.pop();
s.push(temp);
// If we reach the Food coordinates
// return true
if (i == fx and j == fy) {
return true;
}
// Checking the Up direction.
if (d == 0) {
if (i - 1 >= 0 and maze[i - 1][j] and
visited[i - 1][j]) {
node temp1(i - 1, j);
visited[i - 1][j] = false;
s.push(temp1);
}
}
// Checking the left direction
else if (d == 1) {
if (j - 1 >= 0 and maze[i][j - 1] and
visited[i][j - 1]) {
node temp1(i, j - 1);
visited[i][j - 1] = false;
s.push(temp1);
}
}
// Checking the down direction
else if (d == 2) {
if (i + 1 < n and maze[i + 1][j] and
visited[i + 1][j]) {
node temp1(i + 1, j);
visited[i + 1][j] = false;
s.push(temp1);
}
}
// Checking the right direction
else if (d == 3) {
if (j + 1 < m and maze[i][j + 1] and
visited[i][j + 1]) {
node temp1(i, j + 1);
visited[i][j + 1] = false;
s.push(temp1);
}
}
// If none of the direction can take
// the rat to the Food, retract back
// to the path where the rat came from.
else {
visited[temp.x][temp.y] = true;
s.pop();
}
}
// If the stack is empty and
// no path is found return false.
return false;
}
// Driver code
int main()
{
// Initially setting the visited
// array to true (unvisited)
memset(visited, true, sizeof(visited));
// Maze matrix
int maze[N][M] = {
{ 1, 0, 1, 1, 0 },
{ 1, 1, 1, 0, 1 },
{ 0, 1, 0, 1, 1 },
{ 1, 1, 1, 1, 1 }
};
// Food coordinates
fx = 2;
fy = 3;
if (isReachable(maze)) {
cout << "Path Found!" << '\n';
}
else
cout << "No Path Found!" << '\n';
return 0;
}

Knight's Tour Brute Force Recursion

I'm trying to write a program that allows the user to enter any coordinate on a chess board and complete the knight's tour using brute force recursion. I am getting an infinite loop and I have no idea why. This is in C++, and I have to write this only using brute force recursion. After entering the starting place for the knight, my console output window prints the current board after each move (only temporarily, for troubleshooting purposes), but according to my output, the move number is stuck at 1, and the program isn't trying any other moves. Any help is appreciated.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
void printBoard();
bool moveKnight(int col, int row, int movNum);
int totalMoves = 0;
int board[7][7] = { { 0 } };
int main()
{
cout << "Welcome to the Knight's Tour Program! Enter a starting place for the knight on a chess board to get started.\n";
int col;
int row;
int a;
int b;
while (1 == 1)
{
col = 0;
row = 0;
cout << "Enter column (0-7): ";
cin >> col;
cout << "Enter row (0-7): ";
cin >> row;
if (row < 0 || row > 7 || col < 0 || col > 7)
{
cout << "Invalid knight placement. Please try again.\n";
}
else
{
break;
}
}
int movNum = 1;
board[col][row] = movNum;
totalMoves++;
moveKnight(col, row, movNum);
if (moveKnight(col, row, movNum == true))
{
cout << "Tour finished! Total moves: " << totalMoves << endl;
printBoard();
cout << "\n\n";
}
system("pause");
return 0;
}
void printBoard()
{
cout << "Current board\n";
for (int i = 0; i < 8; i++)
{
for (int x = 0; x < 8; x++)
{
cout << setw(3) << board[i][x] << " ";
if (x == 7)
{
cout << "\n\n";
}
}
}
cout << "\n";
}
bool moveKnight(int col, int row, int movNum)
{
printBoard(); //just for troubleshooting
cout << "\n" << totalMoves << endl;
if (moveKnight(col, row, movNum) == false)
{
board[col][row] = 0; //if there are no available moves then set the current space to 0 and move back a spot
}
if (movNum == 64)
{
return true; //if tour complete return true
}
if (totalMoves % 10000 == 0)
{
printBoard(); //printBoard() every 10000 moves
}
if (col >= 0 && col <= 7 && row >= 0 && row <= 7 && board[row][col] == 0) //check if space is on board and if it is unoccupied
{
board[col][row] = movNum;
totalMoves++;
if (moveKnight(col + 1, row - 2, movNum + 1) != false)
moveKnight(col + 1, row - 2, movNum + 1);
else if (moveKnight(col + 2, row - 1, movNum + 1) != false)
moveKnight(col + 2, row - 1, movNum + 1);
else if (moveKnight(col + 2, row + 1, movNum + 1) != false)
moveKnight(col + 2, row + 1, movNum + 1);
else if (moveKnight(col + 1, row + 2, movNum + 1) != false)
moveKnight(col + 1, row + 2, movNum + 1);
else if (moveKnight(col - 1, row + 2, movNum + 1) != false)
moveKnight(col - 1, row + 2, movNum + 1);
else if (moveKnight(col - 2, row + 1, movNum + 1) != false)
moveKnight(col - 2, row + 1, movNum + 1);
else if (moveKnight(col - 2, row - 1, movNum + 1) != false)
moveKnight(col - 2, row - 1, movNum + 1);
else if (moveKnight(col - 1, row - 2, movNum + 1) != false)
moveKnight(col - 1, row - 2, movNum + 1);
else
return false;
}
}
If you look in the moveKnight() function, notice that the line if (moveKnight(col, row, movNum) == false) does a recursive call of the function no matter what the inputs are.
Whenever you use a recursive function, it must have what is called a base case, where a recursive call does not happen. Otherwise, the recursive calls will just keep going on until a stack overflow since one execution of the function will start another one which will start another one and so on..
By the way, the bunch of if statements in the function make no sense since you are calling a function and checking the output, and if it is true then you call the function a second time with the exact same arguments. Also, if you want an infinite loop that you will break later, there is no need for something like while(1 == 1). Use while(1) or while(true).
int board[7][7] = { { 0 } };
Chess board is 8 x 8, so you need 8 elements in the array (from 0 to up to and including 7, that's 8)
if (moveKnight(col, row, movNum == true))
You have syntax erros, the compiler will tell you about all this. In Visual Studio make sure warning level is set to 4. Then make sure the program is compiled with zero errors and zero warnings.
I would recommend writing a program which does not require user input. This will make it easier to debug the program and fix the logic.
Below is a simple recursion which moves the knight until the knight gets stuck at the end. You will have to further improve the logic so that it covers all the squares.
Make sure the recursive function is allowed to break. That's discussed in more detail in the other answer.
int board[8][8] = { 0 };
void printBoard()
{
cout << "Current board\n";
for(int i = 0; i < 8; i++)
{
for(int x = 0; x < 8; x++)
cout << board[i][x] << " ";
cout << "\n";
}
cout << "\n";
}
int test(int &row, int &col, int move_row, int move_col)
{
int r = row + move_row;
int c = col + move_col;
if(r >= 0 && r < 8 && c >= 0 && c < 8 && !board[r][c])
{
row = r;
col = c;
return 1;
}
return 0;
}
bool move_knight(int &row, int &col)
{
board[row][col] = 1;
printBoard();
system("pause");
if(!test(row, col, 1, 2))
if(!test(row, col, 1, -2))
if(!test(row, col, -1, 2))
if(!test(row, col, -1, -2))
if(!test(row, col, 2, 1))
if(!test(row, col, 2, -1))
if(!test(row, col, -2, 1))
if(!test(row, col, -2, -1))
return false;
move_knight(row, col);
return true;
}
int main()
{
int col = 0;
int row = 0;
move_knight(col, row);
system("pause");
return 0;
}

Recursively determine minimum moves to all fields on gameboard

I'm in the process of trying to understand recursion better, so I decided to write a program to determine the shortest paths to all fields on an N * N game board, using recursion (I know BFS would be faster here, this is just for the sake of learning):
void visit(int x, int y, int moves)
{
if (x < 0 || x >= n || y < 0 || y >= n) {
return; // out of board
} else if (board[y][x] != -1) {
// already visited, check if path is shorter
if (moves < board[y][x]) board[y][x] = moves;
return;
} else {
// first time visiting
board[y][x] = moves;
visit(x + 1, y, moves + 1); // right
visit(x, y + 1, moves + 1); // down
visit(x, y - 1, moves + 1); // up
visit(x - 1, y, moves + 1); // left
}
}
# called with visit(0, 0, 0), so it should be able to start at any field
However, for a 3x3 board, it yields the following board:
0 1 2
1 2 3
6 5 4
The first two rows are right, however, the last row (except the last column in the last row) is wrong. It should be:
0 1 2
1 2 3
2 3 4
Here's a 4x4 board:
0 1 2 3
1 2 3 4
12 9 6 5
13 8 7 6
else if (board[y][x] != -1) {
// already visited, check if path is shorter
if (moves < board[y][x]) board[y][x] = moves;
return;
}
Returning here is wrong. You've just lowered the score on this path—there are probably other paths in the area whose scores could be lowered:
void visit(int x, int y, int moves)
{
if (x < 0 || x >= n || y < 0 || y >= n) {
return; // out of board
} else if (board[y][x] == -1 || moves < board[y][x]) {
// first time visiting
board[y][x] = moves;
visit(x + 1, y, moves + 1);
visit(x, y + 1, moves + 1);
visit(x, y - 1, moves + 1);
visit(x - 1, y, moves + 1);
} else {
return;
}
}
Works as expected.
You are doing a depth first search which may find sub-optimal paths to some squares.
To get optimal paths, if your path is shorter you should still visit from it, even if it is already visited.
This would work.
void visit(int x, int y, int moves)
{
if (x < 0 || x >= n || y < 0 || y >= n) {
return; // out of board
}
else if ( board[y][x] == -1 || moves < board[y][x])
{
board[y][x] = moves;
visit(x + 1, y, moves + 1);
visit(x, y + 1, moves + 1);
visit(x, y - 1, moves + 1);
visit(x - 1, y, moves + 1);
}
}
Moreover, if you initialize each element of board with (2*n-2) instead of -1, you can drop the ( board[y][x] == -1 ) condition and have just (moves < board[y][x]) in the else if part.

Trouble with Beginner's C++ Game of Life Program

Background: I am quite a beginner at programming. This is what I have so far in my rough draft for the Game of Life:
#include <iostream>
using namespace std;
int main()
{
//INTRODUCTION
int arraySize;
cout << "What is the length of your square-shaped grid? Enter an integer value greater than 0. Too big will cause problems.";
cin >> arraySize;
int original[arraySize][arraySize];
//REQUESTS INPUT FOR ARRAY
for (int n = 0; n < arraySize; n++)
{
for (int x = 0; x < arraySize; x++)
{
bool ValInput;
cout << "\n" << n << "," << x << "...";
cin >> ValInput;
original[n][x] = ValInput;
}
}
cout << "\n\n\n";
//DISPLAYS ARRAY
for (int row = 0; row < arraySize; row++)
{
for (int column = 0; column < arraySize; column++)
{
cout << original[row][column] << " ";
if (column == arraySize - 1)
{
cout << "\n";
}
}
}
cout << "Next frame.\n\n";
//FORMS NEXT FRAME WITH VALUES OF # OF LIVE NEIGHBORS
int liveNeighbors = 0;
for (int z = 0; z < arraySize; z++)
{
for (int h = 0; h < arraySize; h++)
{
liveNeighbors = 0;
if (z - 1 > -1)
liveNeighbors += original[z - 1][h];
if (z + 1 < arraySize)
liveNeighbors += original[z + 1][h];
if (h - 1 > -1)
liveNeighbors += original[z][h - 1];
if (h + 1 < arraySize)
liveNeighbors += original[z][h + 1];
if (z - 1 > -1, h - 1 > -1)
liveNeighbors += original[z - 1][h -1];
if (z - 1 > -1, h + 1 < arraySize)
liveNeighbors += original[z - 1][h + 1];
if (z + 1 < arraySize, h - 1 > -1)
liveNeighbors += original[z + 1][h - 1];
if (z + 1 < arraySize, h + 1 < arraySize)
{
liveNeighbors += original[z + 1][h + 1];
}
cout << liveNeighbors << " ";
}
}
}
The problem appears in the last step I have made so far (which is showing how many live neighbors each cell has.
Example: If the sample input is first "4" for a 4x4 grid and then you enter in a variety of 1s and 0s, the liveNeighbors value is not realistic. It may be in the hundreds, when the maximum should be only 8.
If you could help me find a solution to my problem, that would be nice. However, please keep in mind that I am a novice.
Thank you :)
Some of your conditions are wrong :
if (z - 1 > -1, h - 1 > -1) /* ... */
if (z - 1 > -1, h + 1 < arraySize) /* ... */
if (z + 1 < arraySize, h - 1 > -1) /* ... */
if (z + 1 < arraySize, h + 1 < arraySize) /* ... */
The comma does not do what you expect, what you need is probably a logical 'and' which in C++ is the operator && :
if ((z - 1 > -1) && (h - 1 > -1)) /* ... */
if ((z - 1 > -1) && (h + 1 < arraySize)) /* ... */
if ((z + 1 < arraySize) && (h - 1 > -1)) /* ... */
if ((z + 1 < arraySize) && (h + 1 < arraySize)) /* ... */
Extra parenthesis added for readability only, they are not required.
Just so you know, this is the standard definition of the comma operator :
A pair of expressions separated by a comma is evaluated left-to-right and the value of the left expression is
discarded.
In your case, the comparisons on the left side of the commas were basically not playing any role in the if condition.
I think that your problem is in this code:
if (z - 1 > -1, h - 1 > -1)
Your intuition is completely correct here, but the way that you've written this in code doesn't mean what you want. In C++, the comma operator is an esoteric operator that means "do both things, but discard the result of the first operation.". In this case, that means "check if z - 1 > -1, then completely discard that result, then see whether h - 1 > -1," which isn't at all what you want. To check and see if both of these conditions hold true, use the && operator:
if (z - 1 > -1 && h - 1 > -1)
That should help fix your bug.
Hope this helps!