why i got assertion failure, vector subscipt out of range - c++

Visual studio said I got no issue but, every time I try to run my code I get an assertion failure error, and the error says that vector subscript is out of range, what should I do to fix this, I dont really know what I am doing wrong.
#include <iostream>
#include <ctime>
#include <windows.h>
#include <conio.h>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
class Human
{
private:
int ap;
int hp;
public:
Human()
{
srand(time(NULL));
ap = rand() % 3 + 8;
hp = rand() % 2 + 9;
}
int getAp() { return ap; }
int getHp() { return hp; }
void dmg(int x) { hp -= x; }
};
class Skeleton
{
private:
int ap;
int hp;
public:
Skeleton()
{
srand(time(NULL));
ap = rand() % 3 + 3;
hp = rand() % 2 + 4;
}
int getAp() { return ap; }
int getHp() { return hp; }
void dmg(int x) { hp -= x; }
};
class game
{
private:
std::vector<Human*> hum;
std::vector<Skeleton*> ske;
bool adv;
int sC;
int hC;
public:
game(int h, int s)
{
srand(time(NULL));
adv = rand() % 2;
sC = s;
hC = h;
for (int i = 0; i < h; i++) { hum.push_back( new Human()); }
for (int i = 0; i < h; i++) { ske.push_back(new Skeleton()); }
}
~game()
{
for (int i = 0; i < hum.size(); i++)
{
Human* current = hum.back();
hum.pop_back();
delete current;
}
for (int i = 0; i < ske.size(); i++)
{
Skeleton* current = ske.back();
ske.pop_back();
delete current;
}
}
void start()
{
int x = hC-1;
int y = sC-1;
bool quit = false;
while (!quit)
{
if (adv)
{
ske[y]->dmg(hum[x]->getAp());
if (ske[y]->getHp() <= 0) { y--; ske.pop_back();}
adv = 0;
}
if (!adv)
{
hum[x]->dmg(ske[y]->getAp());
if (hum[x]->getHp() <= 0) { x--; hum.pop_back(); }
adv = 1;
}
if (hum.size() == 0 || ske.size() == 0)
{
cout << "human left : " << hum.size() << "skeleton left : " << ske.size();
quit = true;
}
}
}
};
int main()
{
game g1(10, 5);
g1.start();
return 0;
}
I always get this error box.
this is the error message i got no idea what are they talkin about.
I also get this, what is this?
this
ive fixed it thx to all of ur comments,
this is the completed code, it may look like garbage but it runs
#include <iostream>
#include <ctime>
#include <windows.h>
#include <conio.h>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
class Human
{
private:
int ap;
int hp;
public:
Human()
{
ap = rand() % 3 + 8;
hp = rand() % 2 + 9;
}
int getAp() { return ap; }
int getHp() { return hp; }
void dmg(int x) { hp -= x; }
};
class Skeleton
{
private:
int ap;
int hp;
public:
Skeleton()
{
ap = rand() % 3 + 3;
hp = rand() % 2 + 4;
}
int getAp() { return ap; }
int getHp() { return hp; }
void dmg(int x) { hp -= x; }
};
class game
{
private:
std::vector<Human*> hum;
std::vector<Skeleton*> ske;
bool adv;
int sC;
int hC;
public:
game(int h, int s)
{
srand(time(NULL));
adv = rand() % 2;
sC = s;
hC = h;
for (int i = 0; i < h; i++) { hum.push_back( new Human()); }
for (int i = 0; i < s; i++) { ske.push_back(new Skeleton()); }
}
~game()
{
for (int i = 0; i < hum.size(); i++)
{
Human* current = hum.back();
hum.pop_back();
delete current;
}
for (int i = 0; i < ske.size(); i++)
{
Skeleton* current = ske.back();
ske.pop_back();
delete current;
}
}
void start()
{
int x = hum.size()-1;
int y = ske.size()-1;
bool quit = false;
while (!quit)
{
if (hum.size() == 0 || ske.size() == 0)
{
cout << "human left : " << hum.size() << "skeleton left : " << ske.size();
quit = true;
break;
}
if (adv)
{
ske.at(y)->dmg(hum.at(x)->getAp());
if (ske.at(y)->getHp() <= 0) { y--; ske.pop_back();}
adv = 0;
}
else if (!adv)
{
hum.at(x)->dmg(ske.at(y)->getAp());
if (hum.at(x)->getHp() <= 0) { x--; hum.pop_back(); }
adv = 1;
}
}
}
};
int main()
{
game g1(8, 20);
g1.start();
return 0;
}

Your final code is somewhat complex than it should be, I have simplified it by:
Remove the windows related header files, they are not used
Use member initializer lists
Modify dmg to return the latest hp
Remove the unnecessary index in start, to use back
Remove the vector of pointers, it's Ok to use objects here
Move the srand call into main(Actually we can use std::random here)
Simplify the while loop in start
#include <ctime>
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
class Human {
private:
int ap;
int hp;
public:
Human() : ap(rand() % 3 + 8), hp(rand() % 2 + 9) {}
int getAp() { return ap; }
int getHp() { return hp; }
int dmg(int x) { return hp -= x; }
};
class Skeleton {
private:
int ap;
int hp;
public:
Skeleton() : ap(rand() % 3 + 3), hp(rand() % 2 + 4) {}
int getAp() { return ap; }
int getHp() { return hp; }
int dmg(int x) { return hp -= x; }
};
class game {
private:
bool adv;
int sC;
int hC;
std::vector<Human> hum;
std::vector<Skeleton> ske;
public:
game(int h, int s) : adv(rand() % 2), sC(s), hC(h), hum(h), ske(s) {}
void start() {
while (!hum.empty() && !ske.empty()) {
if (adv) {
if (ske.back().dmg(hum.back().getAp()) <= 0) {
ske.pop_back();
}
} else {
if (hum.back().dmg(ske.back().getAp()) <= 0) {
hum.pop_back();
}
}
adv = !adv;
}
cout << "human left : " << hum.size() << ", skeleton left : " << ske.size();
}
};
int main() {
srand(time(NULL));
game g1(8, 20);
g1.start();
return 0;
}
Online demo

In function start, ske[y] is accessed with a negative index. std::vector does not like negative indexes, this needs to be fixed.

Related

C++, initialize a 2d array. error:subscript requires array or pointer

New to C++. Here is my code:
#include <string>
#include <cstdlib>
#include <time.h>
using namespace std;
const int Gardensize = 20;//Garden size, a 20X20 2d array
const int initialants = 100;//100 initial ants
const int initialdoodlebug = 5;//5 intial bug
const int antType = 1;//
const int doodleType = 2;//
const char antchar = 'O';//ant will display'O'in the window
const char bugchar = 'X';//
class Garden;
class Organism;
class Ant;
class Doodlebug;
class Garden {
friend class Organism;
friend class Ant;
friend class Doodlebug;
public:
Garden();
~Garden();
int checkType(int x, int y);//check the element type (ant or bug)in the grid
void Display();
private:
Organism grid[Gardensize][Gardensize]; //C2079 'Garden::grid' uses undefined class 'Organism' I have already define the class Organism in advance,have no ideal how to fix this error.
};
Garden::Garden() { //initialize the garden, set all elements in grid to "NULL"
for (int i = 0; i < Gardensize; i++) {
for (int j = 0; j < Gardensize; j++) {
grid[i][j] = NULL; //error:subscript requires array or pointer
}
}
}
Garden::~Garden() {
for (int i = 0; i < Gardensize; i++) {
for (int j = 0; j < Gardensize; j++) {
if (grid[i][j] != NULL) {
grid[i][j] = NULL;
}
}
}
}
void Garden::Display() {
for (int i = 0; i < Gardensize; i++) {
for (int j = 0; j < Gardensize; j++) {
if (grid[i][j].getType == antType) {
cout << antchar;
}
else if (grid[i][j].getType == NULL) {
cout << ".";
}
else if (grid[i][j].getType == doodleType) {
cout << bugchar;
}
}
cout << endl;
}
}
int Garden::checkType(int x, int y) {
return grid[x][y].getType();
}
class Organism {
friend class Garden;
public:
virtual int getType() {}; //
virtual void breed() {};
virtual bool starve() {};
virtual int move( int &breedtoken) {};
protected:
int x = -1; //initial xy place
int y = -1;
Garden garden;
bool moved; //used to define whether org has moved or not
int breedtoken = 0; //used to define whether org need to breed
};
class Ant : public Organism {
public:
Ant() {}; //
Ant(int x, int y, Garden* g)//initial a ant object by define the xy place in the gardene
{
this->x = x;
this->y = y;
garden = *g;
}
~Ant() {};
virtual int getType() {
return antType;
}
virtual int move(int &breedtoken);
virtual void breed() {};
virtual bool starve() { return false; };// ant wont starve
};
int Ant::move(int& breedtoken) {
int dir = rand() % 4;// randomly select direction
switch (dir) {
case 0 :// 0move upwards
if( this->x > 0 && garden.grid[x - 1][y] == NULL ){
garden.grid[x-1][y] = garden.grid[x][y];
garden.grid[x][y] = NULL;
x--;
}
break;
case 1:// 1 move downwards
if (this->x < Gardensize - 1 && garden.grid[x + 1][y] == NULL) {
garden.grid[x + 1][y] = garden.grid[x][y];
garden.grid[x][y] = NULL;
x++;
}
break;
case 2: // 2 move leftwards
if (this->y > 0 && garden.grid[x][y-1] == NULL) {
garden.grid[x][y-1] = garden.grid[x][y];
garden.grid[x][y] = NULL;
y--;
}
break;
case 3: // 3 move to right
if (this->y < Gardensize- 1 && garden.grid[x][y + 1] == NULL) {
garden.grid[x][y + 1] = garden.grid[x][y];
garden.grid[x][y] = NULL;
y++;
}
break;
this->breedtoken += 1;
return breedtoken;
}
}
class Doodlebug :public Organism {
public:
Doodlebug() {};
Doodlebug(int x, int y, Garden* g)
{
this->x = x;
this->y = y;
garden = *g;
}
virtual int getType() {
return doodleType;
}
};
int main()
{
srand(time(NULL));//
Garden garden;
int antCount = 0; //Ant counter, used to intilize 100 ants
int DoodleCount = 0;
Ant antarray[initialants];
Doodlebug doodlebugarray[initialdoodlebug];
while (antCount < initialants) {
int x = rand() % Gardensize;
int y = rand() % Gardensize;
if (garden.checkType(x, y) == NULL) {
antarray[antCount] = Ant(x, y, &garden); //initilize 100 ants
antCount++;
}
}
while (DoodleCount < initialdoodlebug) {
int x = rand() % Gardensize;
int y = rand() % Gardensize;
if (garden.checkType(x, y) == NULL) {
doodlebugarray[DoodleCount] = Doodlebug(x, y, &garden); //用数组的模式创建100只蚂蚁
DoodleCount++;
}
}
garden.Display();//display
}
The project is not finished yet. Right now, the code can initialize 100ants and 5 bugs. It can run properly but keep showing"subscript requires array or pointer " wherever I write grid[i][j] in the for loop. and " 'Garden::grid' uses undefined class 'Organism'" when I define the "Organism grid[][]" in the Garden class. I wonder to know how can i fix these 2 errors, and what's wrong with my 2d array grid?
The problem with the 2d array is caused, because you try to create an array of Organisms, which are up to that point only declared, not defined, and so the compiler doesn't know their size and can't create an array of them. This can b fixed by reordering your classes, or by putting the class declarations in headers. You can also just replace the array with a dynamic array (double pointer), and initialize it after they have been declared.
The other error is just a consequence of the first, fix it and they will both disapear.
You should try reading some book about c or c++ first, and learn a bit about pointers, and design and structure of c++ programs

can't acces member functions of a global object

So i'm trying to make a game inspired by a youtube tutorial but a bit more complex , i had the snake created in the setup function but i moved it since i couldn't acces it's members from other functions and with it being global i can't acces it at all , how can i fix it ?
in the stuff.h header i have colio.h and iostream
bool gameOver;
std::array<std::array<int, 20>, 20> grid;
snake jerry(15, 9);
class object
{
protected:
int m_x, m_y;
object(int y, int x) :m_x(x), m_y(y) {};
public:
const int getX() { return m_x; };
const int getY() { return m_y; };
};
class snake:public object
{
private:
enum direction
{
STOP,
LEFT,
RIGHT,
UP,
DOWN,
};
direction dir;
public:
snake(int y, int x) :object(y, x) {};
const void moveSnake(char c)
{
if (c == 'a') { dir = LEFT; };
if (c == 'd') { dir = RIGHT; };
if (c == 's') { dir = DOWN; };
if (c == 'w') { dir = UP; }
};
const void changeCoords(int y,int x) { m_x = x, m_y = y; };
};
class fruit :public object
{
private:
public:
fruit(int y, int x) :object(y,x) {};
};
void setup()
{
for (int j = 0; j < 20; ++j)
{
for (int i = 0; i < 20; ++i)
{
if (j == 0 || j == 19 || i == 0 || i == 19) // 0=space , 1=# , 2=snake, 3= fruit , 4= snake tail
{
grid[j][i] = 1;
}
else
{
grid[j][i] = 0;
}
}
}
grid[jerry.getY()][jerry.getX]=2;
fruit fr(rand() % 20, rand() % 20);
grid[fr.getY()][fr.getX()] = 3;
}
void draw()
{
for (int j = 0; j < 20; ++j)
{
for (int i = 0; i < 20; ++i)
{
if (grid[j][i]==1)
{
std::cout << "#";
}
else if (grid[j][i]==0)
{
std::cout << " ";
}
else if (grid[j][i] == 2)
{
std::cout << "O";
}
else if (grid[j][i] == 3)
{
std::cout << "F";
}
}
std::cout << std::endl;
}
system("cls");
}
void input()
{
if (_kbhit())
{
jerry.moveSnake(_getch);
}
}
void logic()
{
}
int main()
{
setup();
while (gameOver==false)
{
draw();
input();
logic();
}
return 0;
}

Minimax algorithm for Specker Game

I am creating an minimax player for a game called Specker in c++.
The rules are simple:
There are p players (0 to p - 1) and n heaps (0 to n - 1)
Starting with player 0 each player takes k > 0 coins from a heap x and places m coins (0 <= m < k) on heap y
The winning player is the one which plays last when all coins from all heaps are removed
So I have created the game and some player classes (GreedyPlayer, SpartanPlayer etc.) but they all are a little bit predictable on what they will do. They aren't clever.
so i am creating a player who plays according to minimax (pt18a038)code compiles fine but the program stops responding on execution.
the clever player class:
class pt18a038 : public Player {
private:
string player_type;
public:
pt18a038(const string &n) : Player(n) {
player_type = "Asder aka theRunner";
}
virtual const string &getType() const override {
return player_type;
}
virtual Move play(const State &s) override {
int source_heap = 0;
int target_heap = 0;
int source_coins = 0;
int target_coins = 0;
int sum = 0;
for (source_heap = 0; source_heap < s.getHeaps(); source_heap++) {
for (source_coins = 1; source_coins <= s.getCoins(source_heap); source_coins++) {
for (target_heap = 0; target_heap < s.getHeaps(); target_heap++) {
for (target_coins = 0; target_coins <= source_coins; target_coins++) {
Move m(source_heap, source_coins, target_heap, target_coins);
sum = minimax(s, 3, 0, m);
cout << "Play:" << source_heap << "," << source_coins << "," << target_heap << ","
<< target_coins << ":" << sum << endl;
}
}
}
}
cout << sum << endl;
// ///////////// for debbuging only until minimax is working...
source_heap = 0;
source_coins = 0;
for (int i = 0; i < s.getHeaps(); i++) {
if (s.getCoins(i) > source_coins) {
source_heap = i;
source_coins = s.getCoins(i);
}
}
Move SpartanObject(source_heap, 1, 0, 0);
return SpartanObject;
// /////////////
}
static int minimax(State s, const int &players, int depth, const Move move) {
if (s.winning()) {
cout << "game end!" << endl;
return 1000;
if (depth % players == 0) return 1000; //Maximazing player
else return -1000; //Minimazing player
}
if (depth > 4) {
//cout<<"optimazing"<<endl;
return 0;
}
//cout << s << endl;
s.next(move);
int source_heap = 0;
int target_heap = 0;
int source_coins = 0;
int target_coins = 0;
int max = -100000;
int min = 100000;
int result;
for (source_heap = 0; source_heap < s.getHeaps(); source_heap++) {
for (source_coins = 1; source_coins <= s.getCoins(source_heap); source_coins++) {
for (target_heap = 0; target_heap < s.getHeaps(); target_heap++) {
for (target_coins = 0; target_coins <= source_coins; target_coins++) {
//cout << "Move:" << source_heap << "," << source_coins << "," << target_heap << ","<< target_coins << endl;
Move m(source_heap, source_coins, target_heap, target_coins);
result = minimax(s, players, depth + 1, m);
if (depth % players == 0) {
max = result ? (result > max) : result;
} else {
min = result ? (result < min) : result;
}
}
}
}
}
return max ? (depth % players == 0) : min;
}
};
Here is my code for the rest of the game(it's tested and works fine)
#include <iostream>
#include <stdexcept>
using namespace std;
class Move {
private:
int source_heap, source_coins, target_heap, target_coins;
public:
Move(int sh, int sc, int th, int tc) {
source_heap = sh;
source_coins = sc;
target_heap = th;
target_coins = tc;
}
int getSource() const {
return source_heap;
}
int getSourceCoins() const {
return source_coins;
}
int getTarget() const {
return target_heap;
}
int getTargetCoins() const {
return target_coins;
}
// Let's do some operator overloading
friend ostream &operator<<(ostream &out, const Move &move) {
if (move.getTargetCoins()) {
out << "takes " << move.getSourceCoins() << " coins from heap "
<< move.getSource() << " and puts " << move.getTargetCoins()
<< " coins to heap " << move.getTarget();
} else {
out << "takes " << move.getSourceCoins() << " coins from heap "
<< move.getSource() << " and puts nothing";
}
}
};
class State {
// State with h heaps, where the i-th heap starts with c[i] coins.
private:
int heaps, *heap_coins;
public:
State(int h, const int c[]) {
heaps = h;
heap_coins = new int[heaps];
for (int i = 0; i < heaps; i++)
heap_coins[i] = c[i];
}
~State() {
delete[] heap_coins;
return;
}
int getCoins(int h) const throw(logic_error) {
if (h < 0 || h > heaps) {
throw logic_error(
"Invalid heap number, enter a number between 1 and heaps!");
return 1;
} else {
return heap_coins[h];
}
}
void next(const Move &move) throw(logic_error) {
if ((move.getSource() < 0) || (move.getSource() > heaps) ||
(move.getTarget() < 0) || (move.getTarget() > heaps)) {
throw logic_error("Invalid Heap!");
return;
} else if (
(move.getSourceCoins() < 1) || (move.getTargetCoins() < 0) ||
(move.getSourceCoins() <= move.getTargetCoins()) ||
(move.getSourceCoins() > getCoins(move.getSource()))) {
throw logic_error("Invalid Coin number!");
} else {
heap_coins[move.getSource()] -= move.getSourceCoins();
heap_coins[move.getTarget()] += move.getTargetCoins();
}
}
bool winning() const {
int s = 0;
for (int i = 0; i < heaps; i++)
s += getCoins(i);
return not s; // yeah i know how booleans work :P
}
int getHeaps() const {
return heaps;
}
friend ostream &operator<<(ostream &out, const State &state) {
for (int i = 0; i < state.getHeaps(); i++) {
out << state.heap_coins[i];
if (i != state.getHeaps() - 1)
out << ", ";
}
return out;
}
};
class Player {
public:
Player(const string &n);
virtual ~Player();
virtual const string &getType() const = 0;
virtual Move play(const State &s) = 0;
friend ostream &operator<<(ostream &out, const Player &player);
protected:
string player_name;
};
class GreedyPlayer : public Player {
private:
string player_type;
public:
GreedyPlayer(const string &n) : Player(n) {
player_type = "Greedy";
}
virtual const string &getType() const override {
return player_type;
}
virtual Move play(const State &s) override {
int source_heap = 0;
int source_coins = 0;
for (int i = 0; i < s.getHeaps(); i++) {
if (s.getCoins(i) > source_coins) {
source_heap = i;
source_coins = s.getCoins(i);
}
}
Move GreedyObject(source_heap, source_coins, 0, 0);
return GreedyObject;
}
};
class SpartanPlayer : public Player {
public:
SpartanPlayer(const string &n) : Player(n) {
player_type = "Spartan";
}
virtual const string &getType() const override {
return player_type;
}
virtual Move play(const State &s) override {
int source_heap = 0;
int source_coins = 0;
for (int i = 0; i < s.getHeaps(); i++) {
if (s.getCoins(i) > source_coins) {
source_heap = i;
source_coins = s.getCoins(i);
}
}
Move SpartanObject(source_heap, 1, 0, 0);
return SpartanObject;
}
private:
string player_type;
};
class SneakyPlayer : public Player {
public:
SneakyPlayer(const string &n) : Player(n) {
player_type = "Sneaky";
}
virtual const string &getType() const override {
return player_type;
}
virtual Move play(const State &s) override {
int j = 0;
while (s.getCoins(j) == 0) {
j++;
}
int source_heap = j;
int source_coins = s.getCoins(j);
for (int i = j + 1; i < s.getHeaps(); i++) {
if ((s.getCoins(i) < source_coins) && (s.getCoins(i) > 0)) {
source_heap = i;
source_coins = s.getCoins(i);
}
}
Move SneakyObject(source_heap, source_coins, 0, 0);
return SneakyObject;
}
private:
string player_type;
};
class RighteousPlayer : public Player {
public:
RighteousPlayer(const string &n) : Player(n) {
player_type = "Righteous";
}
virtual const string &getType() const override {
return player_type;
}
virtual Move play(const State &s) override {
int target_heap = 0;
int source_heap = 0;
int source_coins = s.getCoins(0);
int target_coins = source_coins;
for (int i = 1; i < s.getHeaps(); i++) {
if (s.getCoins(i) > source_coins) {
source_heap = i;
source_coins = s.getCoins(i);
} else if (s.getCoins(i) < target_coins) {
target_heap = i;
target_coins = s.getCoins(i);
}
}
source_coins -= source_coins / 2;
Move RighteousObject(
source_heap, source_coins, target_heap, source_coins - 1);
return RighteousObject;
}
private:
string player_type;
};
Player::Player(const string &n) {
player_name = n;
}
Player::~Player() {
player_name.clear();
}
ostream &operator<<(ostream &out, const Player &player) {
out << player.getType() << " player " << player.player_name;
return out;
}
class Game {
private:
int game_heaps, game_players, current_heap, current_player;
int *heap_coins;
Player **players_list;
public:
Game(int heaps, int players) {
heap_coins= new int [heaps];
game_heaps = heaps;
game_players = players;
current_heap = 0;
current_player = 0;
players_list = new Player*[players];
}
~Game() {
delete[] heap_coins;
delete[] players_list;
}
void addHeap(int coins) throw(logic_error) {
if (current_heap > game_heaps)
throw logic_error("All heaps are full with coins!");
else if (coins < 0)
throw logic_error("Coins must be a positive number!");
else {
heap_coins[current_heap++] = coins;
}
}
void addPlayer(Player *player) throw(logic_error) {
if (current_player > game_players)
throw logic_error("All players are added!");
else {
players_list[current_player++] = player;
}
}
void play(ostream &out) throw(logic_error) {
if ((current_player != game_players) && (current_heap != game_heaps)) {
throw logic_error("Have you added all heaps and players?");
} else {
int i = 0;
State currentState(game_heaps, heap_coins);
while (!currentState.winning()) {
out << "State: " << currentState << endl;
out << *players_list[i % game_players] << " "
<< players_list[i % game_players]->play(currentState) << endl;
currentState.next(
players_list[i % game_players]->play(currentState));
i++;
}
out << "State: " << currentState << endl;
i--;
out << *players_list[i % game_players] << " wins" << endl;
}
}
};
int main() {
Game specker(6, 5);
specker.addHeap(10);
specker.addHeap(20);
specker.addHeap(17);
specker.addHeap(17);
specker.addHeap(17);
specker.addHeap(17);
specker.addPlayer(new GreedyPlayer("Alan"));
specker.addPlayer(new SneakyPlayer("Tom"));
specker.addPlayer(new SpartanPlayer("Mary"));
specker.addPlayer(new RighteousPlayer("Robin"));
specker.addPlayer(new pt18a038("Stavros"));
specker.play(cout);
}
Updated
I see a couple of issues in your minimax program, some are serious in nature :
1) Use Alpha Beta pruning to reduce the size of the search tree.
2) There is no proper boundary condition (if depth >5 return score or something) in the minimax recursive call ( see my code snippet for details), the CPU may hang while calling.
3)Your leaf node evaluation is weak, so the evaluated moves , in spite of using minimax algorithm, is not likely to be intelligent ones.
4)To increase the search speed, you may use multi-threading only at the top level branch.
5) If a leaf node gives a winning move while maximizing, you may skip further evaluation by returning a high score.
6) Once your code is functional, refer it at code-review with 'ai' tag , rather than at SO, for more detailed analysis.
int EvaluateLeafNode(State s, const int &players)
{
//TODO analyze here
return score;
}
int minimax(State s, const int &players, int depth , const Move move, int alpha, int beta)
{
if( depth >= 5) return EvaluateLeafNode(s,players); // this was missing in your code
//don't analyze here
//rest of minimax recursive code
}

Invalid use of incomplete type "class"

I know there has been tons of questions like that, but unfortunately after hours of googling and browsing through all of them, none of the answers I read helped. Therefore I am making my own version of my question. The error message I get is: "error: invalid use of incomplete type ‘std::iterator_traits::value_type {aka class Cell}’" My code:
cell.h
#ifndef CELL_H
#define CELL_H
#include <QPushButton>
#include <QMouseEvent>
#include <vector>
class Padding;
class Cell : public QPushButton
{
Q_OBJECT
public:
friend class Padding;
Cell(int x, int y, Padding* padding, QWidget* parent = 0) : QPushButton(parent), x(x), y(y),
padding(padding)
{
setFixedSize(20, 20);
}
Cell(const Cell& object) : QPushButton(), x(object.x), y(object.y), padding(object.padding)
{
setFixedSize(20, 20);
}
int getX() { return x; };
int getY() { return y; };
bool hasMine() { return mine; };
void setHasMine(bool mine) { this -> mine = mine; };
bool isFlagged() { return flagged; };
bool didExplode() { return exploded; };
bool getHasBeenClicked() { return hasBeenClicked; };
void clicked();
~Cell() {};
Cell operator=(const Cell& object)
{
if(&object == this)
{
return *this;
}
padding = object.padding;
x = object.x;
y = object.y;
mine = object.mine;
flagged = object.flagged;
exploded = object.exploded;
hasBeenClicked = object.hasBeenClicked;
setFixedSize(20, 20);
return *this;
}
private:
Padding* padding;
int x;
int y;
bool mine = false;
bool flagged = false;
bool exploded = false;
bool hasBeenClicked = false;
void mousePressEvent(QMouseEvent* e);
void rightClicked();
};
#endif // CELL_H
cell.cpp
#include "cell.h"
#include "padding.h"
void Cell::mousePressEvent(QMouseEvent* event)
{
if(event -> button() == Qt::LeftButton)
{
clicked();
}
else if(event -> button() == Qt::RightButton)
{
rightClicked();
}
}
void Cell::clicked()
{
hasBeenClicked = true;
// TODO: Set the button frame to flat. DONE.
setFlat(true);
// TODO: Make the button not click able. DONE.
setEnabled(false);
// TODO: Display appropriate number on the button, or mine and end the game. DONE.
if(mine)
{
// TODO: Send game over signal and end the game.
//setIcon(QIcon("mine_clicked.png"));
setText("/");
exploded = true;
padding -> gameOver();
}
else
{
setText(QString::number(padding -> countMinesAround(this)));
}
if(padding -> countMinesAround(this) == 0)
{
// Trigger chain reaction; uncover many neighboring cells, if they are not mines.
padding -> triggerChainReactionAround(this);
}
}
void Cell::rightClicked()
{
if(text() != "f")
{
setText("f");
(padding -> minesLeft)--;
}
else
{
setText("");
(padding -> minesLeft)++;
}
flagged = !flagged;
}
padding.h
#ifndef PADDING_H
#define PADDING_H
#include <QWidget>
#include <QGridLayout>
#include <vector>
class Cell;
class Padding : public QWidget
{
Q_OBJECT
public:
friend class Cell;
enum class Difficulty
{
Beginner,
Intermediate,
Advanced,
Custom
};
Padding(QWidget* parent = 0);
void newGame();
void gameOver();
void setLevel(Padding::Difficulty difficulty) { this -> difficulty = difficulty; };
void setPaddingHeight(int height) { paddingHeight = height; };
void setPaddingWidth(int width) { paddingWidth = width; };
void setMines(int mines) { this -> mines = mines; };
int getMinesLeft() { return minesLeft; };
~Padding() {};
private:
struct DifficultyLevelsProperties
{
struct BeginnerProperties
{
const int PADDING_HEIGHT = 9;
const int PADDING_WIDTH = 9;
const int MINES = 10;
} Beginner;
struct IntermediateProperties
{
const int PADDING_HEIGHT = 16;
const int PADDING_WIDTH = 16;
const int MINES = 40;
} Intermediate;
struct AdvancedProperties
{
const int PADDING_HEIGHT = 16;
const int PADDING_WIDTH = 40;
const int MINES = 99;
} Advanced;
} LevelProperties;
Difficulty difficulty = Difficulty::Beginner;
int paddingHeight;
int paddingWidth;
int mines;
// Mines that are not flagged.
int minesLeft;
// Time in seconds since the game was started.
int secondsSinceStart;
std::vector<Cell> cells;
QGridLayout* paddingLayout;
const int CELLS_HEIGHT = 20;
const int CELLS_WIDTH = 20;
int countMinesAround(Cell*);
void triggerChainReactionAround(Cell*);
void updateSecondsSinceStart();
};
#endif // PADDING_H
padding.cpp
#include "padding.h"
#include <QGridLayout>
#include <QTimer>
#include <QTime>
#include <QDebug>
#include "cell.h"
Padding::Padding(QWidget* parent) : QWidget(parent)
{
newGame();
paddingLayout = new QGridLayout(this);
paddingLayout -> setSpacing(0);
}
void Padding::newGame()
{
if(difficulty == Padding::Difficulty::Beginner)
{
paddingHeight = LevelProperties.Beginner.PADDING_HEIGHT;
paddingWidth = LevelProperties.Beginner.PADDING_WIDTH;
mines = LevelProperties.Beginner.MINES;
}
else if(difficulty == Padding::Difficulty::Intermediate)
{
paddingHeight = LevelProperties.Intermediate.PADDING_HEIGHT;
paddingWidth = LevelProperties.Intermediate.PADDING_WIDTH;
mines = LevelProperties.Intermediate.MINES;
}
else if(difficulty == Padding::Difficulty::Advanced)
{
paddingHeight = LevelProperties.Advanced.PADDING_HEIGHT;
paddingWidth = LevelProperties.Advanced.PADDING_WIDTH;
mines = LevelProperties.Advanced.MINES;
}
minesLeft = mines;
cells.clear();
for(int i = 0; i < paddingHeight; i++)
{
for(int j = 0; j < paddingWidth; j++)
{
// TODO: Use smart pointers instead of raw pointers.
Cell* cell = new Cell(j + 1, i + 1, this);
cells.push_back(*cell);
delete cell;
}
}
qsrand(QTime::currentTime().msec());
for(int i = 0; i < mines; i++)
{
// TODO: Fix the randomness of the numbers. DONE.
cells[qrand() % (paddingHeight * paddingWidth) + 1].setHasMine(true);
}
for(int i = 0; i < cells.size(); i++)
{
paddingLayout -> addWidget(&cells[i], cells[i].getY(), cells[i].getX());
}
}
void Padding::gameOver()
{
for(int i = 0; i < cells.size(); i++)
{
cells[i].setEnabled(false);
if((cells[i].hasMine()) && (!cells[i].getHasBeenClicked()))
{
cells[i].clicked();
}
}
}
int Padding::countMinesAround(Cell*)
{
int minesCounter = 0;
for(int i = 0; i < cells.size(); i++)
{
qDebug() << QString::number(cells[i].getX());
if(((x - cells[i].getX() == 0) || (x - cells[i].getX() == 1) || (x -
cells[i].getX() == -1)) && ((y - cells[i].getY() == 0) || (y -
cells[i].getY() == 1) || (y - cells[i].getY() == -1)) &&
(cells[i].hasMine()))
{
minesCounter++;
}
}
return minesCounter;
}
void Padding::triggerChainReactionAround(Cell*)
{
for(int i = 0; i < cells.size(); i++)
{
if(((x - cells[i].getX() == 0) || (x - cells[i].getX() == 1) || (x -
cells[i].getX() == -1)) && ((y - cells[i].getY() == 0) || (y -
cells[i].getY() == 1) || (y - cells[i].getY() == -1)) &&
(!cells[i].getHasBeenClicked()))
{
cells[i].clicked();
}
}
}
Sorry for how long the whole thing, but I could not shorten it as I can't locate what causes the error. Also please ignore any TODO's or any lines that are commented out and I forgot to delete them. Please help!
When you forward declare a type, you can only use pointers or references to that type objects, so this line in padding.h is pretty much not compiling:
std::vector<Cell> cells;
I suppose the compiler complaint comes from where it is trying to decide how to build/destroy a Cell object in a vector. To do that, it needs information about the type, generally from the type declaration (i.e. the header file).

"No instance of constructor "PlayerData::PlayerData" matches the argument list." error Visual Studio is giving me when I try to run the program

Header File
#pragma once
#ifndef PLAYERDATA_H
#define PLAYERDATA_H
#include <string>
using namespace std;
class PlayerData
{
private:
Private member variables
static const int SIZE = 10;
string name; //Player Name
int jnum; //Jersey Number
string team; //Player Team
string position; //Player position
int points[SIZE]; // Array of points for last 10 games
int rebounds[SIZE]; // Array of rebounds for last 10 games
int assist[SIZE]; // Array of assist for last 10 games
double ap = 0.0; // Average number of points
double ar = 0.0; // Average number of rebounds
double aa = 0.0; // Average number of assits
public:
Constructor to initialize data if no data is passed
// Constructor #1
PlayerData()
{
jnum = 0;
name = "";
team = "";
position = "";
for (int i = 0; i < SIZE; i++)
{
points[SIZE] = 0;
rebounds[SIZE] = 0;
assist[SIZE] = 0;
}
}
// Constructor #2
Constructor to accept parameter. Collects jersey number, name, team name, position, array of points for last 10 games, array of rebounds for last 10 games, array of assist for last 10 games.
PlayerData( int jn, string n, string t, string pos, int p[SIZE], int r[SIZE], int a[SIZE])
{
jnum = jn;
name = n;
team = t;
position = pos;
for (int i = 0; i < SIZE; i++)
{
points[SIZE] = p[SIZE];
rebounds[SIZE] = r[SIZE];
assist[SIZE] = a[SIZE];
}
}
// Mutator Function
void setJersery(int jn)
{
jnum = jn;
}
void setName(string n)
{
name = n;
}
void setTeam(string t)
{
team = t;
}
void setPosition(string pos)
{
position = pos;
}
void setPoints(int p[SIZE])
{
for (int z = 0; z < SIZE; z++)
{
points[SIZE] = p[SIZE];
}
}
void setRebounds(int r[SIZE])
{
for (int z = 0; z < SIZE; z++)
{
rebounds[SIZE] = r[SIZE];
}
}
void setAssist(int a[SIZE])
{
for (int z = 0; z < SIZE; z++)
{
assist[SIZE] = a[SIZE];
}
}
// Acessor methods
string getName()
{
return name;
}
int getJersey()
{
return jnum;
}
string getTeam()
{
return team;
}
string getPosition()
{
return position;
}
int getPoints()
{
return points[SIZE];
}
int getRebounds()
{
return rebounds[SIZE];
}
int getAssist()
{
return assist[SIZE];
}
/*
double averageP(int p[], const int SIZE);
double averageR(int r[], const int SIZE);
double averageA(int a[], const int SIZE);
*/
void averageP(int p[], const int SIZE);
void averageR(int r[], const int SIZE);
void averageA(int a[], const int SIZE);
double getAP()
{
return ap;
}
double getAR()
{
return ar;
}
double getAA()
{
return aa;
}
};
#endif // !PLAYERDATA_H
Calculates average points,rebounds, assist from the arrays that were passed.
PlayerData.cpp
#include "PlayerData.h"
using namespace std;
// Calculate average points
void PlayerData::averageP(int p[], const int s)
{
for (int c = 0; c < s; c++)
{
ap += p[c];
}
ap /= s;
//return ap;
}
// Calculate average rebounds
void PlayerData::averageR(int r[], const int s)
{
for (int c = 0; c < s; c++)
{
ar += r[c];
}
ar /= s;
//return ar;
}
// Calculate average assist
void PlayerData::averageA(int a[], const int s)
{
for (int c = 0; c < s; c++)
{
aa += a[c];
}
aa /= s;
//return aa;
}
Main
#include <iostream>
#include <iomanip>
#include "PlayerData.h"
using namespace std;
int main()
{
const int SIZE = 10;
int points[SIZE] = { 10,10,10,10,10,10,10,10,10,10 };
int assist[SIZE] = { 2,2,2,2,2,2,2,2,2,2, };
int rebounds[SIZE] = { 3,3,3,3,3,3,3,3,3,3 };
Here is where the problem occurs. The compiler marks under the 6 as if the int is not part of the arguments for the constructor. I'm not sure why it is doing this. I receive this message "No instance of constructor "PlayerData::PlayerData" matches the argument list."
PlayerData player1(6, "Jimmy Butler", "Chicago Bulls", "Forward", points[SIZE], rebounds[SIZE], assist[SIZE]);
getchar();
return 0;
}
Constructor requires an array of integers and in main you are passing a pointer to int. If you want to pass the whole array you should delete the [SIZE] because that is translated as (if SIZE is 5 for example) "give me the 6th element of 5 element array".
Try calling it like this.
PlayerData player1(6, "Jimmy Butler", "Chicago Bulls", "Forward", points, rebounds, assist);