How to generate random fruit for C++ 2D Snake game - c++

I am having trouble generating random fruit for my Snake game. (I am very new to programming and this is my first language).
When I run my code all works fine so far (except from some minor issues). I'm using Visual Studio C++ in an empty project. Here is my full code (I'm not displaying my #includes):
using namespace std;
bool gameOver = false;
int gameScore;
int fruitX;
int fruitY;
string bGameW = "###########";
string bGameL = "# #\n";
class gameStart
{
public:
void start()
{
cout << bGameW;
cout << bGameL;
cout << bGameL;
cout << bGameL;
cout << bGameL;
cout << bGameL;
cout << bGameL;
cout << bGameL;
cout << bGameL;
cout << bGameW;
}
void generateFruit()
{
srand(time(NULL));
fruitX = rand() % 21;
fruitY = rand() % 21;
bGameW.insert(fruitX, "F");
bGameL.insert(fruitY, "F");
}
void clearscreen()
{
system("cls");
}
private:
};
int main ()
{
gameStart gameObj;
gameObj.generateFruit();
gameObj.clearscreen();
gameObj.start();
return 0;
}
To generate the random the random fruit for the string. I use a string to make the game board, then I create random values for the fruit (X and Y) then I append them into my game board.
But the issue is: I want to make only one fruit with a random X and Y and append it into my game board to display it. But my current code is this:
bGameW.insert(fruitX, "F");
bGameL.insert(fruitY, "F");
This code makes 2 fruits with 1 at a random X and 1 at a random Y. I want to turn these 2 fruits into 1 fruit, with 1 random X and 1 random Y.

There's a whole host of things worth commenting on. Here goes:
bGameW has no \n
bGameW and bGameL are 10 and 11 characters long (both with be 11 after you add the other \n). Your RNG is generating numbers between 0 and 20... if you ever generate a number > 11 (and you will), Bad Things will happen (and probably have).
Snake games like this let you eat multiple fruit, which is why people brought up the whole "don't call srand more than once" thing, as you'll be calling generate fruit every time someone eats the old one. OTOH, that mostly removes the "calling srand multiple times per second can return the same value" problem too.
Rather than writing out those two lines, bGameW and bGameL, I recommend that you build a character array that holds your entire game display (NOT your game state, just the display of that state). You then clear it and redraw it every move. You'll need a game area, walls, something that tracks where your snake is, and the current fruit. You then 'render' all these things into your character-array-game-display. Don't forget to clear it every time you redraw it or you'll get all kinds of problems.
Rather than redrawing everything, you could use something like the "curses" library to clear and redraw specific character locations on the screen. You'd then face problems 'clearing' and redrawing different spots.
As far as programming style goes, you will find that so called "magic numbers" (like 21 in your case) can lead to bugs. What people generally do instead is to define a const with the appropriate value, and then define things in terms of that const.
// constants are often named in ALL_UPPER_CASE_WITH_UNDERSCORES
// to help you recognize them.
const int PLAY_AREA_HEIGHT = 10;
const int PLAY_AREA_WIDTH = 10;
const char EMPTY_PLAY_SQUARE = '.';
// have you learned about 2d arrays yet? Arrays at all?
char playAreaDisplay[PLAY_AREA_HEIGHT][PLAY_AREA_WIDTH];
void wipePlayArea()
{
for (int heightIdx = 0; heightIdx < PLAY_AREA_HEIGHT; ++heightIdx)
{
for (int widthIdx = 0; widthIdx < PLAY_AREA_WIDTH; ++widthIdx)
{
playAreaDisplay[heightIdx][widthIdx] = EMPTY_PLAY_SQUARE;
}
}
}

Related

How can I 'pan out' (make screen bytes smaller) of the console screen to render 2d pyramids larger?

I am using Windows 10 with code blocks to compile my code.
I wonder WHY you want to do that. This seems to be a typical homework assignment problem for practising loops and logic. That usually is restricted to numbers easily fitting on a console. Could you elaborate what causes the need to go beyond say a size of 30? – Yunnosch 10 hours ago
#Yunnosch For pure hypothetical and experimental reasons. I essentially have a dream I could write a program that renders massive 2d pyramids on a console screen, and maybe create some game out of it. I was hoping I could figure out a way to 'pan out' of the console screen thus making the screen bytes smaller. Somebody has to know more than me, and can lead me in the right direction to accomplishing this '2d pyramid rendering' program. Thanks in advance! – Fibonacci 3 mins ago
My goal is to be able to render massive pyramid structures onto a console output screen. The code here simply asks for a number of rows and prints out a pyramid. ex. drawPyramid(50);
#include <iostream> // include iostream
using namespace std; // include std
// Draw pyramid function here
void drawPyramid(int rows)
{
// initializes space and creates for loop to keep track of rows, I and k
int space;
for(int i = 1, k = 0; i <= rows; ++i, k=0)
{
// draws spaces required
for(space = 1; space <= rows-i; ++space)
{
cout << " ";
}
// draws matter
while(k != 2*i-1)
{
cout << "* ";
++k;
}
//prints new line based on rows
cout << endl;
}
}
//driver program
int main()
{
bool fTrue = false;
// loops until user presses '0'
while(!fTrue)
{
cout << "Press (0) to quit...\n";
int i,rows;
cout << "Enter number of rows: \n";
cin >> rows;
drawPyramid(rows); // draw function called
if(rows == 0)
{
fTrue = true;
}
}
return 0;
}
Output:
While the program works great I'd like to be able to pass in bigger values such as drawPyramid(500); or drawPyramid(1000); anything above the value 50 produces results like so.
Results:
Hopefully you can understand what I am trying to ask. I want to be able to 'pan out' and move the asterisks closer together so that I can pass in larger input values into the drawPyramid() function... Thanks in advance!
I am using Windows 10 with code blocks to compile my code.

Displaying content with a for loop

I'm trying to write a program that randomly selects three items from an array that contains five different fruits or vegetables and then display this randomly selected content to the user. Now I'm having trouble understanding why my output is not consistent because sometimes when I run it I'll get something like this:
This bundle contains the following:
Broccoli
With the first two items missing and sometimes I'll get this:
This bundle contains the following:
Tomato
Tomato
Tomato
This is the portion of the code I'm currently having trouble with:
void BoxOfProduce::output() {
cout << "This bundle contains the following: " << endl;
// Use this so it will be truly random
srand(time(0));
for (int f = 0; f < 3; f++) {
// Here were making the random number
int boxee = rand() % 5;
// Adding the content to the box
Box[f] = Box[boxee];
// Now were calling on the function to display the content
displayWord(boxee);
} // End of for loop
} // End of output()
void BoxOfProduce::displayWord(int boxee) {
cout << Box[boxee] << endl;
}
int main() {
BoxOfProduce b1;
b1.input();
b1.output();
Can someone help me understand why i'm getting this output? Thanks!
Don't do it like you are doing it :)
Like #John3136 pointed out, you are messing up your Box variable..
void BoxOfProduce::output()
{
srand(time(NULL)); //keep in mind that this is NOT entirely random!
int boxee = rand() % 5;
int i = 0;
while(i<5)
{
boxee = rand() % 5;
cout<<Box[boxee]<<endl; //this line might be wrong, my point is to print element of your array with boxee index
i++;
}
}
Box[f] = Box[boxee]; is changing the contents of the "Box" you are picking things out of. If the first random number is 3, item 3 gets copied to item 0, so now you have twice as much chance of getting that item the next time through the loop...
You are overwriting the elements of your array with randomly selected item.
Box[f] = Box[boxee];
For eg: If boxee=1 and f=0, it will overwrite element at index 0 with 1, while at same time element at index 1 is same leaving two copies of same item.
Use :std:random_shuffle instead.

C++ After Function Call and Function Completion, Game Crashes Entirely

I've been having an issue with a game I've been making in my C++ game programming class for school. For some reason, after calling a function which I'm using to manage the inventory based stuff, the function seems to complete and work (I think this because I put in cout commands at the end of it and they printed correctly, also the function runs twice in a row, and they both run), my entire game crashes and doesn't reach the next line. I tried commenting out all the code in the function and it still crashed. I commented out the function calls and it worked, but I still can't tell what is wrong with it. I'll put the code for the function and the section were I make the calls:
string inventoryFunction(int h, string ab)
{
if(h == 1)
inventory.push_back(ab);
else
if(h == 2)
{
for(int i=0; i < inventory.size(); i++)
{
if(inventory[i] == ab)
inventory[i].erase();
}
}
else
if(h == 3)
{
cout << inventory[0];
for(int i=1; i < inventory.size(); i++)
cout << ", " << inventory[i];
}
}
The function call:
if(answer.find("village") != string::npos)
{
cout << endl;
cout << "While looking around your village,\nyou found a stone sword and a cracked wooden shield!" << endl;
inventoryFunction(1, "stone sword");
inventoryFunction(1, "cracked wooden shield");
cout << "Would you like to set off on your adventure now?" << endl;
cin >> answer2;
capitalizeLower(answer2);
Not sure there's anything there likely to cause a crash, my advice would be to single-step your code in the debugger to see where it's falling over. It's quite possible the bug is somewhere totally different and it's just being exacerbated by the function calls modifying the vector.
That's the nature of bugs unfortunately, you can never really tell where they're actually coming from without looking closely :-)
However, there are a couple of issues with the code that I'd like to point out.
First, with regard to:
inventory[i].erase();
That doesn't do what you think it does. inventory[i] is the string inside your vector so it's simply erasing the string contents.
If you want to remove the string from the vector, you need something like:
inventory.erase (inventory.begin() + i);
Second, I'd tend to have three separate functions for addToInventory, removeFromInventory and listInventory.
It seems a little ... unintuitive ... to have to remember the magic values for h to achieve what you want to do, and there's no real commonality in the three use cases other than access to the inventory vector (and that's not really reason enough to combine them into the same member function).
On top of that, your function appears to be returning a string but you have no actual return statements and, in fact, none of the three use cases of your function require anything to be passed back.
The signature is better off as:
void inventoryFunction(int h, string ab)
In terms of the second and third points above, I'd probably start with something like:
void addToInventory (string item) {
inventory.push_back(ab);
}
void removeFromInventory (string item) {
for (int i = 0; i < inventory.size(); i++) {
if (inventory[i] == ab) {
inventory.erase (inventory.begin() + i);
break;
}
}
void listInventory () {
cout << inventory[0];
for (int i = 1; i < inventory.size(); i++)
cout << ", " << inventory[i];
}
You may also want to look into using iterators exclusively for the second and third functions rather than manually iterating over the collection with i.
It'll save you some code and be more "C++ic", a C++ version of the "Pythonic" concept, a meme that I hope will catch on and make me famous :-)
So by changing the inventoryFunction to a void function like #Retired Ninja said, the crash has stopped occurring and now the program is working great.
Also, #paxdiablo pointed out that I was using the inventory[i].erase() thing incorrectly, so thanks a bunch to him, because now I won't have to come back on here later to try to fix that :D
string inventoryFunction(int h, string ab)
should return a string but does not have any return statements. Of course it works, after you change it to a void function, which correctly does not return anything. Interesting is, that you are able co compile this code without an error - normally a compiler would show you this problem.

C++ selecting a number of random items without repeating

Write a program that randomly selects from a bag of eight objects.
Each object can be red, blue, orange, or green, and it can be a ball or a cube.
Assume that the bag contains one object for each combination (one red ball, one
red cube, one orange ball, one orange cube, and so on). Write code similar to
Example 5.3, using two string arrays—one to identify colors and the other to
identify shapes.
I am trying to write a program to carry out the above exercise - the problem I am having is the same object can be selected more than once each time.
This is the code so far
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
using namespace std;
int rand_0toN1(int n);
void choose_object();
char *colour[4] =
{"Red", "Blue", "Orange", "Green"};
char *object[2] =
{"Ball", "Cube"};
int main()
{
int n, i;
srand(time(NULL)); // Set seed for randomizing.
while (1) {
cout << "Enter no. of objects to draw ";
cout << "(0 to exit): ";
cin >> n;
if (n == 0)
break;
for (i = 1; i <= n; i++)
choose_object();
}
return 0;
}
void choose_object() {
int c; // Random index (0 thru 4) into
// colours array
int o; // Random index (0 thru 2) into
// object array
c = rand_0toN1(4);
o = rand_0toN1(2);
cout << colour[c] << "," << object[o] << endl;
}
int rand_0toN1(int n) {
return rand() % n;
}
Let's try to solve this by making a real world analogy:
Let's say you have a massive jar of marbles, of the colors listed above. It's so massive (infinite size!) that you always have the same chance to draw a marble of a given color, always 1/4 each time.
How would you do this in real life? Would you just keep picking randomly, chucking the marble away as you draw it? Or would you maybe keep a little list of things you've drawn already?
Or maybe you only have one of each in the jar... You wouldn't put it back in would you? Because that's kind of what you're doing here.
Each of these thought paths will lead you to a good solution. I don't want to provide a code or anything because this kind of assignment is one that teaches you how to think like a computer.
Since this is homework, I'm not going to give an exact answer, but describe what you could do:
Keep a list of objects you've already chosen.
After you choose an object, compare that object to the list of objects you've already chosen. If it's in the list, choose another object. If it's not in the list, add it to the list.
Make sure that you don't try to choose more than 8 objects, or else you'll end up in an infinite loop in part 2.
These would go in your choose_object() subroutine. You could do it in a while() loop, something like:
int seen_before = 0;
while(!seen_before) {
pick your random numbers
if(numbers not in list) {
add to list
break
}
}

C+ program involving functions...Please help me

I am having a hard time with two functions. Here are the project instructions:
Assignment:
Write a program which keeps track of the number of roaches in two adjacent houses for a number of weeks. The count of the roaches in the houses will be determined by the following:
The initial count of roaches for each house is a random number between 10 and 100.
Each week, the number of roaches increases by 30%.
The two houses share a wall, through which the roaches may migrate from one to the other. In a given week, if one house has more roaches than the other, roaches from the house with the higher population migrate to the house with the lower population. Specifically, 30% of the difference (rounded down) in population migrates.
Every four weeks, one of the houses is visited by an exterminator, resulting in a 90% reduction (rounded down) in the number of roaches in that house.
Here's my code:
#include <iostream>
#include <cmath>
using namespace std;
int house, increase, roaches, moreRoaches, fewerRoaches, filthyBeasts, change; // My variables for my four functions
int initialCount(int house);
int weeklyIncrease(int increase);
double roachesMigration(int moreRoaches, int fewerRoaches, int change);
int exterminationTime (int filthyBeasts);
// My four function prototypes
int main()
{
int houseA, houseB;
houseA = initialCount(houseA); //Initializing the initial count of House A.
houseB = initialCount(houseB); //Initializing the initial count of House B.
int week = 0;
for (week = 0; week < 11; week++) // My for loop iterating up to 11 weeks.
{
houseA = weeklyIncrease(houseA);
houseB = weeklyIncrease(houseB);
cout << "For week " << week << ", the total number of roaches in House A is " << houseA << endl;
cout << "For week " << week << ", the total number of roaches in House B is " << houseB << endl;
if((houseA > houseB)) // Migration option 1
{
roachesMigration(moreRoaches, fewerRoaches, change);
}
else if((houseB > houseA)) // Migration option 2
{
roachesMigration(moreRoaches, fewerRoaches, change);
}
if ((week + 1) % 4 == 0) // It's extermination time!
{
if ((rand() % 2) == 0) // Get a random number between 0 and 1.
{
houseB = exterminationTime(houseB);
}
else
{
houseA = exterminationTime(houseA);
}
}
}
return 0;
}
int initialCount(int house) // Initializing both houses to random numbers between 10 and 100.
{
int num;
num = (rand() % 91) + 10;
return num;
}
int weeklyIncrease(int increaseHouses) // Increasing the roaches in both houses by 30% weekly.
{
int increase = 0;
increase = (increaseHouses * .3) + increaseHouses;
return increase;
}
double roachesMigration(int moreRoaches, int fewerRoaches, int change)
{
more -= change;
fewer += change;
change = ((more - fewer) * .3);
return change;
}
int exterminationTime(int filthyBeasts) // Getting rid of the filthy little beasts!
{
filthyBeasts = (filthyBeasts * .1);
return filthyBeasts;
}
The issues are with the migration and extermination functions. My code runs fine, but at weeks 4 and 8, the randomly selected house should get exterminated, and the number of roaches in that house should be 90% less than the previous week. What do you guys think I should do to correct these issues? I really need all the help I can get!
Regarding this line:
roachesMigration(change);
change is not declared in your main function, hence the error. Also, roachesMigration function expects 3 parameters and not 1.
The variable change is not a global variable, but appears inside main (so it has no meaning inside main).
Your roachesMigration fonction is declared with three formal arguments (without default values), but you use it with one actual argument.
Ask your compiler to give you all the warnings and to produce debugging information (g++ -Wall -g on Linux). Improve the code till you get no warnings.
Learn to use a debugger (e.g. gdb on Linux).
Have fun.
Depending on the instructor, you will get zero marks for this code, even if you can get it to work perfectly! This is because you have not used any object orientated design in building your code. In C++, that means classes.
What sort of object do you need for this problem. A house!
What sort of attribute should your house have? Roaches!
So something like this:
class cHouse
{
int MyRoachCount;
...
};
If you start fresh, like this, you will find things start to fall neatly into place.
One possible way to handle the migration is like this pseudocode:
// compute size of migration
count = migration(houseA, houseB)
if (houseA < houseB)
add count to houseA
subtract count from houseB
else
add count to houseB
subtract count from houseA