Negamax algorithm - c++

I have worked quite a bit with my tictactoe, but never got it working. Here is what I have so far:
static int evaluate(board b)
{
if (is_win curr_move_noughts)
{
return 1;
}
else if (is_win crosses)
{
return -1;
}
else
{
return 0;
}
}
int evaluateNegamax(board b)
{
if (curr_move_noughts) // Max player
return evaluate(b);
else
return -evaluate(b);
}
tuple<int, move> Search(int depth, board b)
{
board combined(); =b;
int w = 0;
w = Evaluate(b);
int move;
int bestScore = std::numeric_limits<int>::min();
bool bestMove = false;
if(depth == 0) return w;
int x=0, int y=0;
for (int x = 0; x < 9; ++x) {
for (int y = 0; y < 9; ++y) {
while (!occupied(x,y));
make_move(x, y);
score = -Search(depth-1,b); // recursion
unMake(b);
if(score > bestScore) {
bestScore = score;
bestMove = move;
}
}
}
// return the best move
return make_tuple(bestScore, bestMove);
}
Well, obviously " move " needs to be linked to XY coordinate but I don`t kow how.
I have defined make_move like this:
void make_move( size_t row, size_t col, board & b )
{
if (free(row, col))
{
b[pos(row, col)] = true;
last_move_row = row ;
last_move_col = col ;
}
}

Related

Can't convert memory address to value

thanks for visiting my question! Currently, when I run this code (an implementation of the Set data structure in c++), the memory address of each element in the set is printed instead of the values in the set. To help with debugging, here's my code:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cassert>
#define PB push_back
typedef std::vector<int> vint;
class SetBase
{
public:
SetBase() {}
~SetBase() {}
void insert(int x)
{
if (!this->isInSet(x))
{
this->set.PB(x);
}
}
int size()
{
return this->set.size();
}
bool empty()
{
return this->size() == 0;
}
int operator[](int index)
{
if (index >= 0 && index < this->size())
{
return this->set[index];
}
else
{
return -1;
}
}
bool find(int target)
{
sort(this->set.begin(), this->set.end());
int low = 0, high = this->size();
while (low <= high)
{
long long mid = low + (high - low) / 2;
long long guess = this->set[mid];
if (guess == target)
return true;
else if (guess < target)
low = mid + 1;
else
high = mid - 1;
}
return false;
}
int count(int target)
{
int counter = 0;
for (int i = 0; i < this->set.size(); i++)
{
if (this->set[i] == target)
counter++;
}
return counter;
}
bool operator=(SetBase &other)
{
if (other.size() != this->size())
return false;
for (int i = 0; i < other.size(); i++)
{
if (other[i] != this->set[i])
return false;
}
return true;
}
private:
vint set;
bool isInSet(int target)
{
for (int i = 0; i < this->size(); i++)
{
if (set[i] == target)
{
return true;
}
}
return false;
}
};
class Set : public SetBase
{
public:
void set_union(Set *set1, Set *set2, Set &back_insertor)
{
for (int i = 0; i < set1->size(); i++)
{
if (this->isInSet(back_insertor, i))
{
back_insertor.insert(i);
}
}
}
void set_difference(Set set1, Set set2, Set &back_insertor)
{
// set_difference = set1 - set2
}
void set_intersection(Set set1, Set set2, Set &back_insertor)
{
// set_difference = set1 U set2
for (int i = 0; i < set1.size(); i++)
{
for (int j = 0; j < set2.size(); j++)
{
if (set1[i] == set2[j])
{
back_insertor.insert(set1[i]);
}
}
}
}
void printSet(Set *in)
{
for (int i = 0; i < in->size(); i++)
{
std::cout << &in[i] << "\n";
}
}
private:
bool isInSet(SetBase set1, int target)
{
for (int i = 0; i < set1.size(); i++)
{
if (target == set1[i])
{
return true;
}
}
return false;
}
};
int main()
{
Set *set_1 = new Set();
Set *set_2 = new Set();
Set *back = new Set();
for (int i = 1; i <= 10; i++)
set_1->insert(i);
for (int i = 1; i <= 10; i++)
set_2->insert(i);
set_2->insert(11);
set_1->set_union(set_1, set_2, *back);
set_1->printSet(set_1);
delete set_1;
delete set_2;
delete back;
}
When running the set_1->printSet(set_1); line, here's what I get:
0x7fb498c05a20
0x7fb498c05a38
0x7fb498c05a50
0x7fb498c05a68
0x7fb498c05a80
0x7fb498c05a98
0x7fb498c05ab0
0x7fb498c05ac8
0x7fb498c05ae0
0x7fb498c05af8
Even though this works, I would like to print out the values (integer) instead. Any help would be appreciated! Thanks! :)
Inside printSet(), you use &in[i] to print each element.
The & operator returns the address of the object you are referencing. So, instead of getting the value, you are getting its address. You should remove it, eg:
void printSet(Set *in)
{
for (int i = 0; i < in->size(); i++)
{
std::cout << (*in)[i] << "\n";
}
}

Segmentation Fault when dealing with 2D Arrays [closed]

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 3 years ago.
Improve this question
I'm am trying to dynamically make 2d arrays that are then supposed to be iterated through to check their contents. Whenever I try to use a function that indexes the array I get a segmentation fault. The two functions that are creating the problems are the printg() and get() functions. I'm not sure exactly what I'm doing wrong, but neither of them will work properly for me.
Any help would be great. Thank you.
#ifndef _GRID_H
#define _GRID_H
#include <iostream>
using namespace std;
class Grid
{
public:
Grid();
Grid(const Grid& g2);
Grid(int x, int y, double density);
Grid(string file);
~Grid();
bool check(int x, int y); //check if a cell is inhabited or not
bool isEmpty();//check if a grid is living
bool equals(const Grid& g2);//checks if two grids are equal
void kill(int x, int y);//kill a cell
void grow(int x, int y);//grow a cell
int getSize();
int getNumRows();
int getNumCol();
int getNumLiving();
void printg(int r, int c);
char get(int x, int y) const;
private:
int size; //number of cells in grid
int row; //row length (number of columns)
int column; //column length (number of rows)
int num_living; //number of X's in the grid
char** myGrid;
};
#endif
#include "Grid.h"
#ifndef _GRID_C
#define _GRID_C
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstdlib>
//compile with g++ -I /home/cpsc350/GameOfLife Grid.cpp
using namespace std;
Grid::Grid() //do i need a default constructor????
{
char myGrid[10][10] = {{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};
row = 10;
column = 10;
size = 100;
}
Grid::Grid(const Grid& g2)//copy constructor/////////////help
{
size = g2.size;
row = g2.row;
column = g2.column;
num_living = g2.num_living;
char** myGrid = new char*[row];
for(int i = 0; i < row; i++)
myGrid[i] = new char[column];
for(int i1 = 0; i1 < row; i1++)
{
for(int i2 = 0; i2 < column; i2++)
{
//copy(&g2[i1][i2], &g2[i1][i2]+row*column,&myGrid[i1][i2]);
myGrid[i1][i2] = g2.get(i1,i2);
}
}
}
Grid::Grid(int x, int y, double density)
{
char** myGrid = new char*[x];
for(int i = 0; i < x; i++)
myGrid[i] = new char[y];
row = x;
column = y;
size = x*y;
num_living = size * density;
string str = "";
for(int a = 0; a < num_living; a++)//adds the density of X's to a string
{
str += 'X';
}
for(int a = 0; a < size - num_living; a++)//adds the rest to the string
{
str += '-';
}
int randnum;
//randomly generates indicies in the string str and puts them into the array
for(int i1 = 0; i1 < column; i1++)
{
for(int i2 = 0; i2 < row; i2++)
{
//generate random numbers from index 0 to length of string - 1
if(str.length()>1)
{
randnum = (rand()%(str.length()-1))+1;
}
else
{
randnum = 0;
}
myGrid[i1][i2] = str[randnum];
str.erase(randnum);
}
}
}
Grid::Grid(string file)
{
num_living = 0;
//code to create a 2d array from a filepath
ifstream openfile(file);
//error handling
if(! openfile)
{
cout << "Error, file could not be opened" << endl;
exit(0);
}
openfile >> column;//gets number of rows
openfile >> row;//gets number of columns
size = row*column;
char** myGrid = new char*[row];
for(int i = 0; i < row; i++)
myGrid[i] = new char[column];
for(int x = 0; x<column; x++)
{
for(int y = 0; y<row; y++)
{
openfile >> myGrid[x][y];
if(! openfile)//error handling
{
cout << "Error reading file at " << row << "," << column << endl;
}
if(myGrid[x][y] == 'X')
{
num_living++;
}
}
}
openfile.close();
}
Grid::~Grid()
{
if(myGrid)
{
for(int i = 0; i < row; i++)
{
delete []myGrid[i];
}
delete []myGrid;
}
}
void Grid::kill(int x, int y)
{
if(myGrid[x][y] == 'X')
{
num_living--;
}
myGrid[x][y] = '-';
}
void Grid::grow(int x, int y)
{
if(myGrid[x][y] == '-')
{
num_living++;
}
myGrid[x][y] = 'X';
}
bool Grid::check(int x, int y)
{
if(y<0 || x<0)
{
return(false);
}
return (myGrid[x][y] == 'X');
}
bool Grid::isEmpty()
{
return (num_living == 0);
}
bool Grid::equals(const Grid& g2)
{
if(size != g2.size) //checks if sizes are equal
{
return false;
}
if(row != g2.row)//checks if numRows are equal
{
return false;
}
if(column != g2.column)//checks if numCol are equal
{
return false;
}
if(num_living != g2.num_living)//checks if numliving are equal
{
return false;
}
for(int x = 0; x < row; x++)//checks each element
{
for(int y = 0; y < column; y++)
{
if(myGrid[x][y] != g2.get(x,y))
{
return false;
}
}
}
return true;
}
int Grid::getSize()
{
return(size);
}
int Grid::getNumRows()
{
return(column);
}
int Grid::getNumCol()
{
return(row);
}
int Grid::getNumLiving()
{
return(num_living);
}
void Grid::printg(int r, int c)
{
for(int x = 0; x < r; x++)
{
for(int y = 0; y < c; y++)
{
cout << myGrid[x][y];
}
cout << endl;
}
}
char Grid::get(int x, int y) const
{
return myGrid[x][y];
}
#endif
The problem that I see at first is that both your default and copy constructor do not initialize myGrid. what you are doing in them will create an additional array with the same name which 'shadows' myGrid. instead you have to do:
Grid::Grid(const Grid& g2)
{
size = g2.size;
row = g2.row;
column = g2.column;
num_living = g2.num_living;
myGrid = new char*[row]; // removed "char**" at the start of this line
for(int i = 0; i < row; i++)
myGrid[i] = new char[column];
for(int i1 = 0; i1 < row; i1++)
{
for(int i2 = 0; i2 < column; i2++)
{
//copy(&g2[i1][i2], &g2[i1][i2]+row*column,&myGrid[i1][i2]);
myGrid[i1][i2] = g2.get(i1,i2);
}
}
}
your default constructor has the same problem. but note that you can't initialize it with braces. but you don't have to have a default constructor if you are not using it.

Memory leak without allocating any memory?

I'm working on a coding assignment for a C++ class. When I run my program I seem to be dealing with a memory leakage issue, which is weird since I am NOT explicitly allocating any memory in my code. I ran the program under gdb, and it seems as though the program crashes when running the destructor for a Deck object. I tried stepping through the code, but I when I do so I end up in a host of .h files related to vectors. Then suddenly, it stops. I tried going to a TA for some help, but they seem to be as perplexed as I am on the issue.
# include <stdlib.h>
# include <time.h>
# include <iostream>
# include <vector>
# include <stdio.h>
using namespace std;
//function signatures
float bustProbability (const int);
class Deck
{
public:
//data members
vector <int> cardArray;
vector <int> wasteCards;
//constructor
Deck();
//methods
void shuffleDeck();
void populateDeckWithCards();
void removeCopyCards();
int dealCard();
int remainingCards();
void showCards();
};
void Deck::removeCopyCards() {
for (unsigned int i = 0; i < wasteCards.size(); i++) {
bool removedCopy = false;
for (unsigned int j = 0; j < cardArray.size() && removedCopy == false; j++) {
if (cardArray[j] == wasteCards[i]) {
cardArray.erase (cardArray.begin() + j - 1);
removedCopy = true;
}
}
}
}
int Deck::dealCard() {
if (remainingCards() > 0) {
int tmp = cardArray.back();
wasteCards.push_back(tmp);
cardArray.pop_back();
return tmp;
}
else {
populateDeckWithCards();
removeCopyCards();
shuffleDeck();
//shuffle method
int tmp = cardArray.back();
cardArray.pop_back();
return tmp;
}
}
void Deck::populateDeckWithCards() {
//populate regular cards into array
for (int i = 2; i <= 10; i++) {
for (int j = 0; j < 4; j++) {
cardArray.push_back(i);
}
}
//populate J, Q, K into array
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
cardArray.push_back(10);
}
}
//populating array with Aces... treating them as special case '100'
for (int i = 0; i < 4; i++) {
cardArray.push_back(100);
}
return;
}
void Deck::showCards() {
for (unsigned int i = 0; i < cardArray.size(); i++) {
cout << cardArray[i] << endl;
}
}
Deck::Deck() {
wasteCards.clear();
cardArray.clear();
populateDeckWithCards();
shuffleDeck();
}
void Deck::shuffleDeck() {
int n = cardArray.size();
for(int a = n-1; a > 0; a--) {
int min = 0;
int max = a;
int j = min + rand() / (RAND_MAX / (max-min + 1) + 1);
int tmp = cardArray[a];
cardArray[a] = cardArray[j];
cardArray[j] = tmp;
}
return;
}
int Deck::remainingCards() {
return cardArray.size();
}
class Player {
public:
//data members
vector <int> playerHand;
//constructor
Player();
//methods
bool isBust();
int count();
void hit(Deck&);
void stand();
bool muckHand();
void showHand();
};
Player::Player() {
playerHand.clear();
}
void Player::showHand() {
for (unsigned int i = 0; i < playerHand.size(); i++) {
cout << playerHand[i] << endl;
}
return;
}
int Player::count() {
int handCount = 0;
for (unsigned int i = 0; i < playerHand.size(); i++) {
if (playerHand[i] != 100)
handCount += playerHand[i];
else {
if (playerHand[i] == 100) {
if ((handCount) > 11) {
handCount += 1;
}
else
handCount += 10;
}
}
}
return handCount;
}
bool Player::isBust() {
if (count() > 21)
return true;
else
return false;
}
void Player::hit(Deck& d) {
playerHand.push_back(d.dealCard());
}
void Player::stand() {
return;
}
bool Player::muckHand() {
playerHand.clear();
return true;
}
float bustProbability (const int threshHold) {
int threshHoldReached = 0;
Deck myDeck;
Player myPlayer;
Player dealer;
for (int i = 0; i < 10000; i++) {
myPlayer.hit(myDeck);
dealer.hit(myDeck);
myPlayer.hit(myDeck);
dealer.hit(myDeck);
while (myPlayer.count() < threshHold) {
myPlayer.hit(myDeck);
}
if (!(myPlayer.isBust())) {
++threshHoldReached;
}
myDeck.wasteCards.clear();
myPlayer.muckHand();
dealer.muckHand();
}
float bustFraction = float(threshHoldReached)/float(10000);
return bustFraction;
}
int main () {
cout << "blackjack simulation" << endl;
srand((unsigned int)time(NULL));
cout << bustProbability(19);
return 0;
}
I'm incredibly sorry for just posting my code, but I've spend 4 days on this issue, and I can't even begin to figure out what the problem is.
There is at least the line
cardArray.erase (cardArray.begin() + j - 1);
which seems to be dubious in case of j = 0

Unable to call a public function inside of another public function

(Edit: change suggested in the comments section now allows the desired behavior)
I'm developing an agent-based simulation in C++, and so far I'm able to run 1 simulation and I transcribe the results manually. It consists of an Environment class with a 2-d array with agents (hunters and preys)
To automate the data collection, I'm trying to implement some functions so that I can later transcribe relevant results of each simulation to a CSV file.
The following code in Visual Studio generates the Environment, populates it, counts the agents and display an ASCI map of the hunters and preys with a legend.
#include <iostream>
#include <cstdlib> // for rand
#include <ctime> // for time
#include <vector>
#include <Windows.h> //for color in output
using namespace std;
const int WORLDSIZEX = 100;
const int WORLDSIZEY = 30;
enum AgentType { PREY, HUNTER };
class Environment;
class Agent {
public:
Agent(Environment* aWorld, int xcoord, int ycoord);
virtual ~Agent() { }
virtual AgentType getType() const = 0;
virtual char representation() const = 0;
protected:
int x;
int y;
Environment* world;
private:
};
struct Position {
int x;
int y;
};
class Environment {
public:
Environment(unsigned int seed, int _id, int _initialPopulationPreys, int _initialPopulationHunmters);
~Environment();
Agent* getAt(int x, int y) const;
void setAt(int x, int y, Agent* org);
void display();
Position randomPosition() const;
Position randomPositionHunter() const;
int numberPreys();
int numberHunters();
private:
Agent* grid[WORLDSIZEX][WORLDSIZEY];
void createOrganisms(AgentType orgType, int count);
int id;
int timeStep;
int initialPopulationPreys;
int initialPopulationHunters;
};
class Hunter : public Agent {
public:
Hunter(Environment* aWorld, int xcoord, int ycoord);
AgentType getType() const;
char representation() const;
private:
bool altruistic;
};
class Prey : public Agent {
public:
Prey(Environment* aWorld, int xcoord, int ycoord);
AgentType getType() const;
char representation() const;
private:
int huntingDifficulty;
};
Prey::Prey(Environment* aWorld, int xcoord, int ycoord) : Agent(aWorld, xcoord, ycoord) { huntingDifficulty = int(rand() % 3); }
AgentType Prey::getType() const { return PREY; }
char Prey::representation() const { return 'o'; }
Hunter::Hunter(Environment* aWorld, int xcoord, int ycoord) : Agent(aWorld, xcoord, ycoord) { }
AgentType Hunter::getType() const { return HUNTER; }
char Hunter::representation()const { return 'X'; }
Agent::Agent(Environment* aWorld, int xcoord, int ycoord) {
world = aWorld;
x = xcoord;
y = ycoord;
world->setAt(x, y, this);
}
Environment::Environment(unsigned int seed, int _id, int _initialPopulationPreys, int _initialPopulationHunters) {
srand(seed);
id = _id;
initialPopulationPreys = _initialPopulationPreys;
initialPopulationHunters = _initialPopulationHunters;
for (int i = 0; i < WORLDSIZEX; i++) {
for (int j = 0; j < WORLDSIZEY; j++) {
grid[i][j] = NULL;
}
}
timeStep = 0;
createOrganisms(PREY, initialPopulationPreys);
createOrganisms(HUNTER, initialPopulationHunters);
}
Environment::~Environment() {
for (int i = 0; i < WORLDSIZEX; i++) {
for (int j = 0; j < WORLDSIZEY; j++) {
if (grid[i][j] != NULL) {
delete grid[i][j];
}
}
}
}
Agent* Environment::getAt(int x, int y) const {
if ((x >= 0) && (x < WORLDSIZEX) && (y >= 0) && (y < WORLDSIZEY)) {
return grid[x][y];
}
else {
return NULL;
}
}
void Environment::setAt(int x, int y, Agent* org) {
if ((x >= 0) && (x < WORLDSIZEX) && (y >= 0) && (y < WORLDSIZEY)) {
grid[x][y] = org;
}
}
// Displays the world in ASCII.
void Environment::display() {
int numPreys = 0;
int numHunters = 0;
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Remember how things were when we started
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hstdout, &csbi);
cout << endl << endl;
for (int j = 0; j < WORLDSIZEY; j++) {
for (int i = 0; i < WORLDSIZEX; i++) {
if (grid[i][j] == NULL) {
cout << "_";
}
else {
if (grid[i][j]->getType() == PREY) {
SetConsoleTextAttribute(hstdout, 10);
numPreys++;
}
else if (grid[i][j]->getType() == HUNTER) {
SetConsoleTextAttribute(hstdout, 12);
numHunters++;
}
cout << grid[i][j]->representation();
SetConsoleTextAttribute(hstdout, csbi.wAttributes);
}
}
cout << endl;
}
cout << "Preys 'o': " << numPreys << " Hunters 'X': " << numHunters << endl;
cout << "Timestep:" << timeStep << " World ID:" << id << endl;
}
Position Environment::randomPosition() const { // returns a random number in the range 0 to WORLDSIZEX - 1 (or WORLDSIZEY - 1)
Position p;
p.x = rand() % WORLDSIZEX;
p.y = rand() % WORLDSIZEY;
return p;
}
Position Environment::randomPositionHunter() const { // returns a random number in the central fifth of the grid
Position p;
int subGridSizeX = WORLDSIZEX / 5;
int subGridSizeY = WORLDSIZEY / 5;
p.x = subGridSizeX * 1 + (rand() % (3 * subGridSizeX));
p.y = subGridSizeY * 2 + (rand() % subGridSizeY);
return p;
}
int Environment::numberPreys() {
int numPreys = 0;
for (int j = 0; j < WORLDSIZEY; j++) {
for (int i = 0; i < WORLDSIZEX; i++) {
if (grid[i][j] && grid[i][j]->getType() == PREY) {
numPreys++;
}
}
}
return numPreys;
}
int Environment::numberHunters() {
int numHunters = 0;
for (int j = 0; j < WORLDSIZEY; j++) {
for (int i = 0; i < WORLDSIZEX; i++) {
if (grid[i][j] && grid[i][j]->getType() == HUNTER) {
numHunters++;
}
}
}
return numHunters;
}
void Environment::createOrganisms(AgentType orgType, int count) {
int orgCount = 0;
while (orgCount < count) {
Position p = randomPosition();
Position q = randomPositionHunter();
if (orgType == PREY) {
if (grid[p.x][p.y] == NULL) { // Only put Organism in empty spot
orgCount++;
new Prey(this, p.x, p.y); // Create a Prey and put it into the world
}
}
else if (orgType == HUNTER) {
if (grid[q.x][q.y] == NULL) { // Only put Organism in empty spot
orgCount++;
new Hunter(this, q.x, q.y); // Create a Hunter and put it into the world
}
}
}
}
int main() {
int initialPreys = 60;
int initialHunters = 15;
int id = 0;
//Creating the environment
int seed = time(0);
Environment myWorld(seed, id, initialPreys, initialHunters);
cout << "This is the setup of the environment for all the simulations" << endl;
myWorld.display();
char ch;
return 0;
}
I would like to replace the Environment::display() function with:
void Environment::display() {
int numPreys = numberPreys();
int numHunters = numberHunters();
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Remember how things were when we started
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hstdout, &csbi);
cout << endl << endl;
for (int j = 0; j < WORLDSIZEY; j++) {
for (int i = 0; i < WORLDSIZEX; i++) {
if (grid[i][j] == NULL) {
cout << "_";
}
else {
if (grid[i][j]->getType() == PREY) {
SetConsoleTextAttribute(hstdout, 10);
}
else if (grid[i][j]->getType() == HUNTER) {
SetConsoleTextAttribute(hstdout, 12);
}
cout << grid[i][j]->representation();
SetConsoleTextAttribute(hstdout, csbi.wAttributes);
}
}
cout << endl;
}
cout << "Preys 'o': " << numPreys << " Hunters 'X': " << numHunters << endl;
cout << "Timestep:" << timeStep << " World ID:" << id << endl;
}
But then, the function doesn't display anything and the console window closes after a while.
My question: How can I call the counting functions inside of the display function?

Dijkstra algorithm without diagonal moves

Sorry if this question is a bit stupid, but I can't find a proper solution. I want to get the shortest way from a point to another. I have found a code in internet, but this code give me the path with diagonals and I need it only with vertical and horizontal movements. Anyone could tell me what should I change? Because I've tried several modifications and none of them seem to work. This is the code:
Thanks in advance.
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
class Cell
{
int x;
int y;
public:
int getx(){
return x;
}
int gety(){
return y;
}
void setx(int x){
this->x = x;
}
void sety(int y){
this->y = y;
}
bool operator==(Cell o) {
return x==o.x && y==o.y;
}
Cell operator=(Cell o) {
x = o.x;
y = o.y;
return *this;
}
Cell(int x, int y):x(x),y(y){ }
Cell():x(0),y(0){}
};
vector<Cell> getShortestPath(Cell ori, Cell dest, int array[], int width, int height);
int main()
{
int ejemplo[] = {
0,1,0,1,0,0,0,0, //0: void
0,1,0,1,0,0,0,0, //1: obstacle
0,1,0,1,0,0,0,0,
0,1,0,1,0,0,0,0,
0,1,0,1,0,0,0,0,
0,1,0,1,0,0,0,0,
0,0,0,1,0,0,0,0,
0,0,0,0,0,0,0,0};
vector<Cell> camino= getShortestPath(Cell(2,0),Cell(0,7),ejemplo,8,8);
for(int i = 0; i < camino.size(); i++) {
cout << "(" << camino[i].getx() << ", " << camino[i].gety() << ")" << endl;
}
}
vector<Cell> getShortestPath(Cell ori, Cell dest, int array[], int width, int height)
{
if ( ori == dest )
return vector<Cell>();
unsigned int *sizes = new unsigned int[width*height];
Cell *prev = new Cell[width*height];
for(int i = 0; i < width*height; i++) {
sizes[i] = -1;
prev[i] = Cell(-1,-1);
}
sizes[ori.getx()+ori.gety()*width] = 0;
prev[ori.getx()+ori.gety()*width] = ori;
queue<Cell> porVisitar;
porVisitar.push(ori);
while(!porVisitar.empty())
{
Cell cur = porVisitar.front();
porVisitar.pop();
cout << porVisitar.size() << endl;
for(int i = -1; i < 2; i++)
for(int j = -1; j < 2; j++)
if((cur.getx()+j)>=0 && (cur.getx()+j)<width && (cur.gety()+i)>=0 && (cur.gety()+i)<height && //is not out of bounds
array[(cur.getx()+j)+(cur.gety()+i)*width]==0 && //is not an obstable
sizes[cur.getx()+cur.gety()*width]+1 < sizes[(cur.getx()+j)+(cur.gety()+i)*width] //there is not a better path
) {
sizes[(cur.getx()+j)+(cur.gety()+i)*width]=sizes[cur.getx()+cur.gety()*width]+1;
prev[(cur.getx()+j)+(cur.gety()+i)*width]=Cell(cur.getx(),cur.gety());
porVisitar.push(Cell(cur.getx()+j,cur.gety()+i));
}
}
if(prev[dest.getx()+dest.gety()*width]==Cell(-1,-1))
return vector<Cell>();
Cell pp = dest;
vector<Cell> res(sizes[dest.getx()+dest.gety()*width]+1);
for(int i = res.size()-1; !(pp == ori); i-- )
{
res[i] = pp;
pp = prev[pp.getx()+pp.gety()*width];
}
return res;
Consider the subgraph:
a b c
d N e
f g h
where N is your current node/vertex. When adding neighbors to your potential path list (or queue, or whatever), only add b, d, e, and g. The above code adds a-h.
Hint: this happens in the nested for loop.
Answer: The conditional should read if((i != -1 && i != 1) || (j != 1 && j != -1)).