I've Made A Program That Makes The Whole Game To Work Perfectly, And The Only Thing I Can't Do Is The Checking For A Win.
I've Made The Game In Two Files:
1. Main
2. Functions.
This Is The 'Main' File:
#include <iostream>
#include <sstream>
#include <windows.h>
#include <string>
using namespace std;
void getname();
void scoregiving();
void gamestart();
void boardmaking();
void fullgameplay();
int main()
{
gamestart();
getname();
scoregiving();
fullgameplay();
}
This Is The Functions File:
#include <iostream>
#include <sstream>
#include <Windows.h>
#include <string>
using namespace std;
string p1, p2;
int tu,
board[6][7],
colomuns[7],
makeboard,
makeboard1,
scoregive,
scoregive1,
input,
colomunss,
check,
check1;
void line()
{
cout << "|=|=|=|=|=|=|=|\n|";
}
void getname()
{
cout << "\n\nPlayer, Please Enter Your Name. You'll Be X\n<< ";
cin >> p1;
cout << "2nd Player, Please Enter Your Name. You'll Be O\n<< ";
cin >> p2;
tu = 1;
}
void gamestart()
{
cout << " (--OOO--OOO---OOO--OOO--)\n";
cout << " |XX========XXX========XX|\n";
cout << " ||CONNECT 4 BY: NETVIZHEN||\n";
cout << " |XX========XXX========XX|\n";
cout << " (--OOO--OOO---OOO--OOO--)";
}
void boardmaking()
{
cout << "\n\nBoard:\n";
cout << "\n 0 1 2 3 4 5 6\n";
line();
for (makeboard = 0; makeboard <= 5; makeboard ++)
for (makeboard1 = 0; makeboard1 <= 6; makeboard1++)
{
if (board[makeboard][makeboard1] == 0)
{
cout << " |";
}
else if (board[makeboard][makeboard1] == 1)
{
cout << "X|";
}
else if (board[makeboard][makeboard1] == 2)
{
cout << "O|";
}
if (makeboard1 == 6)
{
cout << "\n";
line();
}
}
}
void scoregiving()
{
for (scoregive = 0 ; scoregive < 6 ; scoregive++)
for (scoregive1 = 0 ; scoregive1 < 7 ; scoregive1++)
board[scoregive][scoregive1] = 0;
for (colomunss = 0; colomunss <= 6; colomunss++)
colomuns[colomunss] = 0;
}
void wincheck()
{
for (check = 0; check <=5; check++)
for (check1 = 0; check1 <= 6; check1++)
if (board[check][check1] == tu)
if (board[check - 1][check1] == tu && board[check - 2][check1] == tu && board[check - 3][check1] == tu && board[check][check1] == tu)
cout << "ggh";
}
void putin()
{
cout << "\n<< ";
cin >> input;
if (input >= 7)
cout << "\nThis Location Is Outside The Board. Please Retry.";
else if (colomuns[input] > 5 )
cout << "\nThis Column Is Full. Please Retry.";
else
{
board[5-colomuns[input]][input] = tu;
colomuns[input]++;
wincheck();
if (tu == 2)
tu--;
else if (tu == 1)
tu++;
}
}
void fullgameplay()
{
while(true)
{
boardmaking();
putin();
}
}
Is it a tic-tac-toe game ?
But if it is then why row & column are not of same size because it will be a problem to determine the winner if he has his wining streak diagonally.
Brute force: from each position, traverse in the eight different directions as long as the position is in the board, not empty and the same as the original position. If you reach 4, then the player in the original position is the winner.
Since you should do it after each play, at most one player can have a connect 4.
You can make an array of the 8 directions to use the needed deltas for x and y for each direction.
As previously mentioned you would want to check each direction either in 8 for loops or with boolean values to check each time.
bool n = true;
bool ne = true;
bool e = true;
bool se = true;
bool s = true;
bool sw = true;
bool w = true;
bool nw = true;
for (int count = 0; count < 4; count++)
{
if (board[x + count][y] != tu)
{
e = false;
}
if (board[x + count][y + count] != tu)
{
ne = false;
}
//continue for each direction.
if(n == true || ne == true || e == true //and so on)
{
//player wins
}
}
This is the main concept that could be used though obviously some changes will have to be made to fit your code.
Related
I'm working on a C++ card game and I'm having an issue where I have variables in different procedures but they don't seem to keep their values in each method.
I am a total beginner when it comes to working with procedures, so apologies for what must seem like such a simple issue.
Here's my code for reference:
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
class player {
public:
string name = "";
int credit = 0;
int bet = 0;
};
class cards {
public:
string suit;
int number = 0;
};
void Initialise() {
//initialise Vars
string suits[4] = { "Coins", "Flasks", "Sabers", "Staves" };
int values[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
}
void DefineCards(cards Card[60]) {
//Define Card Values
for (int c = 0; c < 60; c++) {
if (c >= 0 && c <= 14) {
Card[c].suit = "Coins";
Card[c].number = c;
}
else if (c >= 15 && c <= 29) {
Card[c].suit = "Flasks";
Card[c].number = c - 14;
}
else if (c >= 30 && c <= 44) {
Card[c].suit = "Sabers";
Card[c].number = c - 29;
}
else if (c >= 45 && c <= 60) {
Card[c].suit = "Staves";
Card[c].number = c - 44;
}
}
}
void CreatePlayer(player CurrentPlayer) {
bool correct = false;
string choice;
do {
cout << "Please input your name: " << endl;
cin >> CurrentPlayer.name;
cout << "Your name is " << CurrentPlayer.name << "? (Y/N)" << endl;
cin >> choice;
if (choice == "y" || choice == "Y") {
correct = true;
}
else {
correct = false;
}
} while (correct == false);
CurrentPlayer.credit = 1000;
}
//Game Procedeures
void Betting(player CurrentPlayer){
int pot = 0;
int bet = 0;
bool correct = false;
do {
cout << "Current Bet: " << CurrentPlayer.bet << " Total Pot: " << pot << " Credit: " << CurrentPlayer.credit << "\n\n";
cout << "Please enter a bet to begin: " << endl;
cin >> bet;
if (bet <= CurrentPlayer.credit) {
correct = true;
}
else if (bet > CurrentPlayer.credit) {
cout << "You don't have enough credits.";
}
else if (bet < 1) {
cout << "That's an impossible value, Please try again.";
}
} while (correct == false);
pot = pot + bet;
}
int main(int argc, char** argv) {
cards Card[60];
player CurrentPlayer;
//Initialisation procedeures
Initialise();
DefineCards(Card);
CreatePlayer(CurrentPlayer);
//Game
Betting(CurrentPlayer);
//Display Cards
return 0;
}
Ive been learning C++ and I decided to make a tictactoe project that utilizes a MiniMax algorithm. I have made all the functionality for playing, including 2 player. Why doesn't my minimax algorithm when I choose to play with the AI work ? It always moves to 0 or 8 and I can't figure out why. Any help will be appreciated
TicTacToe.h
#ifndef TICTACTOE_TICTACTOEGAME_H
#define TICTACTOE_TICTACTOEGAME_H
#include <string>
#include <iostream>
#include <vector>
class TicTacToeGame {
struct move{
int score;
int index;
};
public:
const int PLAYER1_INDEX = 1;
const int PLAYER2_INDEX = 2;
const int AI_INDEX = 3;
TicTacToeGame();
void play(TicTacToeGame);
bool hasWon() const;
bool haveTied() const;
char getMarker(int, int) const;
void setMarker(int, int);
void resetMarker(int);
int getCurrentPlayer() const;
std::vector<int> possibleMoves();
private:
char board[3][3];
std::string player1_name;
std::string player2_name;
int currentPlayer;
bool isMultiplayer;
int moveCount = 0;
void init();
void printBoard();
void setPlayer1Name(std::string);
void setPlayer2Name(std::string);
std::string getPlayer1Name() const;
std::string getPlayer2Name() const;
void switchCurrentPlayer();
std::string winMessage();
int getRow(int) const;
int getColumn(int) const;
bool checkMarker(int, int);
void makeAIMove(TicTacToeGame);
move miniMax(TicTacToeGame, int);
};
#endif //TICTACTOE_TICTACTOEGAME_H
TicTacToe.cpp
#include "TicTacToeGame.h"
// Player is MINIMIZER, AI is MAXIMIZER
TicTacToeGame::move TicTacToeGame::miniMax(TicTacToeGame board, int player) {
move current, best;
int otherPlayer = (player == 1) ? 3 : 1;
if (board.hasWon()){
if(player == PLAYER1_INDEX){
best.score = 10;
return best;
} else if(player == AI_INDEX){
best.score = -10;
return best;
}
} else if(board.haveTied()){
best.score = 0;
return best;
}
if(player == AI_INDEX){
best.score = -9999999;
} else best.score = 9999999;
std::vector<int> possibleMoves = board.possibleMoves();
for (int i = 0; i < possibleMoves.size(); i++) {
board.setMarker(possibleMoves[i], player);
current = miniMax(board, otherPlayer);
current.index = possibleMoves[i];
if(player == AI_INDEX){
if(current.score > best.score) {
best = current;
}
} else
if(current.score < best.score){
best = current;
}
board.resetMarker(possibleMoves[i]);
}
std::cout << "best index: " << best.index << " best score: " << best.score << std::endl;
return best;
}
void TicTacToeGame::makeAIMove(TicTacToeGame board) {
int move = miniMax(board, getCurrentPlayer()).index;
setMarker(move, getCurrentPlayer());
std::cout << "\nThe AI has moved to " << move << std::endl;
}
std::vector<int> TicTacToeGame::possibleMoves() {
std::vector<int> possibleMoves;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if(board[i][j] != 'X' && board[i][j] != 'O'){
possibleMoves.push_back(3 * i +j);
}
}
}
return possibleMoves;
}
TicTacToeGame::TicTacToeGame() {
init();
}
// Create the board with indexes
void TicTacToeGame::init() {
currentPlayer = 2;
int k = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++, k++) {
board[i][j] = '0' + k;
}
}
}
// Prints the board int he format of a TicTacToe game
void TicTacToeGame::printBoard() {
std::cout << "\n";
for (int i = 0; i < 3; i++) {
if (i != 0) std::cout << "\n --------------------\n";
for (int j = 0; j < 3; j++) {
std::cout << "\t" << board[i][j];
if (j != 2) std::cout << "\t|";
}
}
}
// Handles the playing
void TicTacToeGame::play(TicTacToeGame game) {
std::string welcome = "\t\t*********************************************\n\t\t*\t\tWelcome to the TicTacToe game !\t\t*\n\t\t*********************************************\n\n\n";
int position = -1;
char multiplayer;
char playAgain;
std::cout << welcome;
while (true){
std::cout << "Do you want to play multiplayer ? (y/n): ";
std::cin >> multiplayer;
multiplayer = tolower(multiplayer);
// Checks if input is valid, asks for another input if not
while (std::cin.fail() || (multiplayer != 'y' && multiplayer != 'n')) {
std::cout << "Invalid entry ! Enter either y OR n: ";
std::cin.clear();
std::cin.ignore(256, '\n');
std::cin >> multiplayer;
multiplayer = tolower(multiplayer);
}
if (multiplayer == 'y') isMultiplayer = true;
else if (multiplayer == 'n') isMultiplayer = false;
break;
}
// Initializing players
std::cout << "Player 1, please type in your name: ";
std::cin >> player1_name;
// Checks if input is valid, asks for another input if not
while (std::cin.fail()) {
std::cout << "Invalid entry ! Re-enter your name: ";
std::cin.clear();
std::cin.ignore(256, '\n');
std::cin >> player1_name;
}
setPlayer1Name(player1_name);
std::cout << getPlayer1Name() << " will be X." << std::endl;
// Only initializes player 2 if it's a multiplayer game
if (isMultiplayer){
std::cout << "\nPlayer 2, please type in your name: ";
std::cin >> player2_name;
// Checks if input is valid, asks for another input if not
while (std::cin.fail()) {
std::cout << "Invalid entry ! Re-enter your name: ";
std::cin.clear();
std::cin.ignore(256, '\n');
std::cin >> player2_name;
}
setPlayer2Name(player2_name);
std::cout << getPlayer2Name() << " will be O.\n" << std::endl;
}
std::cout << "Starting game: \nINSTRUCTIONS: Select the number of the position where you want to play" << std::endl;
// Play loop
while (!hasWon()) {
printBoard();
// Alternate between players after evey move
switchCurrentPlayer();
std::cout << "\ncurrent player is " << currentPlayer << std::endl;
// Player's move
if (currentPlayer == PLAYER1_INDEX || currentPlayer == PLAYER2_INDEX){
while (true) {
std::cin >> position;
// Checks if input is an integer, asks for another input if not
while (std::cin.fail() || position < 0 || position > 8) {
std::cout << "Invalid entry ! Enter a number between 0 and 8 inclusive: ";
std::cin.clear();
std::cin.ignore(256, '\n');
std::cin >> position;
}
// Check if there's an X or O in that position already, if yes - ask for another position to if so. If no - writes X/O
if (checkMarker(getRow(position), getColumn(position))) {
setMarker(position, getCurrentPlayer());
break;
} else {
std::cout
<< "There's already an X/O in that position. Try place it in an empty spot.\nEnter a new position: ";
}
}
}
// AI's move
else if (currentPlayer == AI_INDEX){
makeAIMove(game);
}
moveCount++;
// Checks for a winner or a tie after every move
if (hasWon() || haveTied()) {
if (hasWon()) std::cout << winMessage() << std::endl;
else if(haveTied()) std::cout << "The game is a tie !" << std::endl;
std::cout << "\n\nDo you want to play again ? Enter y OR n: ";
std::cin >> playAgain;
playAgain = tolower(playAgain); // converts to lowercase
// If there's a winner ask if user wants to play another game, stops application if not
while (true) {
if (playAgain != 'y' && playAgain != 'n') {
std::cout << playAgain << std::endl;
std::cout << "Invalid expression ! Enter either y OR n: ";
std::cin >> playAgain;
playAgain = tolower(playAgain); // converts to lowercase
} else if (playAgain == 'y' || playAgain == 'n') break;
}
if (playAgain == 'y') {
std::cout << "Generating a new board " << std::endl;
init();
moveCount = 0;
} else if (playAgain == 'n') {
std::cout << "\nThank you for playing the TicTacToe game !\nExiting the game.";
break;
}
}
}
}
std::string TicTacToeGame::winMessage() {
if (getCurrentPlayer() == 1) { return "\n\n" + getPlayer1Name() + " has won !"; }
else if (getCurrentPlayer() == 2) return "\n\n" + getPlayer2Name() + "has won !";
else return "\n\nThe AI has won !";
}
// Checks for winning conditions
bool TicTacToeGame::hasWon() const {
for (int i = 0; i < 3; ++i) {
// Checking horizontals
if (getMarker(0, i) == getMarker(1, i) && getMarker(1, i) == getMarker(2, i)) {
//cout << "horizontal alignment";
return true;
}
// Chekcing verticals
if (getMarker(i, 0) == getMarker(i, 1) && getMarker(i, 1) == getMarker(i, 2)) {
//cout << "vertical alignment";
return true;
}
}
// Checking diagonals
if (getMarker(0, 0) == getMarker(1, 1) && getMarker(1, 1) == getMarker(2, 2)) return true;
if (getMarker(0, 2) == getMarker(1, 1) && getMarker(1, 1) == getMarker(2, 0)) return true;
// If no alignment
return false;
}
void TicTacToeGame::setPlayer1Name(std::string name) {
player1_name = name;
}
void TicTacToeGame::setPlayer2Name(std::string name) {
player2_name = name;
}
std::string TicTacToeGame::getPlayer1Name() const {
return player1_name;
}
std::string TicTacToeGame::getPlayer2Name() const {
return player2_name;
}
int TicTacToeGame::getCurrentPlayer() const {
return currentPlayer;
}
int TicTacToeGame::getRow(int row) const{
return row / 3;
}
int TicTacToeGame::getColumn(int column) const {
return column % 3;
}
bool TicTacToeGame::checkMarker(int row, int column) {
if (getMarker(row, column) == 'X' || getMarker(row, column) == 'O') return false;
return true;
}
char TicTacToeGame::getMarker(int row, int column) const {
return board[row][column];
}
void TicTacToeGame::setMarker(int position, int player) {
board[getRow(position)][getColumn(position)] = player == 1 ? 'X' : 'O';
}
/* Switches the play either from:
* - PLAYER1 to PLAYER2
* - PLAYER 2 to PLAYER1
* - AI to PLAYER1
* - PLAYER1 to AI
*/
void TicTacToeGame::switchCurrentPlayer() {
if (currentPlayer == PLAYER1_INDEX && !isMultiplayer){
currentPlayer = AI_INDEX;
std::cout << "\n\nIt's the AI's turn now" << std::endl;
} else if (currentPlayer == PLAYER1_INDEX) {
currentPlayer = PLAYER2_INDEX;
std::cout << "\n\nIt's " << getPlayer2Name() << "'s turn, select the position you want to move to:";
} else if (currentPlayer == PLAYER2_INDEX || currentPlayer == AI_INDEX) {
currentPlayer = PLAYER1_INDEX;
std::cout << "\n\nIt's " << getPlayer1Name() << "'s turn, select the position you want to move to:";
}
}
bool TicTacToeGame::haveTied() const {
if (moveCount == 9) return true;
return false;
}
void TicTacToeGame::resetMarker(int position) {
board[getRow(position)][getColumn(position)] = (char) position;
}
main.cpp
#include "TicTacToeGame.h"
int main() {
TicTacToeGame game;
game.play(game);
return 0;
}
This line:
std::cout << "best index: " << best.index << " best score: " << best.score << std::endl;
best.index is uninitialized when this line is printed. That is, you never set best.index to a value.
Further, you are passing an instance of TicTacBoard by value as a parameter to another instance of methods on the same class. Some of your code operates on the board parameter. Other parts work implicitly on this. You probably want to eliminate the passing around of board by value.
Change your code such that it's invoked like this in main.
TicTacToeGame game;
game.play();
And remove all the places where you pass board as a parameter.
I'm making a blackjack game and I have a pointer arrays for my dealer's and player's hand. The issue is that when I randomly generate cards to be stored in the array, they both have the same cards. Not sure if it is because they both point to the same address or something I haven't noticed.
#include <iostream>
#include <ctime>
#include <random>
#include <iomanip>
#include <cstdlib>
using namespace std;
class Blackjack
{
public:
Blackjack();
void playGame();
int pbalance;
int betamount;
int loop= 1;
int *playerbalances;
int pbalan,pbal;
void firstbalance();
void clearhand();
private:
int dhandSize;
int phandSize;
int dhandSum;
int phandSum;
int phit;
int pstand;
bool playerDone;
bool dealerDone;
void addPlayerCard();
void addDealerCard();
void printHand();
void sumHands();
void playerbalance();
void playerbet();
int *dhand[];
int *phand[];
};
Blackjack::Blackjack()
{
srand(time(0));
dhandSize = 0;
phandSize = 0;
dhandSum = 0;
phandSum = 0;
playerDone = false;
dealerDone = false;
}
void Blackjack::playGame()
{
if (pbal>0)
{
// Start the player and dealer with two cards
playerbet();
addPlayerCard();
addPlayerCard();
addDealerCard();
addDealerCard();
sumHands();
printHand();
if (dhandSum == 21)
{
cout << "Dealer has blackjack. Dealer wins.\n";
clearhand();
return;
}
else if (phandSum == 21)
{
cout << "Player has blackjack. Player wins.\n";
clearhand();
return;
}
while (dealerDone == false || playerDone == false)
{
if (playerDone == false)
{
cout << "Would you like to hit? (1 - Yes, 2 - No)\n";
cin >> phit;
if (phit == 1)
{
addPlayerCard();
printHand();
sumHands();
if (phandSum > 21)
{
cout << "Player's hand exceeded 21. Player loses"<<endl;
pbalan =(pbalan - betamount);
cout <<"[you lose $"<<betamount<<" of money!]"<<endl;
cout <<"[your current balance is: $"<<pbalan<<"]"<<endl;
clearhand();
return;
}
}
}
if (playerDone == false)
{
cout << "Would you like to stand? (1 - Yes, 2 - No)\n";
cin >> pstand;
}
if (pstand == 1)
{
playerDone = true;
}
if (dhandSum < 17 && dealerDone != true)
{
addDealerCard();
printHand();
sumHands();
if (dhandSum > 21)
{
cout << "Dealer hand exceeded 21. Dealer loses.\n";
return;
}
}
else if (dhandSum >= 17)
{
dealerDone = true;
}
if (phandSum == 21 && dhandSum == 21)
{
cout << "Push, player and dealer reached 21.\n";
return;
}
else if (phandSum == 21)
{
cout << "Player reached 21. Player wins.\n";
return;
}
else if (dhandSum == 21)
{
cout << "Dealer reached 21. Dealer wins.\n";
pbalan =(pbalan - betamount);
cout <<"[you lose $"<<betamount<<" of money!]"<<endl;
cout <<"[your current balance is: $"<<pbalan<<"]"<<endl;
return;
}
if ((playerDone == true && dealerDone == true) || (phandSize == 5 && phandSize == 5))
{
if (dhandSum < phandSum)
{
cout << "Sum of your hand exceeds the dealer's sum of " << dhandSum << "! You win!";
return;
}
else if (phandSum == dhandSum)
{
cout << "Dealer sum of " << dhandSum << " is equal to the sum of your hand. Tie game.";
return;
}
else if (dhandSum > phandSum)
{
cout << "Sum of your hand is lower than the dealer's sum of " << dhandSum << ". You lose!"<<endl;
pbalan =(pbalan - betamount);
cout <<"[you lose $"<<betamount<<" of money!]"<<endl;
cout <<"[your current balance is: $"<<pbalan<<"]"<<endl;
return;
}
}
}
}
}
void Blackjack::clearhand()
{
for (int i = 0; i < dhandSize; i++) { delete dhand[i]; }
for (int i = 0; i < phandSize; i++) { delete phand[i]; }
phandSize = 0;
dhandSize = 0;
}
void Blackjack::firstbalance()
{
cout << "Welcome to Blackjack" <<endl;
cout << "please enter a starting balance: " <<endl;
cin >> pbal;
playerbalances = &pbalan;
*playerbalances = pbal;
}
void Blackjack::playerbet()
{
cout << "how much do you want to bet?"<<endl;
cin >> betamount;
}
void Blackjack::addPlayerCard()
{
if (phandSize <= 5)
{
*phand[phandSize] = 1 + (rand() % 13);
phandSize++;
}
else
{
cout << "Sorry. You have reached the maximum number of cards (5)." << endl;
playerDone = true;
}
}
void Blackjack::addDealerCard()
{
if (dhandSize <= 5)
{
*dhand[dhandSize] = 1 + (rand() % 13);
dhandSize++;
}
else
{
dealerDone = true;
}
}
void Blackjack::printHand()
{
cout << "Your current hand is...\n";
for (int i = 0; i < phandSize; i++)
{
cout << " -" << *phand[i] << "- \n\n";
}
cout << "Dealer's current hand is...\n";
for (int j = 0; j < dhandSize; j++)
{
cout << " -" << *dhand[j] << "- \n\n";
}
}
void Blackjack::sumHands()
{
dhandSum = 0;
phandSum = 0;
for (int i = 0; i < dhandSize; i++)
{
dhandSum += *dhand[i];
}
for (int j = 0; j < phandSize; j++)
{
phandSum += *phand[j];
}
cout << "Current player hand sum is: " << phandSum << endl;
}
using namespace std;
int main()
{
int exitGame = 1;
int i = 0;
Blackjack play;
if (i<1)
{
play.firstbalance();
i++;
}
do
{
play.playGame();
play.clearhand();
cout << "\nWould you like to play again? (1 - Yes, 2 - No)\n";
cin >> exitGame;
}
while (exitGame == 1);
cout << "\nThanks for playing!\n";
return 0;
}
The dealer cards should be different from the player cards but they are identical when you run the program.
The shows code declares a class with two members, as follows:
int *dhand[];
int *phand[];
These are the two members of the class, but this is not valid, standard C++. Variable-length arrays are not standard C++.
As such, the entire logic in this code becomes unspecified behavior. The behavior you observed was that the two arrays appear to be the same. Right. That's what unspecified behavior means, and this appears to be the behavior that results with your specific C++ compiler and implementation. Your C++ compiler appears to implement this by creating a class member whose size is a grand total of 0 bytes (after all, the size of the array is not specified, so it's nuthin'), with the expectation that this will be the last class member, and the application will be responsible for allocating some extra memory in addition to the one that's required for an instance of this object, in order to achieve a pseudo-array in this fashion.
But with two class members declares thusly, this ends up with two class members that are effectively one and the same. Which is the behavior you observed. Other C++ compilers may very well report a compilation error, since the program being ill-formed, with respect to the C++ standard.
To fix this issue you should replace these class members with proper arrays. Perusing the shown code, it looks like you expect these arrays to be, essentially, variably-sized arrays. This is what std::vector is for, and your C++ book should have one or more chapters that fully explain how to use std::vector to implement an array-like object that can grow and shrink in size, accordingly.
List.cpp (class definitions)
I have been working on code that is suppose to help familiarize with classes. My code currently has a function that displays a menu of options for the users. Option [1] is suppose to add a string, option [2] is suppose to remove a string from the list, option [3] prints the string list, option [4] exits. My option [1] seems to work okay as the user is able to input one string at a time but I am having a hard time with the removal of a string. The strings are currently stored in an array of 10 elements. I believe the function I wrote for the string removal is okay as I have debugged it and it seems successful, however, I am not seeing results on my console window.
My array is located in a private class in my class: string items[MAX_ITEMS]; along with another variable called: int totalItems;
The class is then called in my main function using a switch case:
//This code snippet below is located in a separate cpp file with main
cout << "Please enter the text you want to remove: " << endl;
cin >> userInput;
list1.remove(userInput);
////////////////////////////////////////////////////////////////////
//preprocessor directives
#include <iostream>
#include <string>
//header files
#include "list.h"
using namespace std;
List::List()
{
//clear array prior to starting (set everything to NULL)
for (int i = 0; i < MAX_ITEMS; i++)
{
items[i] = " ";
}
totalItems = 0;
}
//void List::init()
//{
// string items[MAX_ITEMS];
// totalItems = 0;
//}
bool List::insert(const string& data)
{
//verifies that string is not empty, not in the list, and not full
if (data.empty() == true || inList(data) == true || isFull() == true)
{
return false;
}
else
{
// items[isFull)] = data;
// totalItems++;
items[totalItems++] = data;
return true;
}
}
bool List::isEmpty() const
{
//runs through loop to verify array is empty
for (int i = 0; i < MAX_ITEMS; i++)
{
if (items[i].empty() != true)
{
return false;
}
}
return true;
}
//identifies whether the string is full or not
bool List::isFull() const
{
if (totalItems == MAX_ITEMS)
{
return true;
}
else
{
return false;
}
}
//identifies whether the string is already in the list or not
bool List::inList(const string& theList)
{
for (int i = 0; i < MAX_ITEMS; i++)
{
if (items[i] == theList)
{
return true;
}
}
return false;
}
bool List::remove(const string& data)
{
if (inList(data) == true || data.empty() == true)
{
return false;
}
for (int i = 0; i < MAX_ITEMS; i++)
{
if (items[i] == data)
{
items[i] == " ";
for (int j = i; j < MAX_ITEMS; j++)
{
items[j] = items[j + 1];
items[MAX_ITEMS - 1] == " ";
break;
}
}
}
totalItems--;
return true;
}
//prints list
void List::printList()
{
for (int i = 0; i < MAX_ITEMS; i++)
{
cout << i << items[i] << '\t';
}
}
list_test.cpp (main.cpp)
#include <iostream>
#include <string>
//header files
#include "list.h"
using namespace std;
//function prototypes
int showSelection();
int main()
{
List list1;
string userInput = "";
int userChoice;
// list1.init();
userChoice = showSelection();
while (userChoice != 4)
{
switch(userChoice)
{
case 1:
cout << "Please enter the text you want to add: " << endl;
cin >> userInput;
list1.insert(userInput);
/*if (list1.inList(userInput) == false)
{
cout << "Text is already entered in the list!" << endl;
}*/
if (list1.isFull() == true)
{
cout << "You have entered the MAXIMUM amount of elements!" << endl;
}
break;
case 2:
cout << "Please enter the text you want to remove: " << endl;
cin >> userInput;
list1.remove(userInput);
break;
case 3:
cout << "Printed list: " << endl;
list1.printList();
break;
}
userChoice = showSelection();
}
cout << "Goodbye. Please press enter to exit." << endl;
//TESTING PURPOSES FOR FUNCTIONS
cout << list1.insert(userInput) << endl;
cout << list1.isEmpty() << endl;
cout << list1.isFull() << endl;
cout << list1.inList(userInput) << endl;
return 0;
}
/* ===========================================
Name: showSelection
Desc: displays menu for user to choose options
for their inputted string(s).
Args: none
Retn: none
=========================================== */
int showSelection()
{
int userChoice;
bool exit = false;
while (exit == false)
{
cout << "\nTo select an option, please enter the corresponding number: " << endl;
cout << "[1] to add a string" << endl;
cout << "[2] to remove a string" << endl;
cout << "[3] to print a string" << endl;
cout << "[4] to exit" << endl << endl;
cin >> userChoice;
cout << "You entered option: " << userChoice << endl;
cout << '\n';
if (userChoice == 1 || userChoice == 2 || userChoice == 3 || userChoice == 4)
{
exit = true;
}
else
{
cout << "Invalid selection" << endl;
}
}`enter code here`
return userChoice;
}
Here is how you code should probably look:
bool List::remove(const string& data) {
// only check if the list is empty so you don't nececarily go through it
// you shoudn't ask here if the given string is in the list
// because you will search for it anyway just below
if (data.empty())
return false;
for (int i = 0; i < MAX_ITEMS; ++i) {
if (items[i] == data) { // now if it was found
items[i] = " "; // set it to your empty value
--totalItems; // prefix -- is faster then postfix one (no copy is created)
for (int j = i; j < MAX_ITEMS - 1; ++j) {
// stop at j < MAX_ITEMS - 1 because you wouldn't want
// to swap last element with the next because there
// is none behind it
if (items[j + 1] == " ")
// if the next item is already empty you don't need to shift any more
return true;
// swap the next item with much more
// efficient std::swap function
std::swap(items[j], items[j + 1]);
}
return true; // value is removed and items shifted so you can now return
}
}
// if function gets to this point that means the value wasn't found
return false;
}
If you would like to make your code more efficient, I can give you more suggestions on how to do it. This above should answer your question.
Also using an array for a struct like this isn't optimal at all. Using linked listed would mean no shifting would be required.
Edit: replaced long text with a code example
Edit2: added return statement if shifting is no longer necessary
FOR me it's unclear what you want to do as unavailability of full code to run.
But I think this should work as of what I think yo want to do
bool List::remove(const string& data){
for (int i = 0; i < totalItems; i++)
{
if (items[i] == data)
{
for (int j = i; j < totalItems-1; j++)
{
items[j] = items[j+1];
}
totalItems--;
return true;
}
}
return false;
if (inList(data) == true || data.empty() == true)
{
return false;
}
If the data parameter is in your list object, you return without removing anything? this should be !inList(data)
Additionally, when you make it into the loop below this code this loop:
for (int j = i; j < MAX_ITEMS; j++)
{
items[j] = items[j + 1];
items[MAX_ITEMS - 1] == " ";
break;
}
will only execute for j=i, the "break" statement will stop execution of this inner loop, and go back to the outer loop.
EDIT: this is how I personally would go about this problem.
bool List::remove(const string& data)
{
bool retVal;
if (!inList(data) || data.empty())
{
retVal = false;
}
else{
for (int i = 0; i < MAX_ITEMS; i++)
{
if (items[i] == data)
{
items[i] = " ";
for (int j = i; j < (MAX_ITEMS - 1); j++)
{
items[j] = items[j + 1];
}
items[MAX_ITEMS-1] = " ";
}
}
totalItems--;
retVal = true;
}
return retVal;
}
I recently received an assignment to create a bowling program in C++ that simulates two people bowling and outputs the correct score for each frame. My program works by first generating all the throws for each frame and then accumulating the score afterwards in a separate method. I was able to get the program to work when the player bowls a non-perfect game and a perfect game, but I am having problems with when a player bowls all spares. I rigged the code to make it so I have 9 for a first throw and 1 for the second throw (this is in frame.cpp). The total should be 190, but I am getting 191 and I can't seem to find the error. Each bowling class contains an array of 11 frames. I know there are only 10 frames but this is to account for if the player gets a strike on the tenth frame. Any help would be appreciated, thanks.
Here is the frame. h file
#ifndef FRAME_H
#define FRAME_H
#include<iostream>
using namespace std;
class Frame
{
private: int throw1;
int throw2;
int score;
bool spare;
bool strike;
public: Frame();
int genThrow(int size);
int getFirstThrow();
int getSecondThrow();
int getScore();
void setScore(int);
void setFirstThrow(int value1);
void setSecondThrow(int value2);
void setStrike(bool value);
void setSpare(bool value);
bool getStrike();
bool getSpare();
};
#endif
Here is the frame.cpp file
#include "Frame.h"
#include<iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
Frame::Frame()
{
spare = false;
strike = false;
throw1 = 0;
throw2 = 0;
score = 0;
}
//generates a random throw
int Frame::genThrow(int size)
{
int randomNumber = 0;
if (size < 10 || throw1 != 10)
{
randomNumber = 0 + rand() % (11 - throw1); //generate a number between 0 and 10
}
else
{
randomNumber = 0 + rand() % (11);
}
//cout << randomNumber << endl;
return randomNumber;
}
//get first throw
int Frame::getFirstThrow()
{
return throw1;
}
//get second throw
int Frame::getSecondThrow()
{
return throw2;
}
//get the score of both throws
int Frame::getScore()
{
return score;
}
//set the score
void Frame::setScore(int value)
{
score = value;
}
//set the first throw
void Frame::setFirstThrow(int value1)
{
//throw1 = genThrow(value1); //normal generator
//throw1 = 10; //strike game rigged
throw1 = 9; //spare game rigged
}
//set the second throw
void Frame::setSecondThrow(int value2)
{
//throw2 = genThrow(value2); //normal generator
throw2 = 1; //spare game rigged
//throw2 = 10; //strike game rigged
}
//set the strike
void Frame::setStrike(bool value)
{
strike = value;
}
//set the spare
void Frame::setSpare(bool value)
{
spare = value;
}
//get the strike
bool Frame::getStrike()
{
return strike;
}
//get the spare
bool Frame::getSpare()
{
return spare;
}
Here is the bowling.h file
#ifndef BOWLING_H
#define BOWLING_H
#include "Frame.h"
#include<iostream>
using namespace std;
class Bowling
{
private: Frame a[11];
public: void accumulateScore();
void bowl();
void printData();
};
#endif
Here is the bowling.cpp file
#include "Bowling.h"
#include<iostream>
using namespace std;
//takes all of the throw values after bowling and accumulates the correct score
void Bowling::accumulateScore()
{
int totalSum = 0;
for (int x = 0; x < 10; x++)
{
if (a[x].getFirstThrow() + a[x].getSecondThrow() < 10) //not a strike or spare
{
totalSum += a[x].getFirstThrow() + a[x].getSecondThrow();
a[x].setScore(totalSum);
}
else if (a[x].getFirstThrow() == 10) //throws a strike
{
if (x < 9)
{
totalSum += 10 + a[x + 1].getFirstThrow() + a[x + 1].getSecondThrow();
if (a[x + 2].getStrike() == true)
{
totalSum += 10;
}
a[x].setScore(totalSum);
}
}
else if (a[x].getFirstThrow() + a[x].getSecondThrow() == 10) //throws a spare
{
if(x < 10)
{
totalSum += 10 + a[x + 1].getFirstThrow();
a[x].setScore(totalSum);
}
}
}
//player got the 11th frame
if (a[9].getStrike() == true)
{
totalSum += 10 + a[10].getFirstThrow() + a[10].getSecondThrow();
a[9].setScore(totalSum);
}
else if (a[9].getSpare() == true)
{
totalSum += 10;
a[9].setScore(totalSum);
}
}
void Bowling::bowl()
{
//generate all throws and store them in the frames
for (int x = 0; x < 10; x++)
{
a[x].setFirstThrow(x);
if (a[x].getFirstThrow() == 10)
{
a[x].setStrike(true);
}
if (a[x].getStrike() == false)
{
a[x].setSecondThrow(x);
if (a[x].getFirstThrow() + a[x].getSecondThrow() == 10)
{
a[x].setSpare(true);
}
}
a[x].setScore(a[x].getFirstThrow() + a[x].getSecondThrow());
}
//play the 11th frame if they got a strike on the tenth frame
if(a[9].getStrike() == true)
{
a[10].setFirstThrow(10);
if (a[10].getFirstThrow() == 10)
{
a[10].setStrike(true);
}
a[10].setSecondThrow(10);
cout << "The second throw is this value: " << a[10].getSecondThrow() << endl;
if (a[10].getSecondThrow() == 10)
{
a[10].setStrike(true);
}
else if (a[10].getFirstThrow() + a[10].getSecondThrow() == 10)
{
a[10].setSpare(true);
}
a[9].setScore(a[10].getFirstThrow() + a[10].getSecondThrow());
}
}
void Bowling::printData()
{
for (int x = 0; x < 10; x++)
{
cout << "*****************************" << endl;
cout << "Frame " << x + 1 << endl;
cout << "First throw: ";
if (a[x].getStrike() == true)
{
cout << "Strike!" << endl;
}
else
{
cout << a[x].getFirstThrow() << endl;
}
cout << "Second throw: ";
if (a[x].getStrike() == false)
{
if (a[x].getSpare() == true)
{
cout << "Spare!" << endl;
}
else if(a[x].getSpare() == false)
{
cout << a[x].getSecondThrow() << endl;
}
else
{
cout << endl;
}
}
cout << "Score: " << a[x].getScore();
cout << endl;
}
if (a[9].getStrike() == true)
{
cout << "*****************" << endl;
cout << "Frame 11" << endl;
cout << "First throw: ";
if (a[10].getStrike() == true)
{
cout << "Strike!" << endl;
}
else
{
cout << a[10].getFirstThrow() << endl;
}
cout << "Second throw: ";
if (a[10].getStrike() == false)
{
if (a[10].getSpare() == true)
{
cout << "Spare!" << endl;
}
else
{
cout << a[10].getSecondThrow() << endl;
}
}
else
{
cout << "Strike!" << endl;
}
//cout << "Score: " << a[10].getScore();
cout << endl;
}
}
Here is where I test it in main
#include "Bowling.h"
#include<iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
srand(time(0));
int dummy = 0;
//create two players that can bowl
Bowling player1;
Bowling player2;
int player1Score = 0;
int player2Score = 0;
//have the players bowl their throws before accumulating score
player1.bowl();
player2.bowl();
//accumulate the score after all of the throws have been done
player1.accumulateScore();
player2.accumulateScore();
//print player 1 data
cout << "Here are the throws and score for the first player: " << endl;
player1.printData();
//spacing
cout << endl << endl;
//print player 2 data
cout << "Here are the throws and score for the second player: " << endl;
player2.printData();
cout << "Enter a dummy number:" << endl;
cin >> dummy;
return 0;
}