I am new to c++ and qt, but I want to learn. The essence of the problem: the application hangs when you click on the button, although before some edits worked adequately (rolling back edits did not help). As far as I understand it is because of the while loop, but nowhere can I find an answer on how to fix it.
The program itself, what I need to implement, is to write the interaction of predators and herbivores, for a start on a primitive level.
So, please help me with the problem of hanging the application.
Creating classes
class Grass
{...};
class Predator
{...};
class Herbivorous
{...};
Button click processing
void MainWindow::on_pushButton_clicked()
{
int kol_grass = ui->lineEdit_11->text().toInt(), kol_weeks = 0, t, t_x, t_y, kol_H = ui->lineEdit->text().toInt(), kol_P = ui->lineEdit_2->text().toInt(), k = 0, kk = 0;
list<Herbivorous> lst_H;
list<Predator> lst_P;
list<Grass> lst_G;
int kol_die_P_hungry = 0, kol_die_H_hungry = 0, kol_die_P_age = 0, kol_die_H_age = 0, eaten = 0;
int years = 0;
qsrand(QDateTime::currentMSecsSinceEpoch());
//resize dynamic lists
lst_H.resize(kol_H);
lst_P.resize(kol_P);
lst_G.resize(kol_grass);
//creating list iterators
list<Herbivorous>::iterator i = lst_H.begin();
list<Herbivorous>::iterator j = lst_H.begin();
list<Predator>::iterator ii = lst_P.begin();
list<Predator>::iterator jj = lst_P.begin();
list<Grass>::iterator grass_it = lst_G.begin();
//creating grass objects
for (; grass_it != lst_G.end(); grass_it++)
{
//...
}
grass_it = lst_G.begin();
//creating herbivore objects
for (; i != lst_H.end(); i++)
{
//...
}
//creating predator objects
for (; ii != lst_P.end(); ii++)
{
//...
}
i = lst_H.begin();
ii = lst_P.begin();
Then the same cycle
Apparently, the application hangs, when you click on the button. What am I doing wrong?
//as long as both animal species are alive, simulate life
while (lst_H.size() > 0 && lst_P.size() > 0)
{
//grass rendering
for (; grass_it != lst_G.end(); grass_it++)
{
if (grass_it->GetValue() != .0)
{
QTableWidgetItem * grass = new QTableWidgetItem();
grass->setBackground(Qt::green);
ui->tableWidget->setItem(grass_it->GetY(), grass_it->GetX(), grass);
}
}
grass_it = lst_G.begin();
//once a month grass replenishment
if (kol_weeks % 4 == 0)
{
grass_it = lst_G.begin();
for(; grass_it != lst_G.end(); grass_it++)
{
grass_it->Recovery();
}
grass_it = lst_G.begin();
}
//once a month check for starvation
if (kol_weeks % 4 == 0)
{
i = lst_H.begin();
for (; i != lst_H.end(); i++)
{
if (i->GetHungry() <= 0)
{
i->SetInLife(false);//смерть от голода
kol_die_H_hungry++;
}
else
{
i->SetAge(i->GetAge() + 1);//+1 год
}
}
i = lst_H.begin();
ii = lst_P.begin();
for (; ii != lst_P.end(); ii++)
{
if (ii->GetHungry() <= 0)
{
ii->SetInLife(false);//смерть от голода
kol_die_P_hungry++;
}
else
{
ii->SetAge(ii->GetAge() + 1);//+1 год
}
}
ii = lst_P.begin();
}
//once a year old age check
if (kol_weeks == 48)
{
i = lst_H.begin();
kol_weeks = 0;
years++;
for (; i != lst_H.end(); i++)
{
if (i->GetAge() >= ui->lineEdit_3->text().toInt())
{
i->SetInLife(false);//смерть от старости
kol_die_H_age++;
}
else
{
i->SetAge(i->GetAge() + 1);//+1 год
}
}
i = lst_H.begin();
ii = lst_P.begin();
for (; ii != lst_P.end(); ii++)
{
if ((ii->GetAge() >= ui->lineEdit_10->text().toInt()) || (ii->GetHungry() <= 0))
{
ii->SetInLife(false);//смерть от старости или от голода
kol_die_P_age++;
}
else
{
ii->SetAge(ii->GetAge() + 1);//+1 год
}
}
ii = lst_P.begin();
}
//movement of herbivores
for (; i != lst_H.end(); i++)
{
QTableWidgetItem * noherbivorous = new QTableWidgetItem();
noherbivorous->setBackground(Qt::black);
ui->tableWidget->setItem(i->GetY(), i->GetX(), noherbivorous);
if (i->GetInLife() == true)
{
i->Direction();
i->Hungry();
QTableWidgetItem * herbivorous = new QTableWidgetItem();
herbivorous->setBackground(Qt::white);
ui->tableWidget->setItem(i->GetY(), i->GetX(), herbivorous);
}
}
//moving predators
for (; ii != lst_P.end(); ii++)
{
QTableWidgetItem * nopredator = new QTableWidgetItem();
nopredator->setBackground(Qt::black);
ui->tableWidget->setItem(ii->GetY(), ii->GetX(), nopredator);
if (ii->GetInLife() == true)
{
ii->Direction();
ii->Hungry();
QTableWidgetItem * predator = new QTableWidgetItem();
predator->setBackground(Qt::red);
ui->tableWidget->setItem(ii->GetY(), ii->GetX(), predator);
}
}
lst_H.remove_if([] (Herbivorous a) {return (a.GetInLife() == false);});//the removal of dead
lst_P.remove_if([] (Predator a) {return (a.GetInLife() == false);});//the removal of dead
i = lst_H.begin();
j = lst_H.begin();
//death of parents and birth of children (herbivores)
for (; i != lst_H.end(); i++)
{
for (; j != lst_H.end(); j++)
{
if ((i->GetNumber() != j->GetNumber()) && (i->GetInLife() == true) && (j->GetInLife() == true) && (i->GetAge() >= i->GetMin_Rep()) && (i->GetAge() <= i->GetMax_Rep()) && (j->GetAge() >= j->GetMin_Rep()) && (j->GetAge() <= j->GetMax_Rep()))
{
t_x = i->GetX() - j->GetX();
t_y = i->GetY() - j->GetY();
if (((t_x == 1) || (t_x == -1) || (t_x == 0)) && ((t_y == 1) || (t_y == -1) || (t_y == 0)))
{
i->SetInLife(false);
j->SetInLife(false);
//creating children
t = qrand() % (4 + 1);//от 0 до 4 детей
for (int u = 0; u < t; u++)
{
Herbivorous child;
child.SetInLife(true);
child.SetX(qrand() % (234 + 1));//рандом
child.SetY(qrand() % (144 + 1));//рандом
child.SetAge(1);
child.SetFood(ui->lineEdit_6->text().toDouble());
child.SetNumber(kk);
child.SetMax_Rep(ui->lineEdit_4->text().toInt());
child.SetMin_Rep(ui->lineEdit_5->text().toInt());
k++;
lst_H.push_back(child);
}
}
}
}
j = lst_H.begin();
}
ii = lst_P.begin();
jj = lst_P.begin();
//death of parents and birth of children (predators)
for (; ii != lst_P.end(); ii++)
{
for (; jj != lst_P.end(); jj++)
{
if ((ii->GetNumber() != jj->GetNumber()) && (ii->GetInLife() == true) && (jj->GetInLife() == true) && (ii->GetAge() >= ii->GetMin_Rep()) && (ii->GetAge() <= ii->GetMax_Rep()) && (jj->GetAge() >= jj->GetMin_Rep()) && (jj->GetAge() <= jj->GetMax_Rep()))
{
t_x = ii->GetX() - jj->GetX();
t_y = ii->GetY() - jj->GetY();
if (((t_x == 1) || (t_x == -1) || (t_x == 0)) && ((t_y == 1) || (t_y == -1) || (t_y == 0)))
{
ii->SetInLife(false);
jj->SetInLife(false);
//creating children
t = qrand() % (4 + 1);//от 0 до 4 детей
for (int u = 0; u < t; u++)
{
Predator child;
child.SetInLife(true);
child.SetX(qrand() % (234 + 1));//рандом
child.SetY(qrand() % (144 + 1));//рандом
child.SetAge(1);
child.SetFood(ui->lineEdit_8->text().toDouble());
child.SetNumber(k);
child.SetMax_Rep(ui->lineEdit_9->text().toInt());
child.SetMin_Rep(ui->lineEdit_7->text().toInt());
kk++;
lst_P.push_back(child);
}
}
}
}
jj = lst_P.begin();
}
ii = lst_P.begin();
j = lst_H.begin();
//hunting of predators on herbivores
for (; ii != lst_P.end(); ii++)
{
if (ii->GetHungry() < 1)
{
for (; j != lst_H.end(); j++)
{
if ((ii->GetInLife() == true) && (j->GetInLife() == true))
{
t_x = ii->GetX() - j->GetX();
t_y = ii->GetY() - j->GetY();
if (((t_x == 1) || (t_x == -1) || (t_x == 0)) && ((t_y == 1) || (t_y == -1) || (t_y == 0)))
{
j->SetInLife(false);
ii->SetHungry(ii->GetHungry() + 1);
eaten++;
}
}
}
}
j = lst_H.begin();
}
grass_it = lst_G.begin();
//hunting herbivores on the grass
for (; j != lst_H.end(); j++)
{
if (j->GetHungry() < 1)
{
for (; grass_it != lst_G.end(); grass_it++)
{
if ((grass_it->GetValue() > 0) && (j->GetInLife() == true) && (j->GetX() == grass_it->GetX()) && (j->GetY() == grass_it->GetY()))
{
if (grass_it->GetValue() > 0.5)
{
j->SetHungry(j->GetHungry() + 0.5);
grass_it->SetValue(grass_it->GetValue() - 0.5);
}
else
{
j->SetHungry(j->GetHungry() + grass_it->GetValue());
grass_it->SetValue(0);
}
}
}
}
j = lst_H.begin();
}
i = lst_H.begin();
ii = lst_P.begin();
grass_it = lst_G.begin();
//summary of interim results
ui->label_11->setText("The number of herbivores: " + QString::number(lst_H.size()));
...
QEventLoop loop;
QTimer::singleShot(100, &loop, SLOT(quit()));
loop.exec();
kol_weeks++;
}
}```
Related
The other day, I wrote a console game of Tic-Tac-Toe in c++ for my son. He wanted me to add a computer, and I ended us using the minimax algorithm for the first time. I did some quick testing, but really just gave my laptop to my son as soon as it was printing stuff, who played with it for a couple minuets. I looked over his sholder once or twice, and noticed that it wasn't playing optimally, iv'e been trying to debug it, but I can't see where it goes wrong. I tried getting rid of alpha beta prunning, but that did not change anything.
For context, on the board the computer is -1, blank is 0, and the player is 1.
Here is the minimax function:
int minimax(int board[9], int depth, int alpha, int beta, bool isMaxizimaizingPlayer)
{
bool found = false;
for (int i = 0; i < 9; i++)
{
if (board[i] == 0)
{
found = true;
}
}
if (!found)
{
return eval(board);
}
if (depth == 0 || eval(board) != 0)
{
return eval(board);
}
if (isMaxizimaizingPlayer)
{
int maxEval = -2;
for (int spot = 0; spot < 9; spot++)
{
if (board[spot] == 0)
{
board[spot] = 1;
int e = minimax(board, depth - 1, alpha, beta, false);
if (e > maxEval)
{
maxEval = e;
}
//if (beta < alpha)
//{
// break;
//}
board[spot] = 0;
}
}
return maxEval;
}
else {
int minEval = 2;
for (int spot = 0; spot < 9; spot++)
{
if (board[spot] == 0)
{
board[spot] = -1;
int e = minimax(board, depth - 1, alpha, beta, true);
if (e < minEval)
{
minEval = e;
}
//if (beta < alpha)
//{
// break;
//}
board[spot] = 0;
}
}
return minEval;
}
}
To be compleate, here is my eval function:
int eval(int board[9])
{
/*horizontial*/
for (int i = 0; i < 3; i++)
{
if (board[i * 3] == board[i * 3 + 1] && board[i * 3 + 2] == board[i * 3] && board[i * 3] != 0)
{
return board[i * 3];
}
}
/*vertical*/
for (int i = 0; i < 3; i++)
{
if (board[i] == board[i + 3] && board[i] == board[i + 6] && board[i] != 0)
{
return board[i];
}
}
/*Both diags*/
if (board[4] != 0) {
if (board[0] == board[4] && board[0] == board[8])
{
return board[4];
}
if (board[2] == board[4] && board[4] == board[6])
{
return board[4];
}
}
return 0;
}
And here is the inital call:
int spot = 0;
int minEval = 2;
for (int i = 0; i < 9; i++)
{
if (board[i] == 0)
{
board[i] = -1;
int score = minimax(board, 3, -2, 2, false);
if (score < minEval) {
minEval = score;
spot = i;
}
board[i] = 0;
}
}
std::cout << "The computer went in spot " << spot + 1 << std::endl;
board[spot] = -1;
printBoard(board);
It looks like you only call minimax with a depth of three, so the algorithm will only look up to three moves ahead, if you want optimal play you need to set the depth to > 9, so that the agent is always looking ahead to the end of the game.
I'm working in the watershed algortih in C++. I have implemented a source that i've found but i didn't get the expected results. I obtain:
[
But the result should be this:
[
I have charge the image .bmp into a matrix an then i obtain the Gradient of the image using the Sobel operator.
My wathershed algorith now is:
void Watershed() {
stack<punto> s;
punto p, neighbour;
C_Matrix prueba3 (Gradiente.FirstRow(), Gradiente.LastRow(), Gradiente.FirstCol(), Gradiente.LastCol(), -1);
int auxU, auxV, Eaux, L=1;
for (double g = Gradiente.Min(); g <= Gradiente.Max(); g++) {
for (int i = Gradiente.FirstRow(); i <= Gradiente.LastRow(); i++) {
for (int j = Gradiente.FirstCol(); j <= Gradiente.LastCol(); j++) {
if (Gradiente(i, j) == g) {
p.Guarda(i, j);
s.push(p);
}
while (s.empty() == 0) {
p = s.top();
s.pop();
auxU = p.x;
auxV = p.y;
Eaux = -1;
// 8-connectivity
for (int i = 0; i < 8; i++) {
if (i == 0)
neighbour.Guarda(auxU - 1, auxV - 1);
else if (i == 1)
neighbour.Guarda(auxU, auxV - 1);
else if (i == 2)
neighbour.Guarda(auxU + 1, auxV - 1);
else if (i == 3)
neighbour.Guarda(auxU - 1, auxV);
else if (i == 4)
neighbour.Guarda(auxU + 1, auxV);
else if (i == 5)
neighbour.Guarda(auxU - 1, auxV + 1);
else if (i == 6)
neighbour.Guarda(auxU, auxV + 1);
else
neighbour.Guarda(auxU + 1, auxV + 1);
if (neighbour.x >= Gradiente.FirstRow() && neighbour.x <= Gradiente.LastRow()
&& neighbour.y >= Gradiente.FirstCol() && neighbour.y <= Gradiente.LastCol()) {
if (prueba3(neighbour.x, neighbour.y) > 0) {
if (Eaux == -1) {
Eaux = prueba3(neighbour.x, neighbour.y);
}
else if (prueba3(neighbour.x, neighbour.y) != Eaux)
Eaux = 0;
}
}
}
if (auxU >= Gradiente.FirstRow() && auxU <= Gradiente.LastRow()
&& auxV >= Gradiente.FirstCol() && auxV <= Gradiente.LastCol()) {
if (Eaux >= 0) {
prueba3(auxU, auxV) = Eaux;
}
else {
prueba3(auxU, auxV) = L;
L++;
}
}
else {
C_Print("Se sale");
C_PrintNum("AuxU", auxU);
C_PrintNum("AuxV", auxV);
}
}
}
}
}
C_PrintNum("L = ", L);
double max = prueba3.Max();
if (max > 255.0) {
prueba3.Stretch(0, 255);
}
aux = C_Image(prueba3);
}
I don't know where is the fail, maybe my source has mistakes.
I must implement in C++ using diblok The Seeded Region Growing algorithm due to Adams and Bischof which can be found here http://bit.ly/1nIxphj.
It is the fig.2 pseudocode.
After I choose the seeded points using the mouse , it throws this message : Unhandled exception at 0x00416ca0 in diblook.exe: 0xC0000005: Access violation reading location 0x3d2f6e68.
This is the code of the function:
void CDibView::OnLButtonDblClk(UINT nFlags, CPoint point)
{ BEGIN_SOURCE_PROCESSING;
int** labels = new int* [dwHeight];
for(int k = 0;k < dwHeight; k++)
labels[k] = new int[dwWidth];
int noOfRegions = 2;
double meanRegion[2];
double noOfPointsInRegion[2];
for(int i = 0; i < dwHeight ; i++)
for(int j = 0; j < dwWidth ; j++)
{
labels[i][j] = -1;
}
if(noOfPoints < 6)
{
CPoint p = GetScrollPosition() + point;
pos[noOfPoints].x = p.x;
pos[noOfPoints].y = p.y;
int regionLabel = 0;
if(noOfPoints <= noOfPoints / 2)
labels[p.x][p.y] = regionLabel;
else
labels[p.x][p.y] = regionLabel + 1;
noOfPoints++;
}
else
{
// Calculate the mean of each region
for(int i = 0; i < noOfRegions; i++)
{
for(int j = 0 ; j < noOfPoints; j++)
{
if(labels[pos[j].x][pos[j].y] == i)
{
meanRegion[i] += lpSrc[pos[j].x * w + pos[j].y];
}
}
meanRegion[i] /= 3;
noOfPointsInRegion[i] = 3;
}
for(int seedPoint = 0; seedPoint < noOfPoints; seedPoint++)
{
// define list
node *start, *temp;
start = (node *) malloc (sizeof(node));
temp = start;
temp -> next = NULL;
for(int i = -1; i <= 1; i++)
for(int j = -1; j<= 1; j++)
{
if(i == 0 && j == 0) continue;
int gamma = lpSrc[(pos[seedPoint].x + i) * + pos[seedPoint].y + j] - lpSrc[pos[seedPoint].x * w + pos[seedPoint].y];
push(start, pos[seedPoint].x + i, pos[seedPoint].y + j, gamma);
}
sort(start);
if(start != NULL)
{
node *y = start;
pop(start);
int sameNeighbour = 1;
int neighValue = -1;
for(int k = -1; k <= 1; k++)
for(int l = -1; l <= 1;l++)
{
if(k ==0 && l==0) continue;
if(labels[y -> x + k][y -> y + l] != -1)
{
neighValue = labels[y -> x + k][y -> y + l];
break;
}
}
for(int k = -1; k <= 1; k++)
for(int l = -1; l <= 1;l++)
{
if(k == 0 && l==0) continue;
if(labels[y -> x + k][y -> y = 1] != -1 && labels[y -> x + k][y -> y + l] != neighValue)
sameNeighbour = 0;
}
if(sameNeighbour == 1)
{
labels[y -> x][y -> y] = neighValue;
meanRegion[neighValue] = meanRegion[neighValue] * noOfPointsInRegion[neighValue] / noOfPointsInRegion[neighValue] + 1;
noOfPointsInRegion[neighValue]++;
for(int k = -1; k <= 1; k++)
for(int l = -1; l <= 1;l++)
{
if(k == 0 && l == 0) continue;
if(labels[y -> x + k][y -> y + l] == -1 && find(start, y->x + k, y->y + l) == 0)
{
int gammak = meanRegion[neighValue] - lpSrc[(y->x +k) * w + (y->y + l)];
push(start, y->x + k, y->y + l, gammak);
sort(start);
}
}
}
else
{
labels[y->x][y->y] = -1;
}
}
}
int noOfRegionOne = 0;
int noOfRegionTwo = 0;
int noOfBoundary = 0;
for(int i = 0; i< dwHeight; i++)
for(int j = 0;j<dwWidth; j++)
{
if(labels[i][j] == -1)
noOfBoundary++;
else if(labels[i][j] == 0)
noOfRegionOne++;
else if(labels[i][j] == 1)
noOfRegionTwo++;
}
CString info;
info.Format("Boundary %d, One %d, Two %d", noOfBoundary, noOfRegionOne, noOfRegionTwo);
AfxMessageBox(info);
noOfPoints = 0;
}
CScrollView::OnLButtonDblClk(nFlags, point);
END_SOURCE_PROCESSING;
}
After a choose to break the running, this is what is shown http://postimg.org/image/j2sh9k0a1/
Can anybody tell what is wrong and why it doesn't work?
Thanks.
Your screenshot shows that your node (Y is a terrible name, incidentally) has garbage values in it. Offhand, I suspect that 'sort' is overwriting your node values, resulting in garbage. I would create a static copy of your current node to prevent it from changing during processing:
Change
node *y = start;
pop(start);
to
node y = *start;
pop(start);
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 have written a program to solve uva's minesweeper problem (10189) in C++.
I have written the code, and it seems to work correctly on my machine. Unfortunately my submission seems to be giving me run-time error (uva does not mention the error message or reason in such cases). I am pasting the code here:
using namespace std;
void nullCheck(void *ptr)
{
exit(0);
}
typedef unsigned int uint;
class Field
{
public:
vector <vector<uint> > nghBombCnt; //neighbourBombCount
vector <vector<bool> > isBomb;
uint width;
uint height;
public:
Field(uint w, uint h)
{
}
Field() { }
~Field()
{
}
};
int main(void)
{
vector<Field> fieldList;
do
{
Field curField;
uint width, height;
scanf("%u %u", &height, &width);
curField.width = width;
curField.height = height;
for (uint rowCtr = 0; rowCtr < curField.height; rowCtr++)
{
vector<bool> curBombRow;
for (uint colCtr = 0; colCtr < curField.width; colCtr++)
{
char curSymb;
scanf("%1s", &curSymb);
switch (curSymb)
{
case '.':
curBombRow.push_back(false); break;
case '*':
curBombRow.push_back(true); break;
default: break;
}
}
curField.isBomb.push_back(curBombRow);
}
if (!(curField.width == 0 && curField.height == 0))
fieldList.push_back(curField);
else
break;
} while (1);
for (uint fieldCtr = 0; fieldCtr < fieldList.size(); fieldCtr++)
{
Field curField = fieldList.at(fieldCtr);
for (uint rowCtr = 0; rowCtr < curField.height; rowCtr++)
{
vector<uint> curRow;
for (uint colCtr = 0; colCtr < curField.width; colCtr++)
{
uint bombCnt = 0;
if (curField.isBomb[rowCtr][colCtr])
{
curRow.push_back(0);
continue;
}
if (colCtr != 0 && curField.isBomb[rowCtr][colCtr - 1])
bombCnt++; //east
if (rowCtr != 0 && curField.isBomb[rowCtr - 1][colCtr])
bombCnt++; //north
if (rowCtr != curField.height - 1
&& curField.isBomb[rowCtr + 1][colCtr])
bombCnt++; //south
if (colCtr != curField.width - 1
&& curField.isBomb[rowCtr][colCtr + 1])
bombCnt++; //west
if (colCtr != curField.width - 1 && rowCtr != 0
&& curField.isBomb[rowCtr -1][colCtr + 1])
bombCnt++; //north-east
if (colCtr != 0 && rowCtr != curField.height - 1
&& curField.isBomb[rowCtr + 1][colCtr - 1])
bombCnt++; // south-west
if (colCtr != curField.width - 1
&& rowCtr != curField.height - 1
&& curField.isBomb[rowCtr + 1][colCtr + 1])
bombCnt++; //south-east
if (colCtr != 0 && rowCtr != 0
&& curField.isBomb[rowCtr - 1][colCtr - 1])
bombCnt++; //north-west
curRow.push_back(bombCnt);
}
curField.nghBombCnt.push_back(curRow);
}
fieldList[fieldCtr] = curField;
}
for (uint fieldNo = 0; fieldNo < fieldList.size(); fieldNo++)
{
printf("Field #%u:\n", fieldNo + 1);
Field curField = fieldList.at(fieldNo);
for (uint rowCtr = 0; rowCtr < curField.height; rowCtr++)
{
for (uint colCtr = 0; colCtr < curField.width; colCtr++)
{
if (curField.isBomb[rowCtr][colCtr])
printf("*");
else
printf("%u", curField.nghBombCnt[rowCtr][colCtr]);
}
printf("\n");
}
printf("\n");
}
return 0;
}