I'm trying to make sure that my code works correctly so I am having my bool functions print the true or false that they are returning. However, my function checkColSum which checks to see if every column in my parallel array adds up to 15 is printing three trues and a false when I enter the numbers:
4 9 2
3 5 7
8 1 6
I would really appreciate any help regarding this issue. I just can't seem to figure out what's going wrong.
#include <iostream>
using namespace std;
// Global constants
const int ROWS = 3; // The number of rows in the array
const int COLS = 3; // The number of columns in the array
const int MIN = 1; // The value of the smallest number
const int MAX = 9; // The value of the largest number
// Function prototypes
bool isMagicSquare(int arrayRow1[], int arrayRow2[], int arrayRow3[], int size);
bool checkRange(int arrayRow1[], int arrayRow2[], int arrayRow3[], int size, int min, int max);
bool checkUnique(int arrayRow1[], int arrayRow2[], int arrayRow3[], int size);
bool checkRowSum(int arrayrow1[], int arrayrow2[], int arrayrow3[], int size);
bool checkColSum(int arrayrow1[], int arrayrow2[], int arrayrow3[], int size);
bool checkDiagSum(int arrayrow1[], int arrayrow2[], int arrayrow3[], int size);
void fillArray(int arrayRow1[], int arrayRow2[], int arrayRow3[], int size);
void showArray(int arrayrow1[], int arrayrow2[], int arrayrow3[], int size);
int main()
{
/* Define a Lo Shu Magic Square using 3 parallel arrays corresponding to each row of the grid */
int magicArrayRow1[COLS], magicArrayRow2[COLS], magicArrayRow3[COLS];
// Your code goes here
int repeat = 1;
while (repeat == 1) {
fillArray(magicArrayRow1, magicArrayRow2, magicArrayRow3, 3);
showArray(magicArrayRow1, magicArrayRow2, magicArrayRow3, 3);
/*TESTING DELETE BEFORE TURNING IN*/
checkRange(magicArrayRow1, magicArrayRow2, magicArrayRow3, 3, 1, 9); //works
cout << endl;
checkUnique(magicArrayRow1, magicArrayRow2, magicArrayRow3, 3); //doesnt work
cout << endl;
checkRowSum(magicArrayRow1, magicArrayRow2, magicArrayRow3, 3);//works
cout << endl;
checkColSum(magicArrayRow1, magicArrayRow2, magicArrayRow3, 3); //works?? maybe??
/*TESTING DELETE BEFORE TURNING IN*/
if (isMagicSquare(magicArrayRow1, magicArrayRow2, magicArrayRow3, 3) == true) {
cout << endl << "This is a Lo Shu magic square.";
}
else {
cout << endl << "This is not a Lo Shu magic square.";
}
cout << endl << "Would you like to try again? Enter 1 for yes or 0 for no: ";
cin >> repeat;
}
return 0;
}
// Function definitions go here
bool isMagicSquare(int arrayRow1[], int arrayRow2[], int arrayRow3[], int size)
{
bool trueFalse = false;
if (checkRange(arrayRow1, arrayRow2, arrayRow3, 3, 1, 9) == true && checkUnique(arrayRow1, arrayRow2, arrayRow3, 3) == true) {
if (checkRowSum(arrayRow1, arrayRow2, arrayRow3, 3) == true && checkColSum(arrayRow1, arrayRow2, arrayRow3, 3) == true) {
if (checkDiagSum(arrayRow1, arrayRow2, arrayRow3, 3) == true) {
trueFalse = true;
}
}
}
return trueFalse;
}
bool checkRange(int arrayRow1[], int arrayRow2[], int arrayRow3[], int size, int min, int max)
{
bool inRange = true;
int count = 0;
while (inRange && count < size) {
if (arrayRow1[count] < min || arrayRow1[count] > max) {
inRange = false;
}
count++;
}
while (inRange && count < size) {
if (arrayRow2[count] < min || arrayRow2[count] > max) {
inRange = false;
}
count++;
}
while (inRange && count < size) {
if (arrayRow3[count] < min || arrayRow3[count] > max) {
inRange = false;
}
count++;
}
if (inRange == true) {// TEST
cout << "true";
}
if(inRange == false) {
cout << "false";
}
return inRange;
}
bool checkUnique(int arrayRow1[], int arrayRow2[], int arrayRow3[], int size)
{
bool isUnique = false;
int count = 0;
int one = 0;
int two = 0;
int three = 0;
int four = 0;
int five = 0;
int six = 0;
int seven = 0;
int eight = 0;
int nine = 0;
for (int i = 0; i < size; i++)
{ //checks row 1
if (arrayRow1[i] == 1) { //checks if row one contains the value 1 in any position
one++;
}
if (arrayRow1[i] == 2) {
two++;
}
if (arrayRow1[i] == 3) {
three++;
}
if (arrayRow1[i] == 4) {
four++;
}
if (arrayRow1[i] == 5) {
five++;
}
if (arrayRow1[i] == 6) {
six++;
}
if (arrayRow1[i] == 7) {
seven++;
}
if (arrayRow1[i] == 8) {
eight++;
}
if (arrayRow1[i] == 9) {
nine++;
}
}
for (int i = 0; i < size; i++) { //checks row 2
if (arrayRow1[i] == 1) { //checks if row two contains the value 1 in any position
one++; //if the value 1 is present, a count is added
}
if (arrayRow2[i] == 2) {
two++;
}
if (arrayRow2[i] == 3) {
three++;
}
if (arrayRow2[i] == 4) {
four++;
}
if (arrayRow2[i] == 5) {
five++;
}
if (arrayRow2[i] == 6) {
six++;
}
if (arrayRow2[i] == 7) {
seven++;
}
if (arrayRow2[i] == 8) {
eight++;
}
if (arrayRow2[i] == 9) {
nine++;
}
}
for (int i = 0; i < size; i++) { //checks row 1
if (arrayRow3[i] == 1) { //checks if row one contains the value 1 in any position
one++;
}
if (arrayRow3[i] == 2) {
two++;
}
if (arrayRow3[i] == 3) {
three++;
}
if (arrayRow3[i] == 4) {
four++;
}
if (arrayRow3[i] == 5) {
five++;
}
if (arrayRow3[i] == 6) {
six++;
}
if (arrayRow3[i] == 7) {
seven++;
}
if (arrayRow3[i] == 8) {
eight++;
}
if (arrayRow3[i] == 9) {
nine++;
}
}
if (one == 1 && two == 1 && three == 1 && four == 1 && five == 1 && six == 1 && seven == 1 && eight == 1 && nine == 1) { // checks that every variable counting the repition of numbers 1-9 in the arrays is equal to one
isUnique = true;
cout << "True";
}
if (one != 1 || two != 1 || three != 1 || four != 1 || five != 1 || six != 1 || seven != 1 || eight != 1 || nine != 1) {
isUnique = false;
cout << "False";
}
return isUnique;
}
bool checkRowSum(int arrayrow1[], int arrayrow2[], int arrayrow3[], int size)
{
bool magicSquare = true; //variable declares whether it is a magic square or not
int sumRow1 = 0; //sum of row1
int sumRow2 = 0; //sum of row2
int sumRow3 = 0; //sum of row3
for (int i = 0; i < size; i++) {
sumRow1 += arrayrow1[i];
}
for (int i = 0; i < size; i++) {
sumRow2 += arrayrow2[i];
}
for (int i = 0; i < size; i++) {
sumRow3 += arrayrow3[i];
}
if (sumRow1 == 15 && sumRow2 == 15 && sumRow3 == 15) {
magicSquare = true;
cout << "true";
}
else {
magicSquare = false;
cout << "false";
}
return magicSquare;
}
bool checkColSum(int arrayrow1[], int arrayrow2[], int arrayrow3[], int size)
{
bool magicSquare = false;
int sumCol1 = 0;
int sumCol2 = 0;
int sumCol3 = 0;
for (int i = 0; i < size; i++) { //iterates through the array
if (i == 0) { //when i equals 1
sumCol1 += arrayrow1[i];
}
if (i == 1) {
sumCol2 += arrayrow2[i];
}
if (i == 2) {
sumCol3 += arrayrow3[i];
}
}
for (int i = 0; i < size; i++) {
if (i == 0) {
sumCol1 += arrayrow3[i];
}
if (i == 1) {
sumCol2 += arrayrow1[i];
}
if (i == 2) {
sumCol3 += arrayrow2[i];
}
}
for (int i = 0; i < size; i++) {
if (i == 0) {
sumCol1 += arrayrow2[i];
}
if (i == 1) {
sumCol2 += arrayrow3[i];
}
if (i == 2) {
sumCol3 += arrayrow1[i];
}
}
if (sumCol1 == 15 && sumCol2 == 15 && sumCol3 == 15) {
magicSquare = true;
cout << "true";
}
else {
magicSquare = false;
}
return magicSquare;
}
bool checkDiagSum(int arrayrow1[], int arrayrow2[], int arrayrow3[], int size)
{
bool magicSquare = true;
int sumDiag1 = 0;
int sumDiag2 = 0;
sumDiag1 = arrayrow1[0] + arrayrow2[1] + arrayrow3[2];
sumDiag2 = arrayrow1[3] + arrayrow2[1] + arrayrow3[0];
if (sumDiag1 == 15 && sumDiag2 == 15) {
magicSquare = true;
cout << "true";
}
else {
magicSquare = false;
cout << "false";
}
return magicSquare;
}
void fillArray(int arrayRow1[], int arrayRow2[], int arrayRow3[], int size)
{
int userInput;
//fills row 1
for (int i = 0; i < size; i++) { //iterates according to int size which is the number of columns/rows
cout << "Enter the number for row 1, column " << i+1 << ": ";
cin >> userInput;
arrayRow1[i] = userInput;
cout << endl;
}
//fills row 2
for (int i = 0; i < size; i++) {
cout << "Enter the number for row 2, column " << i+1 << ": ";
cin >> userInput;
arrayRow2[i] = userInput;
cout << endl;
}
//fills row 3
for (int i = 0; i < size; i++)
{
cout << "Enter the number for row 3, column " << i+1 << ": ";
cin >> userInput;
arrayRow3[i] = userInput;
cout << endl;
}
}
void showArray(int arrayrow1[], int arrayrow2[], int arrayrow3[], int size)
{
for (int i = 0; i < size; i++) { //displays row 1
cout << arrayrow1[i] << " ";
}
cout << endl; //moves down one row
for (int i = 0; i < size; i++) { //displays row 2
cout << arrayrow2[i] << " ";
}
cout << endl; //moves down one row
for (int i = 0; i < size; i++) { //displays row 3
cout << arrayrow3[i] << " ";
}
cout << endl; //moves down one row
}
Related
I am currently trying to make a tic tac toe AI in c++. I am currently making a function to check if the winstate of the game but when I try to run it i get this error:
61:34: error: cannot convert ‘std::string’ {aka ‘std::__cxx11::basic_string’} to ‘std::string ()[3]’ {aka ‘std::__cxx11::basic_string ()[3]’}
61 | cout << HasWon(Board[3][3], Length);
| ~~~~~~~~~~^
| |
| std::string {aka std::__cxx11::basic_string}
main.cpp:6:19: note: initializing argument 1 of ‘int HasWon(std::string (*)[3], int)’
6 | int HasWon(string GameBoard[3][3], int boardLength);
| ~~~~~~~^~~~~~~~~~~~~~~
I know that it has to do with char and strings but I have no idea how to implement it in my current program. Heres the code:
#include <iostream>
using namespace std;
int AIMove(int PlayerMove);
int HasWon(string GameBoard[3][3], int boardLength);
int main () {
int Length = 3;
string Board[Length][Length] = {
{" ", " ", " "},
{" ", " ", " "},
{" ", " ", " "},
};
int NodeMap[Length][Length] = {
{0,0,0},
{0,0,0},
{0,0,0},
};
int NodeNumber = 1;
for(int h = Length - 1; h >= 0;h--) {
for(int d = 0; d < Length;d++) {
NodeMap[h][d] = NodeNumber;
NodeNumber++;
}
}
int Player;
bool HasMoved = false;
bool run = true;
while(run) {
//Prints Tic Tac Toe board to the screen
for(int h = 0; h < Length;h++) {
cout << " ";
for(int d = 0; d < Length;d++) {
cout << Board[h][d];
if(d < Length - 1) { cout <<"||"; }
}
if(h < Length - 1) { cout << "\n---------\n"; }
}
//Gets player input
cout << "\n choose a number 1-9 to place an X: ";
cin >> Player;
//Adds it to the board
HasMoved = false;
while(!HasMoved) {
for(int h = 0; h < Length; h++) {
for(int d = 0; d < Length; d++) {
if(NodeMap[h][d] == Player && Board[h][d] == " ") {
Board[h][d] = "X";
HasMoved = true;
}
}
}
if(!HasMoved) {
cout << "\n choose a number 1-9 to place an X: ";
cin >> Player;
}
}
cout << HasWon(Board[3][3], Length);
}
}
int AIMove(int PlayerMove, int boardLength);
//Checks if anyone has won yet. 0: nothing has happend, 1: tie, 2: X win, 3: O win.
int HasWon(string GameBoard[3][3], int boardLength) {
int xNumber = 0;
int oNumber = 0;
//Checks for vertical wins
for(int d = 0;d < boardLength;d++) {
xNumber = 0;
oNumber = 0;
for(int h = 0;h < boardLength;h++) {
if(GameBoard[h][d] == "X") { xNumber++; }
if(GameBoard[h][d] == "O") { oNumber++; }
if(xNumber == boardLength ) { return 2; }
if(oNumber == boardLength ) { return 3; }
}
}
//Checks for horizontial wins
for(int h = 0;h < boardLength;h++) {
xNumber = 0;
oNumber = 0;
for(int d = 0;d < boardLength;d++) {
if(GameBoard[h][d] == "X") { xNumber++; }
if(GameBoard[h][d] == "O") { oNumber++; }
if(xNumber == boardLength ) { return 2; }
if(oNumber == boardLength ) { return 3; }
}
}
//Checks for diagonal wins
xNumber = 0;
oNumber = 0;
for(int i = boardLength - 1;i >= 0;i--) {
if(GameBoard[i][i] == "X") { xNumber++; }
if(GameBoard[i][i] == "O") { oNumber++; }
if(xNumber == boardLength ) { return 2; }
if(oNumber == boardLength ) { return 3; }
}
xNumber = 0;
oNumber = 0;
for(int i = 0;i < boardLength;i++) {
if(GameBoard[i][i] == "X") { xNumber++; }
if(GameBoard[i][i] == "O") { oNumber++; }
if(xNumber == boardLength ) { return 2; }
if(oNumber == boardLength ) { return 3; }
}
//Checks for a tie
xNumber = 0;
oNumber = 0;
for(int h = 0;h < boardLength;h++) {
for(int d = 0;d < boardLength;d++) {
if(GameBoard[h][d] == "X") { xNumber++; }
if(GameBoard[h][d] == "O") { oNumber++; }
if(xNumber+oNumber == boardLength*boardLength) { return 1; }
}
}
return 0;
}
The problem is that the type of the expression Board[3][3] when passing as a call argument is std::string while the type of the function parameter GameBoard is actually ‘std::string (*)[3]. This is because of string [3][3] decays to string (*)[3] due to type decay.
Thus there is mismatch in the type of the parameter of the function HasWon and the argument passed.
Also note that in standard c++, the size of an array must be a compile time constant. So in you code:
int Length = 3;
string Board[Length][Length]; //this is not standard C++
The statement string Board[Length][Length]; is not standard C++ because Length is not a constant expression.
To solve this you should add a top level const to Length and pass the argument Board instead of Board[3][3] as shown below:
//-vvvvv---------------------------> const added here
const int Length = 3;
//----------------vvvvv------------> changed to Board instead of Board[3][3]
cout << HasWon(Board, Length);
Demo.
Another alternative(better) would be to use std::vector.
I am trying to create a c++ unbeatable tic tac toe AI. after watching several videos on the topic i thought I had it all figured out. An error pops up on the screen saying "Expression: vector subscript out of range". I believe the error is coming from the availableMoves() function. however I do not know why.
The game itself works fine. any help would be appreciated.
#include <iostream>
#include <vector>
#include <ctime>
bool in(std::vector<int> v, int element)
{
for (int i = 0; i < v.size(); i++)
{
if (element == v[i])
{
return true;
}
}
return false;
}
class Board
{
private:
char board[3][3] = { {'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'} };
public:
void displayBoard()
{
std::cout << "___________________" << std::endl;
for (int i = 0; i < 3; i++)
{
std::cout << "| ";
for (int j = 0; j < 3; j++)
{
std::cout << board[i][j] << " | ";
}
std::cout << std::endl;
}
std::cout << "___________________" << std::endl;
}
std::vector<int> availableMoves()
{
std::vector<int> moves;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (board[i][j] != 'X' && board[i][j] != 'O')
{
moves.push_back(i * 3 + j);
}
}
}
return moves;
}
void move(int choice, char mark)
{
int y = choice / 3;
int x = choice - y * 3;
board[y][x] = mark;
}
void revert(int choice)
{
int y = choice / 3;
int x = choice - y * 3;
board[y][x] = (char)choice + 48;
}
int checkWin()
{
for (int i = 0; i < 3; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
{
if (board[i][0] == 'X')
{
return 1;
}
else if (board[i][0] == 'O')
{
return -1;
}
}
}
for (int i = 0; i < 3; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
{
if (board[0][i] == 'X')
{
return 1;
}
else if (board[0][i] == 'O')
{
return -1;
}
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
{
if (board[0][0] == 'X')
{
return 1;
}
else if (board[0][0] == 'O')
{
return -1;
}
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
{
if (board[0][2] == 'X')
{
return 1;
}
else if (board[0][2] == 'O')
{
return -1;
}
}
return 0;
}
int evaluate()
{
return (checkWin() * -1) * (availableMoves().size() + 1);
}
Board& operator=(Board& b)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
board[i][j] = b.board[i][j];
}
}
return (*this);
}
};
class TicTacToe
{
private:
Board board;
int turn;
int searches = 0;
public:
TicTacToe()
{
std::srand(time(0));
turn = std::rand() % 2;
}
int minimax(int depth, Board curBoard, bool is_max)
{
searches++;
if (depth == 0 || curBoard.checkWin() != 0)
{
return board.evaluate();
}
if (is_max)
{
int max_eval = -2147483647;
for (int i = 0; i < curBoard.availableMoves().size(); i++)
{
curBoard.move(curBoard.availableMoves()[i], 'O');
depth -= 1;
int eval = minimax(depth, curBoard, false);
curBoard.revert(curBoard.availableMoves()[i]);
if (eval > max_eval)
{
max_eval = eval;
}
}
return max_eval;
}
if (!is_max)
{
int min_eval = 2147483647;
for (int i = 0; i < curBoard.availableMoves().size(); i++)
{
curBoard.move(curBoard.availableMoves()[i], 'X');
depth -= 1;
int eval = minimax(depth, curBoard, true);
curBoard.revert(curBoard.availableMoves()[i]);
if (eval < min_eval)
{
min_eval = eval;
}
}
return min_eval;
}
}
void game()
{
while (board.checkWin() == 0 && board.availableMoves().size() != 0)
{
board.displayBoard();
if (turn % 2 == 0)
{
std::cout << std::endl;
int choice;
std::cout << "Enter Your Move: ";
std::cin >> choice;
choice -= 1;
while (!in(board.availableMoves(), choice))
{
std::cout << "Enter A Valid Move: ";
std::cin >> choice;
}
board.move(choice, 'X');
std::cout << std::endl;
turn++;
}
board.displayBoard();
if (board.checkWin() != 0)
{
break;
}
if (turn % 2 == 1)
{
int ai = minimax(9 - (turn % 2), board, true);
std::cout << searches;
std::cin.get();
turn++;
}
}
if (board.checkWin() == 1)
{
std::cout << "You Won" << std::endl;
}
else if (board.checkWin() == -1)
{
std::cout << "You Lost" << std::endl;
}
else
{
std::cout << "Tie" << std::endl;
}
std::cout << "Would You Like To Play Again Y/N: ";
char playAgain;
std::cin >> playAgain;
if (playAgain == 'Y')
{
Board newBoard;
board = newBoard;
game();
}
}
};
int main()
{
TicTacToe ticTacToe;
ticTacToe.game();
}
Do you know how to debug? If not, you should definitely learn this, it's pretty helpful. But here's some things I found out.
The problem is not in availableMoves(), but in minimax(), more precisely in line 215, where the program calls curBoard. revert(curBoard. availableMoves()[i]).
void revert(int choice)
{
int y = choice / 3;
int x = choice - y * 3;
board[y][x] = (char)choice + 48;
}
for (int i = 0; i < curBoard.availableMoves().size(); i++)
{
curBoard.move(curBoard.availableMoves()[i], 'X');
depth -= 1;
int eval = minimax(depth, curBoard, true);
curBoard.revert(curBoard.availableMoves()[i]);
if (eval < min_eval)
{
min_eval = eval;
}
}
The error happens in the function revert, but I am not sure why. Maybe availableMoves also returns something wrong. Variable i is permanently 0 in the for-loop. So it is possible that there is something wrong at position 0 of the vector moves, which revert cannot handle. Try debugging yourself, maybe you'll find the problem.
I want the program to print "You win" when any of the instances in the champion() function are given. It only shows a winner when "123" is inputted. Whenever three X's are displayed anywhere else the program continues. For instance if three X's are given diagonally the program will still continue. Novice programmer so any criticism is greatly appreciated.
class TicTacToe {
private:
char map[GRID_SIZE][GRID_SIZE];
public:
void computers_turn() {
while (true) {
int choice = (rand() % 9) + 1;
int row = choice / 3;
int col = choice % 3;
char grid_position = map[row][col];
if (grid_position == 'X' || grid_position == 'O') {
std::cout << "Space taken. Try again" << std::endl;
} else {
map[row][col] = (char)'O';
break;
}
}
}
void champion() {
const char* possiblities[8] = {"123", "456", "789", "147",
"258", "369", "159", "753"};
for (int i = 0; i < 8; i++) {
char previous_pos = '0';
bool winner = true;
const char* possible_moves = possiblities[i];
for (int index = 0; index < GRID_SIZE; index++) {
char character = possible_moves[i];
int entered_num = character - '0';
int grid_space = entered_num - '1';
int row = index / GRID_SIZE;
int col = index % GRID_SIZE;
char grid_coordinate = map[row][col];
if (previous_pos == '0') {
previous_pos = grid_coordinate;
} else if (previous_pos == grid_coordinate) {
continue;
} else {
winner = false;
break;
}
}
if (winner) {
puts("You win");
exit(0);
break;
}
}
}
void playgame() {
std::string input;
while (true) {
std::cout << "Go player one" << std::endl;
getline(std::cin, input);
if (input != " ") {
char entered = input.c_str()[0];
if (entered >= '1' && entered <= '9') {
int entered_num = entered - '0';
int index = entered_num - 1;
int row = index / 3;
int col = index % 3;
char grid_position = map[row][col];
if (grid_position == 'X' || grid_position == 'O') {
std::cout << "Space taken. Try again" << std::endl;
} else {
map[row][col] = (char)'X';
break;
}
} else {
std::cout << "Only numbers 1 - 9" << std::endl;
}
} else {
std::cout << "Have to enter something, try again" << std::endl;
}
}
}
void generateGrid() {
int number = 1;
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
map[x][y] = std::to_string(number).c_str()[0];
number += 1;
}
}
}
void tictacToeMap() {
std::cout << std::endl;
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
std::printf(" %c ", map[x][y]);
}
std::cout << std::endl;
}
}
TicTacToe() {
generateGrid();
while (true) {
champion();
tictacToeMap();
playgame();
computers_turn();
}
}
};
int main() {
TicTacToe ticTacToe;
return 0;
}
As the title states i'm having trouble finding the error with the way in which my queue is being populated. It should be holding every visited state node until they have been processed. but the queue is not being populated as it should be. Can anyone help me find the bug? Below is my implementation file for the PuzzleStateNode class and source.cpp
EDIT: After more debugging it would seem that the problem lies with the following chunk of code from the solvePuzzle function. The items are never pushed to my queue, and I don't understand why. Could it be an issue with my unordered_set?
void solvePuzzle(string stateArray[3][3]) {
ofstream oFile("output.txt");
PuzzleStateNode pState(stateArray);
queue<PuzzleStateNode> puzzleQueue;
unordered_set<string> visitedPuzzleStateSet;
if (pState.parityCheck() == true) {
puzzleQueue.push(pState);
for(int i = 0; i < 31; i++){
PuzzleStateNode myTempState(puzzleQueue.front());
//puzzleQueue.pop();
if (visitedPuzzleStateSet.find(myTempState.getPuzzleID()) == visitedPuzzleStateSet.end()) { // is our value in the set? if not then do the following
visitedPuzzleStateSet.emplace(myTempState.getPuzzleID()); // add to the list of visited states.
if (myTempState.getEmptyXArrayPos() == 0 || myTempState.getEmptyXArrayPos() == 1) { // if a move to the right is available
PuzzleStateNode tempState;
tempState = PuzzleStateNode(myTempState);
tempState.moveEmptySquareRight(tempState.getEmptyXArrayPos(), tempState.getEmptyYArrayPos());
if (tempState.checkForSolve() == true) {
tempState.printState(oFile);
oFile << "Puzzle Solved in " << tempState.getMoveCounter() << " movements of the emtpy tile which are listed below." << endl;
tempState.printMoves(oFile);
cout << "Puzzle Solved!" << endl << endl << endl;
oFile.close();
return;
}
else if (tempState.checkForSolve() != true && visitedPuzzleStateSet.find(tempState.getPuzzleID()) == visitedPuzzleStateSet.end()) {
puzzleQueue.push(tempState);
}
else {
cout << "you have visited this already" << endl;
system("pause");
}
}
END EDIT:
PuzzleStateNode.h
#pragma once
#include<queue>
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
using namespace std;
class PuzzleStateNode
{
public:
PuzzleStateNode();
PuzzleStateNode(string tempArray[3][3]);
PuzzleStateNode(const PuzzleStateNode &other);
int getEmptyXArrayPos();
int getEmptyYArrayPos();
int getMoveCounter();
string getPuzzleID();
bool parityCheck();
bool checkForSolve();
void setPuzzleID();
void setEmptyXArrayPos(int x);
void setEmptyYArrayPos(int y);
void incrimentMoveCounter();
void pushToMoveQueue(string move);
void moveEmptySquareDown(int xEmptyPos, int yEmptyPos);
void moveEmptySquareUp(int xEmptyPos, int yEmptyPos);
void moveEmptySquareRight(int xEmptyPos, int yEmptyPos);
void moveEmptySquareLeft(int xEmptyPos, int yEmptyPos);
void printState(ofstream &oFile);
void printMoves(ofstream &oFile);
~PuzzleStateNode();
private:
string puzzleStateArray[3][3];
int moveCounter;
queue<string> moveQueue;
int emptyXArrayPos;
int emptyYArrayPos;
string puzzleID;
};
PuzzleStateNode.cpp
#include "PuzzleStateNode.h"
using namespace std;
PuzzleStateNode::PuzzleStateNode()
{
}
PuzzleStateNode::PuzzleStateNode(string tempArray[3][3])
{
puzzleID = "";
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
puzzleStateArray[i][j] = tempArray[i][j];
puzzleID += tempArray[i][j];
if (puzzleStateArray[i][j] == "E") {
emptyXArrayPos = j;
emptyYArrayPos = i;
}
}
}
moveCounter = 0;
moveQueue.push("The following lists the movement of the Empty or 'E' square until the puzzle is solved: ");
}
PuzzleStateNode::PuzzleStateNode(const PuzzleStateNode &other) {
{ puzzleID = "";
moveCounter = other.moveCounter;
moveQueue = other.moveQueue;
emptyXArrayPos = other.emptyXArrayPos;
emptyYArrayPos = other.emptyYArrayPos;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
puzzleStateArray[i][j] = other.puzzleStateArray[i][j];
puzzleID += other.puzzleStateArray[i][j];
}
}
}
}
int PuzzleStateNode::getEmptyXArrayPos() {
return emptyXArrayPos;
}
int PuzzleStateNode::getEmptyYArrayPos() {
return emptyYArrayPos;
}
int PuzzleStateNode::getMoveCounter() {
return moveCounter;
}
string PuzzleStateNode::getPuzzleID() {
return puzzleID;
}
bool PuzzleStateNode::checkForSolve() {
if (puzzleStateArray[0][0] == "1" && puzzleStateArray[0][1] == "2" && puzzleStateArray[0][2] == "3" && puzzleStateArray[1][0] == "4" && puzzleStateArray[1][1] == "5" && puzzleStateArray[1][2] == "6" && puzzleStateArray[2][0] == "7" && puzzleStateArray[2][1] == "8" && puzzleStateArray[2][2] == "E") {
return true;
}
return false;
}
void PuzzleStateNode::setPuzzleID() {
puzzleID = "";
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
puzzleID += puzzleStateArray[i][j];
}
}
}
void PuzzleStateNode::setEmptyXArrayPos(int x) {
emptyXArrayPos = x;
}
void PuzzleStateNode::setEmptyYArrayPos(int y) {
emptyXArrayPos = y;
}
void PuzzleStateNode::incrimentMoveCounter() {
moveCounter++;
}
void PuzzleStateNode::pushToMoveQueue(string move) {
moveQueue.push(move);
}
void PuzzleStateNode::printMoves(ofstream &oFile) {
string tempString;
for (int i = 0; i < moveQueue.size(); i++) {
cout << moveQueue.front() << endl;
moveQueue.push(moveQueue.front());
moveQueue.pop();
}
cout << endl << endl;
}
void PuzzleStateNode::printState(ofstream &oFile) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cout << puzzleStateArray[i][j];
}
cout << endl;
}
cout << endl;
}
void PuzzleStateNode::moveEmptySquareDown(int xEmptyPos, int yEmptyPos) {
puzzleStateArray[yEmptyPos][xEmptyPos] = puzzleStateArray[yEmptyPos + 1][xEmptyPos];
puzzleStateArray[yEmptyPos + 1][xEmptyPos] = "E";
moveQueue.push("Down");
moveCounter++;
cout << "Moving Down" << endl;
emptyYArrayPos = yEmptyPos + 1;
}
void PuzzleStateNode::moveEmptySquareUp(int xEmptyPos, int yEmptyPos) {
puzzleStateArray[yEmptyPos][xEmptyPos] = puzzleStateArray[yEmptyPos - 1][xEmptyPos];
puzzleStateArray[yEmptyPos - 1][xEmptyPos] = "E";
moveQueue.push("Up");
moveCounter++;
cout << "Moving Up" << endl;
emptyYArrayPos = yEmptyPos - 1;
}
void PuzzleStateNode::moveEmptySquareLeft(int xEmptyPos, int yEmptyPos) {
puzzleStateArray[yEmptyPos][xEmptyPos] = puzzleStateArray[yEmptyPos][xEmptyPos - 1];
puzzleStateArray[yEmptyPos][xEmptyPos - 1] = "E";
moveQueue.push("Left");
moveCounter++;
cout << "Moving Left" << endl;
emptyXArrayPos = xEmptyPos - 1;
}
void PuzzleStateNode::moveEmptySquareRight(int xEmptyPos, int yEmptyPos) {
puzzleStateArray[yEmptyPos][xEmptyPos] = puzzleStateArray[yEmptyPos][xEmptyPos + 1];
puzzleStateArray[yEmptyPos][xEmptyPos + 1] = "E";
moveQueue.push("Right");
moveCounter++;
cout << "Moving Right" << endl;
emptyXArrayPos = xEmptyPos + 1;
}
bool PuzzleStateNode::parityCheck() // counts number of swaps for a bubble sort excluding swaps involving the empty space
{
enter code here
// Puzzles with odd swaps have odd parity and are unsolvable.
string parityCheckString = "";
char tempChar;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
parityCheckString += puzzleStateArray[i][j];
}
}
int counter = 0;
for (int j = 0; j < 8; j++) {
for (int i = 0; i < 8; i++) {
if (parityCheckString[i] > parityCheckString[i + 1]) {
if (parityCheckString[i] == 'E') {
tempChar = parityCheckString[i];
parityCheckString[i] = parityCheckString[i + 1];
parityCheckString[i + 1] = tempChar;
}
else {
tempChar = parityCheckString[i];
parityCheckString[i] = parityCheckString[i + 1];
parityCheckString[i + 1] = tempChar;
counter += 1;
}
}
}
}
if (counter % 2 == 0) {
cout << "Even Parity, solving the 8 puzzle!" << endl;
return true;
}
else {
cout << "Parity is odd and puzzle is unsolvable. Skipping to next Puzzle." << endl;
return false;
}
}
PuzzleStateNode::~PuzzleStateNode()
{
}
source.cpp
#include"PuzzleStateNode.h"
#include<string>
#include<fstream>
#include<iostream>
#include<unordered_set>
using namespace std;
int main() {
void solvePuzzle(string stateArray[3][3]);
ifstream inFile("input.txt");
ofstream outFile("output.txt");
string puzNum;
int numberOfPuzzles;
string junk;
getline(inFile, puzNum); // read number of puzzles
numberOfPuzzles = stoi(puzNum); // convert value to int.
for (int i = 0; i < numberOfPuzzles; i++) {
string stateArray[3][3]; // populates a temporary puzzle state.
string temp;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
while (temp != "1" && temp != "2" && temp != "3" && temp != "4" && temp != "5" && temp != "6" && temp != "7" && temp != "8" && temp != "E") {
temp = inFile.get();
}
stateArray[i][j] = temp;
temp = inFile.get();
}
}
solvePuzzle(stateArray);
}
system("pause");
return 0;
}
void solvePuzzle(string stateArray[3][3]) {
ofstream oFile("output.txt");
PuzzleStateNode pState(stateArray);
queue<PuzzleStateNode> puzzleQueue;
unordered_set<string> visitedPuzzleStateSet;
if (pState.parityCheck() == true) {
puzzleQueue.push(pState);
for(int i = 0; i < 31; i++){
PuzzleStateNode myTempState(puzzleQueue.front());
//puzzleQueue.pop();
if (visitedPuzzleStateSet.find(myTempState.getPuzzleID()) == visitedPuzzleStateSet.end()) { // is our value in the set? if not then do the following
visitedPuzzleStateSet.emplace(myTempState.getPuzzleID()); // add to the list of visited states.
if (myTempState.getEmptyXArrayPos() == 0 || myTempState.getEmptyXArrayPos() == 1) { // if a move to the right is available
PuzzleStateNode tempState;
tempState = PuzzleStateNode(myTempState);
tempState.moveEmptySquareRight(tempState.getEmptyXArrayPos(), tempState.getEmptyYArrayPos());
if (tempState.checkForSolve() == true) {
tempState.printState(oFile);
oFile << "Puzzle Solved in " << tempState.getMoveCounter() << " movements of the emtpy tile which are listed below." << endl;
tempState.printMoves(oFile);
cout << "Puzzle Solved!" << endl << endl << endl;
oFile.close();
return;
}
else if (tempState.checkForSolve() != true && visitedPuzzleStateSet.find(tempState.getPuzzleID()) == visitedPuzzleStateSet.end()) {
puzzleQueue.push(tempState);
}
else {
cout << "you have visited this already" << endl;
system("pause");
}
}
if (myTempState.getEmptyXArrayPos() == 1 || myTempState.getEmptyXArrayPos() == 2) {
PuzzleStateNode tempState;
tempState = PuzzleStateNode(myTempState);
tempState.moveEmptySquareLeft(tempState.getEmptyXArrayPos(), tempState.getEmptyYArrayPos());
tempState.incrimentMoveCounter();
if (tempState.checkForSolve() == true) {
tempState.printState(oFile);
oFile << "Puzzle Solved in " << tempState.getMoveCounter() << " movements of the emtpy tile which are listed below." << endl;
tempState.printMoves(oFile);
cout << "Puzzle Solved!" << endl;
oFile.close();
return;
}
else if (tempState.checkForSolve() != true && visitedPuzzleStateSet.find(tempState.getPuzzleID()) == visitedPuzzleStateSet.end()) {
puzzleQueue.push(tempState);
}
else {
cout << "you have visited this state" << endl;
system("pause");
}
}
if (myTempState.getEmptyYArrayPos() == 0 || myTempState.getEmptyYArrayPos() == 1) {
PuzzleStateNode tempState;
tempState = PuzzleStateNode(myTempState);
tempState.moveEmptySquareDown(tempState.getEmptyXArrayPos(), tempState.getEmptyYArrayPos());
if (tempState.checkForSolve() == true) {
tempState.printState(oFile);
oFile << "Puzzle Solved in " << tempState.getMoveCounter() << " movements of the emtpy tile which are listed below." << endl;
tempState.printMoves(oFile);
cout << "Puzzle Solved!" << endl;
oFile.close();
return;
}
else if (tempState.checkForSolve() != true && visitedPuzzleStateSet.find(tempState.getPuzzleID()) == visitedPuzzleStateSet.end()) {
puzzleQueue.push(tempState);
}
else {
cout << "you have this state already" << endl;
system("pause");
}
}
if (myTempState.getEmptyYArrayPos() == 1 || myTempState.getEmptyYArrayPos() == 2) {
PuzzleStateNode tempState(myTempState);
tempState = PuzzleStateNode(myTempState);
tempState.moveEmptySquareUp(tempState.getEmptyXArrayPos(), tempState.getEmptyYArrayPos());
if (tempState.checkForSolve() == true) {
tempState.printState(oFile);
oFile << "Puzzle Solved in " << tempState.getMoveCounter() << " movements of the emtpy tile which are listed below." << endl;
tempState.printMoves(oFile);
cout << "Puzzle Solved!" << endl;
oFile.close();
return;
}
else if (tempState.checkForSolve() != true && visitedPuzzleStateSet.find(tempState.getPuzzleID()) == visitedPuzzleStateSet.end()) {
puzzleQueue.push(tempState);
}
else {
cout << "have visited this state already" << endl;
system("pause");
}
}
}
}
}
else
oFile.close();
return;
}
I found the problem! I was never resetting puzzle id's after copying so all puzzle states had the same ID for my set.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am a beginner in c++ and I am trying to make a chess game I is not finished yet. When I try to compile the code below it gives me
error: function definition is not allowed here. for isValidMove, movePiece, and Main
Can anyone tell me why it gives me that.
The code is :
#include <iostream>
#include <string>
#include <stdlib.h>
#include <ctype.h>
#include <cmath>
#include <algorithm>
using namespace std;
char board[8][8] = {
'R','N','B','Q','K','B','N','R',
'P','P','P','P','P','P','P','P',
'-','-','-','-','-','-','-','-',
'-','-','-','-','-','-','-','-',
'-','-','-','-','-','-','-','-',
'-','-','-','-','-','-','-','-',
'p','p','p','p','p','p','p','p',
'r','n','b','q','k','b','n','r'};
void swap(char board[8][8], int inRow, int inCol, int outRow, int outCol) {
char tmp = board[inRow][inCol];
board[inRow][inCol] = board[outRow][outCol];
board[outRow][outCol] = tmp;
}
void printBoard(char board[8][8]) {
cout << "# a b c d e f g h " << endl;
for(int i = 0; i <= 7; i++) {
cout << 8 - i << " ";
for(int j = 0; j <= 7; j++) {
cout << board[i][j] << " ";
}
cout << endl;
}
}
bool isValidMoveRook(int inCol, int inRow, int outCol, int outRow, char board[8][8]) {
int smallCol = min(inCol, outCol);
int smallRow = min(inRow, outRow);
int maxCol = max(inCol, outCol);
int maxRow = max(inRow, outRow);
if(inRow == outRow) {
for(int i = smallCol + 1; i < maxCol; i++) {
if(board[inRow][i] != '-') {
return false;
}
}
return true;
}
else if(outCol == inCol) {
for(int i = smallRow + 1; i < maxRow; i++) {
if(board[i][inCol] != '-') {
return false;
}
}
return true;
}
else {
return false;
}
}
bool isValidMoveBishop(int inCol, int inRow, int outCol, int outRow, char board[8][8]) {
int rowDiff = outRow - inRow;
int colDiff = outCol - inCol;
if(abs(outRow - inRow) == abs(outCol - inCol)) {
if(rowDiff < 0 && colDiff < 0) {
for(int i = 1; i > rowDiff; i--) {
if(board[inRow + rowDiff][inCol + rowDiff] != '-') {
return false;
}
}
}
}
else {
return true;
}
}
bool isValidMove(int inCol, int inRow, int outCol, int outRow, char board[8][8]) {
if(board[inRow][inCol] == '-') {
return false;
}
else {
if(board[inRow][inCol] == 'R' || board[inRow][inCol] == 'r' && isValidMoveRook(inCol, inRow, outCol, outRow, board)) {
return true;
}
}
}
void movePiece(char board[8][8]) {
string input;
string output;
cout << "Please enter your piece position : ";
cin >> input;
cout << "Please enter where you want to place your piece : ";
cin >> output;
int inCol = input[0] - 'a';
int inRow = 7 - (input[1] - '1');
int outCol = output[0] - 'a';
int outRow = 7 - (output[1] - '1');
while(!isValidMove(inCol, inRow, outCol, outRow, board)) {
cout << "Invalid input try again" << endl;
cout << "Please enter your piece position : ";
cin >> input;
cout << "Please enter where you want to place your piece : ";
cin >> output;
inCol = input[0] - 'a';
inRow = 7 - (input[1] - '1');
outCol = output[0] - 'a';
outRow = 7 - (output[1] - '1');
}
if(board[outRow][outCol] == '-') {
swap(board, inRow, inCol, outRow, outCol);
}
else {
if(isupper(board[inRow][inCol]) != isupper(board[outRow][outCol])) {
board[outRow][outCol] = board[inRow][inCol];
board[inRow][inCol] = '-';
}
}
}
int main() {
printBoard(board);
while (true) {
movePiece(board);
printBoard(board);
}
}
You are missing a closing } in isValidMoveBishop. Thus, the function's definition is not ended, and the compiler thinks you're trying to define another function inside it:
bool isValidMoveBishop(int inCol, int inRow, int outCol, int outRow, char board[8][8]) {
int rowDiff = outRow - inRow;
int colDiff = outCol - inCol;
if(abs(outRow - inRow) == abs(outCol - inCol)) {
if(rowDiff < 0 && colDiff < 0) {
for(int i = 1; i > rowDiff; i--) {
if(board[inRow + rowDiff][inCol + rowDiff] != '-') {
return false;
}
}
}
} // This closing } was missing in the OP
else {
return true;
}
}