Running two loops at the same time ? moving and traveling using loops - c++

I am a first year Computer Engineer so I am a little bit amatuer in coding C++, anyway I am creating a game where there are two spaceships shooting each other. I currently succeeded making the first spaceship move by using a while loop and the GetASyncKeyState function. but now I am making the bullets travel. I used for loop, and I did succeed in making the bullet travel upward. But there's a problem, I can't move the spaceship until the for loop stop or the bullet reach the top of the console window (I am using console btw). is there a way to both run the for loop and while at the same time ? or to run two different function at the same time since GameMovement() is for the movement of spaceship and BulletTravel() is for the bullet. and I am calling BulletTravel() from GameMovement().
void GameMovements()
{
bool FirstInitialization = true;
int Player1XCoordinate = 55, Player2XCoordinate = 55;
int Player1YCoordinateU = 28, Player1YCoordinateD = 29;
while (true)
{
BulletPattern(Player1XCoordinate);
if (FirstInitialization == true)
{
GameBorderAndStatus();
SetCoordinate(Player1XCoordinate, Player1YCoordinateU);
cout << " ^ \n";
SetCoordinate(Player1XCoordinate, Player1YCoordinateD);
cout << "^==|==^ \n";
FirstInitialization = false;
}
//MOVEMENTS FOR PLAYER 1
else if (GetAsyncKeyState(VK_LEFT) && Player1XCoordinate != 16)
{
system("cls");
GameBorderAndStatus();
Sleep(10);
Player1XCoordinate -= 3;
SetCoordinate(Player1XCoordinate, Player1YCoordinateU);
cout << " ^ \n";
SetCoordinate(Player1XCoordinate, Player1YCoordinateD);
cout << "^==|==^ \n";
}
else if (GetAsyncKeyState(VK_RIGHT) && Player1XCoordinate != 94)
{
system("cls");
GameBorderAndStatus();
Player1XCoordinate += 3;
Sleep(10);
SetCoordinate(Player1XCoordinate, Player1YCoordinateU);
cout << " ^ \n";
SetCoordinate(Player1XCoordinate, Player1YCoordinateD);
cout << "^==|==^ \n";
}
else if (GetAsyncKeyState(VK_UP) && Player1YCoordinateU != 24)
{
system("cls");
GameBorderAndStatus();
Player1YCoordinateU -= 2;
Player1YCoordinateD -= 2;
Sleep(10);
SetCoordinate(Player1XCoordinate, Player1YCoordinateU);
cout << " ^ \n";
SetCoordinate(Player1XCoordinate, Player1YCoordinateD);
cout << "^==|==^ \n";
}
else if (GetAsyncKeyState(VK_DOWN) && Player1YCoordinateU != 28)
{
system("cls");
GameBorderAndStatus();
Player1YCoordinateU += 2;
Player1YCoordinateD += 2;
Sleep(10);
SetCoordinate(Player1XCoordinate, Player1YCoordinateU);
cout << " ^ \n";
SetCoordinate(Player1XCoordinate, Player1YCoordinateD);
cout << "^==|==^ \n";
}
}
}
void GameBorderAndStatus()
{
//Draw game border
for (int i = 0; i < 31; i++)
{
SetCoordinate(15, i);
cout << "|";
SetCoordinate(104, i);
cout << "|";
}
}
void BulletPattern(int Player1MuzzleLocation)
{
for (int i = 25; i != 3; i--)
{
Sleep(100);
SetCoordinate(Player1MuzzleLocation + 3, i);
}
}
void SetCoordinate(int CoordinateX, int CoordinateY)
{
COORD Coordinate;
Coordinate.X = CoordinateX;
Coordinate.Y = CoordinateY;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Coordinate);
}

Rather than using two different functions and moving one object within each, you might find better results keeping track of where each object should be, and using one function to draw both.
It's a little hard to tell what's going on in your code since some functions and variable declarations are missing (I don't see you ever actually drawing a bullet, for example - might be a bug in your BulletPattern?), but something like this might do the trick:
void GameMovements()
{
while (true)
{
//MOVEMENTS FOR PLAYER 1
if (GetAsyncKeyState(VK_LEFT) && Player1XCoordinate != GAMEBOARD_LEFT)
{
Player1XCoordinate -= 3;
}
else if (GetAsyncKeyState(VK_RIGHT) && Player1XCoordinate != GAMEBOARD_RIGHT)
{
Player1XCoordinate += 3;
}
else if (GetAsyncKeyState(VK_UP) && Player1YCoordinate != SPACESHIP_TOP)
{
Player1YCoordinate -= 2;
}
else if (GetAsyncKeyState(VK_DOWN) && Player1YCoordinate != SPACESHIP_BOTTOM)
{
Player1YCoordinate += 2;
}
Sleep(10);
UpdateBulletPosition();
DrawObjects();
}
}
void UpdateBulletPosition()
{
//if the bullet hits the top of the screen, remove it
if (bulletYCoordinate == GAMEBOARD_TOP)
{
bulletXCoordinate = 0;
bulletYCoordinate = 0;
}
//I assume you're automatically generating bullets whenever possible; you'll have to adjust this conditional if that's not the case
//no bullet? generate one
if (bulletXCoordinate == 0)
{
bulletXCoordinate = Player1XCoordinate + 3;
bulletYCoordinate = 25;
}
else
{
bulletYCoordinate--;
Sleep(100);
}
}
void DrawObjects()
{
//wipe the screen and show status first
system("cls");
GameBorderAndStatus();
SetCoordinate(Player1XCoordinate, Player1YCoordinate);
cout << " ^ \n";
SetCoordinate(Player1XCoordinate, Player1YCoordinate + 1);
cout << "^==|==^ \n";
//only draw the bullet if there's a bullet there to draw
if (bulletXCoordinate != 0)
{
SetCoordinate(bulletXCoordinate, bulletYCoordinate);
cout << ".\n";
}
}
const int GAMEBOARD_LEFT = 16;
const int GAMEBOARD_RIGHT = 94;
const int GAMEBOARD_TOP = 3;
const int SPACESHIP_TOP = 24;
const int SPACESHIP_BOTTOM = 28;
int Player1XCoordinate = 55, Player2XCoordinate = 55;
int Player1YCoordinate = 28;
int bulletXCoordinate = 0, bulletYCoordinate = 0;
I also made some tweaks to the rest of your code. Every case in your if-else block used the same basic drawing code, so I pulled that out of the if-else entirely. That also let me drop the entire initialization if-else.
I also dropped one of your vertical coordinates for the spaceship. You really don't need two; just keep track of the upper coordinate and draw the lower half of the ship at Player1YCoordinate + 1.
Finally, I replaced your hardcoded board edges with constants. Magic numbers are generally frowned upon; using named constants makes it easier to determine why you're using a given value in a given location, as well as making it easier to update the code in the future (perhaps you need to update for a different console size).

Related

How would i change the display of the arrays from numbers to strings C++

it is precoded and is an assignment i cant figure it out without changing most of the code any help would be appreciated thank you. when you run the program its like farmville and the code will display the "land" as 0 1 2 3 4 5 6 one of those the assignment is to change those 0 1 2 ect.. to be be able to say "unplowed" "plowed" "dead" ect. ive tried multiple things and i cant figure it out for the life of me thank you for any insight you have
#include <iostream>
#include <time.h>
#include <windows.h> // WinApi header
#include <stdlib.h>
#include <MMSystem.h>
#include <string.h>
#include <string>
using namespace std;
// Constants
const int SIZE_OF_FARM = 5;
// Global variables
int farmGrid[SIZE_OF_FARM]; // Declare 5 squares as size of your farm.
int coins = 300;
// Function declarations
void doGameLoop();
void sleep(unsigned int mseconds);
void plowTheLand();
void displayTheFarm();
void seedTheLand();
void harvestTheLand();
void beep();
void main() // START HERE!
{
/*
Initialize the farmGrid array.
A value of 0 means fallow ground (unplowed),
1 means plowed,
2 means seeded with strawberries,
3 means growing,
4 means died,
5 means ripe,
6 means harvested
*/
farmGrid[0] = 0;
farmGrid[1] = 0;
farmGrid[2] = 0;
farmGrid[3] = 0;
farmGrid[4] = 0;
doGameLoop();
}
void displayTheFarm()
{
//system("cls");
cout << endl;
for (int i=0; i<SIZE_OF_FARM; i++)
{
cout << farmGrid[i] << endl;
}
}
/*
Delaying example: sleep(3000); // Delays for 3 seconds.
*/
void sleep(unsigned int mseconds)
{
clock_t goal = mseconds + clock();
while (goal > clock());
}
void doGameLoop()
{
char response = ' '; // defaults to nothing
do
{
displayTheFarm();
cout << endl;
// I input a color for the display here
system("Color F3");
// END
cout << "<<< Menu - Coins=" << coins << " >>>" << endl;
cout << "P - Plow" << endl;
cout << "S - Seed" << endl;
cout << "H - Harvest" << endl;
cout << "X - eXit" << endl;
cout << "Select a letter: ";
cin >> response;
if (response == 'P' || response == 'p')
{
plowTheLand();
//ADDED SOUND TO INPUTS---------------------------------------------
PlaySound("C:\\SOUNDS\\BELLS.WAV", NULL, SND_ASYNC);
//----------------------------------------------------------------------------
// _------------------------------------------------------------------------
}
else if (response == 'S' || response == 's')
{
seedTheLand();
//ADDED SOUND TO INPUTS---------------------------------------------
PlaySound("C:\\SOUNDS\\BELLS.WAV", NULL, SND_ASYNC);
//----------------------------------------------------------------------------
// _------------------------------------------------------------------------
}
else if (response == 'H' || response == 'h')
{
harvestTheLand();
//ADDED SOUND TO INPUTS---------------------------------------------
PlaySound("C:\\SOUNDS\\BELLS.WAV", NULL, SND_ASYNC);
//----------------------------------------------------------------------------
// _------------------------------------------------------------------------
}
else
{
beep(); // Audible sound for invalid entry.
}
} while( response != 'x' && response != 'X' );
}
void plowTheLand()
{
if (farmGrid[0] == 0) // if fallow ground then you may plow
{
farmGrid[0] = 1;
farmGrid[1] = 1;
farmGrid[2] = 1;
farmGrid[3] = 1;
farmGrid[4] = 1;
coins = coins - 25; // cost 10 per plot. CHANGED TO 5 COINS
}
else
{
beep();
}
}
void seedTheLand()
{
if (farmGrid[0] == 1) // if plowed ground then you may seed.
{
// Plant seed, cost 50 per plot.
farmGrid[0] = 2;
farmGrid[1] = 2;
farmGrid[2] = 2;
farmGrid[3] = 2;
farmGrid[4] = 2;
coins = coins - 250;
displayTheFarm();
sleep(5000); // wait 5 seconds
// Now they are ripe.
farmGrid[0] = 5;
farmGrid[1] = 5;
farmGrid[2] = 5;
farmGrid[3] = 5;
farmGrid[4] = 5;
}
else
{
beep();
}
}
void harvestTheLand()
{
if (farmGrid[0] == 5) // if ripe then you may harvest.
{
// Harvest, street value of 100 per strawberry.
farmGrid[0] = 6;
farmGrid[1] = 6;
farmGrid[2] = 6;
farmGrid[3] = 6;
farmGrid[4] = 6;
coins = coins + 500;
displayTheFarm();
sleep(5000); // wait 5 seconds
// Now they are fallow ground again.
farmGrid[0] = 0;
farmGrid[1] = 0;
farmGrid[2] = 0;
farmGrid[3] = 0;
farmGrid[4] = 0;
}
else
{
beep();
}
}
void beep()
{
Beep(523,100); // 523 hertz (C5) for 100 milliseconds
//Beep(587,500);
//Beep(659,500);
//Beep(698,500);
//Beep(784,500);
}
If I understand you right, you can use a switch as the previous answer suggested, or this, or something else:
std::string farmStatus[] = { "Plowed", "Seeded with strawberries", "Growing",
"Died", "Ripe", "Harvested" };
void displayTheFarm()
{
for (int i = 0; i < SIZE_OF_FARM; i++)
cout << farmStatus[farmGrid[i]] << endl;
}
All you need is a switch case right where you display your so-called grid, for instance
for (int i=0; i<SIZE_OF_FARM; i++)
{
switch(farmGrid[i]) {
case 0: std::cout << “unplowed”; break;
case 1: ...
}
}

Error with array displaying

int move_player() {
if (GetAsyncKeyState(VK_RIGHT) && current_x<max_x) {
int old_x = current_x;
int new_x = current_x+1;
path[old_x] = '_';
path[new_x] = player;
system("cls");
cout << endl;
for (int a=0; a <= 9; a++) {
cout << path[a];
}
} else if (GetAsyncKeyState(VK_LEFT) && current_x>min_x) {
int old_x = current_x;
int new_x = current_x-1;
path[old_x] = '_';
path[new_x]=player;
system("cls");
cout << endl;
for (int b = 0; b <= 9; b++) {
cout << path[b];
}
}
return current_x;
}
What the bulk of code does is it just moves around an object (only right or left). It starts by showing the object on the far left and then I can move it right once but after it just does nothing when I press the right or left key.
How can I solve it?
How can I solve it?
You'll need to use a while loop around the if-else block.
or
call move_player in a while loop in the calling function.

Error C2440, Battleship C++

My compiler is telling me that I have an error, but I've e-mailed my instructor and he says my code is perfectly fine.
The error is Error:
1 error C4716: 'ShipPlacement' : must return a value, line 139
I'm unsure as to where I went wrong exactly so I'm going to share my code for ShipPlacement:
ShipPlacement(Coord grid[10][10])
{
CoordAndBearing SetBowAndDirection();
CoordAndBearing cab;
cab = SetBowAndDirection();
int start;
if((cab.dir == 3) || (cab.dir == 1)) // GOING HORIZONTAL //
{
if (cab.dir == 3)
start = cab.bx;
else
start = cab.bx - 4;
for(int i = start; i <= start + 4; i = i + 1)
{
grid[i][cab.by].isShip = true;
}
}
else // GOING VERTICAL
{
if(cab.dir == 0)
start = cab.by;
else
start = cab.by - 4;
for (int i = start; i <=start + 4; i = i + 1)
{
grid[cab.bx][i].isShip = true;
}
}
}
And here is my int main:
int main()
{
srand((unsigned int) time (NULL));
void ShipPlacement(Coord grid[10][10]);
Coord grid[10][10];
SetGridParameters(grid);
ShipPlacement(grid);
int ammo = 18;
int hits = 0;
while (hits < 5 && ammo >0 )
{
int x;
int y;
DisplayGrid(grid);
cout << "Ammo left = " << ammo << endl;
cout << "Enter Coord: " << endl;
cin >> x >> y;
ammo= ammo - 1;
if (grid [x][y].isShip == true)
{
hits = hits + 1;
}
else
{
cout << " You missed... " << endl;
}
}
DisplayGrid(grid);
if(hits == 5 )
{
cout << "You sunk the U.S.S McCall!!";
}
else
{
cout << " You lost ";
}
system("pause");
return 0;
}
You've defined the ShipPlacement function without a return type. Some (most?) compilers will issue a warning stating they're assuming it returns an int, followed by an error since it doesn't.
Just explicitly define it as "returning" void (i.e., void ShipPlacement(Coord grid[10][10])), and you should be fine.

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++ While loop that stops if an array is equal too zero

I'm having a little bit problem with my game. What I want is when one out of two arrays becomes all 0's the loop will stop. Currently the loop stops when both arrays are equal to zero.
What I think is the problem but don't have a solution is that I have both array statements in one loop, it will run from top too bottom EVEN if array1(border1) has gotten all 0's.
What to you think?
void ShootAtShip(int board1[], int board2[], string names[], int cap) {
const int hit = 0;
int shot = 0;
bool won = false;
int temp;
for (int i = 0; i < cap; i++) {
while ((board1[i] != 0 || board2[i] != 0)) { //detects if any board has all their ships shot down
cout << names[1] << " set a position to shoot." << endl;
cin >> shot;
temp = shot;
while ((shot >= cap) || (shot < 0)) { //detects if the number is allowed
cout << "That number is not allowed, "<< names[1] << " set a position to shoot." << endl;
cin >> shot;
}
if (board1[shot] != 0) {
board1[shot] = 0;
cout << "Hit!" << endl;
}
else {
cout << "You missed." << endl;
}
shot = 0;
cout << names[0] << " set a position to shoot." << endl;
cin >> shot;
while ((shot >= cap) || (shot < 0)) { //detects if the number is allowed
cout << "That number is not allowed, " << names[0] << " set a position to shoot." << endl;
cin >> shot;
}
if (board2[shot] != 0) {
board2[shot] = 0;
cout << "Hit!" << endl;
}
else {
cout << "You missed." << endl;
}
}
}
cout << "Testing is while loop stops";
}
The key is that you have to check the state of the entire board at each loop iteration. Like this:
void ShootAtShip(int board1[], int board2[], string names[], int cap) {
for (int i = 0; i < cap; i++)
{
while ( 1 )
{
bool board1HasShips = false;
bool board2HasShips = false;
for ( int j = 0; j < cap; j++ )
{
if ( board1[j] != 0 )
{
board1HasShips = true;
break;
}
}
for ( int j = 0; j < cap; j++ )
{
if ( board2[j] != 0 )
{
board2HasShips = true;
break;
}
}
if ( !board1HasShips || !board2HasShips ) break;
// past this point we know that both boards have ships.
// shoot at ships
}
}
}
Especially when writing games, it's a good idea to try and organize your code into functions.
Personally I would do something like this:
bool isGameOver(int board1[], int board2[], size_t cap)
{
bool lost1 = true;
bool lost2 = true;
for (size_t i = 0; i < cap && lost1 != false; ++i)
if (board1[i] != 0)
lost1 = false;
if (lost1)
return true;
for (size_t i = 0; i < cap && lost2 != false; ++i)
if (board2[i] != 0)
lost2 = false;
return lost2;
}
Then use this as a conditional to break the loop.
Since you are using c++ however, why not abstract the boards into a class? This would allow you to store info such as how many ships are left in each board.
Also consider using the std::array class template in c++ so you won't have to pass the array size seperately and try to use size_t or std::size_t for array indexing.