How to exit this TicTacToe Game loop? [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am trying to make a TicTacToe Game, but something isn't working in my code. I made a new class called TicTacToeGame and I have my source.cpp (main file). Everything was fine until I made a loop to test if a space is occupied.
Since then, it asks me to enter a coordinate for X. I give it an answer and then it asks me for a Y coordinate. I give it an answer; but, again it asks for a Y coordinate, and if I give him a bad input it start spamming me with that question or tells me that I've introduced a bad input.
What can I do? I want to know what's wrong.
TicTacToeGame.h
#pragma once
class TicTacToeGame
{
public:
TicTacToeGame();
void playGame();
private:
bool placeMarker(int x, int y, char currentPlayer);
int getXCoord();
int getYCoord();
char board[3][3];
// Clears the board
void clearBoard();
// Prints the board
void printBoard();
};
TicTacToe.cpp
#include "TicTacToeGame.h"
#include <iostream>
using namespace std;
TicTacToeGame::TicTacToeGame()
{
clearBoard();
};
void TicTacToeGame::playGame()
{
char player1 = 'X';
char player2 = 'Y';
char currentPlayer = 'X';
bool isDone = false;
int x, y;
while (isDone == false) {
printBoard();
x = getXCoord();
y = getYCoord();
if (placeMarker(x, y, currentPlayer) == false) {
cout << "That spot is occupied\n";
}
else
{
// Switch player so every player can put markers
if (currentPlayer == player1) {
currentPlayer = player2;
}
else
{
currentPlayer = player1;
}
}
}
}
int TicTacToeGame::getXCoord()
{
bool isInputBad = true;
int x;
while (isInputBad == true) {
cout << "Enter the X coordinate: ";
cin >> x;
if (x < 1 || x > 3) {
cout << "Invalid coordinate!\n";
}
else
{
isInputBad = false;
}
}
return x - 1;
}
int TicTacToeGame::getYCoord()
{
bool isInputBad = true;
int y;
while (isInputBad == true) {
cout << "Enter the Y coordinate: ";
cin >> y;
}
if (y < 1 || y > 3) {
cout << "Invalid coordinate!\n";
}
else
{
isInputBad = false;
}
return y - 1;
}
bool TicTacToeGame::placeMarker(int x, int y, char currentPlayer)
{
if (board[y][x] != ' ') {
return false;
}
board[y][x] = currentPlayer;
return true;
}
void TicTacToeGame::clearBoard()
{
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = ' ';
}
}
}
void TicTacToeGame::printBoard()
{
cout << endl;
cout << " |1 2 3|\n";
for (int i = 0; i < 3; i++) {
cout << "--------\n";
cout << i+1 << "|" << board[i][0] << "|" << board[i][1] << "|" << board[i][2] << "|\n";
}
cout << "--------\n";
}
source.cpp
#include "TicTacToeGame.h"
#include <iostream>
using namespace std;
int main()
{
TicTacToeGame game;
game.playGame();
system("PAUSE");
return 0;
}

Your while loop will never exit,
The X Coord While Loop:
while (isInputBad == true) {
cout << "Enter the X coordinate: ";
cin >> x;
if (x < 1 || x > 3) {
cout << "Invalid coordinate!\n";
}
else
{
isInputBad = false;
}
} // end of while loop
The Y Coord While loop:
while (isInputBad == true) {
cout << "Enter the Y coordinate: ";
cin >> y;
} // end of while loop
if (y < 1 || y > 3) {
cout << "Invalid coordinate!\n";
}
else
{
isInputBad = false;
}
See how the validation code is outside of the while loop for the Y Coord?
The while condition isInputBad will always equal true because it would get set to false after the loop.
Move the end of the while loop after the if statement and it should work.

Related

Tic Tac Toe minimax algorithm in C++

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.

Removing and shifting remaining elements in an array C++

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;
}

C++ Maze Solving algorithm segmentation fault

The task is to create a randomly generated maze and then solve it, the issue is that whenever I recursively search the maze for the exit, i get a segmentation fault at runtime. Most of the cout is for debugging.
The Main File (where error persists)
#include <string>
#include <cmath>
#include <cstdlib>
#include "Main.h"
#include "Maze.h"
int main(int argc, char *argv[])
{
// Process the command line arguments and seed the random number
// generator, if necessary
unsigned int seed;
if(argc == 4)
{
seed = static_cast<unsigned int>(atoi(argv[1]));
cout << "Initializing pseudorandom number generator with seed "
<< seed << endl;
srand(seed);
}
else if(argc > 4)
{
cout << "Improper usage of Main\n";
exit(0);
}
cout << "Beginning execution\n";
// The first couple of numbers don't seem quite random,
// so "prime the pump" by calling rand() twice
(void) rand(); (void) rand();
mazeTest();
cout << "Finishing execution\n";
return 0;
}
void mazeTest()
{
int height = 0;
int width = 0;
cout << "Enter height (positive integer): ";
cin >> height;
cout << height << "\n";
cout << "Enter width (positive integer): ";
cin >> width;
cout << width << "\n";
MazeBuilder theMazeBuilder(height, width);
cout << "CREATED MAZE BUILDER\n";
Maze theMaze(theMazeBuilder);
cout << "CREATED THE MAZE\n";
cout << "The Maze:\n" << theMaze.toString();
solveMaze(theMaze);
}
void solveMaze(const Maze& theMaze)
{
cout << "ENTERED solveMaze()\n";
thePath = new int[theMaze.getHeight()*theMaze.getWidth()];
bool **wasHere;
for(int i = 0; i < theMaze.getHeight(); i++)
{
for(int j = 0; i < theMaze.getWidth(); j++)
{
wasHere[i][j] = false;
}
}
cout << "PATH INITIALIZED\n";
if(search(theMaze, theMaze.getEntranceRow(), 0, wasHere, thePath, thePathLength))
{
theMaze.toString(thePath, thePathLength);
}
}
bool search(const Maze& theMaze, int row, int col,
bool**& wasHere, int *aPath, int currentPathLength)
{
if(col == theMaze.getWidth()-1 && row == theMaze.getExitRow())
{
cout << "FOUND EXIT\n";
thePathLength = currentPathLength;
thePath = aPath;
return true;
}
if(wasHere[row][col] == true)
return false;
wasHere[row][col] = true;
if(row != 0 && theMaze.at(row,col).isWall(UP) == false)
{
if(search(theMaze, row-1, col, wasHere, aPath, currentPathLength))
{
aPath[currentPathLength] = UP;
currentPathLength++;
cout << "UP\n";
return true;
}
}
if(col != theMaze.getWidth()-1 && theMaze.at(row,col).isWall(RIGHT) == false)
{
if(search(theMaze, row, col+1, wasHere, aPath, currentPathLength))
{
aPath[currentPathLength] = RIGHT;
currentPathLength++;
cout << "RIGHT\n";
return true;
}
}
if(row != theMaze.getHeight()-1 && theMaze.at(row,col).isWall(DOWN) == false)
{
if(search(theMaze, row+1,col, wasHere, aPath, currentPathLength))
{
aPath[currentPathLength] = DOWN;
currentPathLength++;
cout << "DOWN\n";
return true;
}
}
if(col != 0 && theMaze.at(row,col).isWall(LEFT) == false)
{
if(search(theMaze, row, col-1, wasHere, aPath, currentPathLength))
{
aPath[currentPathLength] = LEFT;
currentPathLength++;
cout << "LEFT\n";
return true;
}
}
cout << "DEAD END\n----------------------------\n";
return false;
}
Important methods used...
Maze::at(int row, int col)
returns the cell at given row and column
Maze::toString() or toString(int* thePath, int thePathLength)
default: prints out just the maze using ASCII characters to cmd
with parameters: Prints out maze with solution using ASCII characters to cmd
Cell::isWall(direction)
returns whether or not there is a wall in that direction
(directions are constants declared and handled in Cell)
Other Info:
Maze is a dynamic 2d array of Cells
The maze is constructed properly (can output an unsolved maze properly)
The problem:
bool **wasHere;
for(int i = 0; i < theMaze.getHeight(); i++)
{
for(int j = 0; i < theMaze.getWidth(); j++)
{
wasHere[i][j] = false;
The reason:
wasHere is an uninitialized pointer to a pointer to a bool. You then dereference the first pointer causing undefined behavior (such as perhaps a crash...).

C++ Bowling Simulator Program

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;
}

Connect 4 - Cant Program Checking If Someone Won

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.