I'm making a version of nine-board Tic Tac Toe. (Each move determines the board in which the opposing player must move)
My standard Board
draws fine with:
gameplay->board->draw(w, h, d);
But when I try to draw a 3x3 group of Board
s to make the SuperBoard
on which the entire game is played, the individual Board
s give EXC_BAD_ACCESS
on: gameplay->superBoard->drawBig(w, h, d);
Where am I going wrong?
Code:
gameBoard.h:
struct Location {
int col;
int row;
int err;
};
class Board {
public:
// ctor
Board();
~Board();
// func
void draw(float w, float h, float d);
void draw(float x, float y, float w, float h, float d);
int move(int col, int row, int player);
int getWinCount(int player);
bool isFull();
private:
int squares[3][3];
};
class SuperBoard {
public:
// ctor
SuperBoard();
~SuperBoard();
// func
void drawBig(float w, float h, float d);
int getWinCount(int player);
Location move(int col, int row, int player);
// vars
Board* boards[3][3];
};
gameBoard.cpp:
#include "gameBoard.h"
#import "ProjectHeader.h"
Board::Board() {
// init vars
winCountPlayer1 = winCountPlayer2 = 0;
// init board
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
squares[i][j] = 0;
}
}
}
Board::~Board() {
}
void Board::draw(float x, float y, float w, float h, float d) {
ofPushMatrix();
ofTranslate(x, y);
// first, draw the basic board:
float border = SCREEN_BORDER * (w / ofGetWidth());
// vert
ofLine(w/2 - d/6, h/2 - (d/2 - border), w/2 - d/6, h/2 + (d/2 - border));
ofLine(w/2 + d/6, h/2 - (d/2 - border), w/2 + d/6, h/2 + (d/2 - border));
// horiz
ofLine(w/2 - (d/2 - border), h/2 - d/6, w/2 + (d/2 - border), h/2 - d/6);
ofLine(w/2 - (d/2 - border), h/2 + d/6, w/2 + (d/2 - border), h/2 + d/6);
// then draw the moved moves:
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
if (squares[i][j] == 1) { // X
ofSetColor(player1color);
// descending stroke:
ofLine(i*d/3 + (w/2 - d/2),
j*d/3 + (h/2 - d/2),
i*d/3 + w/2 - d/2 + d/3,
j*d/3 + h/2 - d/2 + d/3);
// ascending stroke:
ofLine(i*d/3 + w/2 - d/2,
j*d/3 + h/2 - d/2 + d/3,
i*d/3 + w/2 - d/2 + d/3,
j*d/3 + h/2 - d/2);
} else if (squares[i][j] == 2) { // O
ofSetColor(player2color);
ofCircle(i*d/3 + w/2 - d/3, j*d/3 + h/2 - d/3, d/6);
}
}
}
// then draw a line through any wins:
ofSetLineWidth(d*0.03);
for (int i=0; i<3; i++) {
// check rows
if (squares[i][0] == squares[i][1] && squares[i][1] == squares[i][2] && squares[i][2] != 0) {
ofSetColor(squares[i][0] == 1 ? player1win : player2win);
ofLine(w/2 - d/3 + i*(d/3), h/2 - d/2, w/2 - d/3 + i*(d/3), h/2 + d/2);
}
// check columns
if (squares[0][i] == squares[1][i] && squares[1][i] == squares[2][i] && squares[2][i] != 0) {
ofSetColor(squares[0][i] == 1 ? player1win : player2win);
ofLine(w/2 - d/2, h/2 - d/3 + i*(d/3), w/2 + d/2, h/2 - d/3 + i*(d/3));
}
// check diagonals
if (squares[0][0] == squares[1][1] && squares[1][1] == squares[2][2] && squares[2][2] != 0) {
ofSetColor(squares[0][0] == 1 ? player1win : player2win);
ofLine(w/2 - d/2, h/2 - d/2, w/2 + d/2, h/2 + d/2);
}
if (squares[0][2] == squares[1][1] && squares[1][1] == squares[2][0] && squares[2][0] != 0) {
ofSetColor(squares[0][2] == 1 ? player1win : player2win);
ofLine(w/2 - d/2, h/2 + d/2, w/2 + d/2, h/2 - d/2);
}
}
ofPopMatrix();
}
void Board::draw(float w, float h, float d) {
ofSetColor(0);
ofNoFill();
ofSetLineWidth(d*0.02);
ofSetCircleResolution(100);
draw(0, 0, w, h, d);
}
int Board::move(int _c, int _r, int player) {
// first, see if we can legally move here:
if (squares[_c][_r] == 0) {
squares[_c][_r] = player;
// then, see if the move caused a win:
int wincount = getWinCount(player);
// return the player who won, or zero if no win yet
if (wincount > 0) {
return player;
} else return GAME_STATE_NORMAL;
// otherwise return an error:
} else if (squares[_c][_r] == player) {
return ERROR_SQUARE_TAKEN_BY_PLAYER;
} else {
return ERROR_SQUARE_TAKEN_BY_OPPONENT;
}
}
int Board::getWinCount(int player) {
cout << "Board state:" << endl;
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
cout << squares[j][i] << " ";
}
cout << endl;
} cout << endl;
// For multi-board games this now handles more than one win per board.
int wincount = 0;
for (int i=0; i<3; i++) {
// check rows
if (squares[i][0] == squares[i][1] &&
squares[i][1] == squares[i][2] &&
squares[i][2] == player) wincount++;
// check columns
if (squares[0][i] == squares[1][i] &&
squares[1][i] == squares[2][i] &&
squares[2][i] == player) wincount++;
}
// check diagonals
if (squares[0][0] == squares[1][1] &&
squares[1][1] == squares[2][2] &&
squares[2][2] == player) wincount++;
if (squares[0][2] == squares[1][1] &&
squares[1][1] == squares[2][0] &&
squares[2][0] == player) wincount++;
return wincount;
}
bool Board::isFull() {
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
if (squares[i][j] == 0) return false;
}
}
return true;
}
//-------------------------------------------- // Superboard code: //--------------------------------------------
SuperBoard::SuperBoard() {
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
boards[j][i] = new Board();
}
}
}
SuperBoard::~SuperBoard() {
}
void SuperBoard::drawBig(float w, float h, float d) {
ofSetColor(0);
ofSetLineWidth(d*0.02);
// first, draw the big board dividing lines:
float border = SCREEN_BORDER;
// vert
ofLine(w/2 - d/6, h/2 - (d/2 - border), w/2 - d/6, h/2 + (d/2 - border));
ofLine(w/2 + d/6, h/2 - (d/2 - border), w/2 + d/6, h/2 + (d/2 - border));
// horiz
ofLine(w/2 - (d/2 - border), h/2 - d/6, w/2 + (d/2 - border), h/2 - d/6);
ofLine(w/2 - (d/2 - border), h/2 + d/6, w/2 + (d/2 - border), h/2 + d/6);
// then, draw each of our small boards in place:
float _d = d/3;
float _w = w/3;
float _h = h/3;
for (int i=0; i<3; i++) {
for (int j=0; i<3; j++) {
float _x = (w/2 - d/2) + i * _d;
float _y = (h/2 - d/2) + j * _d;
boards[i][j]->draw(_x, _y, _w, _h, _d);
}
}
}
int SuperBoard::getWinCount(int player) {
int winCount;
for (int i=0; i<3; i++) {
for (int j=0; i<3; j++) {
winCount += boards[i][j]->getWinCount(player);
}
}
return winCount;
}
Location SuperBoard::move(int col, int row, int player) {
int result;
for (int i=0; i<3; i++) {
for (int j=0; i<3; j++) {
if (boards[j][i]->isActive()) {
result = boards[j][i]->move(col, row, player);
}
boards[j][j]->setIsActive(false);
}
}
Location loc;
if (result >= 0) {
loc.col = col;
loc.row = row;
boards[col][row]->setIsActive(true);
loc.err = 0;
} else {
loc.err = result;
}
return loc;
}