Last week I've make an assignment in which we had to code a Tic-Tac-Toe game using a 3*3 board. Now, I am trying to do by myself the same game but with a player's customizable board size.
I ask the user for the quantity of rows and columns hw wishes, I correctly create the game board and print this one using my << overloader function. Everything seems to be okay. BUt when I try to do a movement(place a mark in the board), the x and y coordinates passed by the user does not match with what we see on screen.
I do not know if the error comes from my SetPosition() or AtPosition(). This is the first time I deal with this kind of array, so I hope someone can help me. (sorry for my bad english)
There you have my driver file and my GameBoard.h and .cpp If you need more infomration, ask me.
#include "GameBoard.h"
#include <iostream> /*cout, cin*/
#include <stdlib.h> /* rand, srand */
#include <time.h> /* time */
using namespace std;
// ************Prototypes*************
int RandomInt(int low, int high); // generate a random number
// ***********************************
int main(void)
{
// *************Variables************
int x_size; // the user decide of the size of the board
int y_size; // the user decide of the size of the board
int x_player; // the user x-coordinate
int y_player; // the user y-coordinate
int ID_player = 1; // player ID
int x_computer; // the computer x-coordinate
int y_computer; // the computer y-coordinate
int ID_computer = 2; // computer ID
int keepplaying = 0; // use this for game loop until we do not have the check win function
// **********************************
srand(time(0));
// ask to the user which size he wants to use
cout << "Welcome to my Tic Tae Toe Game!" << endl;
cout << "What size do you want?" << endl;
cout << "Insert number of rows" << endl;
cin >> x_size;
cout << "Insert number of columns" << endl;
cin >> y_size;
cout << "This is the GameBoard we are using" << endl;
// create the GameBoard
Board myBoard(x_size, y_size);
// set all the array to 0
myBoard.ResetBoard();
// prints the 2D array
cout << myBoard << endl;
cout << "You are the player 1 and you play against the computer (number 2). Good Luck!" << endl;
do
{
// ask to the user the coordinates in which he wants to place the mark
do
{
cout << "Player 1 turn! " << endl;
cout << "Insert x coordinate: ";
cin >> x_player ;
cout << "Insert y coordinate: ";
cin >> y_player ;
}
while( (x_player < 0 || x_player > x_size) || (y_player < 0 || y_player > y_size) || myBoard.AtPosition(x_player, y_player) != 0 );
// while the cell is not available or the coordinates are not valide
myBoard.SetPosition(x_player, y_player , ID_player); // the mark has been placed
// print the move
cout << myBoard << endl;
cout << "End of turn!" << endl;
// The computer place a mark: the x and y coordinates are randomly generated
cout << "Computer Turn:" << endl;
do
{
x_computer = RandomInt(0,x_size);
y_computer = RandomInt(0,y_size);
}while(myBoard.AtPosition(x_computer, y_computer) != 0);
myBoard.SetPosition(x_computer, y_computer, ID_computer);
cout << myBoard << endl;
}while(keepplaying != 1) ;
//return 0;
}
// This function create a random number
int RandomInt(int low, int high)
{
int number = rand() % (high - low + 1) + low;
return number;
}
This is the main.cpp, it will ask for user's data and then call the function declared and defined in my class Board
#include <iostream> /*cout, cin, ostream*/
class Board
{
public:
/* Board()
{
x = 3;
y = 3;
//player_ID = 1;
//computer_ID = 2;
}*/
Board(int x_, int y_); // non-default constructor
void SetPosition(int x, int y, int player); // Place a mark
int AtPosition(int x, int y); // return the ID of the cell
void ResetBoard(void); // set all the array to be 0
friend std::ostream& operator<<(std::ostream &os, const Board &rhs); // overload the << operator
private:
int x; // x-coordinates
int y; // y-coordinates
int *board; // contains the board in a 2D array (3*3 gameboard)
int player_ID; // player ID
int computer_ID; // computer ID
};
There you have my header file for my class
#include "GameBoard.h"
// non-default constructor
Board::Board(int x_, int y_)
{
x = x_;
y = y_;
board = new int[x*y];
}
// Goes through the board array and set all the ID to 0
void Board::ResetBoard()
{
for(int i = 0; i < x*y; i++)
{
board[i] = 0;
}
}
// returns the ID of the passed cell
int Board::AtPosition(int x, int y)
{
return board[x*y];
}
// put a mark in the cell and return true
void Board::SetPosition(int x, int y, int player_ID)
{
board[x*y +x] = player_ID;
//value = pd[row * 4 + column];
}
std::ostream& operator<<(std::ostream &os, const Board &rhs)
{
for (int i = 0; i < rhs.x*rhs.y; i++)
{
if(i % rhs.y == 0)
{
os << std::endl;
}
os << rhs.board[i];
}
return os;
}
I hope that everything is clear and well comented
So in your Board
class you have:
// returns the ID of the passed cell
int Board::AtPosition(int x, int y)
{
return board[x*y];
}
// put a mark in the cell and return true
void Board::SetPosition(int x, int y, int player_ID)
{
board[x*y +x] = player_ID;
//value = pd[row * 4 + column];
}
So you're using x
and y
as you parameter names which are shadowing the x and y class members. You need to think about what you are trying to do. For a 3 x 3 array you have:
0 1 2
3 4 5
6 7 8
In your code it seems you intend to use x as the column number and y as the row number (but not consistently, so I can't be sure). So for x=1 and y=2 your index is 5. So how do you calculate that? You have:
board[x*y +x] = player_ID;
You need (something like):
board[this->x*y +x] = player_ID;
And also in AtPosition
you need:
return board[this->x*y +x];
But I would recommend re-naming your vars to avoid shadowing. Maybe the member vars would be better called xsize
/ysize
or xlen
/ylen
.
Also in operator<<
you have:
if(i % rhs.y == 0)
{
os << std::endl;
}
os << rhs.board[i];
Which I think needs to be:
if(i % rhs.x == 0)
{
os << std::endl;
}
os << rhs.board[i];
(Because I'm guessing rhs.x
is the width, but if it's not, you have other code that's wrong.)