@
anup30
Points to remember.
• OP is a first time beginner.
• He is modifying a program template his professor gave him.
• That crap from rosetta code deliberate obfuscates the (junk) code (I was considering replacing it myself).
• Suppose you are OP's professor, and your student turns something like that in. Instant F, right?
(And potential for expulsion.)
• 1st link: overload with concepts he doesn't understand yet.
• 2nd link: more code that doesn't work like OP's assignment.
@
lethien
I'm really trying to distill this problem down to as simple as possible, but I know it isn't a particularly easy problem to get your head around. The fact is that N-Queens is notoriously difficult to do well. We're working with a simple brute-force method here, which is enough to get you through the assignment but not overload you with stuff you haven't learned in a first term class.
sorry for my bad, I don"t understand allocating my elements. |
Don't feel sorry. It is always good to say "I don't understand" about something. Some people look at me stupid when I say that, but more often than not, when I ask the question there were many others also
thinking the question.
If you want to use an array of values, they must exist before you use them. A
std::vector allows you to create an array of values of any size you want, but by default it does
nothing -- there are no values.
You must first tell it how many values to create before you can use them.
1 2
|
vector <int> xs; // a vector of values -- with no values
xs[ 2 ] = 7; // Program fails and/or crashes -- cannot access memory that doesn't exist/belong to you
|
Let's fix the problem:
1 2 3
|
vector <int> xs( 12 ); // a vector of 12 distinct values -- the vector constructor creates them for you
xs[ 2 ] = 7; // Works, because the third element of five elements exists
xs[ 5 ] = 9; // Failure and/or crash, because the sixth element does not exist.
|
What this means for your code is that you have a vector of zero elements (
v1D) but treat it as if it had
BoardSize elements.
The technical time of the crash is not in your code -- it is in your professor's. The
solutions vector is expected to be zero or more solutions (vectors of
BoardSize elements), but your code is returning a vector that contains solutions with zero elements. When your professor's code tries to access an element of the first solution -- which isn't there -- it causes the program to crash.
A solution
A solution represents queens on a board. There are
BoardSize rows on the board, so there must also be
BoardSize queens on the board, and hence,
BoardSize elements in a solution.
Each element is a lookup. For element 0 (row 0) the queen will be at the value's column. So, for a 4x4 board, a valid solution is a vector of the following values:
{ 1, 3, 0, 2 }
That is:
at row 0, the queen is in column 1
at row 1, the queen is in column 3
at row 2, the queen is in column 0
at row 3, the queen is in column 2
Get it?
You'll notice that when your professor prints the solution, he adds one to all those values, so you see a solution as
(1,2) (2,4) (3,1) (4,3)
instead of
(0,1) (1,3) (2,0) (3,2)
Is safe to place piece at (row,column)?
I'm not sure why you went and changed your
SAFE() function when before I indicated to you that it worked correctly. Because now it does not. Here's what you had before (IIRC):
1 2 3 4 5 6 7 8 9 10 11 12
|
bool SAFE(vector<int> CHECK, int row, int column)
{
for (int i = 0; i < row; i++)
{
if (CHECK[i] == column)
return false;
if (abs(v1D[i]-column) == abs(i-row))
return false;
}
return true;
}
|
Try to follow through the code to see what it does for each of the (row,column) values in the solution. What does the above code return for (0,1)? For (1,3)? Etc.
An aside on names
Part of your confusion is evident in the names of things in the code. For example, a 'solution' has had the following different names in your code:
v1D CHECK column_solutions
Of these, my favorite is the last, but why not just call it a 'solution'? Once you chose a name, try to use the same name for the same thing everywhere in your code. For example:
1 2
|
bool SAFE(vector<int> column_solutions, int row, int column)
{
|
Choosing a good name for a thing helps you not be confused about your code.
Finding a solution
You need to concentrate on how to place queens on the board.
You need to see what you are doing in action, I think. Here is a small program to help. I assume you are on Windows. (If you are not, let me know.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
#include <chrono>
#include <cstdlib>
#include <iostream>
#include <thread>
#include <string>
using namespace std;
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
void goto_xy( int x, int y )
{
static HANDLE hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
COORD coords = { (SHORT)x, (SHORT)y };
SetConsoleCursorPosition( hStdOut, coords );
}
#else
#error Complain to Duoas that you are using unix.
#endif
void print( int x ) { for (int n = 0; n < 4; n++) { goto_xy( 0, 3-n );
cout << string( x % 4, '-' ) << "Q" << string( 4 - x % 4 - 1, '-' ) <<
string( 7, ' ' ) << "\n"; x >>= 2; } goto_xy( 0, 4 ); cout << string( 10,
' ' ) << "\n"; } int main() {
system("cls"); // don't do this, btw.
for (int x = 0; x < 0x100; x++) { print( x ); if ((x == 114) || (x == 141))
{ cout << "A solution!" << flush; this_thread::sleep_for( chrono::seconds( 1 )
); cout << "\r" << string( 11, ' ' ) << flush; } else this_thread::sleep_for(
chrono::milliseconds( 250 ) ); } cout << "all done. found two solutions.\n"; }
|
THIS ONLY SHOWS YOU HOW THINGS WORK. It does NOT solve the N-Queens problem, not even for a 4x4 board. Don't try to figure it out. It won't help you in your assignment.
Just watch the animation to see how your code should work through the possible solutions.
Then you can start thinking about how to use a 'solution' vector to help you do it.
Hope this helps.