Qt creator multiple definition within build folder - c++

I am getting a weird error message with Qt creator which makes no sense why it is occuring at all.. I am at the moment programming an ai player for a ludo simulator, which has been written as a QT gui. I've creates a C++ class named player_q_learning, but for some reason is moc_player_q_learning.cpp created within the build folder, and create a multiple definition of the function which i already defined in player_q_learning... Why am I running into this error?
/home/Vato/Desktop/ludo-gui/build-ludo-Desktop-Debug/moc_player_q_learning.cpp:116: error: multiple definition of `player_q_learning::calc_input(float*, int, int)'
ludo.pro
#-------------------------------------------------
#
# Project created by QtCreator 2016-03-15T10:40:30
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ludo
TEMPLATE = app
SOURCES += main.cpp\
dialog.cpp \
game.cpp \
ludo_player.cpp \
ludo_player_random.cpp \
player_q_learning.cpp
HEADERS += dialog.h \
game.h \
ludo_player.h \
positions_and_dice.h \
ludo_player_random.h \
player_q_learning.h
FORMS += dialog.ui
CONFIG += object_with_source
QMAKE_CXXFLAGS += -std=c++11 -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -Wunused
main.cpp
#include "dialog.h"
#include <QApplication>
#include "game.h"
#include <vector>
#include "ludo_player.h"
#include "ludo_player_random.h"
#include "positions_and_dice.h"
Q_DECLARE_METATYPE( positions_and_dice )
using namespace std;
int main(int argc, char *argv[]){
QApplication a(argc, argv);
qRegisterMetaType<positions_and_dice>();
//instanciate the players here
ludo_player p1, p2;
ludo_player_random p3, p4;
game g;
g.setGameDelay(010); //if you want to see the game, set a delay
// Add a GUI <-- remove the '/' to uncomment block
// Dialog w;
// QObject::connect(&g,SIGNAL(update_graphics(std::vector<int>)),&w,SLOT(update_graphics(std::vector<int>)));
// QObject::connect(&g,SIGNAL(set_color(int)), &w,SLOT(get_color(int)));
// QObject::connect(&g,SIGNAL(set_dice_result(int)), &w,SLOT(get_dice_result(int)));
// QObject::connect(&g,SIGNAL(declare_winner(int)), &w,SLOT(get_winner(int)));
// w.show();
//Or don't add the GUI
//QObject::connect(&g,SIGNAL(close()),&a,SLOT(quit()));
//*/
//set up for each player
QObject::connect(&g, SIGNAL(player1_start(positions_and_dice)),&p1,SLOT(start_turn(positions_and_dice)));
QObject::connect(&p1,SIGNAL(select_piece(int)), &g, SLOT(movePiece(int)));
QObject::connect(&g, SIGNAL(player1_end(std::vector<int>)), &p1,SLOT(post_game_analysis(std::vector<int>)));
QObject::connect(&p1,SIGNAL(turn_complete(bool)), &g, SLOT(turnComplete(bool)));
QObject::connect(&g, SIGNAL(player2_start(positions_and_dice)),&p2,SLOT(start_turn(positions_and_dice)));
QObject::connect(&p2,SIGNAL(select_piece(int)), &g, SLOT(movePiece(int)));
QObject::connect(&g, SIGNAL(player2_end(std::vector<int>)), &p2,SLOT(post_game_analysis(std::vector<int>)));
QObject::connect(&p2,SIGNAL(turn_complete(bool)), &g, SLOT(turnComplete(bool)));
QObject::connect(&g, SIGNAL(player3_start(positions_and_dice)),&p3,SLOT(start_turn(positions_and_dice)));
QObject::connect(&p3,SIGNAL(select_piece(int)), &g, SLOT(movePiece(int)));
QObject::connect(&g, SIGNAL(player3_end(std::vector<int>)), &p3,SLOT(post_game_analysis(std::vector<int>)));
QObject::connect(&p3,SIGNAL(turn_complete(bool)), &g, SLOT(turnComplete(bool)));
QObject::connect(&g, SIGNAL(player4_start(positions_and_dice)),&p4,SLOT(start_turn(positions_and_dice)));
QObject::connect(&p4,SIGNAL(select_piece(int)), &g, SLOT(movePiece(int)));
QObject::connect(&g, SIGNAL(player4_end(std::vector<int>)), &p4,SLOT(post_game_analysis(std::vector<int>)));
QObject::connect(&p4,SIGNAL(turn_complete(bool)), &g, SLOT(turnComplete(bool)));
g.start();
return a.exec();
}
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
ui->graphicsView->setBackgroundBrush(QBrush(QColor(240,240,239)));
diceBG = scene->addRect(0,-150,100,100,QPen(Qt::black,3,Qt::SolidLine,Qt::RoundCap, Qt::RoundJoin),QBrush(Qt::green));
diceRoll = scene->addSimpleText(QString::number(0),QFont("Courier", 72, QFont::Bold, true));
diceRoll->setPos(25,-150);
// Colors
std::vector<std::pair<QColor,QColor> >base_colors {
std::make_pair(QColor(92,170,119),QColor(185,219,125)), //G
std::make_pair(QColor(237,235,89),QColor(237,234,138)), //Y
std::make_pair(QColor(92,93,170),QColor(111,111,170)), //B
std::make_pair(QColor(237,57,60),QColor(237,114,125)) //R
};
QBrush white(Qt::white);
QPen blackPen(Qt::black);
blackPen.setWidth(1);
// Cross
scene->addRect(415,-155,160,960,blackPen,QBrush(QColor(195,195,194)));
scene->addRect(15,245,960,160,blackPen,QBrush(QColor(195,195,194)));
scene->addRect(415,245,160,160,QPen(QColor(195,195,194)),QBrush(QColor(195,195,194))); //clean center
// Goal stretch
scene->addRect(50,290,350,70,blackPen,QBrush(base_colors[0].first));
scene->addRect(460,-120,70,350,blackPen,QBrush(base_colors[1].first));
scene->addRect(590,290,350,70,blackPen,QBrush(base_colors[2].first));
scene->addRect(460,420,70,350,blackPen,QBrush(base_colors[3].first));
int x_pos = -10; //start place for green
int y_pos = 220;
int offset = 70;
int small_offset = 50;
int large_offset = 80;
//home fields
home_fields.push_back(QPointF(0,0));
home_fields.push_back(QPointF(630,-170));
home_fields.push_back(QPointF(800,445));
home_fields.push_back(QPointF(190,630));
for(size_t f = 0; f < home_fields.size(); ++f){
addHomeField(home_fields[f].x(),home_fields[f].y(),QBrush(base_colors[f].first));
}
// Playing fields
std::vector<std::pair<char,char> > directions{std::make_pair(1,-1),std::make_pair(1,1),std::make_pair(-1,1),std::make_pair(-1,-1) };
for(size_t d =0; d < directions.size(); ++d){
for(int i=0; i<5;++i){
if(d % 2 == 0)
x_pos += directions[d].first * offset;
else
y_pos += directions[d].second * offset;
fieldPos.push_back(QPointF(x_pos,y_pos));
}
x_pos += directions[d].first * small_offset;
y_pos += directions[d].second * small_offset;
for(int i=0; i<5;++i){
fieldPos.push_back(QPointF(x_pos,y_pos));
if(d % 2 == 0)
y_pos += directions[d].second * offset;
else
x_pos += directions[d].first * offset;
}
for(int i=0; i<2;++i){
fieldPos.push_back(QPointF(x_pos,y_pos));
if(d % 2 == 0)
x_pos += directions[d].first * large_offset;
else
y_pos += directions[d].second * large_offset;
}
fieldPos.push_back(QPointF(x_pos,y_pos));
}
//goal stretches
for(int x=60; x<=340; x+=offset)
fieldPos.push_back(QPointF(x,300));
for(int y=-110; y<=170; y+=offset)
fieldPos.push_back(QPointF(470,y));
for(int x=880; x>=600; x-=offset)
fieldPos.push_back(QPointF(x,300));
for(int y=710; y>=430; y-=offset)
fieldPos.push_back(QPointF(470,y));
QImage globe_img("../globe.png");//http://www.clker.com/clipart-world-black-and-white.html
QImage star_img("../star.png"); //http://www.clker.com/clipart-2568.html
// QGraphicsPixmapItem globe( QPixmap::fromImage(QImage("../globe.png")));
// QGraphicsPixmapItem star( QPixmap::fromImage(QImage("../star.png")));
for(size_t c = 0; c < base_colors.size(); ++c){
scene->addEllipse(fieldPos[0+13*c].x(),fieldPos[0+13*c].y(),50,50,QPen(base_colors[c].first),QBrush(base_colors[c].second));
for(int i=1; i < 13; ++i){
if(i == 8){
QGraphicsPixmapItem * globe = new QGraphicsPixmapItem( QPixmap::fromImage(globe_img));
globe->setPos(fieldPos[i+13*c]);
globe->setScale(0.5);
scene->addItem(globe);
} else if(i == 5 || i == 11){
QGraphicsPixmapItem * star = new QGraphicsPixmapItem( QPixmap::fromImage(star_img));
star->setPos(fieldPos[i+13*c]);
star->setScale(0.5);
scene->addItem(star);
} else {
scene->addEllipse(fieldPos[i+13*c].x(),fieldPos[i+13*c].y(),50,50,blackPen,white);
}
}
}
for(size_t g = 52; g < fieldPos.size(); ++g){
scene->addEllipse(fieldPos[g].x(),fieldPos[g].y(),50,50,blackPen,white);
}
create_graphic_players();
std::vector<int> init_pos(16,-1);
update_graphics(init_pos);
}
void Dialog::update_graphics(std::vector<int> player_positions){
QPointF p;
for(size_t i = 0; i < player_positions.size(); ++i){
if(player_positions[i] == -1){
p = home_fields[i / 4];
if(i % 4 == 0)
graphic_player[i]->setPos(p.x()+65 ,p.y()+15 );
else if(i % 4 == 1)
graphic_player[i]->setPos(p.x()+65 ,p.y()+115);
else if(i % 4 == 2)
graphic_player[i]->setPos(p.x()+15 ,p.y()+65 );
else if(i % 4 == 3)
graphic_player[i]->setPos(p.x()+115,p.y()+65 );
} else if(player_positions[i] == 99){
if(i/4 == 0){
if(i % 4 == 0) graphic_player[i]->setPos(405,300); //left
else if(i % 4 == 1) graphic_player[i]->setPos(405,270);
else if(i % 4 == 2) graphic_player[i]->setPos(405,330);
else if(i % 4 == 3) graphic_player[i]->setPos(435,300);
} else if(i/4 == 1){
if(i % 4 == 0) graphic_player[i]->setPos(470,235); //up
else if(i % 4 == 1) graphic_player[i]->setPos(440,235);
else if(i % 4 == 2) graphic_player[i]->setPos(500,235);
else if(i % 4 == 3) graphic_player[i]->setPos(470,265);
} else if(i/4 == 2){
if(i % 4 == 0) graphic_player[i]->setPos(535,300); //right
else if(i % 4 == 1) graphic_player[i]->setPos(535,270);
else if(i % 4 == 2) graphic_player[i]->setPos(535,330);
else if(i % 4 == 3) graphic_player[i]->setPos(505,300);
} else if(i/4 == 3){
if(i % 4 == 0) graphic_player[i]->setPos(470,365); //down
else if(i % 4 == 1) graphic_player[i]->setPos(440,365);
else if(i % 4 == 2) graphic_player[i]->setPos(500,365);
else if(i % 4 == 3) graphic_player[i]->setPos(470,335);
}
} else {
graphic_player[i]->setPos(fieldPos[player_positions[i]]);
}
}
ui->graphicsView->repaint();
}
void Dialog::create_graphic_players(){
graphic_player.clear();
QBrush piece;
QPen blackPen(Qt::black);
blackPen.setWidth(1);
for(int c = 0; c<4; ++c){
if(c == 0){
piece = QBrush(QColor(Qt::green));
} else if(c == 1){
piece = QBrush(QColor(Qt::yellow));
} else if(c == 2){
piece = QBrush(QColor(Qt::blue));
} else if(c == 3){
piece = QBrush(QColor(Qt::red));
}
for(int i = 0; i<4; ++i){
graphic_player.push_back(scene->addEllipse(5,5,40,40,blackPen,piece));
}
}
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::showEvent(QShowEvent *) {
ui->graphicsView->fitInView(scene->itemsBoundingRect(),Qt::KeepAspectRatio);
}
void Dialog::resizeEvent(QResizeEvent *){
ui->graphicsView->fitInView(scene->itemsBoundingRect(),Qt::KeepAspectRatio);
}
void Dialog::get_winner(int color){
scene->addRect(0,500,1000,200,QPen(Qt::black,3,Qt::SolidLine,Qt::RoundCap, Qt::RoundJoin),QBrush(active_color));
QGraphicsSimpleTextItem * win = scene->addSimpleText(QString("Winner is found!"),QFont("Courier", 72, QFont::Bold, true));
win->setPos(50,550);
}
void Dialog::get_color(int color){
switch(color){
case 0:
active_color = Qt::green;
break;
case 1:
active_color = Qt::yellow;
break;
case 2:
active_color = Qt::blue;
break;
case 3:
active_color = Qt::red;
default:
break;
}
}
void Dialog::get_dice_result(int dice){
current_dice_roll = dice;
diceBG->setBrush(active_color);
diceRoll->setText(QString::number(current_dice_roll));
ui->graphicsView->repaint();
}
void Dialog::addHomeField(int x, int y,QBrush brush){
QBrush whiteBrush(Qt::white);
QPen blackPen(Qt::black);
blackPen.setWidth(1);
scene->addEllipse(x,y,180,180,blackPen,brush);
scene->addEllipse(x+65 ,y+15 ,50,50,blackPen,whiteBrush);
scene->addEllipse(x+65 ,y+115,50,50,blackPen,whiteBrush);
scene->addEllipse(x+15 ,y+65 ,50,50,blackPen,whiteBrush);
scene->addEllipse(x+115,y+65 ,50,50,blackPen,whiteBrush);
}
game.cpp
#include "game.h"
#define DEBUG 0
game::game(){
game_delay = 1000;
game_complete = false;
turn_complete = true;
for(int i = 0; i < 16; ++i){
player_positions.push_back(-1);
}
color = 3;
}
void game::reset(){
game_complete = false;
turn_complete = true;
for(auto i : player_positions){
i = -1;
}
color = 3;
}
int game::rel_to_fixed(int relative_piece_index){
return relative_piece_index + color * 4;
}
int game::isStar(int index){
if(index == 5 ||
index == 18 ||
index == 31 ||
index == 44){
return 6;
} else if(index == 11 ||
index == 24 ||
index == 37 ||
index == 50){
return 7;
}
return 0;
}
int game::isOccupied(int index){ //returns number of people of another color
int number_of_people = 0;
if(index != 99){
for(size_t i = 0; i < player_positions.size(); ++i){
if(i < color*4 || i >= color*4 + 4){ //Disregard own players
if(player_positions[i] == index){
++number_of_people;
}
}
}
}
return number_of_people;
}
bool game::isGlobe(int index){
if(index < 52){ //check only the indexes on the board, not in the home streak
if(index % 13 == 0 || (index - 8) % 13 == 0 || isOccupied(index) > 1){ //if more people of the same team stand on the same spot it counts as globe
return true;
}
}
return false;
}
void game::send_them_home(int index){
for(size_t i = 0; i < player_positions.size(); ++i){
if(i < color*4 || i >= color*4 + 4){ //this way we don't skip one player position
if(player_positions[i] == index){
player_positions[i] = -1;
}
}
}
}
void game::move_start(int fixed_piece){
if(dice_result == 6 && player_positions[fixed_piece] < 0){
player_positions[fixed_piece] = color*13; //move me to start
send_them_home(color*13); //send pieces home if they are on our start
}
}
int game::next_turn(unsigned int delay = 0){
if(game_complete){
return 0;
}
switch(color){
case 0:
case 1:
case 2:
++color;
break;
case 3:
default:
color = 0;
break;
}
global_color = color;
rollDice();
relative.dice = getDiceRoll();
relative.pos = relativePosition();
emit set_color(color);
emit set_dice_result(dice_result);
msleep(delay);
switch(color){
case 0:
emit player1_start(relative);
break;
case 1:
emit player2_start(relative);
break;
case 2:
emit player3_start(relative);
break;
case 3:
emit player4_start(relative);
default:
break;
}
return 0;
}
void game::movePiece(int relative_piece){
int fixed_piece = rel_to_fixed(relative_piece); //index of the piece in player_positions
int modifier = color * 13;
int relative_pos = player_positions[fixed_piece];
int target_pos = 0;
if(player_positions[fixed_piece] == -1){ //if the selected piece is in the safe house, try to move it to start
move_start(fixed_piece);
} else {
//convert to relative position
if(relative_pos == 99){
std::cout << "I tought this would be it ";
} else if(relative_pos < modifier) {
relative_pos = relative_pos + 52 - modifier;
} else if( relative_pos > 50) {
relative_pos = relative_pos - color * 5 - 1;
} else {//if(relative >= modifier)
relative_pos = relative_pos - modifier;
}
if(DEBUG) std::cout << "color: " << color << " pos: " << relative_pos << " + " << dice_result << " = " << relative_pos + dice_result;
//add dice roll
relative_pos += dice_result; //this is relative position of the selected token + the dice number
int jump = isStar(relative_pos); //return 0 | 6 | 7
if(jump){
if(jump + relative_pos == 57){
relative_pos = 56;
} else {
relative_pos += jump;
}
}
//special case checks
if(relative_pos > 56 && relative_pos < 72){ // go back
target_pos = 56-(relative_pos-56) + color * 5 + 1; //If the player moves over the goal, it should move backwards
}else if(relative_pos == 56 || relative_pos >= 99){
target_pos = 99;
}else if(relative_pos > 50){ // goal stretch
target_pos = relative_pos + color * 5 + 1;
} else {
int new_pos = relative_pos + color * 13;
if(new_pos < 52){
target_pos = new_pos;
} else { //wrap around
target_pos = new_pos - 52; //this is the global position wrap around at the green entry point
}
}
//check for game stuff
if(isOccupied(target_pos)){
if(isGlobe(target_pos)){
target_pos = -1; //send me home
} else {
send_them_home(target_pos);
}
}
if(DEBUG) std::cout << " => " << target_pos << std::endl;
player_positions[fixed_piece] = target_pos;
}
std::vector<int> new_relative = relativePosition();
switch(color){
case 0:
emit player1_end(new_relative);
break;
case 1:
emit player2_end(new_relative);
break;
case 2:
emit player3_end(new_relative);
break;
case 3:
emit player4_end(new_relative);
default:
break;
}
emit update_graphics(player_positions);
}
std::vector<int> game::relativePosition(){
std::vector<int> relative_positons;
int modifier = color * 13;
//from start id to end
for(int i = color*4; i < player_positions.size(); ++i){
relative_positons.push_back(player_positions[i]);
}
//from 0 to start id
for(int i = 0; i < color*4; ++i){
relative_positons.push_back(player_positions[i]);
}
for(size_t i = 0; i < relative_positons.size(); ++i){
if(relative_positons[i] == 99 || relative_positons[i] == -1){
relative_positons[i] = (relative_positons[i]);
} else if(relative_positons[i] < modifier) {
relative_positons[i] = (relative_positons[i]+52-modifier);
} else if(relative_positons[i] > 50) {
relative_positons[i] = (relative_positons[i]-color*5-1);
} else if(relative_positons[i] > modifier) {
relative_positons[i] = (relative_positons[i]-modifier);
}
}
return std::move(relative_positons);
}
void game::turnComplete(bool win){
game_complete = win;
turn_complete = true;
if(game_complete){
std::cout << "player: " << color << " won" << std::endl;
emit declare_winner(color);
}
}
void game::run() {
if(DEBUG) std::cout << "color: relative pos => fixed\n";
while(!game_complete){
if(turn_complete){
turn_complete = false;
msleep(game_delay/4);
next_turn(game_delay - game_delay/4);
}
}
emit close();
QThread::exit();
}
ludo_player.cpp
#include "ludo_player.h"
#include <random>
ludo_player::ludo_player(){
}
int ludo_player::make_decision(){
if(dice_roll == 6){
for(int i = 0; i < 4; ++i){
if(pos_start_of_turn[i]<0){
return i;
}
}
for(int i = 0; i < 4; ++i){
if(pos_start_of_turn[i]>=0 && pos_start_of_turn[i] != 99){
return i;
}
}
} else {
for(int i = 0; i < 4; ++i){
if(pos_start_of_turn[i]>=0 && pos_start_of_turn[i] != 99){
return i;
}
}
for(int i = 0; i < 4; ++i){ //maybe they are all locked in
if(pos_start_of_turn[i]<0){
return i;
}
}
}
return -1;
}
void ludo_player::start_turn(positions_and_dice relative){
pos_start_of_turn = relative.pos;
dice_roll = relative.dice;
int decision = make_decision();
emit select_piece(decision);
}
void ludo_player::post_game_analysis(std::vector<int> relative_pos){
pos_end_of_turn = relative_pos;
bool game_complete = true;
for(int i = 0; i < 4; ++i){
if(pos_end_of_turn[i] < 99){
game_complete = false;
}
}
emit turn_complete(game_complete);
}
ludo_player_random.cpp
#include "ludo_player_random.h"
ludo_player_random::ludo_player_random(){
}
int ludo_player_random::make_decision(){
std::vector<int> valid_moves;
if(dice_roll == 6){
for(int i = 0; i < 4; ++i){
if(pos_start_of_turn[i]<0){
valid_moves.push_back(i);
}
}
}
for(int i = 0; i < 4; ++i){
if(pos_start_of_turn[i]>=0 && pos_start_of_turn[i] != 99){
valid_moves.push_back(i);
}
}
if(valid_moves.size()==0){
for(int i = 0; i < 4; ++i){
if(pos_start_of_turn[i] != 99){
valid_moves.push_back(i);
}
}
}
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> piece(0, valid_moves.size()-1);
int select = piece(gen);
return valid_moves[select];
}
void ludo_player_random::start_turn(positions_and_dice relative){
pos_start_of_turn = relative.pos;
dice_roll = relative.dice;
int decision = make_decision();
emit select_piece(decision);
}
void ludo_player_random::post_game_analysis(std::vector<int> relative_pos){
pos_end_of_turn = relative_pos;
bool game_complete = true;
for(int i = 0; i < 4; ++i){
if(pos_end_of_turn[i] < 99){
game_complete = false;
}
}
emit turn_complete(game_complete);
}
player_q_learning.cpp
http://pastebin.com/bjwFDLgj
player_q_learning.h
http://pastebin.com/zUrnvdsL
I can't add the .h due to body character limit upto 30000 chars. I hope the .cpp gives an idea of how the .h files are constructed..

You declared calc_input to be a signal, so you must not implement it. It's Qt that provides its implementation (in the MOC-generated file), such that when it is emitted it calls the slots that have been connected to it.
If you didn't intend it to be a signal (as it seems to me, given that you never connect nor emit it), move its declaration outside the signals: section, so that it becomes a "regular" method.

Related

Tic tac toe Minimax Algorithm Having Weird Behavior (C++)

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.

Why doesn't the Player.x and Player.y variables change?

Edit #2: Ok, I did another *.cpp to check if the codes for Arrow Keys were right. Doing that, I noticed keyPressed variable in detectKeyPressing() had the wrong type of variable, so I changed it from char to int and changed the codes.
Once I did that, it worked. Now I have put the limits, so the Player cannot go outside the square. But I have another problem, the movement is too tough and if you press the keys too fast, the instructions run with a annoying delay. I know I should use either Sleep(ms) or Delay(ms), but I don't know when I should use it.
This is the new code:
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <Windows.h>
using namespace std;
int detectKeyPressing() {
// 0: Escape
// 1: Enter
//2: Up
// 3: Left
// 4: Down
// 5: Right
int keyPressed = 0;
while (keyPressed != 27) {
if (keyPressed == 0 || keyPressed == 224) {
keyPressed = _getch(); //First value of _getch() when any of the arrow keys are pressed is "224", the next one is the code depending of which arrow you pressed
}
else if (keyPressed == 13) {
return 1;
}
else {
switch (keyPressed) {
//Up
case 72:
return 2;
break;
//Left
case 75:
return 3;
break;
//Down
case 80:
return 4;
break;
//Right
case 77:
return 5;
break;
//Default
default:
return -1;
break;
}
}
};
return 0;
};
int mainMenu() {
int enterPressed = 0;
cout << "Press Enter to Begin, or ESC to exit" << endl;
enterPressed = detectKeyPressing();
system("cls");
return enterPressed;
};
void draw(int playerX, int playerY) {
//Player coordinates, made for testing
cout << "Player.x = " << playerX << endl << "Player.y = " << playerY << endl;
//The next 8 spaces go blank
for (int i = 1; i < 8; i++) {
cout << endl;
}
//Square Limit Making
//Top Limit
for (int iw = 1; iw < 80; iw++) {
cout << "-";
}
cout << endl;
//Border limits and inside the Square
for (int ih = 1; ih < 30; ih++) {
//Left border
cout << "|";
//Inside the Square
for (int iw = 1; iw < 78; iw++) {
if (iw == playerX && ih == playerY) {
cout << "a"; //This is supposed to be ♥ but I don't know how to put it in the screen with a cout
}
else {
cout << " ";
}
}
//Right border
cout << "|" << endl;
}
//Bottom limit
for (int iw = 1; iw < 80; iw++) {
cout << "-";
}
}
int main() {
//Hide cursor
HANDLE hCon;
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
cci.dwSize = 1;
cci.bVisible = FALSE;
SetConsoleCursorInfo(hCon, &cci);
//Variable Making
int gameStarted = -1; // 1 if game is running, 0 if not
//int t = 0; //Turn Counter, not useful for now
Sleep(200); //Wait to get a new seed
srand(time(NULL)); //Seed for rand()
//Menu Loop, remember, 1 if game starts running, 0 if you exit
while (gameStarted > 1 || gameStarted < 0) {
gameStarted = mainMenu();
}
//Like Void Start() in Unity
if (gameStarted == 1) {
int pressedKey = -1; //Creating pressedKey at Start
class Player {
public:
int life = 20;
int accuracy = 80 + (rand() % 100) / 20;
int damage = 5 + (accuracy / 10) + (rand() % 100) / 50;
bool isAlive = true;
int x = 39;
int y = 24;
int speed = 1;
};
class Enemy {
public:
int life = 100;
int satisfaction = 0;
bool isAlive = true;
bool isSatisfied = false;
int damage = 2 + (rand() % 100) / 20;
};
Player Player;
Enemy Enemy;
draw(Player.x, Player.y);
//Like Void Update() in Unity
while (gameStarted != 0) {
pressedKey = detectKeyPressing(); // Save detectKeyPressing()'s return in pressedKey
//Draw if proyectile is moving - not yet
//Draw if player is moving (pay attention specially to this part)
if (pressedKey == 0) {
gameStarted = 0; //if ESC is pressed, exit the loop and exits
}
//If any of the Arrow Keys are pressed
else if (pressedKey > 1 && pressedKey < 6) {
switch (pressedKey) {
//Up
case 2:
Sleep(200);
if (Player.y == Player.speed) {
Player.y = Player.speed; //Top Limit
}
else {
Player.y -= Player.speed;
}
break;
//Left
case 3:
Sleep(200);
if (Player.x == Player.speed) {
Player.x = Player.speed; //Left Limit
}
else {
Player.x -= Player.speed;
}
break;
//Down
case 4:
Sleep(200);
if (Player.y == 30 - Player.speed) {
Player.y = 30 - Player.speed; //Bottom Limit
}
else {
Player.y += Player.speed;
}
break;
//Right
case 5:
Sleep(200);
if (Player.x == 78 - Player.speed) {
Player.x = 78 - Player.speed; //Right Limit
}
else {
Player.x += Player.speed;
}
break;
};
system("cls"); //Erase all
draw(Player.x, Player.y); //Redraw everything, with Player.x or Player.y modified
};
};
};
return 0;
};
Edit #1: I fixed the mistakes you told me, here's the main function modified. It isn't working though.
int main(){
//Hide cursor
HANDLE hCon;
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
cci.dwSize = 50;
cci.bVisible = FALSE; //Changed "TRUE" to "FALSE"
SetConsoleCursorInfo(hCon, &cci);
//Variable Making
int gameStarted = -1; // 1 if game is running, 0 if not
//int t = 0; //Turn Counter, not useful for now
Sleep(200); //Wait to get a new seed
srand(time(NULL)); //Seed for rand()
//Menu Loop, remember, 1 if game starts running, 0 if you exit
while (gameStarted > 1 || gameStarted < 0) {
gameStarted = mainMenu();
}
//Like Void Start() in Unity
if (gameStarted == 1) {
int pressedKey = -1; //Creating pressedKey at Start
class Player {
public:
int life = 20;
int accuracy = 80 + (rand() % 100) / 20;
int damage = 5 + (accuracy / 10) + (rand() % 100) / 50;
bool isAlive = true;
int x = 39;
int y = 24;
int speed = 2;
};
class Enemy {
public:
int life = 100;
int satisfaction = 0;
bool isAlive = true;
bool isSatisfied = false;
int damage = 2 + (rand() % 100) / 20;
};
Player Player;
Enemy Enemy;
draw(Player.x, Player.y);
//Like Void Update() in Unity
while (gameStarted != 0) {
pressedKey = detectKeyPressing(); //Save detectKeyPressing()'s return in pressedKey
//Draw if proyectile is moving - not yet
//Draw if player is moving (pay attention specially to this part)
if (pressedKey == 0) {
gameStarted = 0; //if ESC is pressed, exit the loop and exits
}
//If any of the Arrow Keys are pressed
else if (pressedKey > 1 && pressedKey < 6) {
cout << "There's no problem in Else If statement"; //Couts made for testing
switch (pressedKey) {
cout << "There's no problem in Switch statement";
//Up
case 2:
Player.y -= Player.speed;
cout << "You moved Up";
break;
//Left
case 3:
Player.x -= Player.speed; //Fixed Left movement
cout << "You moved Left";
break;
//Down
case 4:
Player.y += Player.speed;
cout << "You moved Down";
break;
//Right
case 5:
Player.x += Player.speed;
cout << "You moved Right";
break;
};
//system("cls"); //Erase all
//draw(Player.x, Player.y); //Redraw everything, with Player.x and Player.y supposedly modified
};
};
};
return 0;
};
Initial Post: I'm trying to do something like an Undertale normal fight and now I'm doing the "dodging attacks" part, but I'm stuck at making the player move (Yep, that "a") because it didn't update when I press an arrow key (for movement). It is supposed to draw, and put the Player in Player.x and Player.y, so I did something in main() to edit these variables depending on the arrow key you pressed, and then erase and re-draw with the Player.x or Player.y modified.
Here's the code:
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <Windows.h>
using namespace std;
int detectKeyPressing(){
// 0: Escape
// 1: Enter
// 2: Up
// 3: Left
// 4: Down
// 5: Right
char keyPressed = 0;
while (keyPressed != 27){
if(keyPressed == 0){
keyPressed = _getch();
}
else if(keyPressed == 13){
return 1;
}
else{
switch (keyPressed) {
//Up
case 65:
return 2;
break;
//Left
case 68:
return 3;
break;
//Down
case 66:
return 4;
break;
//Right
case 67:
return 5;
break;
//Default
default:
return -1;
break;
}
}
};
return 0;
};
int mainMenu(){
int enterPressed = 0;
cout << "Press Enter to Begin, or ESC to exit" << endl;
enterPressed = detectKeyPressing();
system("cls");
return enterPressed;
};
void draw(int playerX, int playerY) {
//Player coordinates, made for testing
cout << "Player.x = " << playerX << endl << "Player.y = " << playerY << endl;
//The next 8 spaces go blank
for (int i = 1; i < 8; i++) {
cout << endl;
}
//Square Limit Making
//Top Limit
for (int iw = 1; iw < 80; iw++) {
cout << "-";
}
cout << endl;
//Border limits and inside the Square
for (int ih = 1; ih < 30; ih++) {
//Left border
cout << "|";
//Inside the Square
for (int iw = 1; iw < 78; iw++) {
if (iw == playerX && ih == playerY){
cout << "a"; //This is supposed to be ♥ but I don't know how to put it in the screen with a cout
}
else {
cout << " ";
}
}
//Right border
cout << "|" << endl;
}
//Bottom limit
for (int iw = 1; iw < 80; iw++) {
cout << "-";
}
}
int main(){
//Hide cursor
HANDLE hCon;
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
cci.dwSize = 50;
cci.bVisible = TRUE;
SetConsoleCursorInfo(hCon, &cci);
//Variable Making
int gameStarted = -1; // 1 if game is running, 0 if not
//int t = 0; //Turn Counter, not useful for now
Sleep(200); //Wait to get a new seed
srand(time(NULL)); //Seed for rand()
//Menu Loop, remember, 1 if game starts running, 0 if you exit
while (gameStarted > 1 || gameStarted < 0) {
gameStarted = mainMenu();
}
//Like Void Start() in Unity
if (gameStarted == 1) {
class Player {
public:
int life = 20;
int accuracy = 80 + (rand() % 100) / 20;
int damage = 5 + (accuracy / 10) + (rand() % 100) / 50;
bool isAlive = true;
int x = 39;
int y = 24;
int speed = 2;
};
class Enemy {
public:
int life = 100;
int satisfaction = 0;
bool isAlive = true;
bool isSatisfied = false;
int damage = 2 + (rand() % 100) / 20;
};
Player Player;
Enemy Enemy;
draw(Player.x, Player.y);
//Like Void Update() in Unity
while (gameStarted != 0) {
//Draw if proyectile is moving - not yet
//Draw if player is moving (pay attention specially to this part)
if (detectKeyPressing() == 0) {
gameStarted = 0; //if ESC is pressed, exit the loop and exits
}
//If any of the Arrow Keys are pressed
else if (detectKeyPressing() > 1 && detectKeyPressing() < 6) {
switch (detectKeyPressing()) {
//Up
case 2:
Player.y -= Player.speed;
break;
//Left
case 3:
Player.x += Player.speed;
break;
//Down
case 4:
Player.y += Player.speed;
break;
//Right
case 5:
Player.x += Player.speed;
break;
};
system("cls"); //Erase all
draw(Player.x, Player.y); //Redraw everything, with Player.x and Player.y supposedly modified
};
};
};
return 0;
};
I did a few tests and it seems that the else if in "//If any of the Arrow Keys is Pressed" part isn't running but I don't know why.
I would really appreciate any help you can provide. Sorry if anything isn't well written, I'm not a native english speaker.
Where you have this comment
//Draw if proyectile is moving - not yet add a variable to save your pressed key, something like
int pressedKey = detectKeyPressing();
Then, use that variable to check which condition is met within your if-else.
What’s happening is that you’re calling your function, thus asking/waiting for an input each time a condition is being checked.

Run-Time Check Failure #2 Stack around the variable 'maze' were corrupted

Run-Time Check Failure #2 Stack around the variable 'maze' were corrupted.
Whenever I compile and run my program, I receive this error whenever the program finishes running. I believe the problem is happening in my addPaths function in my implementation. I posted all my code just in case. This program is creating a maze and the addPaths function is "digging" the paths for the user to move through. The path direction is chosen at random and the paths are only drawn at even number spaces on the maze.
HEADER:
const int HEIGHT = 3;
const int WIDTH = 5;
class Coordinate
{
public:
int row, column;
};
class Maze
{
public:
Maze();
~Maze();
void buildMaze();
void displayMaze();
void addPaths();
void startGame();
void movePlayer(int);
bool solved();
int getKey();
void addDestinationToGrid();
private:
char grid[WIDTH][HEIGHT];
Coordinate player;
const static char PLAYER = 'P';
const static char DESTINATION = 'X';
const static char START = 'S';
const static char PATH = ' ';
const static char WALL = (char)219;
};
IMPLEMENTATION:
#include <iostream>
#include "maze.h"
#include <windows.h>
#include <stack>
using std::cout;
using std::endl;
Maze::Maze()
{
buildMaze();
}
Maze::~Maze()
{
cout << "yay";
}
void Maze::buildMaze()
{
for (int x = 0; x <= HEIGHT-1; x++)
{
for (int y = 0; y <= WIDTH-1; y++)
{
grid[x][y] = WALL;
//SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
}
}
}
void Maze::displayMaze()
{
for (int x = 0; x <= HEIGHT-1; x++)
{
for (int y = 0; y <= WIDTH-1; y++)
{
cout << grid[x][y];
}
cout << endl;
}
}
void Maze::startGame()
{
int input;
do
{
input = getKey();
movePlayer(input);
} while (!solved());
}
bool Maze::solved()
{
return true;
}
void Maze::movePlayer(int direction)
{
if (direction == VK_UP || direction == VK_DOWN || direction == VK_LEFT || direction == VK_RIGHT)
{
COORD newCoord = { player.column + 1, player.row + 1 };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), newCoord);
if (grid[player.row][player.column] == START)
{
cout << START;
}
else
{
cout << PATH;
}
}
}
int Maze::getKey()
{
int result = 0;
while (!solved() && result == 0)
{
short MAX_SHORT = 0x7FFF; //111111111111111
if (GetAsyncKeyState(VK_LEFT) & MAX_SHORT)
{
result = VK_LEFT;
}
else if (GetAsyncKeyState(VK_UP) & MAX_SHORT)
{
result = VK_UP;
}
else if (GetAsyncKeyState(VK_RIGHT) & MAX_SHORT)
{
result = VK_RIGHT;
}
else if (GetAsyncKeyState(VK_DOWN) & MAX_SHORT)
{
result = VK_DOWN;
}
}
return result;
}
void Maze::addPaths()
{
Coordinate currentLocation;
Coordinate startLocation;
//Coordinate endLocation; //not used yet
std::stack<Coordinate> myStack;
currentLocation.row = (((rand() % HEIGHT) / 2) * 2);
currentLocation.column = (((rand() % WIDTH) / 2) * 2);
startLocation = currentLocation;
grid[currentLocation.row][currentLocation.column] = START;
player = currentLocation;
do
{
bool canMoveUp = !(currentLocation.row == 0 || grid[currentLocation.row - 2][currentLocation.column] != WALL);
bool canMoveDown = !(currentLocation.row == HEIGHT - 1 || grid[currentLocation.row + 2][currentLocation.column] != WALL);
bool canMoveLeft = !(currentLocation.column == 0 || grid[currentLocation.row][currentLocation.column - 2] != WALL);
bool canMoveRight = !(currentLocation.column == WIDTH - 1 || grid[currentLocation.row][currentLocation.column + 2] != WALL);
if (canMoveUp || canMoveDown || canMoveLeft || canMoveRight)
{
myStack.push(currentLocation);
//choose random location to dig
bool moveFound = false;
while (moveFound != true)
{
int direction = rand() % 4;
if (direction == 0 && canMoveUp)
{
moveFound = true;
grid[currentLocation.row - 2][currentLocation.column] = PATH;
grid[currentLocation.row - 1][currentLocation.column] = PATH;
currentLocation.row -= 2;
}
else if (direction == 1 && canMoveDown)
{
moveFound = true;
grid[currentLocation.row + 2][currentLocation.column] = PATH;
grid[currentLocation.row + 1][currentLocation.column] = PATH;
currentLocation.row += 2;
}
else if (direction == 2 && canMoveLeft)
{
moveFound = true;
grid[currentLocation.row][currentLocation.column - 2] = PATH;
grid[currentLocation.row][currentLocation.column - 1] = PATH;
currentLocation.column -= 2;
}
else if (direction == 3 && canMoveRight)
{
moveFound = true;
grid[currentLocation.row][currentLocation.column + 2] = PATH;
grid[currentLocation.row][currentLocation.column - 2] = PATH;
currentLocation.column += 2;
}
}
}
else if (!myStack.empty())
{
currentLocation = myStack.top();
myStack.pop();
}
}
while (!myStack.empty());
addDestinationToGrid();
}
void Maze::addDestinationToGrid()
{
int randomRow = rand() % HEIGHT;
int randomColumn = rand() % WIDTH;
while (grid[randomRow][randomColumn] != PATH)
{
randomRow = rand() % HEIGHT;
randomColumn = rand() % WIDTH;
}
grid[randomRow][randomColumn] = DESTINATION;
}
MAIN:
#include <iomanip>
#include <iostream>
#include "maze.h"
using namespace std;
int main()
{
Maze maze;
maze.addPaths();
maze.displayMaze();
maze.startGame();
/*if (maze.solved())
{
cout << " You Win!";
}*/
}
There are two problems. One is that you are not consistent in the order you access elements of grid. It is declared grid[WIDTH][HEIGHT] but most (but not all) accesses use a HEIGHT based index first. This isn't causing your problems since WIDTH is greater than HEIGHT and you stay within the object's memory when doing normal accesses to it.
The problem is this line:
grid[currentLocation.row][currentLocation.column - 2] = PATH;
in the moveRight handler. The column offset should be + 1, not - 2. The way it is can cause you to write to memory before the first element of grid.

SDL_Rect not visible

I have multiple SDL_Rects creating a snake that is supposed to stay in a specific area. Sometimes when the "snake" reaches the boundaries a part disappears.
void Snake::update(SDL_Surface *screen, int level)
{
old_pos.first = snake_rect[0];
if(x_axis)
snake_rect[0].x += snake_speed * level * direction_multiplier;
else if(!x_axis)
snake_rect[0].y += snake_speed * level * direction_multiplier;
for(unsigned int i = 1; i < snake_rect.size(); ++i)
{
old_pos.second = snake_rect[i];
snake_rect[i] = old_pos.first;
old_pos.first = old_pos.second;
}
boundariesCheck(screen);
/// Making the enemy move randomly
if(rand() % 100 < 10)
{
if(x_axis)
{
x_axis = false;
direction.second = rand() % 2;
if(direction.second)
direction_multiplier = 1;
else if(!direction.second)
direction_multiplier = -1;
}
else if(!x_axis)
{
x_axis = true;
direction.first = rand() % 2;
if(direction.first)
direction_multiplier = 1;
else if(!direction.first)
direction_multiplier = -1;
}
}
}
void Snake::draw(SDL_Surface *screen)
{
for(unsigned int i = 1; i < snake_rect.size(); ++i)
{
SDL_FillRect(screen, &snake_rect[i], 0xFF0000);
}
SDL_FillRect(screen, &snake_rect[0], 0xFF5500);
}

Overview rpg tiled space

I'm trying to make it where the character is in a tile and when they move up or down it moves to the next tile but I'm not sure how to do that. Right now, I have it set up where the character moves by pixels but I want it to move by 1 square.
The code right now is this, and it works, but it's glitchy in pixel mode. I believe if it was by blocks it might work better but I might change it anyway.
float spritewidth = sprite->stretchX;
float spriteheight = sprite->stretchY;
float bushwidth = bush->stretchX;
float bushheight = bush->stretchY;
//Basic border collision
if (sprite->x <= 0)
sprite->x = 0;
if (sprite->y <= 0)
sprite->y = 0;
if (sprite->x >= 455)
sprite->x = 455;
if (sprite->y >= 237)
sprite->y = 237;
if ( (sprite->x + spritewidth > bush->x) && (sprite->x < bush->x + bushwidth) && (sprite->y + spriteheight > bush->y) && (sprite->y < bush->y + bushheight) )
{
bushcol = 1;
}
else
{
bushcol = 0;
}
if (osl_keys->held.down)
{
if (bushcol == 1)
{
sprite->y = bush->y - spriteheight - 3;
bushcol = 0;
}
else
{
bushcol = 0;
sprite->y += 3;
}
}
if (osl_keys->held.up)
{
if (bushcol == 1)
{
sprite->y = bush->y + bushheight + 3;
bushcol = 0;
}
else
{
bushcol = 0;
sprite->y -= 3;
}
}
if (osl_keys->held.right)
{
if (bushcol == 1)
{
sprite->x = bush->x - spritewidth - 3;
bushcol = 0;
}
else
{
bushcol = 0;
sprite->x += 3;}
}
if (osl_keys->held.left)
{
if (bushcol == 1)
{
sprite->x = bush->x + bushwidth + 3;
bushcol = 0;
}
else
{
bushcol = 0;
sprite->x -= 3;
}
}
If you want the character to move one tile/square/block at a time, just move the sprite the number of pixels the tile is wide (or tall).
const int tile_width = 32; // or something
// and then
sprite->x += tile_width;