C++ for loop crashes halfway through - c++

I've just started learning about C++ and I'm currently stuck with this for loop that crashes everytime I execute it (it's part of a larger code)
void placeItem()
{
int settler = 20, castle = 5, tower = 10, mine = 10, E = 100;
int player1Settler = 0, player1Castle = 0, player1Tower = 0, player1Mine = 0;
int player2Settler = 0, player2Castle = 0, player2Tower = 0, player2Mine = 0;
int dice, x, y;
currentBoardStatus();
cout << "Player " << playerTurn(1 || 2) << " starts first." << endl;
for (int game = 1; game <= 46; game++)
{
system("CLS");
cout << "Turn #" << game << endl;
dice = rand() % 6 + 1;
x = rand() % 10 + 1;
y = rand() % 10 + 1;
cout << "Dice number: " << dice << endl;
if (dice < 4 && settler > 0)
{
cout << "Settler placed on [" << x << "] [" << y << "]" << endl;
gameBoard(x, y) = "S";
settler = settler--;
if (playerTurn(1))
{
player1Settler = player1Settler + 1;
}
else
{
player2Settler = player2Settler + 1;
}
currentBoardStatus();
}
else if (dice = 4 && castle > 0)
{
cout << "Castle placed on [" << x << "] [" << y << "]" << endl;
gameBoard(x, y) = "C";
castle = castle--;
if (playerTurn(1))
{
player1Castle = player1Castle + 1;
}
else
{
player2Castle = player2Castle + 1;
}
currentBoardStatus();
}
else if (dice = 5 && tower > 0)
{
cout << "Tower placed on [" << x << "] [" << y << "]" << endl;
gameBoard(x, y) = "T";
tower = tower--;
if (playerTurn(1))
{
player1Tower = player1Tower + 1;
}
else
{
player2Tower = player2Tower + 1;
}
currentBoardStatus();
}
else if (dice = 6 && mine > 0)
{
cout << "Mine placed on [" << x << "] [" << y << "]" << endl;
gameBoard(x, y) = "M";
mine = mine--;
if (playerTurn(1))
{
player1Mine = player1Mine + 1;
}
else
{
player2Mine = player2Mine + 1;
}
currentBoardStatus();
}
else
{
cout << "Player skips his/her turn." << endl;
}
nextTurn();
//currentBoardStatus();
system("pause");
}
}
As soon as the loop goes to 16, the entire console application stops responding, and stops there, only letting me exit.

Your code crashes because of
string gameBoard(int i, int j)
{
string arr[10][10];
return arr[i][j];
}
AND
x = rand() % 10 + 1;
y = rand() % 10 + 1;
x and y will have a value between 1 and 10, but the size of arr is 10 and its maximum valid index is 9. Therefore if x or y is 10 (or both), they'll access undefined memory.
Aside from this, there are many flaws with your code like:
dice = 4 when wanting to compare the value (which actually assigns the value 4 to dice as #KeithSmith pointed out)
The fact that you create string arr in int main() and never use it, but declare another string arr inside string gameBoard() and then return an index from it (which is undefined)

Related

C++ Putting a character into a cin for a while loop causes the loop to execute outside of it [duplicate]

This question already has answers here:
Why do I get an infinite loop if I enter a letter rather than a number? [duplicate]
(4 answers)
Closed 5 years ago.
I decided to try to make a little game. It's a simple survival game. Part of it has people try to survive as long as they can by choosing options. I've scaled down the game as much as possible from 1000 lines to this for the minimum case.
At one part of the game it asks, "You were visited by a gifting clown. On a scale of 0-10, how badly do you want a gift?"
If they answer 0-10, the loop works fine. If they answer with a character, like y or n, the loop basically forces the game to execute where it no longer asks players for input on any other choices.
A previous while loop works, one where it will continue so long as the player is alive. This clown while loop is nested inside of it. I have broken up the while loop with the clown section to where I think the problem is... And also included the full code just in case it's not inside there.
My goal is simply if a character is put into it, that it doesn't break this game.
main.cpp - clown section
encounterHurt = 0;
randomEncounter = rand() % 8;
cin.ignore(1, '\n');
if (randomEncounter == 1 && clown == true){
encounterChoice = 1;
cout << "\n\nYou were visited by a gifting clown. \nOn a scale of 0-10, how badly do you want a gift? ";
while (encounterChoice >= 0 && encounterChoice <= 10){
cin >> encounterChoice;
encounterFood = (rand() % 3) + encounterChoice / 2;
encounterWood = (rand() % 3) + encounterChoice / 2;
encounterMedicine = (rand() % 2);
encounterBullets = (rand() % 2);
if (encounterChoice > 0){
encounterHurt = (rand() % 10) - encounterChoice;
if (encounterHurt <= 1){
health--;
cout << "The crazy clown stabs you, but still provides gifts.";
}
}
if (encounterFood > 0) {
cout << "\nYou were provided with " << encounterFood << " food." << endl;
food += encounterFood;
}
if (encounterWood > 0) {
cout << "\nYou were provided with " << encounterWood << " wood." << endl;
wood += encounterWood;
}
if (encounterMedicine > 0) {
cout << "\nYou were provided with " << encounterMedicine << " medicine." << endl;
medicine += encounterMedicine;
}
if (encounterBullets > 0) {
cout << "\nYou were provided with " << encounterBullets << " bullets." << endl;
bullets += encounterBullets;
}
encounterChoice = 11;
}
main.cpp - Condensed code
#include <iostream>
#include <iomanip>
#include <random>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main() {
srand (time(NULL));
int randNumber = 0;
int food = 4;
int wood = 4;
int medicine = 2;
int bullets = 8;
int money = 25;
int randomEncounter = 0;
int hunt = 0;
bool axe = false;
int axeTemp = 0;
int axeBonus = 0;
int lumberTemp = 0;
int lumber = 0;
int findStore = 0;
int storeChoice = 0;
bool gun = false;
int gunSearch;
int gunTemp;
int gunBonus = 0;
int gunFind = 0;
// int searches;
// int searchesBonus;
int farmFind = 0;
int farmFood = 0;
int farmSearch = 0;
bool farm = false;
string description;
int foodTemp = 0;
int woodTemp = 0;
int medicineTemp = 0;
int bulletsTemp = 0;
int moneyTemp = 0;
int huntTemp = 0;
int huntSuccess = 0;
char huntChoice;
int encounterFood = 0;
int encounterWood = 0;
int encounterBullets = 0;
int encounterMedicine = 0;
int encounterHurt = 0;
unsigned int encounterChoice = 0;
int hurt = 0;
int health = 3;
int healthMax = 3;
int days = 1;
char action = '0';
char pause = '1';
char classChoice;
char mainChoice;
bool clown = true;
int clownHealth = 5;
char clownChoice;
int yourShot = 0;
int clownShot = 0;
string place;
//Food 1 per day per person. Can expand to include more people.
//Fuel 1 per day, takes that much to stay warm even if fewer people
//Medicine used one per wound
//Bullets 1 to hunt, though can spend more to increase chance of success.
//Days how many days that they have survied.
//Health, everyone starts with three health. Good, okay, bad, dead.
cout << "\nFood: " << food << " Wood: " << wood << " Medicine: " << medicine << " Bullets: " << bullets << " Health: " << health << endl;
while (health > 0){
cout << "\nDay: " << days;
cout << "\nFood: " << food
<< "\nWood: " << wood
<< "\nMedicine: " << medicine
<< "\nBullets: " << bullets
<< "\nHealth: " << health
<< "\nMoney: " << money << endl;
if (food >= 1){
food--;
}
if (wood >= 1){
wood--;
}
if (food <= 0){
health--;
cout << "Health lost due to lack of food" << endl;
}
if (health < healthMax && medicine > 0){
health++;
medicine--;
cout << "Health pack used to heal your character\nHealth : " << health << endl;
}
action = '0';
cout << "\n1: Find food" << endl;
cout << "What's your action? ";
cin >> action;
cout << endl;
if (action == '1'){
//
//Section for random sites to search.
//
//
randNumber = rand() % 4;
description = "";
//Maybe + days at the end, and subtract some, so that they eventually run out of places to check.
if (randNumber >= 0 && randNumber < 2) {
place = "supermarket";
foodTemp = (rand() % 4) + 1;
woodTemp = (rand() % 2) + 0;
bulletsTemp = (rand() % 2) + 0;
medicineTemp = (rand() % 2) + 1;
moneyTemp = (rand() % 5) + 5;
}
if (randNumber >= 2 && randNumber < 4) {
place = "boat house";
foodTemp = (rand() % 2) + 1;
woodTemp = (rand() % 4) + 1;
bulletsTemp = (rand() % 2) + 0;
medicineTemp = (rand() % 2) + 0;
moneyTemp = (rand() % 3) + 0;
}
cout << "You have come to the " << place << "." << endl;
cout << description << endl;
food += foodTemp;
wood += woodTemp;
bullets += bulletsTemp;
medicine += medicineTemp;
money += moneyTemp;
if (foodTemp > 0)
cout << "You have found " << foodTemp << " food." << endl;
if (woodTemp > 0)
cout << "You have found " << woodTemp << " wood." << endl;
if (medicineTemp > 0)
cout << "You have found " << medicineTemp << " medicine." << endl;
if (bulletsTemp > 0)
cout << "You have found " << bulletsTemp << " bullets." << endl;
if (moneyTemp > 0)
cout << "You have found " << moneyTemp << " money." << endl;
cout << "\nFood: " << food << " Wood: " << wood << " Medicine: " << medicine << " Bullets: " << bullets
<< " Health: " << health << " Money: " << money << endl;
//End of search rooms.
}
//Random encounter chance to see if they can gain additional items.
encounterHurt = 0;
randomEncounter = rand() % 8;
cin.ignore(1, '\n');
if (randomEncounter == 1 && clown == true){
encounterChoice = 1;
cout << "\n\nYou were visited by a gifting clown. \nOn a scale of 0-10, how badly do you want a gift? ";
while (encounterChoice >= 0 && encounterChoice <= 10){
cin >> encounterChoice;
encounterFood = (rand() % 3) + encounterChoice / 2;
encounterWood = (rand() % 3) + encounterChoice / 2;
encounterMedicine = (rand() % 2);
encounterBullets = (rand() % 2);
if (encounterChoice > 0){
encounterHurt = (rand() % 10) - encounterChoice;
if (encounterHurt <= 1){
health--;
cout << "The crazy clown stabs you, but still provides gifts.";
}
}
if (encounterFood > 0) {
cout << "\nYou were provided with " << encounterFood << " food." << endl;
food += encounterFood;
}
if (encounterWood > 0) {
cout << "\nYou were provided with " << encounterWood << " wood." << endl;
wood += encounterWood;
}
if (encounterMedicine > 0) {
cout << "\nYou were provided with " << encounterMedicine << " medicine." << endl;
medicine += encounterMedicine;
}
if (encounterBullets > 0) {
cout << "\nYou were provided with " << encounterBullets << " bullets." << endl;
bullets += encounterBullets;
}
encounterChoice = 11;
}
//Option to attack clown
//
//
}
//End of random encounter from the clown.
//Pause mechanic to prevent the game from cycling.
// pause = 'b';
// while (pause != 'a'){
// cout << "\nEnter a to continue: ";
// cin >> pause;
// }
//End of game message
cout << endl;
if (days == 100){
cout << "You have made it to 100 days. You have beaten this game. You can quit now, or try to see how long you'll last." << endl;
}
//Add day at end of while loop.
days++;
}
cout << "You have died after " << days << " days" << endl;
}
From another Stack Overflow question...
When an error occurs when reading from a stream, an error flag gets
set and no more reading is possible until you clear the error flags.
That's why you get an infinite loop.
cin.clear(); // clears the error flags
// this line discards all the input waiting in the stream
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

I can't find the source of this Segmentation Fault: 11 error

I do realize that there are many posts on this error, but I've looked through several of these and still can't seem to apply them to my own code. I think I'm having some sort of memory error, but I don't know what's causing it or how to resolve it. I've included the segment of code that I think is causing the problem. Here's what the code is supposed to do: I've segmented an image into different colored patches (this works successfully). Now I want the user to be able to click on a patch and have the whole patch be colored light purple. The recoloring should extend to the border of the selected patch, or to the edge of the image, whichever comes first. The function included below takes the x,y coordinate of the mouse click, and the id (determined by color) of the patch the user clicked. It adds the pixel corresponding to this x,y coordinate to a stack, and then sees if there are any pixels with the same id directly adjacent to our pixel which have not yet been recolored. If there are, we call the function again on that pixel. When we find ourselves with no new pixels to move on to, we pop that pixel from the stack and return to the last pixel we haven't exhausted yet. The reason I think this is a memory error is that my function actually works on small colored patches, but freaks out when it has to recolor large patches. Thanks in advance for the help!
void recurse(int x, int y, int runs,int label){
//0 is the 0 row, 0 col --> 1 is the 1st row, 0th col
cout << "in recurse" << endl;
//int label = labels.at<int>(y + x*my_img.rows,0);
cout << "that label " << label << endl;
cout << "vec size " << uncolored.size() << endl;
cout << "runs " << runs << endl;
pixel tempPixel(x,y);
//add this to the list of potential spots if new
cout << "patched current " << patched(x,y) << endl;
if(patched(x,y) == 0){
cout << "trying to add " << endl;
uncolored.push_back(tempPixel);
cout << "added " << endl;
my_img.at<Vec3b>(y,x)[0] = 241;
my_img.at<Vec3b>(y,x)[1] = 217;
my_img.at<Vec3b>(y,x)[2] = 212;
}
//recolor
bool up_good = true;
bool down_good = true;
bool left_good = true;
bool right_good = true;
int up = -1;
int down = -1;
int left = -1;
int right = -1;
//check surroundings
if((y - 1) < 0){
up_good = false;
}
if((y + 1) >= my_img.cols){
down_good = false;
}
if((x - 1)< 0){
left_good = false;
}
if((x + 1) >= my_img.rows){
right_good = false;
}
if(up_good){
up = labels.at<int>((y - 1) + x*my_img.rows,0);
}
if(down_good){
down = labels.at<int>((y + 1) + x*my_img.rows,0);
}
if(left_good){
left = labels.at<int>(y + (x - 1)*my_img.rows,0);
}
if(right_good){
right = labels.at<int>(y + (x + 1)*my_img.rows,0);
}
/*
my_img.at<Vec3b>(y - 1,x)[0] = 241;
my_img.at<Vec3b>(y - 1,x)[1] = 0;
my_img.at<Vec3b>(y - 1,x)[2] = 0;
my_img.at<Vec3b>(y + 1,x)[0] = 241;
my_img.at<Vec3b>(y + 1,x)[1] = 0;
my_img.at<Vec3b>(y + 1,x)[2] = 0;
my_img.at<Vec3b>(y,x - 1)[0] = 241;
my_img.at<Vec3b>(y,x - 1)[1] = 0;
my_img.at<Vec3b>(y,x - 1)[2] = 0;
my_img.at<Vec3b>(y,x + 1)[0] = 241;
my_img.at<Vec3b>(y,x + 1)[1] = 0;
my_img.at<Vec3b>(y,x + 1)[2] = 0;
*/
/*if(runs % 1000 == 0){
cout << "XOX! " << endl;
imshow("My Window",my_img);
cvWaitKey(0);
}*/
//if that is the same label and not yet purple
if(up == label and patched(x,y - 1) == 0 and up_good == true){
//uncolored.push_back(tempPixel);
cout << "leaving" << endl;
recurse(x,y - 1,runs + 1,label);
}
else if(down == label and patched(x,y + 1) == 0 and down_good == true){
//uncolored.push_back(tempPixel);
cout << "leaving" << endl;
recurse(x,y + 1,runs + 1,label);
}
else if(left == label and patched(x - 1,y) == 0 and left_good == true){
//uncolored.push_back(tempPixel);
cout << "leaving" << endl;
recurse(x - 1,y,runs + 1,label);
}
else if(right == label and patched(x + 1,y) == 0 and right_good == true){
//uncolored.push_back(tempPixel);
cout << "leaving" << endl;
recurse(x + 1,y,runs + 1,label);
}
else{
// if not surrounded by anything good
if(uncolored.size() > 1){
cout << " popping " << endl;
//this is no longer a good pixel
uncolored.pop_back();
cout << " popped " << endl;
// return to the last good pixel
cout << " assigning " << endl;
tempPixel = uncolored[uncolored.size() - 1];
cout << " assigned " << tempPixel.x << " " << tempPixel.y << endl;
recurse(tempPixel.x,tempPixel.y,runs + 1,label);
}
else{
cout << " done! " << endl;
}
}
}

How do I exit a loop in C++ without using break?

I'm writing a code to swap integers in an array and I want to know how I can exit a loop without using a break statement and keeping my logic consistent. Here is my code below:
int swapped = 0;
if (arrays[0][first] % 2 == 0)
{
cout << arrays[0][first] << " is odd " << endl;
for (int i = 1; i < arraycount; ++i)
{
for (int j = 1; j < arrays[i][0] + 1; ++j)
{
if (arrays[i][j] % 2 != 0)
{
int temp = arrays[i][j];
cout << "Array #" << 1 << " value " << arrays[0][first] << " swapped with "
<< "Array #" << i << " value " << temp;
arrays[i][j] = arrays[0][first];
arrays[0][first] = temp;
swapped = 1;
break;
}
}
if (swapped) {
break;
}
Use goto [I'll be bashed because of this].
if (arrays[0][first] % 2 == 0)
{
cout << arrays[0][first] << " is odd " << endl;
for (int i = 1; i < arraycount; ++i)
{
for (int j = 1; j < arrays[i][0] + 1; ++j)
{
if (arrays[i][j] % 2 != 0)
{
int temp = arrays[i][j];
cout << "Array #" << 1 << " value "
<< arrays[0][first] << " swapped with "
<< "Array #" << i << " value " << temp;
arrays[i][j] = arrays[0][first];
arrays[0][first] = temp;
goto done;
}
}
done:
something;
for (int i = 1; i < arraycount && !swapped; ++i)
{
for (int j = 1; j < arrays[i][0] + 1 && !swapped; ++j)
{
if(arrays[i][j] % 2 != 0)
int temp = arrays[i][j];
cout << "Array #" << 1 << " value " << arrays[0][first] << " swapped with " << "Array #" << i << " value " << temp;
arrays[i][j] = arrays[0][first];
arrays[0][first] = temp;
swapped = 1;
}
}
}
this will do the same thing you have in inner loop.
Using a Break statement does not necessarily make your codes logic inconsistent and breaks are often useful to improve the readability of your code. But in answer to your question this can be achieved by utilizing while loops and logical boolean operators. A modified version of your code is below, I have tried to modify it as little as possible so you can still see your code within the example. There are a few logical errors in your code that I have left in the example below that you might want to look into. In particular the line below will print "is odd" when in fact the number would be even. If you where wanting to check if the number arrays[0][first] is odd then the following if statement would be needed if (arrays[0][first] % 2 != 0) instead of if (arrays[0][first] % 2 == 0).
Logical Error
if (arrays[0][first] % 2 == 0)
{
cout << arrays[0][first] << " is odd " << endl;
This is the code without using breaks.
bool swapped = true;
if (arrays[0][first] % 2 == 0)
{
cout << arrays[0][first] << " is odd " << endl;
int i = 1;
while ( (i < arraycount) && swapped)
{
int j = 1;
bool if_odd = true;
while ((j < arrays[i][0] + 1) && if_odd)
{
if (arrays[i][j] % 2 != 0)
{
int temp = arrays[i][j];
cout << "Array #" << 1 << " value " << arrays[0][first] << " swapped with "
<< "Array #" << i << " value " << temp;
arrays[i][j] = arrays[0][first];
arrays[0][first] = temp;
swapped = false;
if_odd = false;
}
j++;
}
i++;
}
}

Error 139 Segmentation Fault

I wrote the following code, but can not figure out why I am getting a segmentation fault.
EXTRA CODE:
// A game keeps track of a Pack, and whether it should be shuffled, the score
// and how many points it takes to win, and the Players in the game
struct Game {
Pack pack; // Pack of cards
bool shuffle; // Shuffle the pack after each hand
int score[NUM_PARTNERSHIPS]; // Score for each partnership
int points_to_win; // Number of points to win the game
Player players[NUM_PLAYERS]; // Players in this game, in order around table
};
Player* Player_to_left(int playerindex, Game *game_ptr){
int index = (playerindex + 1)%4;
Player *player_ptr = &(game_ptr->players[index]);
return player_ptr;
}
static int Get_player_index(Player *player_ptr, Game *game_ptr){
Player *one_player = &(game_ptr->players[0]);
if(strcmp(player_ptr->name,one_player->name) == 0)
return 0;
Player *two_player = &(game_ptr->players[1]);
if(strcmp(player_ptr->name,two_player->name) == 0)
return 1;
Player *three_player = &(game_ptr->players[2]);
if(strcmp(player_ptr->name,three_player->name) == 0)
return 2;
Player *four_player = &(game_ptr->players[3]);
if(strcmp(player_ptr->name,four_player->name) == 0)
return 3;
return 0;
}
THE MAIN PROBLEM:
Player* Play_trick(Game *game_ptr, int leadindex, Player *lead_ptr, Suit trump){
Card cards[4] = {Player_lead_card(lead_ptr, trump)};
Card_print(cards); cout << " led by " << lead_ptr->name << endl;
int second = (leadindex + 1)%4;
Player *two_player = Player_to_left(leadindex, game_ptr);
cards[1] = Player_lead_card(two_player, trump);
if(second >= 0 && second <= 4)
Card_print(cards+1); cout << " led by " << two_player->name << endl;
int third = (second + 1)%4;
Player *third_player = Player_to_left(second, game_ptr);
cards[2] = Player_lead_card(third_player, trump);
if(third >= 0 && third <= 4)
Card_print(cards+2); cout << " led by " << third_player->name << endl;
int fourth = (third + 1)%4;
Player *fourth_player = Player_to_left(third, game_ptr);
cards[3] = Player_lead_card(fourth_player, trump);
if(fourth >= 0 && fourth <=4)
Card_print(cards+3); cout << " led by " << fourth_player->name << endl;
Card *highest = cards;
int itemp = 0;
for(int i = 1; i < 4; ++i){
if(Card_compare(cards, (cards + i), trump) < 0){
highest = (cards + i);
itemp = i;
}
}
if(itemp == 0){
cout << lead_ptr->name << " takes the trick" << endl;
return lead_ptr;
}
if(itemp == 1){
cout << two_player->name << " takes the trick" << endl;
return two_player;
}
if(itemp == 2){
cout << third_player->name << " takes the trick" << endl;
return third_player;
}
if(itemp == 3){
cout << fourth_player->name << " takes the trick" << endl;
return fourth_player;
}
return fourth_player;
}

Seg fault from attempting to access out of range array, unknown to why

I am working on a school project (I was allowed to do a simulation in C++ for my Science Fair project) and everything is going pretty ok (besides another bug that I had an issue with) until now. In order to fully understand what I am doing, I suggest that you take a quick glance at this page.
Okay. Below is my code. When you try to run it, you can clearly see that some bots' x and y cordinates are in the negatives, which shouldn't be happening. I have triple checked all the operations and everything looks fine to me. I used this to help me understand X and Y locations relative in arrays. Is there any clear issue of my mistake? I am still getting used to multidimensional arrays, so please take that into consideration. Also, I am aware that most of it is highly inefficient; cleaning it up will be a project itself. Thank you and Happy Holidays!
*My issues are coming from the moveBot functions, which are towards the bottom. It didn't seem right to have you read over unnecessary parts.
Updated Code:
// NANORG SIMULATION
// CREATED BY JACOB HARTMANN FOR THE SCIENCE FAIR (2013)
// CODED IN C++
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <cstdlib>
#include "bot.h"
using namespace std;
signed int map [40][70]; //2D array x first, then y
int mapBot [40][70]; //If bot is there, 1. If not, 0 This array keeps track if there is a bot in a location
signed int currentTick = 0; //Signed just in case something goes wrong and goes into the -s
int maxTick = 1000000; //Should always stay at 1mil
signed int totalEnergy = 0; //For some reason, when I add this here, everything breaks.
Bot bots[50];
void setupMap();
void tick();
void updateTickOutput();
void outputMapValue(int x, int y);
void assignBotID();
void setupBot();
void moveBot();
void manualMoveBot(int botID);
void mutateBot(int botID, int level, int sT);
void ckLoc(int botIdent);
void reassignLoc(int botID);
void gatherEnergy(int botID);
int main() {
cout << " ----------------------" << endl;
cout << " NANORG Simulation V1.3.1" << endl;
cout << "Created in C++ by Jacob Hartmann" << endl;
cout << " ----------------------" << endl << endl;
srand (time(NULL));
cout << "Setting up map.. (Step 1)" <<endl;
setupMap();
cout << "Assigning botIDs.. (Step 2)" << endl;
assignBotID();
cout << "Setting up bots.. (Step 3)" << endl;
setupBot();
cout << "Starting ticks.. (Step 4)" << endl;
tick();
// outputMapValue(5,5);
// mutateBot(5, 2); //Just to test
/* cout << endl << "X before: " << bots[5].x_cord << " Y before: " << bots[5].y_cord << endl;
moveBot(5);
cout << "X after: " << bots[5].x_cord << " Y after: " << bots[5].y_cord << endl;
cout << "Energy before: " << bots[5].energy <<endl;
gatherEnergy(5);
cout << "Energy after: " << bots[5].energy << endl; */ //DEBUG
return 0;
}
void setupMap(){
// srand (time(NULL)); //Not a good idea to put it here
for(int i = 0; i < 40; i++){
for(int j = 0; j < 70; j++){ // We add one extra (70) so it fills the entire array. Same for above
map[i][j] = rand() % 2 + 1; // 1==normal 2==toxic
}
}
// outputMapValue(5,4); //Debugging purposes
// outputMapValue(7,9);
cout << "Map setup - \033[0;32mSuccessful" << "\033[0m" << endl;
}
void outputMapValue(int x, int y){
cout << "The chunk value at (" << x+1 << ", " << y+1 << ") is: ";
cout << map[x][y]; //Outputting the value of (x,y)
if(map[x][y]==1){ //If (x,y) is == 1, the chunk is fine to eat
cout << " | Chunk is not toxic." << endl;
}
if(map[x][y]==2){
cout << " | Chunk is toxic." << endl;
}
}
void updateTickOutput() {
//cout << "Map Size (x,y): " << " " << mapsizeX << "," << mapsizeY << endl; This function used to just refresh everything, including map size, which really isn't needed. cout << "Current Tick: " << currentTick << " " << "Max Tick: " << maxTick << endl; //Just outputting currentTick and maxTick
cout << "Score: " << totalEnergy << endl;
}
void tick() {
while(true){
if(currentTick <= maxTick){
currentTick += 1;
moveBot();
/* if(currentTick >= 900000){ //If currentTick is over 900,000: we will begin to output individual ticks. Anything less and we get a seg fault.
updateTickOutput(); //See above
}*/
// cout << "tick!"; This was for debugging, before I made the updateTickOutput() function to make sure that the program actually ticked
}
else if(currentTick == maxTick){
cout << endl << "Done!" << endl; //Report that we are finished with the simulation.
// assignBotID(); //Make sure every bot has the proper ID. Moved to main()
break; //Kill the loop
}
// updateTickOutput(); //No real need for this, anymore.
}
}
void setupBot(){
srand(time(NULL));
for(int botNumber=0;botNumber <= 50; botNumber++){
// cout << "debug (botNumber): " << botNumber << endl; //Debug feature
bots[botNumber].x_cord = rand() % 39 + 1;
// cout << "debug (bot x cord): " << bots[botNumber].x_cord << endl; //Debug feature
int bufferX = bots[botNumber].x_cord;
bots[botNumber].y_cord = rand() % 69 + 1;
// cout << "debug (bot y cord): " << bots[botNumber].y_cord << endl; //Debug feature
int bufferY = bots[botNumber].y_cord;
if(mapBot[bufferX][bufferY] == 1){
cout << endl <<"A bot already is here!" << endl;
reassignLoc(botNumber);
}
else{
mapBot[bufferX][bufferY] = 1; //Take the bot's cords and make sure everyone knows that a bot is there.
// cout<< "debug (map location):"<<mapBot[bufferX][bufferY] << endl ; Just a nice debug feature
}
// if(botNumber==5){
// cout << "bot 5 assigned"; //I broke this entire function a while back and I used this to test if I was assigning bots correctly.
// }
}
/* cout << endl << "X: " << bots[5].x_cord+1 << endl; //Just some debugging stuff below
cout << "Y: " << bots[5].y_cord+1 << endl;
// cout << "The value at " << mapBot[bots[5].x_cord]<<","<< mapBot[bots[5].y_cord]<<" is: " << mapBot[bots[5].x_cord][bots[5].y_cord]; //This is a very messed up debug feature, but it still works.
cout << endl << "X: " << bots[6].x_cord+1 << endl;
cout << "Y: " << bots[6].y_cord+1 << endl;
cout << mapBot[6][6];
*/
cout << "Bot setup - \033[0;32mSuccessful" << "\033[0m" << endl;
}
void assignBotID(){
for(int i = 0; i < 50; ++i){
bots[i].id = i + 1;
}
/* int botNumber = 0;
string botName = "Bot";
string finalName;
string buffer;
while(botNumber <50){
if(botNumber < 50){
botNumber = botNumber + 1;
buffer = to_string(botNumber);
finalName = botName + buffer;
//finalName.id = botNumber; A very very broken line.
bots[botNumber].id = botNumber;
// cout << finalName << ":"<< bots[botNumber].id << endl; A super awesome debugging output to make sure the bot's id is correct
}
else if((botNumber = 51)){ //Redundancy :)
break;
}
}*/
}
void mutateBot(int botID, int level, int sT){
if((sT=2)){
bots[botID].mutationLevel = bots[botID].mutationLevel + level;
}
else if((sT=1)){
bots[botID].mutationLevel = bots[botID].mutationLevel - level;
}
// cout << botID << ":" << bots[botID].mutationLevel << endl; //Just a quick debugging feature to make sure it worked
}
void ckLoc(int botIdent){
int bufferX;
int bufferY;
bufferX = bots[botIdent].x_cord; //Just set the buffers. Uses a bit more memory, but that is okay.
bufferY = bots[botIdent].y_cord;
// cout << bufferX << endl << bufferY;
if(mapBot[bufferX][bufferY] ==1){
cout << "Bot lives here!";
reassignLoc(botIdent);
}
}
void reassignLoc(int botID){
bots[botID].x_cord = rand() % 39 + 1;
bots[botID].y_cord = rand() % 69 + 1;
ckLoc(botID);
}
void moveBot(){
for(int botID=1;botID<=50;botID++){
int direction = 0;
// int bufX = bots[botID].x_cord;
// int bufY = bots[botID].y_cord;
direction = rand() % 4 + 1;
if(direction == 1){ //NORTH
if(bots[botID].y_cord==0 || mapBot[bots[botID].x_cord][bots[botID].y_cord=-1] == 1){
//cout << "error moving bot - N ";
manualMoveBot(botID);
}
else{
//cout << "BufferY: " << bufferY;
bots[botID].y_cord -= 1;
gatherEnergy(botID);
}
}
else if(direction == 2){ //EAST
if(bots[botID].x_cord == 39 || mapBot[bots[botID].x_cord+=1][bots[botID].y_cord] == 1){
//cout << "error moving bot - E";
manualMoveBot(botID);
}
else{
bots[botID].x_cord += 1;
gatherEnergy(botID);
}
}
else if(direction == 3){ //SOUTH
if(bots[botID].y_cord == 69 || mapBot[bots[botID].x_cord][bots[botID].y_cord+=1] == 1){
//cout << "error moving bot - S ";
manualMoveBot(botID);
}
else{
bots[botID].y_cord += 1;
gatherEnergy(botID);
}
}
else if(direction == 4){ //WEST
if(bots[botID].x_cord == 0 or mapBot[bots[botID].x_cord=-1][bots[botID].y_cord] == 1){
//cout << "error moving bot - W";
manualMoveBot(botID);
}
else{
bots[botID].x_cord -= 1;
gatherEnergy(botID);
}
}
// gatherEnergy(botID); //Moved this to indivdual (spelling) stuff above. Just in case :)
// cout << endl << "Direction: " << direction << endl; //Debug
}
}
void manualMoveBot(int botID){
int direction = 0;
// int bufX = bots[botID].x_cord;
// int bufY = bots[botID].y_cord;
direction = rand() % 4 + 1;
if(direction == 1){ //NORTH
if(bots[botID].y_cord==0 || mapBot[bots[botID].x_cord][bots[botID].y_cord-1] == 1){
//cout << "error moving bot - N ";
manualMoveBot(botID);
}
else{
//cout << "BufferY: " << bufferY;
bots[botID].y_cord -= 1;
gatherEnergy(botID);
}
}
else if(direction == 2){ //EAST
if(bots[botID].x_cord == 39 || mapBot[bots[botID].x_cord+1][bots[botID].y_cord] == 1){
//cout << "error moving bot - E";
manualMoveBot(botID);
}
else{
bots[botID].x_cord += 1;
gatherEnergy(botID);
}
}
else if(direction == 3){ //SOUTH
if(bots[botID].y_cord == 69 || mapBot[bots[botID].x_cord][bots[botID].y_cord+1] == 1){
//cout << "error moving bot - S ";
manualMoveBot(botID);
}
else{
bots[botID].y_cord -= 1;
gatherEnergy(botID);
}
}
else if(direction == 4){ //WEST
if(bots[botID].x_cord == 0 or mapBot[bots[botID].x_cord-1][bots[botID].y_cord] == 1){
//cout << "error moving bot - W";
manualMoveBot(botID);
}
else{
bots[botID].x_cord += 1;
gatherEnergy(botID);
}
}
}
void gatherEnergy(int botID){
// int mV = map[bufferX][bufferY]; //Eeeeh, doesn't work here
int x = bots[botID].x_cord;
int y = bots[botID].y_cord;
// cout << "id: " << botID << endl;
// cout << "x: " << x;
// cout << endl << "y: " << y << endl;
if(1==map[x][y]){ //Good chunk
bots[botID].energy += 2000;
totalEnergy += 2000;
// cout << totalEnergy << endl; //Debug
}
else if(2==map[x][y]){ //Bad chunk (toxic)
mutateBot(botID, 1, 2);
}
}
You have several problems.
The main one is that indices of array:
so for Bot bots[50]; valid indices are [0; 49].
For map, according to contest it should be int mapBot [40][70];
so you may access element starting from mapBot[0][0] to mapBot[39][69].
You confound = and == in some comparison.
= does an assignment when == do a comparison.
I see you add extra parenthesis to remove a warning.
You have to read/understand more carefully warning messages.
so else if((currentTick = maxTick)){ in tick for example, should be else if (currentTick == maxTick) {.
Same in mutateBot...
In AssigningBotID, you increment index before accessing the array
and do redundant checks. following is enough:
void assignBotID() {
for (int i = 0; i < 50; ++i) {
bots[i].id = i /* + 1 */; // uncomment if id should be [1; 50]
// A super awesome debugging output to make sure the bot's id is correct
//std::cout << "Bot" << i << ":"<< bots[i].id << endl;
}
}
in manualMoveBot your test may change the position, since you use +=:
mapBot[bots[botID].x_cord += 1][bots[botID].y_cord] == 1
should be mapBot[bots[botID].x_cord + 1][bots[botID].y_cord] == 1
Your logic forget to update mapBot: the old place should be set to 0,
the new place should be set to 1.
Note that during initialization, it is not always set neither...
EDIT:
You should only call srand (time(NULL)); once (the one in main())
setupBot() should be something like (and so reassignLoc and ckLoc may be removed):
void setupBot() {
for (int i = 0; i < 50; ++i) {
int x, y;
do {
x = rand() % 40; // [0; 39]
y = rand() % 70; // [0; 69]
while (mapBot[x][y] == 1);
bots[i].x_cord = x;
bots[i].y_cord = y;
mapBot[x][y] = 1;
}
cout << "Bot setup - \033[0;32mSuccessful" << "\033[0m" << endl;
}
mutateBot has not be fixed: replace = by == for comparison.
void moveBot() {
for (int i = 0; i < 50; ++i) {
manualMoveBot(botID);
}
}
void manualMoveBot(int botID) {
const int oldX = bots[botID].x_cord;
const int oldY = bots[botID].y_cord;
int newX = oldX;
int newY = oldY;
int direction = rand() % 4 + 1;
if (direction == 1) { // NORTH
newY = oldY - 1;
} else if (direction == 2) { // EAST
newX = oldX + 1;
} else if (direction == 3) { // SOUTH
newY = oldY + 1;
} else if (direction == 4) { // WEST
newX = oldX - 1;
}
if (newX < 0 || 40 <= newX
|| newY < 0 || 70 <= newY
|| mapBot[newX][newY] == 1) {
cout << "error moving bot";
#if 0
// if this code is active, we may have infinite loop
// when bot is completely surrounded.
manualMoveBot(int botID);
#endif
return;
}
bots[botID].x_cord = newX;
bots[botID].y_cord = newY;
mapBot[newX][newY] = 1;
mapBot[oldX][oldY] = 0;
gatherEnergy(botID);
}