I am building a simple Tac Tac Toe game in C++ but I get a vector subscription error when it’s the computers turn. I can’t find the reason for this error please tell me.
here’s my code:
//Tic-Tac-Toe
//Plays the game of Tic-Tac-Toe with a human opponent
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
//global constants
const char X = 'X';
const char O = 'O';
const char EMPTY = ' ';
const char TIE = 'T';
const char NO_ONE = 'N';
//function prototypes
void instructions();
char asYesNo(string question);
int askNumber(string question, int high, int low = 0);
char humanPiece();
char opponent(char piece);
void displayBoard(const vector<char>& board);
char winner(const vector<char>& board);
bool isLegal(const vector<char>& board, int move);
int humanMove(const vector<char>& board, char human);
int computerMove(vector<char> board, char computer);
void announceWinner(char winner, char computer, char human);
//main function
int main()
{
int move;
const int NUM_SQUARES = 9;
vector<char> board(NUM_SQUARES, EMPTY);
instructions();
char human = humanPiece();
char computer = opponent(human);
char turn = X;
displayBoard(board);
while (winner(board) == NO_ONE)
{
if (turn == human)
{
move = humanMove(board, human);
board[move] = human;
}
else
{
move = computerMove(board, computer);
board[move] = computer;
}
displayBoard(board);
turn = opponent(turn);
}
announceWinner(winner(board), computer, human);
return 0;
}
//displays instructions
void instructions()
{
cout << "Welcome to the ultimate man-machine showdown: Tic-Tac-Toe.\n";
cout << "--where human brain is pit against silicon processor\n\n";
cout << "Make your move known by entering a number, 0 - 8. The number\n";
cout << "corresponds to the desired board position, as illustrated:\n\n";
cout << " 0 | 1 | 2\n";
cout << " ---------- \n";
cout << " 3 | 4 | 5\n";
cout << " ---------- \n";
cout << " 6 | 7 | 8\n\n";
cout << "Prepare yourself, human. The battle is about to begin.\n\n";
}
//asks 'yes' or 'no' until it gets an answer either equel to 'y' or 'n'
char askYesNo(string question)
{
char response;
do
{
cout << question << "(y/n): ";
cin >> response;
}while (response != 'y' && response != 'n');
return response;
}
//asks a number within a range ans keeps asking untill the number is within that range, next it return that number within the specific range
int askNumber(string question, int high, int low)
{
int number;
do
{
cout <<question << " (" <<low <<" - " <<high <<"): ";
cin >> number;
}while (number > high || number < low);
return number;
}
//asks who will go first, X always starts cuz of tradition
char humanPiece()
{
char go_first = askYesNo("Do you require the first move?");
if (go_first == 'y')
{
cout <<"\nThen take the first move, you will need it!\n";
return X;
}
else
{
cout <<"\nYour bravery will be your undoing...I will go first.\n";
return O;
}
}
//cuz X always starts we need to decide who will be X
char opponent(char piece)
{
if (piece == X)
{
return O;
}
else
{
return X;
}
}
//Displays the board
void displayBoard(const vector<char>& board)
{
cout <<"\n\t" <<board[0] << " | " <<board[1] << " | "<<board[2];
cout <<"\n\t" <<"---------";
cout <<"\n\t" <<board[3] << " | " <<board[4] << " | "<<board[5];
cout <<"\n\t" <<"---------";
cout <<"\n\t" <<board[6] << " | " <<board[7] << " | "<<board[8];
cout <<"\n\t" <<"---------";
cout <<"\n\n";
}
//checks every possible way for someone to win, if there is no winner it checks for a tie
char winner(const vector<char>& board)
{
//all possible winning rows
const int WINNING_ROWS[8][3] = {{0, 1, 2},
{3, 4, 5},
{6, 7, 8},
{0, 3, 6},
{1, 4, 7},
{2, 5, 8},
{0, 4, 8},
{2, 4, 6}};
const int TOTAL_ROWS = 8;
//if any winning row has three values that are the same (and not EMPTY),
//then we have a winner
for (int row = 0; row < TOTAL_ROWS; ++row)
{
if ( (board[WINNING_ROWS[row][0]] != EMPTY) &&
(board[WINNING_ROWS[row][0]] == board[WINNING_ROWS[row][1]]) &&
(board[WINNING_ROWS[row][1]] == board[WINNING_ROWS[row][2]]) )
{
return board[WINNING_ROWS[row][0]];
}
}
// since nobody has won, check for a tie (no EMPTY squares left)
if (count (board.begin(), board.end(), EMPTY) == 0)
return TIE;
// since nobody has won an it isn't a tie, the game ain't over
return NO_ONE;
}
//checks if the move is legal
inline bool isLegal(int move , const vector<char>& board)
{
return (board[move] == EMPTY);
}
//asks the human to typ his move and checks if it legal
int humanMove(const vector<char>& board, char human)
{
int move = askNumber("Where will you move?", (board.size() -1));
while (!isLegal(move, board))
{
cout <<"\nThat square is already occupied, foolish human.\n";
move = askNumber("Where will you move?", (board.size() -1));
}
cout <<"Fine...\n";
return move;
}
//calculate's the computers move
int computerMove(vector<char> board, char computer)
{
//three good steps to win:
//
//1. if the computer can win, make that winning move
//2. if the human can win, block that son of a b*tch
//3. otherwise take the middle, if not possible the corners and so on
unsigned int move = O;
bool found = false;
//if the computer can win, make that winning move
while (!found && move < board.size())
{
if (isLegal (move, board))
{
board[move] = computer;
found = winner(board) == computer;
board[move] = EMPTY;
}
if (!found)
{
++move;
}
}
//if the human can win, block that son of a b*tch
if (!found)
{
move = O;
char human = opponent(computer);
while (!found && move < board.size())
{
if (isLegal(move, board))
{
board[move] = human;
found = winner(board) == human;
board[move] = EMPTY;
}
if (!found)
{
++move;
}
}
}
//otherwise take the middle, if not possible the corners and so on
if (!found)
{
move = O;
unsigned int i = O;
const int BEST_MOVES[] = {4, 0, 2, 6, 8, 1, 3, 5, 7};
//pick best open square
while (!found && i < board.size())
{
move = BEST_MOVES[i];
if (isLegal(move, board))
{
found = true;
}
++i;
}
}
cout <<"I shall take a square number " <<move <<endl;
return move;
}
//tells (epicly) who won the game
void announceWinner(char winner, char computer, char human)
{
if (winner == computer)
{
cout << winner <<"'s won!\n";
cout << "As i predicted, human, I am triumphant once more -- proof\n";
cout << "that computers are superior to humans in all regards.\n";
}
else if (winner == human)
{
cout << winner <<"'s won!\n";
cout <<"No, no! It cannot be! Somehow you tricked me, human.\n";
cout <<"But never again! I, the computer, so swear it!\n";
}
else
{
cout <<"It's a tie.\n";
cout <<"You were most lucky, human, and somehow managed to tie me.\n";
cout <<"Celebrate... for this is the best you will ever archieve.\n";
}
}
Sorry for the long code.
If you need more info, comment.
In computerMove you wrote
Which is defined by
So… move is worth 79 (ASCII value of the letter O), which is bigger than the size of your board (9). As a result none of the loops of computerMove is executed because you always have move > board.size() and you return move = 79 – so the error, because you exceed the size of board at line:
What you want is probably
at each step of your function computerMove()