tictactoe and copying an array - c++

Hello I am working on a tic-tac-toe project on my own. I am not taking a programming class so its not homework.
I have written pretty much the rest of the code and am now working on the AI.
For the AI i am going to have it take a copy of the (2 dimensional array) and it check if it can win in a move, then if the player can, then if it can in 2 moves, then the player and so on, there are some other things i will include. So in order to do this i think i need to pass a copy of the array, but i am not sure how to copy an array. So that is basically my question, how do you copy an array?

You can wrap the array into a class, in which case it'll be copied automatically by the default-generated copy constructor and assignment operator:
enum EField { empty, cross, oh };
typedef std::array<EField, 9> TTTBoard; // C++11, or use std::tr1::array
Or do it manually:
struct TTTBoard
{
EField data[9]; // or even EField data[3][3]
};
Now you can copy it at will:
TTTBoard b;
TTTBoard c = b;

A neat trick you could do without concerning yourself with array copying is to create a type for your 3x3 board:
struct TicTac{
int board[3][3];
}
And just pass that as the argument to your function.

What kind of array do you have?
I'm assuming you have the plain old school integer array.
when you have:
int Array[3][3];
then to copy it's contents to another array you will have to loop each element.
this can be done like this:
int MyArray[3][3];
int CopyHere[3][3];
for(int i = 0; i < sizeof(MyArray); ++i)
{
for(int j = 0; j < sizeof(MyArray[i]); ++j)
{
CopyHere[i][j] = MyArray[i][j];
}
}
I have somewhere an old TicTacToe script, lemme look for it.
Edit: found it:
http://pastebin.com/Xp5iT2b0
Here is the related topic:
http://forum.sa-mp.com/showthread.php?t=259549

Related

Do all arrays in C++ classes have to be dynamically allocated, or just their member variables?

For an assignment, I had to separate some code for Conway's Game of Life into multiple files, but now I'm trying to get a deeper understanding of why the code was written the way it was. I have a class, World, and part of the constructor for that class looks like this:
world.h:
class World {
public:
// Constructor/destructor
World();
~World();
void updateWorld();
...
private:
char **m_grid_1;
char **m_grid_2;
...
};
world.cpp:
World::World()
{
m_toggle = true;
m_grid_1 = new char*[MAX_ROWS];
m_grid_2 = new char*[MAX_ROWS];
for (int i = 0; i < MAX_ROWS; i++) {
m_grid_1[i] = new char[MAX_COLS];
m_grid_2[i] = new char[MAX_COLS];
}
...
}
MAX_ROWS and MAX_COLS are globals that live in a header now.
Arrays have always kind of confused me, so these questions might seem kind of basic:
What does char** mean in the context of the member variable m_grid_1 or m_grid_2? Pointer to a pointer of chars? Those members are 2D arrays, so I'm not sure why pointers are used here instead.
Why is new used here in combination with that loop in the constructor? Couldn't you just say m_grid_1[MAX_ROWS][MAX_COLS];?
Also, rather than toggle between the two grids, if I wanted to make a local copy of m_grid_1 in the member function updateWorld() and use that local copy to get the next state of the game, would I need to use new? This is what I have now, and it seems to work, but I'm not sure if I'm doing something wrong by not dynamically allocating the 2D array here:
void World::updateWorld() {
char grid_copy[MAX_ROWS][MAX_COLS];
for (int i = 0; i < MAX_ROWS; i++) {
for (int j = 0; j < MAX_COLS; j++) {
grid_copy[i][j] = m_grid_1[i][j];
}
}
// loop over grid_copy to find next state of m_grid_1
}
Do all arrays in C++ classes have to be dynamically allocated?
Not in general.
or just their member variables?
Member variables don't have to be allocated dynamically either.
What does char** mean ... Pointer to a pointer of chars?
It is a pointer to pointer to char.
Those members are 2D arrays
Correction: Those members are pointers. They used pointers, therefore they are not arrays.
Why is new used here in combination with that loop in the constructor?
Because the author of the program chose to use it.
Couldn't you just say m_grid_1[MAX_ROWS][MAX_COLS];?
Maybe. If MAX_ROWS and MAX_COLS are compile time constant and if they are small, then sure.
If I wanted to make a local copy of m_grid_1 in the member function updateWorld() and use that local copy to get the next state of the game, would I need to use new?
If the question is whether you need dynamic allocation, then maybe. See the answer above.
There is hardly ever need to use new. A simpler and safer way to create a dynamic array is to use std::vector.

Const vector query in C++

#include < vector >
using namespace std;
class Rclass
{
public:
vector<int> ir0T;
vector<int> ir1T;
private:
int f();
}
int Rclass::f()
{
ir0T.clear();
ir1T.clear();
ir0T.push_back(1);
ir1T.push_back(2);
}
this throws error
"Rclass.cpp:90: error: member function 'clear' not viable: 'this' argument has type 'const vector', but function is not marked const
ir0T.clear();
^~~~"
Rclass.cpp:91: error: member function 'clear' not viable: 'this' argument has type 'const vector', but function is not marked const
ir1T.clear();"
why?
^~~~
I tried adding "const vector ir0T;"
You cannot set the matrix member variable to a local varable created in a local member function - the local variable will be destroyed when the function ends and then the matrix member variable won't be pointing to anything. So instead, if you insist on using a raw pointer, use calloc() because it allocates the memory like malloc and then it sets it all to zero. The main problem with this is that then you need a copy constructor, assignment operator and destructor - That's not the way to go if you can help it. It would be better to use a std::vector<std::vector<int>> because all the dynamic allocation and deallocation is hidden from you. Plus you can reserve the size if you know it ahead of time. How to initializ the "vector"-ized version to zero can be seen here: Initializing a two dimensional std::vector
#include <vector>
class CS
{
private:
std::vector<std::vector<int> > Rightalpha;
public:
void CreateMtrx(int a, int b)
{
// Defaults to zero initial value
Rightalpha = std::vector<std::vector<int> >(a, std::vector<int>(b));
}
};
int main()
{
CS cs;
cs.CreateMtrx(4,4);
return 0;
};
A better alternative if it is fixed and you know ahead of time how big the matrix is: you can just use a plain array directly as a member variable instead of using a pointers to dynamically allocated memory. If the matrix is small (like 4x4) this will give you cache locality and a performance improvement. Plus if you are using c++11 you can clear the array at the declaration and you don't need a CreateMatrix() member variable at all - something like this:
class CS
{
private:
int Rightalpha[4][4] = {};
};
int main()
{
CS cs;
return 0;
};
Or like one of the comments suggested you could use std::array instead of a plain array, if you want a nice STL-like interface to the array. There are some advantages listed here: Replace fixed size arrays with std::array?
Firstly a few fundamentals.
When CreateMtrx() returns Rightalpha will become invalid as a will destruct.
And I would recommend using lower camel case naming for variables and upper camel case for types. i.e. rightAlpha instead of Rightalpha, to avoid confusion with types.
As for your actual question you can initialise a 2D array with a nested loop:
for(unsigned int i = 0; i < 4; i++)
{
for(unsigned int j = 0; j < 4; j++)
{
rightAlpha[i][j] = 0;
}
}
Finally, when asking for help 'craps up' is not conducive to constructive answers. It is important to be clear on what your expected behaviour is and what results you are actually seeing.
If Rightalpha is a data member of your class it doesn't need to be an int**. You probably just want it to be an int[4][4] and skip using a local variable 'a' in your create function.
If you really want it to be a pointer, just make it an int*, and use it with 2D-array syntax. Instead of: int a[4][4]; Do: int* a = new [4*4];
I see from the comment that you can't change the type of Rightalpha. You will then need to do manual memory management. You will need to initialize you int** with the new operator.
You will need to allocate each array in the 2D array.
rightAlpha = new int*[4];
for (int i = 0 ; i < 4 ; i++) {
rightAlpha[i] = new int[4];
}
You can read more about initialisation of a multi-dimentional arrays here:
How do I declare a 2d array in C++ using new?
Even if that works, you will need to free and manage memory and deal carefully with all the pitfalls of manual memory management. That's why I strongly suggest to use a std::vector<int>:
struct CS {
createMatrix() {
rightAlpha = std::vector<int>(4*4);
}
private:
std::vector<int> rightAlpha;
With this solution, you don't need to worry about memory stuff as the std::vector will do it for you.
If you need matrix semantics, you can add a function that returns the right element according to a j i position.
int operator()(int i, int j) const {
return rightAlpha[j+4*i];
}
It may be used like this:
CS myCs;
myCs(3, 2);

how to declare an array of objects without calling object constructor

Given a struct like
struct Square
{
Square(Color p_color): color_(p_color) {}
Color color_;
};
how can i declare a two dimensional array and later initialize it. For example,
typedef Square (&Square8x8)[8][8];
Square8x8 initSquares()
{
Square board[ROWS][COLS]; //declare the array
for(int row=0;row<ROWS;row++)
for(int col=0;col<COLS;col++)
{
if(col%2 == 0)
board[row][col]= Square(WHITE); //actual initlization
else
board[row][col] = Square(BLACK);
}
return board;
}
You misunderstand the point of a constructor, which is to ensure an object is always initialized and valid during its entire lifecycle. Thus the invocation of a constructor cannot be in any way delayed or postponed.
It's a typical XY-problem though - you're asking for help with an intended solution, not a problem. The real problem is that you don't want to postpone the constructor, but initialize it later on. Construction and initialization are related subjects, but not identical.
The best solution is to give your class a setColor or initialize function, separate from the constructor. An alternative solution (which is closer to your question) is to declare the array not as objects, but as pointers, and then really instantiate the object later on with new Square(WHITE). I'd go for the first though, the second requires a lot more lifecycle control with explicit deletion.
You need a default constructor for Square which is able to call without parameters. For example:
struct Square
{
Square() {} // <------------------------- For example
Square(Color p_color): color_(p_color) {}
Color color_;
};
Otherwise, you should use pointer to Square and new them later. For example:
struct Square
{
Square(Color p_color): color_(p_color) {}
Color color_;
};
const int ROWS = 8;
const int COLS = 8;
In this case, you should use pointers:
std::unique_ptr<Square> board[ROWS][COLS];
for (int i=0; i<ROWS; i++)
for (int j=0; j<COLS; j++)
board[i][j] = std::unique_ptr<Square>(new Square(RED));
or (for bare pointers)
Square* board[ROWS][COLS];
for (int i=0; i<ROWS; i++)
for (int j=0; j<COLS; j++)
board[i][j] = new Square(RED);
....
// Be careful, you should delete them all
In case you don't want to use a default constructor you can use the constructor you already have.
This solution uses std::vector, which I also recommend you use.
std::vector<Square> myVector( ROWS*COLS, Square(WHITE) );
this will create an array of ROWS * COLS elements, each initialized to the value of Square(WHITE).
You could create a Board class, which uses such a vector inside and offers functionalities such as initializing a board of arbitrary size and indexing a Square in the linear vector based on Row and Column information.
You can also do:
Square board[2][2] = {Square(WHITE), Square(WHITE), Square(WHITE), Square(WHITE) };
but it doesn't really scale well.
Create an array of (smart) pointers instead of an array. One purpose of pointers is so objects can be initialized later.

How to copy a structure with pointers to data inside?

I am using the CUDD package for BDDs manipulation.
I want to make a copy for a big data structure in it that is called the DdManager.
The problem is : this data structure has so many pointers inside it , so when I make a direct copy it is a "shallow" copy(as some use the term) i.e. : the pointers in the new copy point to the same places pointed to by the original copy , so when I change in anyone of them I also change in the other which is undesirable ....
Trying to make a copy function by hand is not feasible because the data structure is really big and very detailed with many pointer to other complex structures also !!!
I have tried the vector solutions described here but I did not get the expected result because there are many nested structures and pointers and I want a completely new copy.
Here is a code sample of what I want to do :
#include <iostream>
#include <cstdlib>
#include <string.h>
#include <vector>
using namespace std;
struct n1
{
int a;
char *b;
};
struct n2
{
int **c;
struct n1 *xyz;
};
typedef struct
{
vector<struct n2> x;
}X;
int main()
{
struct n2 s1;
s1.xyz = (struct n1*)malloc(sizeof(struct n1));
s1.xyz->a = 3;
s1.xyz->b = (char*)malloc(5);
s1.xyz->b[0] = '\0';
strcat(s1.xyz->b,"Mina");
s1.c = (int**)malloc(5 * sizeof(int*));
for(int i = 0; i < 5; i++)
s1.c[i] = (int*)malloc(5 * sizeof(int));
for(int i = 0; i < 5; i++)
for(int j = 0 ; j < 5 ; j++)
s1.c[i][j] = i + j;
X struct1,struct2;
vector<struct n2>::iterator it;
it = struct1.x.begin();
it = struct1.x.insert(it,s1);
it = struct2.x.begin();
it = struct2.x.insert(it,struct1.x[0]);
cout<<"struct2.x[0].c[1][2] = "<<struct2.x[0].c[1][2] <<" !"<<endl; // This is equal to 3
(struct2.x[0].c[1][2])++; //Now it becomes 4
cout<<"struct2.x[0].c[1][2] = "<<struct2.x[0].c[2][2] <<" !"<<endl; //This will print 4
cout<<"s1.c[1][2] "<< s1.c[1][2]<<" !"<<endl; // This will also print 4 ... that's the wrong thing
return 0;
}
Despite other saying that you have to
make a copy function by hand
...to solve this, I think that's the wrong approach for you. Here's why, and here's a suggestion.
You're trying to create a copy of a CUDD ddManager object, which is an integral part of the complex CUDD library. CUDD internally uses reference counts for some objects (which might help you here...) but the ddManager object effectively represents an entire instance of the library, and I've no ideas how the reference counts would work across instances.
The CUDD library and it's associated C++ wrapper doesn't seem to provide the necessary copy constructors for creating separate copies of the ddManager, and to add these would probably involve serious effort, and detailed internal knowledge of a library that you are just trying to use as a client. While it's possible to do this, it's complex thing to do.
Instead, I'd look at trying to write out the current BDD to a file/stream/whatever, and then read it back into a new instance of a ddManager. There's a library called dddmp that should help you with this.
I'd also recommend that the C++ wrapper was modified to make the ddManager class non-copyable.
"Trying to make a copy function by hand is not feasible because the data structure is really big and very detailed with many pointer to other complex structures also !!! "
This is exactly what you have to do.
The objective approach means that you don't write one big do-it-all copy method. Instead, every object (structure) copies only itself, and then call it's sub-object copy methods, etc, etc until there is nothing more left to copy.
There is no such thing as "vector solution", vector is simply the smallest object with it's smallest copy method.
There is no difference between struct and class, so just write them copy methods.
Only you know the structure of your data, so you're the only One who can save the humankind (or copy this data).

Initializing an array of objects

I'm currently working on a card game, and I'm having trouble with some initialization code:
// in my class...
Card cards[20];
// in method...
for(int i = 0; i <= 20;i++)
cards++ = new Card(i, /*i as char +*/ "_Card.bmp");
The trouble is that my compiler's telling me that cards++ is not an l-value. I've read up on the whole pointer-array equivalence thing, and I thought I understood it, but alas, I can't get it to work. My understanding is that since cards degrades to a pointer, and the new operator gives me a pointer to the location of my new instance of Card, then the above code should compile. Right?
I've tried using a subscript as well, but isn't cards+i, cards++, and cards[i] just 3 ways of saying the same thing? I thought that each of those were l-values and are treated as pointers.
Card cards[20];
cards is already an array of objects. They are constructed with the default constructor(constructor with no arguments). There is no need to new again. Probably you need a member function equivalent to constructor arguments and assign through it.
for ( int i=0; i<20; ++i ) // array index shouldn't include 20
cards[i].memberFunction(/*....*/);
Even simpler is to use std::vector
std::vector<Card> cards;
for( int i=0; i<20; ++i )
cards.push_back(Card(i, /*i as char +*/ "_Card.bmp"); )
The code Card cards[20]; already creates an array of 20 Card objects and creates them with the default constructor. This may not be what you want given your code.
I would suggest using vector instead.
std::vector<Card> cards;
for(int i = 0; i < 20;i++)
{
cards.push_back(Card(i, /*i as char +*/ "_Card.bmp"));
}
Note that your for loop goes from 0 to 20 and thus one past the end of the array.
If you want to avoid unnecessary constructor calls and unnecessary resizing, then it's more complicated, because C++ normally initialises each objects one-by-one as it's allocated. One workaround is to do it the Java way -- use a loop and an array of pointers, like so:
Card *cards[20];
for (int i=0; i<20; i++) {
cards[i] = new Card(i);
}
Another option is to use malloc to get explicitly uninitialized memory:
Card *cards = malloc(20 * sizeof(Card));
for (int i=0; i<20; i++) {
new (&(cards[i])) Card(i);
}
Well, there is another possibility, when you are ok with your constructors being called automatically at initialization:
// in my class...
Card cards[20] = { Card(0, "0_Card.bmp"), Card(1, "1_Card.bmp"), /* ... */ };
The huge downside is that you cannot use a loop in this case.
An array name, cards in your code, contains the address of the first element of the array. Such addresses are allocated at run time and you cannot change them. Hence the compiler complaining about cards being not an l-value.
But you can definitely specify what those addresses can hold by using a pointer like below:
// in my class...
Card cards[20];
Card *cardsPointer = cards;// Pointer contains the address of the
//1st element of 'cards' array.
// in method...
for(int i = 0; i < 20; i++)
*(cardsPointer++) = Card(i, /*i as char +*/ "_Card.bmp");// Note that
// there is no 'new' operator as 'cardsPointer' has type 'Card *' and
// not 'Card **'. And 'cardsPointer' has type 'Card *' as the array is
// of type 'Card'.