I am implementing an algorithm by Moller on calculating triangle triangle intersection and I cannot quite wrap my head around something:
Given two planes of the intersecting triangles, we have their corresponding equations in the form of N*P + d = 0 where N is the cross product two vectors in the plane and P is any point on the plane. d can also be calculated.
Considering the triangles are not co-planar, their intersection will be a line L = P + tD where D is the N(first plane) * N(second plane) - this is the direction of the line, P is any point on the line and t is the parameter. The algorithm stops at calculating segments of intersection of triangles with their opposing triangles' planes in terms of t. Now if these segments overlap, the triangles intersect. But again, these segments are expressed only in terms of t. I, however, want to go further and actually get the coordinates of the intersection.
So here is the question - given the two planes, three points which lie on the planes (the points of the triangles) and the line L = P + tD where we know the D and the ts, how can I calculate the points of the segments?
Any help would be greatly appreciated,
Thank you
I am adding the code of what i've got so far:
{
//Implimentation of Tomas Moller's intesection finding algorithm with additions to determine the coorninates of the intersection
//Vertex vectors
Vector3f Va0(a.Point1.X, a.Point1.Y, a.Point1.Z);
Vector3f Va1(a.Point2.X, a.Point2.Y, a.Point2.Z);
Vector3f Va2(a.Point3.X, a.Point3.Y, a.Point3.Z);
Vector3f Vb0(b.Point1.X, b.Point1.Y, b.Point1.Z);
Vector3f Vb1(b.Point2.X, b.Point2.Y, b.Point2.Z);
Vector3f Vb2(b.Point3.X, b.Point3.Y, b.Point3.Z);
//First, find the plane equation of triangle b = Pb
//N dot X + d = 0 where X is any point on the plane
auto N2 = (Vb1 - Vb0).cross((Vb2 - Vb0));
N2.normalize();
float d2 = (N2 * (-1)).dot(Vb0);
//We'll then find the signed distance from each point of the triangle a to plane Pb
float da_0 = Round(N2.dot(Va0) + d2);
float da_1 = Round(N2.dot(Va1) + d2);
float da_2 = Round(N2.dot(Va2) + d2);
//reject intersetion if none of the points lie on the plane and all have the same sign
//meaning that the triangle a lies on one side of the triangle b
if (da_0 != 0 && da_1 != 0 && da_2 != 0 && da_0 > 0 && da_1 > 0 && da_2 > 0)
return nullptr;
if (da_0 != 0 && da_1 != 0 && da_2 != 0 && da_0 < 0 && da_1 < 0 && da_2 < 0)
return nullptr;
//do the same thing for the other triangle
auto N1 = (Va1 - Va0).cross((Va2 - Va0));
N1.normalize();
float d1 = (N1 * (-1)).dot(Va0);
float db_0 = Round(N1.dot(Vb0) + d1);
float db_1 = Round(N1.dot(Vb1) + d1);
float db_2 = Round(N1.dot(Vb2) + d1);
if (db_0 != 0 && db_1 != 0 && db_2 != 0 && db_0 > 0 && db_1 > 0 && db_2 > 0)
return nullptr;
if (db_0 != 0 && db_1 != 0 && db_2 != 0 && db_0 < 0 && db_1 < 0 && db_2 < 0)
return nullptr;
#pragma region Coplanar Triangles
if (db_0 == 0 && db_1 == 0 && db_2 == 0)
{
//if the triangles are coplanar we'll find the intersection in 2d space
return nullptr;
}
#pragma endregion
#pragma region Triangles are in 3D space
else
{
//Triangles are not coplanar and the intersection line is some line L = O + tD
//where D = N1 cross N2 - direction of the line and O is some point on it
//We will find the the intersection segment of the first triangle with the plane os the second triangle and visa versa
//If the two segments overlap, the triangles intesect
auto D = N1.cross(N2);
D.normalize();
#pragma region Point Contact Between the Triangles
//first reject intersection if one triangle only touches the other with one point
if ((da_0 == 0 && da_1 > 0 && da_2 > 0) || (da_0 == 0 && da_1 < 0 && da_2 < 0))
return nullptr;
if ((da_0 > 0 && da_1 == 0 && da_2 > 0) || (da_0 < 0 && da_1 == 0 && da_2 < 0))
return nullptr;
if ((da_0 > 0 && da_1 > 0 && da_2 == 0) || (0 > da_0 && da_1 < 0 && da_2 == 0))
return nullptr;
if ((db_0 == 0 && db_1 > 0 && db_2 > 0) || (db_0 == 0 && db_1 < 0 && db_2 < 0))
return nullptr;
if ((db_0 > 0 && db_1 == 0 && db_2 > 0) || (db_0 < 0 && db_1 == 0 && db_2 < 0))
return nullptr;
if ((db_0 > 0 && db_1 > 0 && db_2 == 0) || (0 > db_0 && db_1 < 0 && db_2 == 0))
return nullptr;
#pragma endregion
//If the above passes, proceed with 3d triangle intersection. Start with triangle a and plane Pb,
//there will be one point of a on one side of the Pb and two points of a on the other side of Pb. Let's find them:
#pragma region Triangle A
tuple<Vector3f, Vector3f> edgeA1;
tuple<Vector3f, Vector3f> edgeA2;
float dV0 = 1;
float dV1 = 1;
float dV2 = 1;
if ((da_0 > 0 && da_1 <= 0 && da_2 <= 0) || (da_0 < 0 && da_1 >= 0 && da_2 >= 0))
{
edgeA1 = make_tuple(Va1, Va0);
edgeA2 = make_tuple(Va0, Va2);
dV0 = da_1;
dV1 = da_0;
dV2 = da_2;
}
else if ((da_0 <= 0 && da_1 > 0 && da_2 <= 0) || (da_0 >= 0 && da_1 < 0 && da_2 >= 0))
{
edgeA1 = make_tuple(Va0, Va1);
edgeA2 = make_tuple(Va1, Va2);
dV0 = da_0;
dV1 = da_1;
dV2 = da_2;
}
else if ((da_0 <= 0 && da_1 <= 0 && da_2 > 0) || (da_0 >= 0 && da_1 >= 0 && da_2 < 0))
{
edgeA1 = make_tuple(Va0, Va2);
edgeA2 = make_tuple(Va2, Va1);
dV0 = da_0;
dV1 = da_2;
dV2 = da_1;
}
//pi = D * Vi where i = 0, 1, 2
auto pA_0 = D.dot(get<0>(edgeA1));
auto pA_1 = D.dot(get<0>(edgeA2));
auto pA_2 = D.dot(get<1>(edgeA2));
//The tA_1 and tA_2 define the interval of the intersection of triangle a with the line L
float tA_1 = pA_0 + (pA_1 - pA_0) * (dV0 / (dV0 - dV1));
float tA_2 = pA_1 + (pA_2 - pA_1) * (dV1 / (dV1 - dV2));
#pragma endregion
//Now repeat for triangle b
#pragma region Triangle B
tuple<Vector3f, Vector3f> edgeB1;
tuple<Vector3f, Vector3f> edgeB2;
if ((db_0 > 0 && db_1 <= 0 && db_2 <= 0) || (db_0 < 0 && db_1 >= 0 && db_2 >= 0))
{
edgeB1 = make_tuple(Vb1, Vb0);
edgeB2 = make_tuple(Vb0, Vb2);
dV0 = db_1;
dV1 = db_0;
dV2 = db_2;
}
else if ((db_0 <= 0 && db_1 > 0 && db_2 <= 0) || (db_0 >= 0 && db_1 < 0 && db_2 >= 0))
{
edgeB1 = make_tuple(Vb0, Vb1);
edgeB2 = make_tuple(Vb1, Vb2);
dV0 = db_0;
dV1 = db_1;
dV2 = db_2;
}
else if ((db_0 <= 0 && db_1 <= 0 && db_2 > 0) || (db_0 >= 0 && db_1 >= 0 && db_2 < 0))
{
edgeB1 = make_tuple(Vb0, Vb2);
edgeB2 = make_tuple(Vb2, Vb1);
dV0 = db_0;
dV1 = db_2;
dV2 = db_1;
}
//pi = D * Vi where i = 0, 1, 2
auto pB_0 = D.dot(get<0>(edgeB1));
auto pB_1 = D.dot(get<0>(edgeB2));
auto pB_2 = D.dot(get<1>(edgeB2));
//The tA_1 and tA_2 define the interval of the intersection of triangle a with the line L
float tB_1 = pB_0 + (pB_1 - pB_0) * (dV0 / (dV0 - dV1));
float tB_2 = pB_1 + (pB_2 - pB_1) * (dV1 / (dV1 - dV2));
#pragma endregion
#pragma region Determine Overlap
bool intersect = false;
float intPoint1;
float intPoint2;
//Order the segments
if (tA_1 > tA_2)
{
float temp = tA_1;
tA_1 = tA_2;
tA_2 = temp;
}
if (tB_1 > tB_2)
{
float temp = tB_1;
tB_1 = tB_2;
tB_2 = temp;
}
//Check for overlap
if (tB_1 >= tA_1 && tB_2 <= tA_2)
{
intPoint1 = tB_1;
intPoint2 = tB_2;
intersect = true;
}
else if (tA_1 >= tB_1 && tA_2 <= tB_2)
{
intPoint1 = tA_1;
intPoint2 = tA_2;
intersect = true;
}
else if (tB_1 >= tA_1 && tB_1 < tA_2 && tB_2 > tA_2)
{
intPoint1 = tB_1;
intPoint2 = tA_2;
intersect = true;
}
else if (tA_1 >= tB_1 && tA_1 < tB_2 && tA_2 > tB_2)
{
intPoint1 = tA_1;
intPoint2 = tB_2;
intersect = true;
}
#pragma endregion
if (!intersect)
return nullptr;
//If an overlap found, perform the last step of the algorithm and find the actual points of the intersection segment
else
{
}
}
#pragma endregion
}
Related
Given the following code pattern, wherein I am trying to state a vector direction in increments of 45 degrees over the integers int x and int y, inside of a circle positioned at the origin
// x == 0 && y == 0 case is already taken cared of
if(x > 1) {
if(y == 0) {
// horizontal right
m_rotation = 0;
}else if(y < 1) {
// diagonal down right
m_rotation = 315;
} else if(y > 1) {
// diagonal up right
m_rotation = 45;
}
} else if(x == 0) {
if(y < 1) {
// vertical down
m_rotation = 270;
} else if(y > 1) {
// vertical up
m_rotation = 90;
}
} else if(x < 1){
if(y == 0) {
// horizontal left
m_rotation = 180;
}else if(y < 1) {
// diagonal down left
m_rotation = 225;
} else if(y > 1) {
// diagonal up left
m_rotation = 135;
}
}
I am looking for an elegant way to make this compact. I know there's the spaceship operator <=>, but I need to restrict myself to C++17.
Things I have tried
Nesting ternary operators with m_rotation = x > 1? (y < 1? (y == 0? 0: 315): 45): (x == 0? (y < 1? 270: 90): (y < 1? (y == 0? 180: 225): 135));, but this looks weird
I tried putting the x == 0 case inside x < 1 case and transform the later into else, but that does not simplify enough the code
Using absolute values to compare x and y, but I quickly get lost
Nothing else really, I don't know what else to try
Something like
constexpr int rotation[3][3] = {
{225, 180, 135},
{270, 0, 90},
{315, 0, 45},
};
if (x != 0 || y != 0) // if (!(x == 0 && y == 0))
m_rotation = rotation[1 + sign(x)][1 + sign(y)];
There is a closed form:
// standard sign functions
int xs = x < 0 ? -1 : x > 0;
int ys = y < 0 ? -1 : y > 0;
return 180 - 45 * (xs + 2) * ys + 90 * (xs * xs + xs) * (ys * ys - 1);
or shorter
return 180 * (x < 0 || y) - 45 * (xs + 2) * ys;
This question concerns the edges of a depth first search operating on an adjacency matrix.
Given an adjacency matrix:
{1,0,0,1},
{1,1,0,0},
{0,0,0,1},
{1,1,1,1}
I have a perfectly working DFS like so:
typedef std::vector<std::vector<short>> matrix;
void myClass::dfs(short row, short column, std::shared_ptr<matrix> m_visited, const matrix &sky) {
if (m_visited->at(row).at(column) == 1) {
return;
}
m_visited->at(row).at(column) = 1; //Mark the node as visited
if(row+1 <= sky.size()-1 && sky.at(row+1).at(column) == 1) { //Look horizontally forward
dfs(row+1, column, m_visited, sky);
}
if(row-1 >= 0 && sky.at(row-1).at(column) == 1) { //Look horizontally backward
dfs(row-1, column, m_visited, sky);
}
if(column+1 <= sky.at(0).size()-1 && sky.at(row).at(column+1) == 1) { //Look vertically down
dfs(row, column+1, m_visited, sky);
}
if(column-1 >= 0 && sky.at(row).at(column-1) == 1) { //Look vertically up
dfs(row, column-1, m_visited, sky);
}
}
I've now been given the explicit task to replace
std::vector<std::vector<short>> matrix
with
std::unordered_set<std::vector<size_t>> matrix
My problem:
size_t is unsigned, so for example when row = 0 (where row is of type size_t), row -1 is undefined, and (row -1 > 0) evaluates to true on my compiler.
How can I test whether row -1 is still inside the boundaries of my adjacency matrix using size_t ?
It's simple math: row - 1 > 0 <=> row > 1 and column - 1 > 0 <=> column > 1. You can replace
if(row-1 >= 0 && sky.at(row-1).at(column) == 1)
with
if(row >= 1 && sky.at(row-1).at(column) == 1)
and
if(column-1 >= 0 && sky.at(row).at(column-1) == 1)
with
if(column >= 1 && sky.at(row).at(column-1) == 1)
You should also consider replacing
if(row+1 <= sky.size()-1 && sky.at(row+1).at(column) == 1)
with
if(sky.size() >= 2 && row <= sky.size()-2 && sky.at(row+1).at(column) == 1)
and
if(column+1 <= sky.at(0).size()-1 && sky.at(row).at(column+1) == 1)
with
if(sky.at(row).size() >= 2 && column <= sky.at(row).size()-2 && sky.at(row).at(column+1) == 1)
to avoid all kinds of wrap-around.
I have a bool function used in a test to see whether or not two objects are neighbours. If they are, a previous function InitFaceCheck() will write either 0 or 1 into a global array N[16] (16 cases to check for).
for (n = 0; n < count; n++ )
{
int l = 0;
for (m = 0; m < count; m++ )
{ InitFaceCheck(tet[n], tet_copy[m]); //
if( (tet[n].ID != tet_copy[m].ID) && (isNeighbour(N) == 1) ) // if T's
{
for(j = 0; j < 16; j++){
printf("N[%i] = %i ",j, N[j]);
}
printf("\n");
tet[n].next[l] = tet_copy[m].ID; // mark them as neighbours
l++; // neighbour counter
};
}
}
The InitFaceCheck() function evaluates if any the two tetrahedra share any of their faces (i.e. they share a face if the share the x,y,z coords of the three vertices that constitute that face) in total there are 16 tests, only 2 are included here:
void InitFaceCheck (TETRA a, TETRA b)
{
/*... Setup of bool variables to be used in CheckFace () ....
a bit tedious due to having .x .y .z components but it is solid for our purposes ... */
bool f11 = ( (a.vert[0].x == b.vert[0].x) && (a.vert[0].y == b.vert[0].y) && (a.vert[0].z == b.vert[0].z) &&
(a.vert[1].x == b.vert[1].x) && (a.vert[1].y == b.vert[1].y) && (a.vert[1].z == b.vert[1].z) &&
(a.vert[2].x == b.vert[2].x) && (a.vert[2].y == b.vert[2].y) && (a.vert[2].z == b.vert[2].z) );
bool f12 = ( (a.vert[0].x == b.vert[0].x) && (a.vert[0].y == b.vert[0].y) && (a.vert[0].z == b.vert[0].z) &&
(a.vert[1].x == b.vert[3].x) && (a.vert[1].y == b.vert[3].y) && (a.vert[1].z == b.vert[3].z) &&
(a.vert[2].x == b.vert[2].x) && (a.vert[2].y == b.vert[2].y) && (a.vert[2].z == b.vert[2].z) );
.......
// write output of tests to global array N, so as to make them accessible to all functions
N[0] = f11;
N[1] = f12;
N[2] = f13;
N[3] = f14;
N[4] = f21;
N[5] = f22;
N[6] = f23;
N[7] = f24;
N[8] = f31;
N[9] = f32;
N[10] = f33;
N[11] = f34;
N[12] = f41;
N[13] = f42;
N[14] = f43;
N[15] = f44;
The isNeighbour function looks like this:
bool isNeighbour (int a[16])
{
return (a[0] || a[1] || a[2] || a[3] || a[4] || a[5] || a[6] || a[7] || a[8]
|| a[9] || a[10] || a[11] || a[12] || a[13] || a[14] || a[15]);
// int i = 0;
//for (i = 0; i < 16; i++)
// {
// if ( a[i] == 1 ) return true;
//
// }
}
The output looks something like this:
T4092
T4100
N[0] = 0 N[1] = 0 N[2] = 0 N[3] = 0 N[4] = 0 N[5] = 0 N[6] = 0 N[7] = 0 N[8] = 1 N[9] = 0 N[10] = 0 N[11] = 0 N[12] = 0 N[13] = 0 N[14] = 0 N[15] = 0
T4101
T4120
N[0] = 0 N[1] = 0 N[2] = 1 N[3] = 0 N[4] = 0 N[5] = 0 N[6] = 0 N[7] = 0 N[8] = 0 N[9] = 0 N[10] = 0 N[11] = 0 N[12] = 0 N[13] = 0 N[14] = 0 N[15] = 0
T4169
N[0] = 0 N[1] = 0 N[2] = 0 N[3] = 0 N[4] = 0 N[5] = 0 N[6] = 0 N[7] = 0 N[8] = 0 N[9] = 0 N[10] = 0 N[11] = 0 N[12] = 1 N[13] = 0 N[14] = 0 N[15] = 0
N[0] = 0 N[1] = 1 N[2] = 0 N[3] = 0 N[4] = 0 N[5] = 0 N[6] = 0 N[7] = 0 N[8] = 0 N[9] = 0 N[10] = 0 N[11] = 0 N[12] = 0 N[13] = 0 N[14] = 0 N[15] = 0
My questions are the following:
why won't the commented out part of isNeighbour() work (it crashes)
? is the condition in the if loop correct ? (is it doing what I
think it is doing?)
why is N[] being rewritten as 0 when a tetrahedron has more than 1
neighbour (see T4169 with two lines of N[], in the second line,
N[12] was previously evaluated to be true (=1),
why is it when evaluating for the second time and it finds N[1]=1;
N[12] is reset to 0.
-and for the love of god is there anyway I could achieve a similar result but in a more elegant manner ? Also I am aware that I might
be violating basic rules of coding so please do not hesitate to
point them out!
Thank you
EDIT: this indeed C. I asked around and was told to include and bool should work just fine.
I have been searching for a Sudoku Solving Algorithm for a while and I found this code. But I have some difficulties. I can't understand it. If there are conflicts with all numbers between 1 and 9 in a single cell, the program should stop, right? But it continues. Can somebody explain me how the code works, please? Here it is:
bool Sudoku::Help_Solve(int i, int j)
{
int nextrow, nextcol;
while(change[i][j] == 1) //We find the first cell in which we can change the number
{
j++;
if(j > 9)
{
j = 1;
i++;
}
if(i > 9) return true;
}
for(int p = 1; p <= 9; p++)
{
if(Game.Check_Conflicts(p, i, j)) //We are checking for conflicts
{
board[i][j] = p;
nextrow = i;
nextcol = j+1;
if(nextcol > 9)
{
nextcol = 1;
nextrow++;
}
if(nextcol == 1 && nextrow == 10) return true;
if(Game.Help_Solve(nextrow, nextcol)) return true;
}
}
board[i][j] = 0;
return false;
}
Not enough code to explain properly, what happens in Game.Check_Conflicts(p, i, j), is this function getting called recursively?
Here is the whole code if you want to see it:
#include <iostream>
#include <iomanip>
#include <time.h>
#include <cstdlib>
#include <windows.h>
using namespace std;
class Sudoku
{
private:
int board[9][9];
int change[9][9];
public:
Sudoku();
void Print_Board();
void Add_First_Cord();
bool Help_Solve(int i, int j);
bool Check_Conflicts(int p, int i, int j);
};
Sudoku Game;
void setcolor(unsigned short color) //The function that you'll use to
{ //set the colour
HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hcon,color);
}
Sudoku::Sudoku()
{
for(int i = 0; i <= 9; i++)
for(int j = 0; j <= 9; j++)
board[i][j] = 0;
}
void Sudoku::Print_Board()
{
for(int i = 1; i <= 9; i++)
{
for(int j = 1; j <= 9; j++)
{
if(change[i][j] == 1)
{
setcolor(12);
cout << board[i][j] << " ";
setcolor(7);
}
else cout << board[i][j] << " ";
if(j%3 == 0) cout << "| ";
}
cout << endl;
if(i%3 == 0) cout << "------+-------+--------" << endl;
}
}
void Sudoku::Add_First_Cord()
{
board[1][1] = 5; change[1][1] = 1;
board[1][2] = 3; change[1][2] = 1;
board[1][5] = 7; change[1][5] = 1;
board[2][1] = 6; change[2][1] = 1;
board[2][4] = 1; change[2][4] = 1;
board[2][5] = 9; change[2][5] = 1;
board[2][6] = 5; change[2][6] = 1;
board[3][2] = 9; change[3][2] = 1;
board[3][3] = 8; change[3][3] = 1;
board[3][8] = 6; change[3][8] = 1;
board[4][1] = 8; change[4][1] = 1;
board[4][5] = 6; change[4][5] = 1;
board[4][9] = 3; change[4][9] = 1;
board[5][1] = 4; change[5][1] = 1;
board[5][4] = 8; change[5][4] = 1;
board[5][6] = 3; change[5][6] = 1;
board[5][9] = 1; change[5][9] = 1;
board[6][1] = 7; change[6][1] = 1;
board[6][5] = 2; change[6][5] = 1;
board[6][9] = 6; change[6][9] = 1;
board[7][2] = 6; change[7][2] = 1;
board[7][7] = 2; change[7][7] = 1;
board[7][8] = 8; change[7][8] = 1;
board[8][4] = 4; change[8][4] = 1;
board[8][5] = 1; change[8][5] = 1;
board[8][6] = 9; change[8][6] = 1;
board[8][9] = 5; change[8][9] = 1;
board[9][5] = 8; change[9][5] = 1;
board[9][8] = 7; change[9][8] = 1;
board[9][9] = 9; change[9][9] = 1;
}
bool Sudoku::Check_Conflicts(int p, int i, int j)
{
for(int k = 1; k <= 9; k++)
if(board[i][k] == p) return false;
for(int q = 1; q <= 9; q++)
if(board[q][j] == p) return false;
/*
*00
000
000
*/
if((j == 1 || j == 4 || j == 7) && (i == 1 || i == 4 || i == 7))
{
if(board[i][j+1] == p || board[i][j+2] == p || board[i+1][j] == p ||
board[i+2][j] == p || board[i+1][j+1] == p || board[i+1][j+2] == p ||
board[i+2][j+1] == p || board[i+2][j+2] == p)return false;
}
/*
000
000
*00
*/
if((j == 1 || j == 4 || j == 7) && (i == 3 || i == 6 || i == 9))
{
if(board[i-1][j] == p || board[i-2][j] == p || board[i][j+1] == p ||
board[i][j+2] == p || board[i-1][j+1] == p || board[i-1][j+2] == p ||
board[i-2][j+1] == p || board[i-2][j+2] == p)return false;
}
/*
000
*00
000
*/
if((j == 1 || j == 4 || j == 7) && (i == 2 || i == 5 || i == 8))
{
if(board[i-1][j] == p || board[i-1][j+1] == p || board[i-1][j+2] == p ||
board[i][j+1] == p || board[i][j+2] == p || board[i+1][j] == p ||
board[i+1][j+1] == p || board[i+1][j+2] == p)return false;
}
/*
0*0
000
000
*/
if((j == 2 || j == 5 || j == 8) && (i == 1 || i == 4 || i == 7))
{
if(board[i][j-1] == p || board[i][j+1] == p || board[i+1][j+1] == p ||
board[i+1][j-1] == p || board[i+1][j] == p || board[i+2][j-1] == p ||
board[i+2][j] == p || board[i+2][j+1] == p)return false;
}
/*
000
0*0
000
*/
if((j == 2 || j == 5 || j == 8) && (i == 2 || i == 5 || i == 8))
{
if(board[i-1][j] == p || board[i-1][j-1] == p || board[i-1][j+1] == p ||
board[i][j+1] == p || board[i][j-1] == p || board[i+1][j+1] == p ||
board[i+1][j] == p || board[i+1][j-1] == p)return false;
}
/*
000
000
0*0
*/
if((j == 2 || j == 5 || j == 8) && (i == 3 || i == 6 || i == 9))
{
if(board[i][j-1] == p || board[i][j+1] == p || board[i-1][j] == p ||
board[i-1][j+1] == p || board[i-1][j-1] == p || board[i-2][j] == p ||
board[i-2][j+1] == p || board[i-2][j-1] == p) return false;
}
/*
00*
000
000
*/
if((j == 3 || j == 6 || j == 9) && (i == 1 || i == 4 || i == 7))
{
if(board[i][j-1] == p || board[i][j-2] == p || board[i+1][j] == p ||
board[i+1][j-1] == p || board[i+1][j-2] == p || board[i+2][j] == p ||
board[i+2][j-1] == p || board[i+2][j-2] == p) return false;
}
/*
000
00*
000
*/
if((j == 3 || j == 6 || j == 9) && (i == 2 || i == 5 || i == 8))
{
if(board[i-1][j] == p || board[i-1][j-1] == p || board[i-1][j-2] == p ||
board[i][j-1] == p || board[i][j-2] == p || board[i+1][j] == p ||
board[i+1][j-1] == p || board[i+1][j-2] == p) return false;
}
/*
000
000
00*
*/
if((j == 3 || j == 6 || j == 9) && (i == 3 || i == 6 || i == 9))
{
if(board[i][j-1] == p || board[i][j-2] == p || board[i-1][j] == p ||
board[i-1][j-1] == p || board[i-1][j-2] == p || board[i-2][j] == p ||
board[i-2][j-1] == p || board[i-2][j-2] == p) return false;
}
return true;
}
bool Sudoku::Help_Solve(int i, int j)
{
int nextrow, nextcol;
while(change[i][j] == 1)
{
j++;
if(j > 9)
{
j = 1;
i++;
}
if(i > 9) return true;
}
for(int p = 1; p <= 9; p++)
{
if(Game.Check_Conflicts(p, i, j))
{
board[i][j] = p;
nextrow = i;
nextcol = j+1;
if(nextcol > 9)
{
nextcol = 1;
nextrow++;
}
if(nextcol == 1 && nextrow == 10) return true;
if(Game.Help_Solve(nextrow, nextcol)) return true;
}
}
board[i][j] = 0;
return false;
}
int main()
{
Game.Add_First_Cord();
Game.Help_Solve(1, 1);
Game.Print_Board();
system("pause");
return 0;
}
It looks like Sudoku::Check_Conflicts returns true if the number CAN be placed there, or false if it CAN'T be placed there due to a simple conflict. A different function name could maybe better self-document the code.
The thing is rhat I can't understand why it continues if in the end it
returns false :/
It doesn't ALWAYS return at the bottom of the function tho':
bool Sudoku::Help_Solve(int i, int j)
{
int nextrow, nextcol;
while(change[i][j] == 1) //We find the first cell in which we can change the number
{
j++;
if(j > 9)
{
j = 1;
i++;
}
if(i > 9) return true;
-------------------------^^^^
returns true if we have filled all squares.
}
for(int p = 1; p <= 9; p++)
{
if(Game.Check_Conflicts(p, i, j)) //We are checking for conflicts
{
board[i][j] = p;
nextrow = i;
nextcol = j+1;
if(nextcol > 9)
{
nextcol = 1;
nextrow++;
}
if(nextcol == 1 && nextrow == 10) return true;
-----------------------------------------------------^^^^
returns when we have filled everything!
if(Game.Help_Solve(nextrow, nextcol)) return true;
---------------------------------------------------------^^^^
returns if we filled at the next level of solution.
}
}
board[i][j] = 0;
return false;
-----------^^^^^ returns if we failed to fill the whole thing.
}
As someone else mentioned in a comment, there are some trivial things that can be done to improve on the algorithm - such as looking for the "most suitable place to fill first" [which doesn't improve the worst case, but it does improve the typical case].
I have written a Sudoku solver that uses a similar algorithm, but it tries to find the cell with the lowest number of candidates (possible numbers to go in the that cell) and only tries recursively if there are multiple choices.
I'm very new to C++ and was wondering if if there is a better way of doing this. It's going to run on an Arduino so I can't use ArrayLists or anything.
byte GetFreeCell(short x, short y)
{
byte possibleMoves[4] = {0,0,0,0};
if (y - 2 >= 0 && _grid[y - 2][x] == 0)
possibleMoves[0] = 1;
if (x + 2 < WIDTH && _grid[y][x + 2] == 0)
possibleMoves[1] = 2;
if (y + 2 < HEIGHT && _grid[y + 2][x] == 0)
possibleMoves[2] = 3;
if (x - 2 >= 0 && _grid[y][x - 2] == 0)
possibleMoves[3] = 4;
if (possibleMoves[0] == 0 && possibleMoves[1] == 0 && possibleMoves[2] == 0 && possibleMoves[3] == 0) {
return 0;
}
byte move = 0;
while(move == 0){
move = possibleMoves[random(4)];
}
return move;
}
Thanks,
Joe
byte GetFreeCell(short x, short y)
{
byte possibleMoves[4];
byte index = 0;
if (y - 2 >= 0 && _grid[y - 2][x] == 0)
possibleMoves[index++] = 1;
if (x + 2 < WIDTH && _grid[y][x + 2] == 0)
possibleMoves[index++] = 2;
if (y + 2 < HEIGHT && _grid[y + 2][x] == 0)
possibleMoves[index++] = 3;
if (x - 2 >= 0 && _grid[y][x - 2] == 0)
possibleMoves[index++] = 4;
return index ? possibleMoves[random(index)] : 0;
}
You can do yourself a favor and use this:
https://github.com/maniacbug/StandardCplusplus/#readme
Then you can sanitize your code by using standard containers.
Also, there's no ArrayList in C++. That's Java. With the above library, you can use std::vector instead.