How to randomize the creation of objects of different classes? c++ - c++

I'm doing project with classes in c++ which consists of a car that avoids obstacles on a board. I want to randomize the appearance of the object of classes EnemiesCar, Nail, Hole (the last two are subclasses of the first). The problem is that when i generate random number, it change too fast and the object that had appeared then disappears (the objects on the board come out intermittently between other object because the random number changes too fast). How can I fix this problem? Are there other solution for randomize objects of class? (I tried to do this function in Game::randomAppear(EnemiesCar &myEn, Nail &myNe, Hole &myHo), below I leave only the class EnemiesCar because its subclasses are similar).
Game.cpp
#include "Game.h"
#include "Nail.h"
#include "EnemiesCar.h"
#include "Car.h"
#include "Hole.h"
#include <windows.h>
#include <iostream>
#include <thread>
#include <stdlib.h> /* srand, rand */
#include <ctime>
using namespace std;
Game::Game(){
running = true;
counter = 100;
maxScore = 0;
maxLevel = 1;
timeS = 100.0;
level = 1;
levelUp = 1000;
levelDown = 0;
}
void Game::gotoXY(int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void Game::resetBoard()
{
for(int j=0;j<20;j++){
for(int i=1;i<20;i++){
matrix[i][j]=0;
}
}
}
void Game::createTab()
{
for(int j=0;j<20;j++){
for(int i=0;i<21;i++){
if(i==0 || i==20){
gotoXY(i,j);
cout<<"b";
}else if(j == 19){
gotoXY(i,j);
cout<<"*";
}else if(matrix[i][j]==1){
gotoXY(i,j);
cout<<"m";
}else if(matrix[i][j]==2){
gotoXY(i,j);
cout<<"e";
}else if(matrix[i][j]==3){
gotoXY(i,j);
cout<<"c";
}else if(matrix[i][j]==4){
gotoXY(i,j);
cout<<"h";
}else {
gotoXY(i,j);
cout<<" ";
}
}
}
}
void Game::checkSamePosition(EnemiesCar EN, Nail NE)
{
if(NE.xPos == EN.xPos && NE.yPos == EN.yPos){
NE.xPos = NE.xPos + 2;
}
}
int Game::checkMaxScore()
{
if(maxScore < counter){
maxScore = counter;
}
return maxScore;
}
int Game::checkMaxLevel()
{
if(maxLevel < level){
maxLevel = level;
}
return maxLevel;
}
void Game::TabLevelUp()
{
system("cls");
gotoXY(5, 5);
cout << "Next Level" << endl;
gotoXY(5, 7);
cout << "Level: " << level;
}
void Game::TabLevelDown()
{
system("cls");
gotoXY(5, 5);
cout << "Previous Level" << endl;
gotoXY(5, 7);
cout << "Level: " << level;
}
void Game::gameLevels(Car &car)
{
if(counter == levelUp){
level++;
TabLevelUp();
Sleep(5000);
gotoXY(40, 9);
cout << "level " << level;
levelDown = levelUp;
levelUp = levelUp + 1000;
gotoXY(40, 10);
cout << "next " << levelUp;
if(timeS >= 40){
double update = timeS - 20.0;
timeS = update;
gotoXY(40, 7);
cout << "tmpIf " << timeS;
Sleep(update);
}else if(timeS == 20 || timeS == 30){
double update = timeS - 10.0;
timeS = update;
gotoXY(40, 7);
cout << "tmpIf " << timeS;
Sleep(update);
}else if(timeS >= 10 && timeS < 20){
double update = timeS - 5.0;
timeS = update;
gotoXY(40, 7);
cout << "tmpIf " << timeS;
Sleep(update);
}else if(timeS == 0){
Sleep(timeS);
}else{
double update = timeS - 0.5;
timeS = update;
gotoXY(40, 7);
cout << "tmpIf " << timeS;
Sleep(update);
}
playGame(car);
}else if(counter < levelDown){
level--;
TabLevelDown();
Sleep(5000);
levelUp = levelDown;
levelDown = levelDown - 1000;
if(timeS >= 40 && timeS < 100){
double update = timeS + 20.0;
timeS = update;
gotoXY(45, 7);
cout << "tmpIf " << timeS;
Sleep(update);
}else if(timeS == 20 || timeS == 30){
double update = timeS + 10.0;
timeS = update;
gotoXY(45, 7);
cout << "tmpIf " << timeS;
Sleep(update);
}else if(timeS == 10 && timeS < 20){
double update = timeS + 5.0;
timeS = update;
gotoXY(45, 7);
cout << "tmpIf " << timeS;
Sleep(update);
}else if(timeS < 10 && level <= 17){
double update = timeS + 0.5;
timeS = update;
gotoXY(45, 7);
cout << "tmpIf " << timeS;
Sleep(update);
}else{
Sleep(timeS);
}
playGame(car);
}else{
Sleep(timeS);
}
}
void Game::showLevelScore()
{
gotoXY(50, 1);
cout<<"Score: " << counter;
gotoXY(50, 3);
cout<<"Level: " << level;
}
void Game::gameEnd()
{
if(counter <= 0){
running = false;
Sleep(1000);
system("cls");
gotoXY(5,4);
cout << "GAME OVER!!!";
gotoXY(5,6);
cout << "MAX LEVEL: " << checkMaxLevel();
gotoXY(5,7);
cout << "MAX SCORE: " << checkMaxScore();
gotoXY(0,0);
}
}
int Game::generateRandomNumber()
{
int rEne = rand() % 3;
gotoXY(50, 5);
cout << "R: " << rEne << endl;
return rEne;
}
void Game::randomAppear(EnemiesCar &myEn, Nail &myNe, Hole &myHo)
{
int rEne = generateRandomNumber();
if(rEne == 0){
myEn.appear();
myEn.drawEnemies(myEn.xPos, myEn.yPos, matrix);
myEn.move();
}else if(rEne == 1){
myNe.appear();
myNe.drawNails(myNe.xPos, myNe.yPos, matrix);
myNe.move();
}else{
myHo.appear();
myHo.drawHoles(myHo.xPos, myHo.yPos, matrix);
myHo.move();
}
}
void Game::playGame(Car &mycar){
EnemiesCar myEnmCar = EnemiesCar();
Nail nails = Nail();
Hole holes = Hole();
while(this->running){
srand (time(NULL));
resetBoard();
randomAppear(myEnmCar, nails, holes);
checkSamePosition(myEnmCar, nails);
/*myEnmCar.appear();
myEnmCar.drawEnemies(myEnmCar.xPos, myEnmCar.yPos, matrix);
myEnmCar.move();*/
/*gotoXY(3, 22);
cout << "enmpos: " << myEnmCar.xPos << myEnmCar.yPos << endl;*/
/*nails.appear();
nails.drawNails(nails.xPos, nails.yPos, matrix);
nails.move();
holes.appear();
holes.drawHoles(holes.xPos, holes.yPos, matrix);
holes.move();*/
mycar.drawCar(mycar.xPos, mycar.yPos, matrix);
mycar.checkCollusion(myEnmCar, nails, holes, &counter, &level);
createTab();
myEnmCar.addScore(mycar, &counter);
nails.addScore(mycar, &counter);
holes.addScore(mycar, &counter);
showLevelScore();
checkMaxLevel();
checkMaxScore();
gameEnd();
gameLevels(mycar);
}
}
void Game::startGame()
{
srand (time(NULL));
Car mycar = Car();
thread myThread(&Car::myListener, &mycar, &mycar);
playGame(mycar);
Sleep(5000);
myThread.detach();
}
EnemiesCar.h
#ifndef ENEMIESCAR_H
#define ENEMIESCAR_H
#include "Game.h"
class Game;
class Car;
class Nail;
class EnemiesCar
{
public:
const int xInit[9] = {2, 4, 6, 8, 10, 12, 14, 16, 18};
int xPos;
int yPos;
Game games = Game();
EnemiesCar();
void appear();
void drawEnemies(int x, int y, int myMatr[21][20]);
//void draw();
void move();
void addScore(Car car, int *countScore);
};
#endif // ENEMIESCAR_H
EnemiesCar.cpp
#include <windows.h>
#include <iostream>
#include "EnemiesCar.h"
#include "Game.h"
#include "Car.h"
#include "Nail.h"
using namespace std;
EnemiesCar::EnemiesCar()
{
int randomX = rand() % 6;
xPos=xInit[randomX];
yPos=0;
}
/*void EnemiesCar::drawEnemies(int x, int y)
{
Game games = Game();
if(y<20 && y>=-0){
games.matrix[x][y] = 2;
cout << "drawEne" <<endl;
}
}*/
void EnemiesCar::appear()
{
if(yPos==18){
int randomNo = rand() % 21;
/*games.gotoXY(35, 7);
cout << "a: " << randomNo << " ";*/
if(randomNo >= 0 && randomNo <= 3){
xPos = 2;
}else if(randomNo == 4 || randomNo == 5){
xPos = 4;
}else if(randomNo == 6 || randomNo == 7){
xPos = 6;
}else if(randomNo == 8 || randomNo == 9){
xPos = 8;
}else if(randomNo == 10 || randomNo == 11){
xPos = 10;
}else if(randomNo == 12 || randomNo == 13){
xPos = 12;
}else if(randomNo == 14 || randomNo == 15){
xPos = 14;
}else if(randomNo == 16 || randomNo == 17){
xPos = 16;
}else{
xPos = 18;
}
yPos = -3;
}
}
void EnemiesCar::drawEnemies(int x, int y, int myMatr[21][20])
{
if(y<20 && y>=-0){
myMatr[x][y] = 2;
myMatr[x-1][y+1] = 2;
myMatr[x+1][y+1] = 2;
myMatr[x][y+1] = 2;
myMatr[x][y+2] = 2;
}
}
void EnemiesCar::move()
{
yPos++;
}
void EnemiesCar::addScore(Car car, int *countScore)
{
if((this->xPos <= car.xPos-3 && this->yPos == 16) || (this->xPos >= car.xPos+3 && this->yPos == 16)){
*countScore = *countScore + 100;
}
}

It seems that what you need to do is separate the appearance/drawing from the generation of the random number. You need to keep track of the "random enemies" you've already generated, and take them - and only them - into account when drawing your board; and independently of this, once every few turns or when triggered by appropriate events, generate a new random enemy/car/whatever, adding it to the set of already-generated ones.

Related

I got the error code -1073741571 in my snake game

I'm making a snake game and it's basically done; however sometimes when I run it it works at first then clears (that might be in my code, it has a lot of clears) and returns error code -1073741571.
This is the code:
#include <iostream>
#include <string>
#include <stdio.h>
#include <conio.h>
#include "windows.h"
#include <vector>
#include <random>
#include <ctime>
#include <cmath>
#include <windows.h>
using namespace std;
struct point
{
int x;
int y;
};
bool goTo(point p,vector<point>& snek)
{
bool flag=false;
for (size_t i = 0; i < snek.size(); i++)
{
if (p.x == snek[i].x && p.y == snek[i].y)
{
return true;
}
}
for (int i=snek.size()-1; i >0; i--)
{
snek[i] = snek[i - 1];
}
snek[0] = p;
return false;
}
void makeFood(point& apple, vector<point> snek)
{
bool appleValid = true;
apple.x = (rand() % 19) + 1;
apple.y = (rand() % 19) + 1;
for (int i = 0; i < snek.size() - 1; i++)
{
if (apple.x == snek[i].x && apple.y == snek[i].y)
{
appleValid = false;
break;
}
}
if (!appleValid)
{
srand(time(NULL));
makeFood(apple,snek);
}
}
int main()
{
vector<point> snek;
snek.push_back({ 10,10 });
snek.push_back({ 10,9 });
snek.push_back({ 10,8 });
snek.push_back({ 10,7 });
int highscore= 0, score;
bool tutorial = false;
bool p = false;
char move = 'w';
char sure = 'f';
string board[21][21];
int direction=2;
point apple;
apple.x = rand() % 20;
apple.y = rand() % 20;
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
board[i][j] = " ";
}
}
bool loss = false;
while (true)
{
score = snek.size() - 4;
bool appleEaten = false;
srand(time(NULL));
if (snek[0].x == 0 )
loss = true;
if (snek[0].x == 20 )
loss = true;
if (snek[0].y == 0 )
loss = true;
if (snek[0].y == 20 )
loss = true;
if (loss)
{
system("CLS");
if (score > highscore)
{
highscore = score;
}
cout << "You lost with a score of " << snek.size() - 4 << endl;
cout << "Your highscore for this session is " << highscore<<endl;
cout << "Press any key to play again" << endl;
cout << "Press RMB to quit" << endl;
while (true)
{
if (GetAsyncKeyState(VK_RBUTTON))
{
system("CLS");
cout << "Are you sure you want to quit? Your highscore for this session will be reset" << endl;
cout << "Press Q to quit and P to play again" << endl;
sure = _getch();
if (sure == 'q' || sure == 'Q')
{
_Exit(0);
}
if (sure == 'p' || sure == 'P')
{
p = true;
}
}
if (_kbhit() || p)
{
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
board[i][j] = " ";
}
}
snek.clear();
snek.push_back({ 10,10 });
snek.push_back({ 10,9 });
snek.push_back({ 10,8 });
snek.push_back({ 10,7 });
loss = false;
p = false;
break;
}
}
}
Sleep(100);
if (_kbhit())
{
move = _getch();
}
system("CLS");
switch (move)
{
case 'w':
loss = goTo({ (snek[0].x - 1),snek[0].y }, snek);
Sleep(10);
break;
case 'a':
loss = goTo({ snek[0].x ,(snek[0].y - 1) }, snek);
Sleep(10);
break;
case 's':
loss = goTo({ (snek[0].x + 1),snek[0].y }, snek);
Sleep(10);
break;
case'd':
loss = goTo({ snek[0].x ,(snek[0].y + 1) }, snek);
Sleep(10);
break;
}
board[apple.x][apple.y] = " 0";
for (int k = 0; k < snek.size() - 1; k++)
{
board[snek[k].x][snek[k].y] = " *";
board[snek[snek.size() - 1].x] [snek[snek.size() - 1].y] = " ";
}
if (apple.x == snek[0].x && apple.y == snek[0].y)
{
snek.push_back({snek[snek.size()-1].x+1,snek[snek.size() - 1].y});
appleEaten = true;
}
if (appleEaten)
{
makeFood(apple,snek);
}
for (int i = 0; i < 20; i++)
{
board[0][i] = "--";
board[20][i] = "--";
}
for (int i = 0; i < 20; i++)
{
board[i][0] = '|';
board[i][20] = '|';
}
if (!tutorial)
{
cout << "You are a snake." << endl;
cout << "Your body looks like this" << endl;
cout << "*****" << endl;
cout << "Move with WASD" << endl;
cout << "If you eat the apples, which look like this " << endl << "0" << endl;
cout << "You get bigger. If you try to eat yourself or run into walls, you lose" << endl;
cout << "Click RMB to begin";
while (true)
{
if (GetAsyncKeyState(VK_RBUTTON))
{
system("CLS");
tutorial = true;
break;
}
}
}
for (int i = 0; i < 21; i++)
{
for (int j = 0; j < 21; j++)
{
cout << board[i][j];
}
cout << endl;
}
cout << "Score: " << score;
}
}
EDIT: Most of the time it works fine, only sometimes I get the error
EDIT: The stack overflow is in int main()
Let’s take a closer look at your makeFood function:
void makeFood(point& apple, vector<point> snek)
{
bool appleValid = true;
apple.x = (rand() % 19) + 1;
apple.y = (rand() % 19) + 1;
for (int i = 0; i < snek.size() - 1; i++)
{
if (apple.x == snek[i].x && apple.y == snek[i].y)
{
appleValid = false;
break;
}
}
if (!appleValid)
{
srand(time(NULL));
makeFood(apple,snek);
}
}
Your if statement makes it so that makeFood() is called again when the apple is at the snakes position, but using srand(time(NULL)) will put the apple back into the same place, which calls the function again and again for an infinite amount of time. Remove srand(time(NULL)) in the if(!appleValid) and your program shouldn’t have the issue because you only need to seed random.
if you can, try to convert your random functions to the <random> header, but it should work fine with rand as well :)

I think I have a memory leak?

I am trying to do the Knight's Tour using dynamic arrays because the user will be able to implement their own board size, and where they want to start the knight at in the board.
However, before I changed everything to dynamic arrays, I was able to perform my code just find using static arrays, but now that I switched to dynamic arrays whenever my code executes, I get a memory leak I believe and the program crashes. I was wondering if my deconstructor is not working properly? Or if there is a different way I have to delete the dynamic array?
I am also wondering if there is a way to make this code a little more efficient, more exactly make the Move() function a little more efficient. Thanks.
#include <iostream>
#include <iomanip>
#include "stdafx.h"
using namespace std;
class Knight
{
private:
int Tracker = 1;
int BoardSize;
int **Board = new int*[BoardSize];
public:
Knight(int s)
{
BoardSize = s;
for (int i = 0; i <= s -1; i++)
{
Board[i] = new int[s];
}
for (int i = 0; i <= s - 1; i++)
{
for (int j = 0; j <= s - 1; j++)
{
Board[i][j] = 0;
}
}
}
~Knight()
{
for (int i = 0; i <= BoardSize - 1; i++)
{
delete[] Board[i];
}
delete[] Board;
}
void MarkUp(int &val)
{
val = Tracker;
Tracker++;
}
void MarkDown(int &val)
{
val = 0;
Tracker--;
}
bool PossibleMove(int &val)
{
if (val == 0)
return 1;
else
return 0;
}
void Display()
{
for (int k = 0; k < (BoardSize * 5) + 1; k++)
{
cout << "-";
}
cout << endl;
for (int i = 0; i <= BoardSize - 1; i++)
{
cout << "| ";
for (int j = 0; j <= BoardSize - 1; j++)
{
cout << setw(2) << setfill('0') << Board[i][j] << " | ";
}
cout << endl;
for (int k = 0; k < (BoardSize * 5) + 1; k++)
{
cout << "-";
}
cout << endl;
}
cout << endl << endl;
}
bool Move(int x, int y)
{
if (Tracker > (BoardSize * BoardSize))
{
return true;
}
if (PossibleMove(Board[x][y])) {
if ((x - 2 >= 0) && (y + 1 <= (BoardSize - 1)))
{
MarkUp(Board[x][y]);
if (Move(x - 2, y + 1))
{
return true;
}
else
{
MarkDown(Board[x][y]);
}
}
if ((x - 2 >= 0) && (y - 1 >= 0))
{
MarkUp(Board[x][y]);
if (Move(x - 2, y - 1))
{
return true;
}
else
{
MarkDown(Board[x][y]);
}
}
if ((x - 1 >= 0) && (y + 2 <= (BoardSize - 1)))
{
MarkUp(Board[x][y]);
if (Move(x - 1, y + 2))
{
return true;
}
else
{
MarkDown(Board[x][y]);
}
}
if ((x - 1 >= 0) && (y - 2 >= 0))
{
MarkUp(Board[x][y]);
if (Move(x - 1, y - 2))
{
return true;
}
else
{
MarkDown(Board[x][y]);
}
}
if ((x + 2 <= (BoardSize - 1)) && (y + 1 <= (BoardSize - 1)))
{
MarkUp(Board[x][y]);
if (Move(x + 2, y + 1))
{
return true;
}
else
{
MarkDown(Board[x][y]);
}
}
if ((x + 2 <= (BoardSize - 1)) && (y - 1 >= 0))
{
MarkUp(Board[x][y]);
if (Move(x + 2, y - 1))
{
return true;
}
else
{
MarkDown(Board[x][y]);
}
}
if ((x + 1 <= (BoardSize - 1)) && (y + 2 <= (BoardSize - 1)))
{
MarkUp(Board[x][y]);
if (Move(x + 1, y + 2))
{
return true;
}
else
{
MarkDown(Board[x][y]);
}
}
if ((x + 1 <= (BoardSize - 1)) && (y - 2 >= 0))
{
MarkUp(Board[x][y]);
if (Move(x + 1, y - 2))
{
return true;
}
else
{
MarkDown(Board[x][y]);
}
}
}
return false;
}
};
int main()
{
int size = 0;
int Row, Col;
int opt = 0;
do
{
cout << "Welcome to Knights Tour!" << endl;
cout << "1) Start the Tour." << endl;
cout << "2) Quit." << endl;
cin >> opt;
switch (opt)
{
case 1:
{
cout << "Enter board size:" << endl;
cin >> size;
Knight K1(size);
cout << "Enter Row:" << endl;
cin >> Row;
cout << "Enter Column: " << endl;
cin >> Col;
if (K1.Move(Row, Col))
{
cout << "\nOperation was Successful." << endl;
cout << "Possible Solution:" << endl;
K1.Display();
}
else
{
cout << "\nThat is not Possible." << endl;
}
cout << endl;
break;
}
case 2:
{
exit(0);
break;
}
default:
{
cout << "Not a Valid Option." << endl;
cout << "Try Again Please." << endl;
cout << endl;
break;
}
}
} while (opt != 2);
return 0;
}
This code does not work as you think it does:
int BoardSize;
int **Board = new int*[BoardSize];
The value of BoardSize is going to be whatever happens to be in the memory that gets allocated for it, so the new is going to try to allocate an unknowable size array.
Don't use hand coded dynamic arrays for this. Use std::vector; That's what it's for. In real life production code, you should almost never ever use dynamically allocated arrays. You'll use one of the standard containers.
As noted in the comments by multiple people, memory leaks do not cause crashes (generally).
The issue is that inside the constructor you assign values to the Board array elements. However, you never allocate memory for the Board array itself. I.e. when you do Board[i] = new int[s];, Board points to some random address. This is because the line int **Board = new int*[BoardSize]; is not executed before the constructor starts.
So the following should work:
class Knight {
private:
int BoardSize;
int **Board;
public:
Knight (int s) {
BoardSize = s;
Board = new int*[BoardSize];
// Remainder of code
}
};
However, I really suggest you use std::vector for this instead. Then you won't have to deal with memory (de)allocation at all. That could look as concise as the following:
#include <vector>
class Knight {
private:
int BoardSize;
std::vector<std::vector<int>> Board;
public:
Knight (int s) : BoardSize(s), Board(s, std::vector<int>(s, 0)) { }
};
Note that I initialized the class members directory in the member initializer list.

What character is this?

I'm writing a simple program to generate a box with a user-defined sidelength and border/fill characters. Everything is working as I want it to, except when it prints the box to the terminal, it produces a strange character I cannot find anywhere. I feel like if I know what it is, I might be able to fix it. My header file is here:
#ifndef Box_h
#define Box_h
class Box
{
private:
int pSidelength;
char pBorder;
char pFill;
public:
Box(int pSidelength, char pBorder = '#', char pFill = '*');
int Sidelength;
char Border;
char Fill;
int Area();
int Perimeter();
int GetSize();
int Grow();
int Shrink();
char SetBorder();
char SetFill();
void Draw();
void Summary();
};
#endif Box_h
My source for the class is:
#include <iostream>
#include "box.h"
#include <iomanip>
using namespace std;
Box::Box(int pSidelength, char pBorder, char pFill)
{
if (pSidelength < 1)
{
Sidelength = 1;
}
else if (pSidelength > 39)
{
Sidelength = 39;
}
else
{
Sidelength = pSidelength;
}
if (pBorder != '#')
{
SetBorder();
}
if (pFill != '*')
{
SetFill();
}
}
int main(void)
{
Box MyBox1(3,'#','*');
Box MyBox2(7, '^', '*');
Box MyBox3(10, '$', '%');
MyBox1.Grow();
MyBox2.Shrink();
MyBox1.Summary();
MyBox2.Summary();
MyBox3.Summary();
return 0;
}
int Box::Shrink()
{
if (Sidelength == 1)
{
Sidelength = Sidelength;
}
else
{
Sidelength = Sidelength - 1;
}
return Sidelength;
}
int Box::Grow()
{
if (Sidelength == 39)
{
Sidelength = Sidelength;
}
else
{
Sidelength = Sidelength + 1;
}
return Sidelength;
}
char Box::SetFill()
{
Fill = pFill;
return Fill;
}
char Box::SetBorder()
{
Border = pBorder;
return Border;
}
int Box::Area()
{
int area = (Sidelength)*(Sidelength);
return area;
}
int Box::Perimeter()
{
int perimeter = 4 * (Sidelength);
return perimeter;
}
int Box::GetSize()
{
int size = Sidelength;
return size;
}
void Box::Draw()
{
int j = 1;
int k = 1;
if (Sidelength == 1 || Sidelength == 2)
{
for (int i = 1; i <= Sidelength; i++)
{
while (j <= Sidelength)
{
cout << setw(2) << Border;
j++;
}
j = 1;
}
cout << endl;
}
else
{
for (int i = 1; i <= Sidelength; i++)
{
if (i == 1 || i == Sidelength)
{
while (k <= Sidelength)
{
cout << setw(2) << Border;
k++;
}
cout << endl;
k = 1;
}
else
{
while (j <= Sidelength)
{
if (j == 1 || j == Sidelength)
{
cout << setw(2) << Border;
}
else
{
cout << setw(2) << Fill;
}
j++;
}
cout << endl;
j = 1;
}
}
cout << endl;
}
}
void Box::Summary()
{
cout << "The Sidelength of the box is: " << Box::GetSize() << endl;
cout << "The Perimeter of the box is: " << Box::Perimeter() << endl;
cout << "The Area of the box is: " << Box::Area() << endl;
Box::Draw();
}
The program has a default character associated with Border/Fill, as specified in the header file. When run, it produces this:
What character is that, and any ideas on why it would be appearing in the first place?
The character is random, and could in theory be different every time you run the program.
It's coming from the pBorder member, which is never set to anything.
You got confused with same name of variables.
Box::Box(int pSidelength, char pBorder, char pFill)
{
if (pSidelength < 1)
{
Sidelength = 1;
}
else if (pSidelength > 39)
{
Sidelength = 39;
}
else
{
Sidelength = pSidelength;
}
if (pBorder != ' ') //Here pBorder has '*' but this is local
// pBorder to this Function
{
SetBorder();
}
if (pFill != ' ')
{
SetFill();
}
}
And When you call SetBorder();
It makes Border as pBorder as that was declared in the class which is still unintialized.
char Box::SetBorder()
{
Border = pBorder; //This pBorder is not initialized
return Border;
}
Solution 1
Dont use Function
if (pBorder != ' ')
{
Border = pBorder;
}
Solution 2
Pass pBorder
if (pBorder != ' ')
{
SetBorder(pBorder);
}
char Box::SetBorder(char pBorder)
{
Border = pBorder; //This pBorder is not initialized
return Border;
}

Making Snake Game in Cpp Movement of Snake

I'm beginner to C++. i'm making a snake game in c++ simple game console based. without using any graphics. i had done almost 60% of work the only thing which makes me confuse is the movement of snake after eating "fruit". Below is my code if someone can help me please it'll be very helpful or i want you to give me any hint so that i can continue my code
Here is my header file
snake.h:
#ifndef SNAKE_H
#define SNAKE_H
class snake
{
private:
char key;
int x1, y1, x2, y2, n;
char keyp;
public:
snake()
{
x1=28; y1=12; x2=0; y2=0; n=1;
}
void gotoxy(int x, int y);
void frame();
char movement(char keyp);
char rmove();
char lmove();
char umove();
char dmove();
void rstar();
void rcstar();
void options();
};
#endif // SNAKE_H
Here is my snake.cpp File
Snake.cpp
#include "snake.h"
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
//gotoxy function
COORD coord={0,0};
void snake::gotoxy(int x,int y)
{
coord.X=x;
coord.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}
void snake::frame()
{
for(int i=0;i<=78;i++)
cout << char(45);
for(int i=1;i<22;i++)
{
gotoxy(0,i);
cout << char(124);
gotoxy(63,i);
cout << char(124);
gotoxy(78,i);
cout << char(124);
}
cout << endl;
for(int i=0;i<=78;i++)
cout << char(45);
}
char snake::rmove()
{
for(;x1<=63;x1++)
{
Sleep(200);
if(x1==62)
{
x1=1;
gotoxy(61,y1);
cout << " ";
}
if(x1!=1)
{
gotoxy(x1-1,y1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='a' || keyp=='A' || keyp=='d' || keyp=='D')
continue;
else
break;
}
}
return keyp;
}
char snake::lmove()
{
for(x1;x1>=0;x1--)
{
Sleep(200);
if(x1==0)
{
x1=62;
gotoxy(1,y1);
cout << " ";
}
if(x1!=62)
{
gotoxy(x1+1,y1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='d' || keyp=='D' || keyp=='a' || keyp=='A')
continue;
else
break;
}
}
return keyp;
}
char snake::umove()
{
for(;y1>=0;y1--)
{
Sleep(200);
if(y1==0)
{
y1=21;
gotoxy(x1,1);
cout << " ";
}
if(y1!=21)
{
gotoxy(x1,y1+1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='s' || keyp=='S' || keyp=='w' || keyp=='W')
continue;
else
break;
}
}
return keyp;
}
char snake::dmove()
{
for(;y1<=22;y1++)
{
Sleep(200);
if(y1==22)
{
y1=1;
gotoxy(x1,21);
cout << " ";
}
if(y1!=1)
{
gotoxy(x1,y1-1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='w' || keyp=='W' || keyp=='s' || keyp=='S')
continue;
else
break;
}
}
return keyp;
}
char snake::movement(char keyp)
{
switch(keyp)
{
case 'w':
keyp=umove();
break;
case 's':
keyp=dmove();
break;
case 'd':
keyp=rmove();
break;
case 'a':
keyp=lmove();
break;
}
return keyp;
}
void snake::rcstar()
{
if(x1==x2 && y1==y2)
{
rstar();
n++;
}
gotoxy(65,8);
cout << "Score : " << n-1;
}
void snake::rstar()
{
x2 = rand()%61+1;
y2 = rand()%21+1;
gotoxy(x2, y2);
cout << "*";
}
void snake::options()
{
gotoxy(64,4);
cout << "[P] Pause";
gotoxy(64,5);
cout << "[K] Difficulty";
gotoxy(64,6);
cout << "[Q] Quit";
gotoxy(66,9);
cout << "High Score";
gotoxy(70,10);
cout << "0";
gotoxy(66,13);
cout << "SNAKE 2K ";
gotoxy(65,15);
cout << "Created By";
gotoxy(66,17);
cout << "Khurram";
}
And Here is main main.cpp file
main.cpp
#include <iostream>
#include <conio.h>
#include <windows.h>
#include "snake.h"
using namespace std;
int main()
{
snake a1;
char kph;
a1.load();
system("cls");
a1.frame();
a1.gotoxy(28,12);
cout << "*";
a1.rstar();
a1.options();
kph=getch();
do
{
if(kph=='w' || kph=='s' || kph=='a' || kph=='d')
kph=a1.movement(kph);
else if(kph=='q')
break;
else if(kph=='p' || kph=='P')
kph=getch();
else if(kph=='k' || kph=='K')
{ kph=a1.difficulty(); }
else
continue;
}
while(kph!='q');
a1.gotoxy(0,24);
return 0;
}
First of all i want to say that i know this code is really messed up but i'm beginner and still learning how to make a good program.
Please help me to complete this program.
You are going to need to save the coordinates (positions) of each segment of the snake. You will need to prepend a head and erase a tail segment. You will save the coordinates in a container.
There are many containers such as std::vector, std::list, std::stack and std::deque. I recommend std::deque. This allows you to push new segment coordinates into the back and pop the oldest segment from the top.
The std::deque structure allows growth too. You can push more items than you pop and also pop more than push (until the container is empty).
You can also do this the more difficult method and use an array or std::vector. You would erase the tail (using the coordinates at the end of the array), then move all the coordinates down (to make room for a new head coordinate), then set the first slot to the new coordinate.
Also, please invest some time with your debugger. Debugging your program is a lot faster than using StackOverflow to debug it. Most of us don't have the time to take your program, use a debugger, to find out where the issues are. If the issue is not obvious to most people in the first minute, your question is less likely to be answered (thus more downvotes).
Why are you making 3 programs. Here is how you do it. Make good use of OOP man !
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
bool gameOver;
const int width = 40;
const int height = 20;
int x, y, fruitX, fruitY, score;
int tailX[100], tailY[100];
int ntail;
enum edirecton { STOP = 0, LEFT, RIGHT, UP, DOWN };
edirecton dir;
void Setup()
{
gameOver = false;
dir = STOP;
x = width / 2;
y = height / 2;
fruitX = rand() % width;
fruitY = rand() % height;
score = 0;
}
void Draw()
{
system("cls");
for (int i = 0; i < width + 2; i++)
cout << "|";
cout << endl;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (j == 0)
cout << "|";
if (i == y && j == x)
cout << "O";
else if (i == fruitY && j == fruitX)
cout << "F";
else
{
bool print = false;
for (int k = 0; k < ntail; k++)
{
if (tailX[k] == j && tailY[k] == i)
{
cout << "o";
print = true;
}
}
if (!print)
cout << " ";
}
if (j == width - 1)
cout << "|";
}
cout << endl;
}
for (int i = 0; i < width + 2; i++)
cout << "|";
cout << endl;
cout << "Score= " << score << endl;
}
void Input()
{
if (_kbhit())
{
switch (_getch())
{
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
case 'x':
gameOver = true;
break;
}
}
}
void Logic()
{
int prevX = tailX[0];
int prevY = tailY[0];
int prev2X, prev2Y;
tailX[0] = x;
tailY[0] = y;
for (int i = 1; i < ntail; i++)
{
prev2X = tailX[i];
prev2Y = tailY[i];
tailX[i] = prevX;
tailY[i] = prevY;
prevX = prev2X;
prevY = prev2Y;
}
switch (dir)
{
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
break;
}
//if (x > width || x<0 || y>height || y < 0)
//gameOver = true;
if (x >= width)
x = 0;
else if (x < 0)
x = width - 1;
if (y >= height)
y = 0;
else if (y < 0)
y = height - 1;
for (int i = 0; i < ntail; i++)
{
if (tailX[i] == x && tailY[i] == y)
gameOver = true;
}
if (x == fruitX && y == fruitY)
{
score += 10;
fruitX = rand() % width;
fruitY = rand() % height;
ntail++;
}
}
int main()
{
Setup();
while (!gameOver)
{
Draw();
Input();
Logic();
Sleep(80);
}
return 0;
}

C++ do while keeps repeating

#include <iostream>
#include <string>
#include <cctype>
#include <sstream>
using namespace std;
int getTreeNo(int);
int getSpeciesCode(int);
float getDbh(float);
int getTotHt(int);
int getTotHt(int);
double calcTotVol(double[], double[], float, int);
int main() {
int i = 0;
int treeNo = 0;
int speciesCode = 0;
string speciesDesc[6] = {};
float dbh = 0.00;
int totalHt = 0;
double totalVol = 0.00;
int Species[6] = {};
double b0[6] = {};
double b1[6] = {};
int noTrees = 0;
treeNo = getTreeNo(treeNo);
/* Gets number of trees for calculations*/
speciesCode = getSpeciesCode(speciesCode);
/* Get Species code from user*/
dbh = getDbh(dbh);
/* get DBH from user*/
totalHt = getTotHt(totalHt);
/*Gets tree height from user*/
totalVol = calcTotVol(b0, b1, dbh, totalHt);
/* Calculates values */
/* All constants and variables
int treeNo;
int speciesCode;
string speciesDesc[6];
float dbh;
int totalHt;
double totalVol;
int Species[6];
double b0[6];
double b1[6];
int noTrees;
double avgTotVol;
*/
if (speciesCode = 11) {
speciesDesc[0] = "Loblolly Pine";
} else if (speciesCode = 12) {
speciesDesc[1] = "White Pine";
} else if (speciesCode = 13) {
speciesDesc[2] = "Red Pine";
} else if (speciesCode = 21) {
speciesDesc[3] = "White Oak";
} else if (speciesCode = 22) {
speciesDesc[4] = "Red Oak";
} else if (speciesCode = 23) {
speciesDesc[5] = "Other Oak";
}
Species[0] = 11;
Species[1] = 12;
Species[2] = 13;
Species[3] = 21;
Species[4] = 22;
Species[5] = 23;
if (speciesCode = 11) {
b0[0] = 1.2446;
} else if (speciesCode = 12) {
b0[1] = 0.000;
} else if (speciesCode = 13) {
b0[2] = 2.0822;
} else if (speciesCode = 21) {
b0[3] = .7316;
} else if (speciesCode = 22) {
b0[4] = 1.6378;
} else if (speciesCode = 23) {
b0[5] = .7554;
}
if (speciesCode = 11) {
b1[0] = .002165;
} else if (speciesCode = 12) {
b1[1] = .002364;
} else if (speciesCode = 13) {
b1[2] = .002046;
} else if (speciesCode = 21) {
b1[3] = .001951;
} else if (speciesCode = 22) {
b1[4] = .002032;
} else if (speciesCode = 23) {
b1[5] = .002174;
}
totalVol = b0[6] + b1[6] * pow(dbh, 2) * totalHt;
for (i = 0; i < treeNo; i++) {
cout << "Tree Number " << i + 1 << ": " << speciesCode << dbh << totalHt
<< speciesDesc[6] << b0[6] << b1[6] << totalVol;
}
}
/************************************************************************************************
* *************/
int getTreeNo(int treeNo) {
do {
cout << "Please enter the number of trees :" << endl;
cin >> treeNo;
if ((treeNo <= 0) || (treeNo > 999)) {
cout << "ERROR!!!,You cannot have more then999 entries" << endl;
}
} while ((treeNo <= 0) || (treeNo > 999));
return treeNo;
}
int getSpeciesCode(int speciesCode) {
do {
cout << "Please enter your Species Code";
cin >> speciesCode;
} while ((speciesCode != 11) || (speciesCode != 12) ||
(speciesCode != 13) || (speciesCode != 21) ||
(speciesCode != 22) || (speciesCode != 23));
cout << "ERROR!!!,That information does not exist wthin our system" << endl;
return speciesCode;
}
float getDbh(float dbh) {
do {
cout << "Please enter the DBH of the tree, The DBH must be greter then "
"and equal to five and less then 50.6" << endl;
cin >> dbh;
if ((dbh < 5) || (dbh > 50.6)) {
cout << "ERROR!!!, The DBH must be greter then and equal to five "
"and less then 50.6" << endl;
}
} while ((dbh < 5) || (dbh > 50.6));
return dbh;
}
int getTotHt(int totalHt) {
do {
cout << "Please enter the height of the tree" << endl;
cin >> totalHt;
if ((totalHt < 24) || (totalHt > 160)) {
cout << "ERROR!!!, Please enter a height thats not larger then "
"160, but greater then 24" << endl;
}
} while (totalHt < 24 || totalHt > 160);
{ return totalHt; }
}
double calcTotVol(double array[], double array1[], float dbh, int totalHt) {
double totalVol;
totalVol = array[6] + array1[6] * pow(dbh, 2) * totalHt;
return totalVol;
}
can anyone help me my speciesCode function keeps looping and will not accept my input actually I do not believe any function is accepting it I have worked for hours to try to figure out why and am stuck
thanks for any help
the condition in this while statement will never ever be false, and your loop will never exit. In order for it to be false, speciesCode has to have more than 1 value at a time.
while((speciesCode != 11) || (speciesCode != 12) || (speciesCode != 13) || ...)
You probably want to keep repeating until you get a valid code. In that case use &&
while((speciesCode != 11) && (speciesCode != 12) && (speciesCode != 13) && ...)