I have been having difficulty solving the N Queen problem, I am able to implement most of my functions, but the function that places the Queen recursively with backtracking. The placeQueens function is using a provided pseudocode that is required for the project. I had to create the array on the heap that is pointing to boardPtr, which is also required. I have a while loop condition that I have but I am not sure if it's correct. I have tried looking online for similar code but none of them were able to help me.
Here is my code:
#include <iostream>
#include "ChessBoard.h"
int main()
{
// Create a board
ChessBoard myBoard;
/* Loop through board sizes from 3 to 13.
Since 3 and 13 are invalid you should see
board sizes 4 and 12 twice. */
for (int i = 3; i <= 13; i++)
{
myBoard.setSize(i);
/* Attempt to solve the N-Queens Problem. If the solve
code is working it should find solutions for all
sizes. */
if (!myBoard.solve())
std::cout << "Sorry, no solution was found for board size "
<< myBoard.getSize() << "." << std::endl << std::endl;
else
{
std::cout << "Size " << myBoard.getSize()
<< " solution:" << std::endl;
myBoard.displayBoard();
std::cout << std::endl << std::endl;
}
}
return 0;
}
#include "ChessBoard.h"
#include <iostream>
using namespace std;
bool ChessBoard::placeQueens( int column)
{
int row = 0;
if (column >= boardSize)
{
// The board is filled, problem is solved.
return true;
}
else
{
while (row < boardSize && column < boardSize) // unconsidered rows exist in column
{
if ((canPlace(boardPtr, row, column)) == true) //[row][column] is unattacked
{
//Place a queen in the un - attacked square.
boardPtr[row][column] = 'Q';
//Do a recursive call to try and place queens in subsequent columns :
if (!placeQueens(column + 1))
{
//If we’re here, placement of the last queen resulted in a dead end; no solution could be found.Remove the last queen placed.
boardPtr[row][column] = '*';
//Move to next row so search can continue in next iteration.
row++;
}
else
{
// If we’re here, recursive calls were able to place queens in all columns to the right of column, the problem is solved.
return true;
}
}
else
{
//Square is attacked, move to next row.
row++;
}
}
//All rows have been considered in column without a successful queen placement.Backtrack by returning false.
return false;
}
}
bool ChessBoard::canPlace(char** boardPtr, int row, int column)
{
int i, j;
// Check row
for (i = 0; i < column; i++)
if (boardPtr[row][i] )
return false;
// Check upper diagonal
for (i = row, j = column; i >= 0 && j >= 0; i--, j--)
if (boardPtr[i][j])
return false;
// Check lower diagonal
for (i = row, j = column; j >= 0 && i < boardSize; i++, j--)
if (boardPtr[i][j] )
return false;
return true;
}
ChessBoard::ChessBoard()
{
boardSize = 8;
boardPtr = nullptr;
}
ChessBoard::ChessBoard(int size)
{
if (size < 4)
{
boardSize = 4;
}
else if (size > 12)
{
boardSize = 12;
}
}
ChessBoard::~ChessBoard()
{
}
int ChessBoard::setSize(int size)
{
delete[] boardPtr;
//Initialize array at size 4
if (size < 4)
{
boardSize = 4;
char** chessBoard = new char* [4];
for (int i = 0; i < 4; i++)
{
chessBoard[i] = new char[4];
}
// Point initialized ChessBoard to boardPtr
boardPtr = chessBoard;
// Fill ChessBoard with *
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardSize; j++)
{
boardPtr[i][j] = '*';
}
}
}
//Initialize array at size 12
else if (size > 12)
{
boardSize = 12;
char** chessBoard = new char* [12];
for (int i = 0; i < size; i++)
{
chessBoard[i] = new char[12];
}
// Point initialized ChessBoard to boardPtr
boardPtr = chessBoard;
// Fill ChessBoard with *
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardSize; j++)
{
boardPtr[i][j] = '*';
}
}
}
//Initialize array at given size
else
{
boardSize = size;
char** chessBoard = new char* [size];
for (int i = 0; i < size; i++)
{
chessBoard[i] = new char[size];
}
// Point initialized ChessBoard to boardPtr
boardPtr = chessBoard;
// Fill ChessBoard with *
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardSize; j++)
{
boardPtr[i][j] = '*';
}
}
}
return 1;
}
int ChessBoard::getSize()
{
return boardSize;
}
bool ChessBoard::solve()
{
int column = 0;
if (placeQueens(column) == false)
{
return false;
}
else
{
return true;
}
}
void ChessBoard::displayBoard()
{
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardSize; j++)
{
cout << boardPtr[i][j] << " ";
}
cout << endl;
}
}
#ifndef CHESSBOARD_H
#define CHESSBOARD_H
class ChessBoard
{
private:
char** boardPtr;
int boardSize;
bool placeQueens( int column);
bool canPlace(char** boardPtr, int row, int col);
public:
ChessBoard();
ChessBoard(int size);
~ChessBoard();
int setSize(int size);
int getSize();
bool solve();
void displayBoard();
};
#endif
Interesting task you have! I decided to implement my own code from scratch for solving N Queen problem. Actually I implemented it for any board size N, not just equal to 8.
I didn't fix bugs in your code, but instead implemented my own solution. Although it may be not the answer you want, still it would be a good thing from educational point of view. Hoping that there would be other answers later that are fixing bugs in your code, as you wished.
I made code very optimized, so it is not very simple from first side, but solves task very fast, using BackTracking, with several extra techniques of speeding it up.
After program finishes it prints to console all solutions in a nice form. Please scroll down below the code to see example of console output.
First program has some extra descriptive comments to show what's happenning in program.
Notice that I provided two codes below, first is simplified version, that is more easy to understand, so it is better from educational point of view. Second code is advanced one, it is more difficult, but solves task fast. Please look at first code if you want just to learn basics, and look at second code if you want to learn advanced techniques.
Simplified:
Try it online!
#include <iostream>
#include <vector>
#include <string>
void Output(std::vector<std::vector<bool>> & board, std::vector<std::string> & lines, bool last);
void Solve(std::vector<std::vector<bool>> & board, std::vector<std::string> & lines,
int N, int & num_sol, int cnt = 0, int start_i = 0, int start_j = 0, int depth = 0) {
if (cnt >= N) {
Output(board, lines, false);
// Increase number of solutions.
++num_sol;
return;
}
// Traverse whole board starting from last queen
for (int i = start_i; i < board.size(); ++i)
for (int j = i == start_i ? start_j : 0; j < board[i].size(); ++j) {
bool attacked = false;
// k-loop checks if position [i][j] is being attacked
for (int k = 0; k < (board.size() > board[i].size() ?
board.size() : board[i].size()); ++k)
if (
// Is there horizontal attack
k < board[i].size() && k != j && board[i][k] ||
// Is there vertical attack
k < board.size() && k != i && board[k][j] ||
// Is there main diagonal attack
k < board.size() && k != i && 0 <= j - i + k &&
j - i + k < board[i].size() && board[k][j - i + k] ||
// Is there secondary diagonal attack
k < board.size() && k != i && 0 <= j + i - k &&
j + i - k < board[i].size() && board[k][j + i - k]
) {
attacked = true;
break;
}
if (attacked)
continue;
// Position [i][j] is not under attack, hence placing a queen
board[i][j] = true;
// Recursive descend to place another queen
Solve(board, lines, N, num_sol, cnt + 1, i, j + 1, depth + 1);
// Backtrack, to delete previous queen
board[i][j] = false;
}
if (depth == 0)
Output(board, lines, true);
}
// Function of outputting solutions to console
void Output(std::vector<std::vector<bool>> & board, std::vector<std::string> & lines, bool last) {
if (1) {
if (!last) {
for (int i = 0; i < board.size(); ++i) {
for (int j = 0; j < board[i].size(); ++j)
lines[i].push_back(board[i][j] ? 'Q' : '.');
lines[i] += "|";
}
}
if (lines.at(0).size() >= 70 || last && !lines.at(0).empty()) {
for (int i = 0; i < lines.size(); ++i)
std::cout << lines[i] << std::endl;
for (int j = 0; j < lines.at(0).size(); ++j)
std::cout << (lines.at(0)[j] == '|' ? '+' : '-');
std::cout << std::endl;
lines.clear();
lines.resize(board.size());
}
}
}
int main() {
// rows - number of rows in a board, cols - number of columns in a board
// N - number of queens to be placed
int const rows = 8, cols = 8, N = 8;
// Filling with empty values board [rows][cols]
std::vector<std::vector<bool>> board(rows, std::vector<bool>(cols));
std::vector<std::string> lines(rows);
// Answer, number of solutions
int num_sol = 0;
// Starting a backtracking
Solve(board, lines, N, num_sol);
// Outputting answer
std::cout << "Number of solutions: " << num_sol << std::endl;
}
Advanced:
Try it online!
#include <iostream>
#include <string>
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
enum { max_rows = 32, max_cols = 32, max_max_rows_cols = MAX(max_rows, max_cols) };
void Output(bool (& board)[max_rows][max_cols], std::string (& lines)[max_rows],
int rows, int cols, bool last);
void Solve(bool (& board)[max_rows][max_cols], std::string (& lines)[max_rows],
bool (& busy_cols)[max_cols], bool (& busy_diagA)[2 * max_max_rows_cols],
bool (& busy_diagB)[2 * max_max_rows_cols],
int rows, int cols, int N, int & num_sol, int cnt = 0, int start_i = 0, int depth = 0) {
if (cnt >= N) {
Output(board, lines, rows, cols, false);
++num_sol;
return;
}
int const max_rows_cols = MAX(rows, cols);
if (rows - start_i < N - cnt)
return;
int avail_cols[max_cols];
int avail_cols_cnt = 0;
for (int j = 0; j < cols; ++j)
if (!busy_cols[j]) {
avail_cols[avail_cols_cnt] = j;
++avail_cols_cnt;
}
if (avail_cols_cnt < N - cnt)
return;
for (int i = start_i; i < rows; ++i)
for (int jj = 0; jj < avail_cols_cnt; ++jj) {
int const j = avail_cols[jj];
if (busy_diagA[max_rows_cols + j - i] || busy_diagB[j + i])
continue;
board[i][j] = true;
busy_cols[j] = true;
busy_diagA[max_rows_cols + j - i] = true;
busy_diagB[j + i] = true;
Solve(board, lines, busy_cols, busy_diagA, busy_diagB,
rows, cols, N, num_sol, cnt + 1, i + 1, depth + 1);
board[i][j] = false;
busy_cols[j] = false;
busy_diagA[max_rows_cols + j - i] = false;
busy_diagB[j + i] = false;
}
if (depth == 0)
Output(board, lines, rows, cols, true);
}
void Output(bool (& board)[max_rows][max_cols], std::string (& lines)[max_rows],
int rows, int cols, bool last) {
if (1) {
if (!last) {
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j)
lines[i].push_back(board[i][j] ? 'Q' : '.');
lines[i] += "|";
}
}
if (lines[0].size() >= 70 || last && !lines[0].empty()) {
for (int i = 0; i < rows; ++i)
std::cout << lines[i] << std::endl;
for (int j = 0; j < lines[0].size(); ++j)
std::cout << (lines[0][j] == '|' ? '+' : '-');
std::cout << std::endl;
for (int i = 0; i < rows; ++i)
lines[i].clear();
}
}
}
int main() {
int const rows = 8, cols = 8, N = 8;
bool board[max_rows][max_cols] = {};
std::string lines[max_rows] = {};
bool busy_cols[max_cols] = {};
bool busy_diagA[2 * max_max_rows_cols] = {};
bool busy_diagB[2 * max_max_rows_cols] = {};
int num_sol = 0;
Solve(board, lines, busy_cols, busy_diagA, busy_diagB, rows, cols, N, num_sol);
std::cout << "Number of solutions: " << num_sol << std::endl;
}
Output:
Q.......|Q.......|Q.......|Q.......|.Q......|.Q......|.Q......|.Q......|
....Q...|.....Q..|......Q.|......Q.|...Q....|....Q...|....Q...|.....Q..|
.......Q|.......Q|...Q....|....Q...|.....Q..|......Q.|......Q.|Q.......|
.....Q..|..Q.....|.....Q..|.......Q|.......Q|Q.......|...Q....|......Q.|
..Q.....|......Q.|.......Q|.Q......|..Q.....|..Q.....|Q.......|...Q....|
......Q.|...Q....|.Q......|...Q....|Q.......|.......Q|.......Q|.......Q|
.Q......|.Q......|....Q...|.....Q..|......Q.|.....Q..|.....Q..|..Q.....|
...Q....|....Q...|..Q.....|..Q.....|....Q...|...Q....|..Q.....|....Q...|
--------+--------+--------+--------+--------+--------+--------+--------+
.Q......|.Q......|.Q......|.Q......|..Q.....|..Q.....|..Q.....|..Q.....|
.....Q..|......Q.|......Q.|.......Q|Q.......|....Q...|....Q...|....Q...|
.......Q|..Q.....|....Q...|.....Q..|......Q.|.Q......|.Q......|......Q.|
..Q.....|.....Q..|.......Q|Q.......|....Q...|.......Q|.......Q|Q.......|
Q.......|.......Q|Q.......|..Q.....|.......Q|Q.......|.....Q..|...Q....|
...Q....|....Q...|...Q....|....Q...|.Q......|......Q.|...Q....|.Q......|
......Q.|Q.......|.....Q..|......Q.|...Q....|...Q....|......Q.|.......Q|
....Q...|...Q....|..Q.....|...Q....|.....Q..|.....Q..|Q.......|.....Q..|
--------+--------+--------+--------+--------+--------+--------+--------+
..Q.....|..Q.....|..Q.....|..Q.....|..Q.....|..Q.....|..Q.....|..Q.....|
....Q...|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|
.......Q|.Q......|.Q......|.Q......|...Q....|...Q....|.......Q|.......Q|
...Q....|....Q...|......Q.|......Q.|Q.......|.Q......|Q.......|Q.......|
Q.......|.......Q|Q.......|....Q...|.......Q|.......Q|...Q....|....Q...|
......Q.|Q.......|...Q....|Q.......|....Q...|....Q...|......Q.|......Q.|
.Q......|......Q.|.......Q|.......Q|......Q.|......Q.|....Q...|.Q......|
.....Q..|...Q....|....Q...|...Q....|.Q......|Q.......|.Q......|...Q....|
--------+--------+--------+--------+--------+--------+--------+--------+
..Q.....|..Q.....|..Q.....|..Q.....|...Q....|...Q....|...Q....|...Q....|
.....Q..|......Q.|......Q.|.......Q|Q.......|Q.......|.Q......|.Q......|
.......Q|.Q......|.Q......|...Q....|....Q...|....Q...|....Q...|......Q.|
.Q......|.......Q|.......Q|......Q.|.......Q|.......Q|.......Q|..Q.....|
...Q....|....Q...|.....Q..|Q.......|.Q......|.....Q..|.....Q..|.....Q..|
Q.......|Q.......|...Q....|.....Q..|......Q.|..Q.....|Q.......|.......Q|
......Q.|...Q....|Q.......|.Q......|..Q.....|......Q.|..Q.....|Q.......|
....Q...|.....Q..|....Q...|....Q...|.....Q..|.Q......|......Q.|....Q...|
--------+--------+--------+--------+--------+--------+--------+--------+
...Q....|...Q....|...Q....|...Q....|...Q....|...Q....|...Q....|...Q....|
.Q......|.Q......|.Q......|.Q......|.....Q..|.....Q..|.....Q..|......Q.|
......Q.|......Q.|.......Q|.......Q|Q.......|.......Q|.......Q|Q.......|
..Q.....|....Q...|....Q...|.....Q..|....Q...|.Q......|..Q.....|.......Q|
.....Q..|Q.......|......Q.|Q.......|.Q......|......Q.|Q.......|....Q...|
.......Q|.......Q|Q.......|..Q.....|.......Q|Q.......|......Q.|.Q......|
....Q...|.....Q..|..Q.....|....Q...|..Q.....|..Q.....|....Q...|.....Q..|
Q.......|..Q.....|.....Q..|......Q.|......Q.|....Q...|.Q......|..Q.....|
--------+--------+--------+--------+--------+--------+--------+--------+
...Q....|...Q....|...Q....|...Q....|...Q....|...Q....|....Q...|....Q...|
......Q.|......Q.|......Q.|.......Q|.......Q|.......Q|Q.......|Q.......|
..Q.....|....Q...|....Q...|Q.......|Q.......|....Q...|...Q....|.......Q|
.......Q|.Q......|..Q.....|..Q.....|....Q...|..Q.....|.....Q..|...Q....|
.Q......|.....Q..|Q.......|.....Q..|......Q.|Q.......|.......Q|.Q......|
....Q...|Q.......|.....Q..|.Q......|.Q......|......Q.|.Q......|......Q.|
Q.......|..Q.....|.......Q|......Q.|.....Q..|.Q......|......Q.|..Q.....|
.....Q..|.......Q|.Q......|....Q...|..Q.....|.....Q..|..Q.....|.....Q..|
--------+--------+--------+--------+--------+--------+--------+--------+
....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|
Q.......|.Q......|.Q......|.Q......|.Q......|..Q.....|..Q.....|..Q.....|
.......Q|...Q....|...Q....|.....Q..|.......Q|Q.......|Q.......|.......Q|
.....Q..|.....Q..|......Q.|Q.......|Q.......|.....Q..|......Q.|...Q....|
..Q.....|.......Q|..Q.....|......Q.|...Q....|.......Q|.Q......|......Q.|
......Q.|..Q.....|.......Q|...Q....|......Q.|.Q......|.......Q|Q.......|
.Q......|Q.......|.....Q..|.......Q|..Q.....|...Q....|.....Q..|.....Q..|
...Q....|......Q.|Q.......|..Q.....|.....Q..|......Q.|...Q....|.Q......|
--------+--------+--------+--------+--------+--------+--------+--------+
....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|
......Q.|......Q.|......Q.|......Q.|......Q.|......Q.|.......Q|.......Q|
Q.......|Q.......|.Q......|.Q......|.Q......|...Q....|...Q....|...Q....|
..Q.....|...Q....|...Q....|.....Q..|.....Q..|Q.......|Q.......|Q.......|
.......Q|.Q......|.......Q|..Q.....|..Q.....|..Q.....|..Q.....|......Q.|
.....Q..|.......Q|Q.......|Q.......|Q.......|.......Q|.....Q..|.Q......|
...Q....|.....Q..|..Q.....|...Q....|.......Q|.....Q..|.Q......|.....Q..|
.Q......|..Q.....|.....Q..|.......Q|...Q....|.Q......|......Q.|..Q.....|
--------+--------+--------+--------+--------+--------+--------+--------+
.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|
Q.......|.Q......|.Q......|..Q.....|..Q.....|..Q.....|..Q.....|..Q.....|
....Q...|......Q.|......Q.|Q.......|Q.......|Q.......|....Q...|....Q...|
.Q......|Q.......|Q.......|......Q.|.......Q|.......Q|......Q.|.......Q|
.......Q|..Q.....|...Q....|....Q...|...Q....|....Q...|Q.......|Q.......|
..Q.....|....Q...|.......Q|.......Q|.Q......|.Q......|...Q....|...Q....|
......Q.|.......Q|....Q...|.Q......|......Q.|...Q....|.Q......|.Q......|
...Q....|...Q....|..Q.....|...Q....|....Q...|......Q.|.......Q|......Q.|
--------+--------+--------+--------+--------+--------+--------+--------+
.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|
..Q.....|..Q.....|..Q.....|...Q....|...Q....|...Q....|...Q....|.......Q|
......Q.|......Q.|......Q.|Q.......|.Q......|......Q.|......Q.|.Q......|
.Q......|.Q......|...Q....|....Q...|.......Q|Q.......|Q.......|...Q....|
...Q....|.......Q|Q.......|.......Q|....Q...|..Q.....|.......Q|Q.......|
.......Q|....Q...|.......Q|.Q......|......Q.|....Q...|.Q......|......Q.|
Q.......|Q.......|.Q......|......Q.|Q.......|.Q......|....Q...|....Q...|
....Q...|...Q....|....Q...|..Q.....|..Q.....|.......Q|..Q.....|..Q.....|
--------+--------+--------+--------+--------+--------+--------+--------+
......Q.|......Q.|......Q.|......Q.|......Q.|......Q.|......Q.|......Q.|
Q.......|.Q......|.Q......|..Q.....|..Q.....|...Q....|...Q....|....Q...|
..Q.....|...Q....|.....Q..|Q.......|.......Q|.Q......|.Q......|..Q.....|
.......Q|Q.......|..Q.....|.....Q..|.Q......|....Q...|.......Q|Q.......|
.....Q..|.......Q|Q.......|.......Q|....Q...|.......Q|.....Q..|.....Q..|
...Q....|....Q...|...Q....|....Q...|Q.......|Q.......|Q.......|.......Q|
.Q......|..Q.....|.......Q|.Q......|.....Q..|..Q.....|..Q.....|.Q......|
....Q...|.....Q..|....Q...|...Q....|...Q....|.....Q..|....Q...|...Q....|
--------+--------+--------+--------+--------+--------+--------+--------+
.......Q|.......Q|.......Q|.......Q|
.Q......|.Q......|..Q.....|...Q....|
...Q....|....Q...|Q.......|Q.......|
Q.......|..Q.....|.....Q..|..Q.....|
......Q.|Q.......|.Q......|.....Q..|
....Q...|......Q.|....Q...|.Q......|
..Q.....|...Q....|......Q.|......Q.|
.....Q..|.....Q..|...Q....|....Q...|
--------+--------+--------+--------+
Number of solutions: 92
There are several issues, starting from the multiple memory leaks (see e.g. the empty destructor or the delete[] boardPtr; at the beginning of ChessBoard::setSize), but what prevents the program to solve the problem is this:
bool ChessBoard::canPlace(char** boardPtr, int row, int column)
{
int i, j;
// Check row
for (i = 0; i < column; i++)
if (boardPtr[row][i] )
// ^^^^^^^^^^^^^^^^
return false;
// ...
}
That condition and the following ones should be boardPtr[row][i] == 'Q', because, as written, it just check if the char is not 0, while an empty spot is indicated by a . in this program.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am writing a C++ code for a Sudoku solver.
The code must work for a 9x9, 16x16 and 25x25 grid. My code only works for a 9x9 grid. I am not sure why. May someone please help me. I think I need to make the 16x16 and 25x25 codes work faster somehow. How do I do this?
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
vector<int> tokenize(string s, string del);
void readAPuzzle(vector<vector<int>> &grid);
void printGrid(vector<vector<int>> grid);
bool isValid(int i, int j, vector<vector<int>> grid);
bool isValid(vector<vector<int>> grid);
bool search(vector<vector<int>> &grid);
int getFreeCellList(vector<vector<int>> grid, vector<pair<int, int>> &freeCellList);
int main()
{
// Read a Sudoku puzzle
vector<vector<int>> puzzle;
readAPuzzle(puzzle);
if (!isValid(puzzle))
cout << "Invalid input" << endl;
else if (search(puzzle)){
printGrid(puzzle);
}
else
cout << "No solution" << endl;
return 0;
}
vector<int> tokenize(string s, string del)
{
vector<int> row;
int start = 0;
int end = s.find(del);
while (end != -1) {
row.push_back(stoi( s.substr(start, end - start)));
start = end + del.size();
end = s.find(del, start);
}
row.push_back(stoi( s.substr(start, end - start)));
return row;
}
void readAPuzzle(vector<vector<int>> &grid){
string line;
getline(cin, line);
vector<int> firstRow = tokenize(line, " ");
grid.push_back(firstRow);
for(int i = 0; i < firstRow.size()-1; i++){
getline(cin, line);
vector<int> row = tokenize(line, " ");
grid.push_back(row);
}
}
/** Obtain a list of free cells from the puzzle */
int getFreeCellList(vector<vector<int>> grid, vector<pair<int, int>> &freeCellList)
{
// 81 is the maximum number of free cells
int numberOfFreeCells = 0;
for (int i = 0; i < grid.size(); i++)
for (int j = 0; j < grid.size(); j++)
if (grid[i][j] == 0)
{
freeCellList[numberOfFreeCells].first = i;
freeCellList[numberOfFreeCells].second = j;
numberOfFreeCells++;
}
return numberOfFreeCells;
}
/** Print the values in the grid */
void printGrid(vector<vector<int>> grid)
{
for (int i = 0; i < grid.size(); i++)
{
for (int j = 0; j < grid.size(); j++)
cout << grid[i][j] << " ";
cout << endl;
}
}
/** Search for a solution */
bool search(vector<vector<int>> &grid)
{
int k = 0; // Start from the first free cell
bool found = false; // Solution found?
const int n = grid.size();
vector<pair<int, int>> freeCellList(n*n);
int numberOfFreeCells = getFreeCellList(grid, freeCellList);
while (!found)
{
int i = freeCellList[k].first;
int j = freeCellList[k].second;
if (grid[i][j] == 0)
grid[i][j] = 1; // Start with 1
if (isValid(i, j, grid))
{
if (k + 1 == numberOfFreeCells)
{ // No more free cells
found = true; // A solution is found
}
else
{ // Move to the next free cell
k++;
}
}
else if (grid[i][j] < grid.size())
{
grid[i][j] = grid[i][j] + 1; // Check the next possible value
}
else
{ // grid[i][j] is 9, backtrack
while (grid[i][j] == grid.size())
{
grid[i][j] = 0; // Reset to free cell
if (k == 0)
{
return false; // No possible value
}
k--; // Backtrack
i = freeCellList[k].first;
j = freeCellList[k].second;
}
grid[i][j] = grid[i][j] + 1; // Check the next possible value
}
}
return true; // A solution is found
}
/** Check whether grid[i][j] is valid in the grid */
bool isValid(int i, int j, vector<vector<int>> grid)
{
// Check whether grid[i][j] is valid at the i's row
for (int column = 0; column < grid.size(); column++)
if (column != j && grid[i][column] == grid[i][j])
return false;
// Check whether grid[i][j] is valid at the j's column
for (int row = 0; row < grid.size(); row++)
if (row != i && grid[row][j] == grid[i][j])
return false;
int n = sqrt(grid.size());
// Check whether grid[i][j] is valid in the 3 by 3 box
for (int row = (i / n) * n; row < (i / n) * n + n; row++)
for (int col = (j / n) * n; col < (j / n) * n + n; col++)
if (row != i && col != j && grid[row][col] == grid[i][j])
return false;
return true; // The current value at grid[i][j] is valid
}
/** Check whether the fixed cells are valid in the grid */
bool isValid(vector<vector<int>> grid)
{
// Check for duplicate numbers
for (int i = 0; i < grid.size(); i++)
for (int j = 0; j < grid.size(); j++)
if (grid[i][j] != 0)
if (!isValid(i, j, grid))
return false;
// Check whether numbers are in the range
for (int i = 0; i < grid.size(); i++)
for (int j = 0; j < grid.size(); j++)
if ((grid[i][j] < 0) || (grid[i][j] > 9))
return false;
return true; // The fixed cells are valid
}
This is the code I have written so far.
Thank you.
In bool isValid(vector<vector<int>>) you have
if ((grid[i][j] < 0) || (grid[i][j] > 9))
return false;
ie a grid with a number > 9 is never considered valid. I cannot tell if there are other errors, but when you only allow numbers in [0,9] it cannot work for 16x16 or 25x25 sized grids.
You are passing the grid by value to some of the functions. You should pass them as const reference instead to avoid unnecessary copies.
Alright so I have created this code. However, when i run it, it stops when it displays 104 for the counter??? I am so frustrated because I don't know how this could happen. The purpose of the code is to do the typical magic number output where the rows all add up to the same thing, the columns all add up to the same thing, and the diaganols all add up to the same thing. I believe the functions to do these calculations are correct, but the counter keeps stopping short of the 10000 attempts I am trying to do.
#include <iostream>
#include<time.h>
#include<stdlib.h>
using namespace std;
void getrandom();
void insertnumber(int n);
bool magic();
void create();
const int rows = 3;
const int cols = 3;
int arr[rows][cols] = { {0,0,0}, {0,0,0} , {0,0,0} };
int main() {
int counter = 0;
do
{
counter++;
cout << counter << endl;
getrandom();
if (counter == 100000)
break;
} while (!magic());
create();
cout << "It took " << counter << " tries." << endl;
return 0;
}
void getrandom() {
int n = 0;
const int size = 9;
int oldnum[size];
for (int i = 0; i < rows * cols; i++) {
oldnum[i] = 0;
}
srand(time(NULL)); // had to import the new libraries to use this
bool used = true;
for (int i = 0; i < size; i++) {
do
{
used = true;
n = rand() % 9 + 1;
if (oldnum[n - 1] == 0)
{
oldnum[n - 1] = n;
used = false;
}
} while (used);
insertnumber(n);
}
}
void insertnumber(int n) {
for (int i = 0; i < rows; i++) {
for (int j = 0; i < cols; j++) {
if (arr[i][j] == 0) {
arr[i][j] = n;
return;
}
}
}
}
bool magic() {
int rowsum = arr[0][0] + arr[0][1] + arr[0][2];
for (int i = 1; i < cols; i++)
{
if (arr[i][0] + arr[i][1] + arr[i][2] != rowsum)
return false;
}
for (int j = 0; j < rows; j++)
{
if (arr[0][j] + arr[1][j] + arr[2][j] != rowsum)
return false;
}
if (arr[0][0] + arr[1][1] + arr[2][2] != rowsum)
return false;
if (arr[0][2] + arr[1][1] + arr[2][0] != rowsum)
return false;
return true;
}
void create() {
{
for (int i = 0; i < rows; i++) {
for (int j = 0; i < cols; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
}
}
You can try using a debugger for such problems.
I think you code crashes because of this:
for (int i = 0; i < rows; i++) {
for (int j = 0; i < cols; j++) {
It looks like you mean j < cols here :)
Check line 76. When I compile and run the code, line 76 is where the exception is thrown.
This line specifically
arr[i][j] = n;
It seems your insertnumber() function is the culprit.
There are so many questions regarding Nqueens problem here. However, my implementation is different. My code checks with the board if queen placement is possible, instead of checking with the position of the previous queen.
It goes like this:
initially, the board has all zeros filled. The algorithm starts with the position (0,0). Then, it checks
row-wise per column to find the first 0. After finding the first zero, it changes the zero to one.
From this point onward, my logic differs. Instead of going to the next column, it first disables all the
positions, which the currently placed queen attacks, i.e. writes -1 on those places, i.e., row, column,
upper diagonal and lower diagonal. Now, the column value increments, and instead of check with the previous queen,
it simply has to find the first zero. Then again, relative positions get disabled.... you get the idea.
The code:
#include <iostream>
int board[8][8];
void printBoard() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
std::cout << board[i][j] << " ";
}
std::cout << "\n";
}
}
void disablePositions(int row, int col) {
//disable row
for (int j = col + 1; j < 8; j++) {
board[row][j] = 2;
}
//disable column
for (int i = 0; i < 8; i++) {
if (board[i][col] == 1) {
continue;
}
board[i][col] = 2;
}
//disable upper diagonal
for (int i = row - 1, j = col + 1; i >= 0 || j < 8; i--, j++) {
board[i][j] = 2;
}
for (int i = row + 1, j = col + 1; i < 8 || j < 8; i++, j++) {
board[i][j] = 2;
}
}
void solve(int initial_row) {
int init = initial_row;
int row = 0;
int col = 0;
while (col != 8) {
for (row = init; row < 8; row++) {
if (board[row][col] == 0) {
board[row][col] = 1;
break;
}
}
if (row == 8) {
col = 0;
initial_row++;
init = initial_row;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
board[i][j] = 0;
}
}
}
else {
init = 0;
disablePositions(row, col);
col++;
}
printBoard();
std::cout << std::endl;
}
}
int main() {
solve(0);
std::cout << std::endl;
}
This code is for 8-queens. The problem is, after it reaches the stage where it starts from [5][0], it just crashes. What is causing the issue?
Also, as it tries to make an optimal choice at every stage, would we call it greedy algorithm?
In your disable upper diagonal loops, you have the condition wrong. Using an || operation, the looping continues when either condition is true, which will lead to out-of-bounds access to the array.
Change the conditions in both for loops to be && (and).
I'm trying to create a 3x3 sliding tile puzzle game and I made the puzzle in a 2d array and now im trying to get the puzzle to slide a tile.
I'm new to debugging and cannot find out why the program isn't receiving the users input for the slide.
#define SLIDE_UP 1
#define SLIDE_DOWN 2
#define SLIDE_LEFT 3
#define SLIDE_RIGHT 4
void InitializeBoard(int[NUM_ROWS][NUM_COLS]);
void PrintBoard(int[NUM_ROWS][NUM_COLS]);
bool slideTile(int[NUM_ROWS][NUM_COLS], int);
void scrambleBoard(int[NUM_ROWS][NUM_COLS]);
bool isBoardSolved(int[NUM_ROWS][NUM_COLS]);
void DeallocateMemory(int[NUM_ROWS][NUM_COLS]);
int** ppRootPointer = NULL;
int main() {
int slidingBoard[NUM_ROWS][NUM_COLS];
char keyStroke = ' ';
int directionCode = UNSET;
int slideDirection = 0;
InitializeBoard(slidingBoard);
PrintBoard(slidingBoard);
slideTile(slidingBoard,slideDirection);
PrintBoard(slidingBoard);
_getch();
DeallocateMemory(slidingBoard);
return 0;
}
void InitializeBoard(int theBoard[NUM_ROWS][NUM_COLS]) {
ppRootPointer = new(int*[NUM_COLS]);
for (int i = 0; i < NUM_COLS; i++) {
ppRootPointer[i] = new(int[NUM_ROWS]);
}
int counter = 1;
int i = 0, j = 0;
for (i = 0; i < NUM_COLS; i++) {
for (j = 0; j < NUM_ROWS; j++) {
ppRootPointer[i][j] = counter++;
}
}
ppRootPointer[i-1][j-1] = PIVOT;
}
void PrintBoard(int theBoard[NUM_ROWS][NUM_COLS]) {
cout << left;
for (int i = 0; i < NUM_COLS; i++) {
for (int j = 0; j < NUM_ROWS; j++) {
if (ppRootPointer[i][j] != PIVOT) {
cout << setw(3) << ppRootPointer[i][j];
}
else {
cout << setw(3) << (char)PIVOT;
}
}
cout << endl;
}
cout << endl << endl;
}
bool slideTile(int theBoard[NUM_ROWS][NUM_COLS], int slideDirection) {
int pivotRow=0;
int pivotCol=0;
bool slidebool;
//once I declare i and j before the loop they go up to 3 instead of 2
//which causes the loop to not work
int i = 0;
int j = 0;
for (i = 0; i < NUM_COLS; i++) {
for (j = 0; j < NUM_ROWS; j++) {
if (theBoard[i][j] == (char)PIVOT) {
pivotCol = i;
pivotRow = j;
break;
}
}
}
//These are to assign pivotRow and Col because they dont get assigned
//inside of the loop
pivotCol = i;
pivotRow = j;
cout << "please enter a number to slide the tile (1 = up, 2 = down, 3 =
left, 4 = right" << endl;
cin >> slideDirection;
if (slideDirection == SLIDE_UP) {
if (pivotRow + 1 > NUM_ROWS) {
slidebool = false;
}
else {
ppRootPointer[pivotRow + 1][pivotCol] = PIVOT;
ppRootPointer[pivotRow][pivotCol] = ppRootPointer[pivotRow + 1]
[pivotCol];
slidebool = true;
}
}
.I'm hoping for the user to be able to enter an integer 1-4 representing the slide for the tile. This would allow me to build the scramble board function and get closer to finishing the code. Thanks to anyone that reads this and tries to help!!
I have an array of 20 x 20 that outputs how hot a plate is. I need to reiterate through a loop until no cell in the array changes more than 0.1 degree(I refresh the values through every iteration. How would you monitor the largest change for any cell in an array in order to determine when to stop iterating? Right now I have tried, but the below doesn't output correctly.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
const int ARRAY_SIZE = 20;
const int NEIGHBORS = 4;
void initialize(double hot_plate[][ARRAY_SIZE]);
bool writeFile(const double HOT_PLATE[][ARRAY_SIZE],
const string FILE_NAME);
double sum_cell(const double HOT_PLATE[][ARRAY_SIZE],
const int CELL_X, const int CELL_Y);
int main()
{
double hot_plate[ARRAY_SIZE][ARRAY_SIZE];
double hot_plate_prev[ARRAY_SIZE][ARRAY_SIZE];
initialize(hot_plate);
string file_name = "hot_plate.csv";
//accuracy up to 4 decmials
int runs = 724;
double hot_plate[ARRAY_SIZE][ARRAY_SIZE];
double hot_plate_prev[ARRAY_SIZE][ARRAY_SIZE];
while (true)
{
// This is your code
for (int i = 0; i < ARRAY_SIZE; i++)
{
for (int j = 0; j < ARRAY_SIZE; j++)
{
if (i > 0 && i < ARRAY_SIZE - 1 && j > 0 && j < ARRAY_SIZE - 1)
{
hot_plate[i][j] = sum_cell(hot_plate, j, i);
}
}
}
bool theSame = true;
for (int i = 0; i < ARRAY_SIZE; i++)
{
for (int j = 0; j < ARRAY_SIZE; j++)
{
if (abs(hot_plate[i][j] - hot_plate_prev[i][j]) < 0.1)
{
theSame = false;
}
hot_plate_prev[i][j] = hot_plate[i][j];
}
}
if (!theSame) break;
}
}
if (writeFile(hot_plate, file_name))
{
cout << "File wrote correctly\n";
}
else
{
cout << "The file did not write!\n";
}
//system("pause");
return 0;
}
double sum_cell(const double HOT_PLATE[][ARRAY_SIZE],
const int CELL_X, const int CELL_Y)
{
/* This code should never go out of bounds as it's in an if statement
if (i > 0 && i < ARRAY_SIZE - 1 && j > 0 && j < ARRAY_SIZE - 1)
*/
double cell_num = HOT_PLATE[CELL_X - 1][CELL_Y]; // Top
cell_num += HOT_PLATE[CELL_X][CELL_Y - 1]; // Left
cell_num += HOT_PLATE[CELL_X][CELL_Y + 1]; // Right
cell_num += HOT_PLATE[CELL_X + 1][CELL_Y]; // Bottom
cell_num /= NEIGHBORS;
return cell_num;
}
// setup the Array so all values are defined when starting
void initialize(double hot_plate[][ARRAY_SIZE])
{
for (int i = 0; i < ARRAY_SIZE; i++)
{
for (int j = 0; j < ARRAY_SIZE; j++)
{
if (i == 0 || i == ARRAY_SIZE - 1)
{
if (j == 0 || j == ARRAY_SIZE - 1)
{
hot_plate[i][j] = 0.0;
}
else
{
hot_plate[i][j] = 100.0;
}
}
else
{
hot_plate[i][j] = 0.0;
}
}
}
}
// Write the data to the CSV file
bool writeFile(const double HOT_PLATE[][ARRAY_SIZE],
const string FILE_NAME)
{
// open the file
ofstream fout(FILE_NAME);
if (fout.fail())
return false;
for (int i = 0; i < ARRAY_SIZE; i++)
{
for (int j = 0; j < ARRAY_SIZE; j++)
{
fout << HOT_PLATE[i][j];
if ( j < ARRAY_SIZE - 1)
{
fout << ", ";
}
else if (i != ARRAY_SIZE - 1)
{
fout << endl;
}
}
}
// close the input stream from the file.
fout.close();
return true;
}
At the beginning of your while loop, you can set a boolean variable called something like allSmallChanges to true. In your inner if statement, you can check to see if the change to hot_plate[i][j] is "too big". If it is too big, then set allSmallChanges to false. Then, just before the end of the while loop, you can break if allSmallChanges is still true.
If you don't want to have that cap of 724 iterations, you can get rid of your runs variable, and change the loop to while(true).
Note: The code in the question got changed after I wrote this answer. I'm not sure this answer still applies. However, I'm also sure that will be the last change to the code in the question. So, I'll leave this answer as-is for now.