Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Recursive-Tic-Tac-Toe-2/Recursive Tic Tac Toe 2/Recursive Tic Tac Toe 2/Board.cpp
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
299 lines (279 sloc)
6.33 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <exception> | |
#include <SFML/Graphics.hpp> | |
#include "Board.h" | |
#include "GlobalVariables.h" | |
#include "Shooter.h" | |
#define and && | |
#define or || | |
#define not ! | |
using namespace std; | |
Board::Board() | |
{ | |
} | |
Board::Board(int xx, int yy, int ww, int hh) | |
{ | |
CreateNewBoard(); | |
x = xx; | |
y = yy; | |
w = ww; | |
h = hh; | |
movesPerformed = 0; | |
winner = EMPTY; | |
} | |
Board::Board(Board* b) | |
{ | |
CreateNewBoard(); | |
for (int i = 0; i < 3; i++) | |
{ | |
for (int j = 0; j < 3; j++) | |
{ | |
this->board[i][j] = b->board[i][j]; | |
} | |
} | |
this->x = b->x; | |
this->y = b->y; | |
this->w = b->w; | |
this->h = b->h; | |
this->movesPerformed = b->movesPerformed; | |
this->winner = b->winner; | |
} | |
Board::~Board() | |
{ | |
} | |
void Board::ProcessMouseEvent() | |
{ | |
//std::cout << "Board.ProcessMouseEvent() not yet implemented\n"; | |
//no need to update this board if the mouse is not in bounds or the board is full | |
if (mouseX < x || mouseY < y || mouseX > x + w || mouseY > y + h || movesPerformed == 9) | |
{ | |
return; | |
} | |
for (int i = 0; i < 3; i++) | |
{ | |
for (int j = 0; j < 3; j++) | |
{ | |
//only have to process less-than since it checks in increasing order | |
//also, only have to check one because the mouse can only click once per turn | |
if (mouseX < x + w * (i + 1) / 3 && mouseY < y + h * (j + 1) / 3) | |
{ | |
if (board[i][j] == EMPTY) | |
{ | |
board[i][j] = (playerOnesTurn ? PLAYER1 : PLAYER2); | |
playerOnesTurn = !playerOnesTurn; | |
movesPerformed++; | |
CheckForWin(); | |
} | |
return; | |
} | |
} | |
} | |
} | |
void Board::Draw() | |
{ | |
if (movesPerformed < 9) | |
{ | |
DrawLines(); | |
DrawPieces(); | |
} | |
else | |
{ | |
DrawWinner(); | |
} | |
} | |
int Board::GetWinner() | |
{ | |
return winner; | |
} | |
void Board::DrawLines() | |
{ | |
//the rectangle defining the verticle lines | |
sf::Vector2f vertLinesSize(lineThickness, h - 2 * distanceFromEdges); | |
sf::RectangleShape vertLine(vertLinesSize); | |
vertLine.setFillColor(lineColor); | |
vertLine.setOutlineColor(lineColor); | |
//set the position of each and draw it | |
vertLine.setPosition(x + w / 3, y + distanceFromEdges); | |
window.draw(vertLine); | |
vertLine.setPosition(x + w * 2 / 3, y + distanceFromEdges); | |
window.draw(vertLine); | |
//draw the horozontal lines | |
sf::Vector2f horzLinesSize(w - 2 * distanceFromEdges, lineThickness); | |
sf::RectangleShape horzLine(horzLinesSize); | |
horzLine.setFillColor(lineColor); | |
horzLine.setOutlineColor(lineColor); | |
//set the position of each and draw it | |
horzLine.setPosition(x + distanceFromEdges, y + h / 3); | |
window.draw(horzLine); | |
horzLine.setPosition(x + distanceFromEdges, y + h * 2 / 3); | |
window.draw(horzLine); | |
} | |
void Board::DrawWinner() | |
{ | |
if (winner == PLAYER1) | |
{ | |
DrawX(x, y, w, h); | |
} | |
else if (winner == PLAYER2) | |
{ | |
DrawO(x, y, w, h); | |
} | |
else | |
{ | |
throw new std::exception("ERROR: winner declared as an invalid type. This is a bug."); | |
//cout << "ERROR: winner declared as an invalid type. This is a bug.\nThere is normally an exception thrown here." << endl; | |
} | |
} | |
void Board::DrawX(int px, int py, int dx, int dy) | |
{ | |
sf::Vector2f size(dx, dy / 3); | |
sf::RectangleShape tl2br(size); //top left to bottom right bar | |
sf::RectangleShape tr2bl(size); //top right to bottom left bar | |
//set the origin to the middle of the shape | |
tl2br.setOrigin(size.x / 2, size.y / 2); | |
tr2bl.setOrigin(size.x / 2, size.y / 2); | |
//set the colors | |
tl2br.setFillColor(xColor); | |
tr2bl.setFillColor(xColor); | |
//set the rotations | |
tl2br.setRotation(45); | |
tr2bl.setRotation(-45); | |
//position | |
tl2br.setPosition(px + dx / 2, py + dy / 2); | |
tr2bl.setPosition(px + dx / 2, py + dy / 2); | |
//draw | |
window.draw(tl2br); | |
window.draw(tr2bl); | |
} | |
void Board::DrawO(int px, int py, int dx, int dy) | |
{ | |
sf::CircleShape shape(dx / 2); | |
shape.setFillColor(oColor); | |
sf::Vector2f pos(px, py); | |
shape.setPosition(pos); | |
window.draw(shape); | |
} | |
void Board::CreateNewBoard() | |
{ | |
//empty it out just to be sure | |
for (int i = 0; i < 3; i++) | |
{ | |
for (int j = 0; j < 3; j++) | |
{ | |
board[i][j] = EMPTY;//(i + j) % 2 + 1;//PLAYER1; | |
} | |
} | |
} | |
void Board::CheckForWin() | |
{ | |
//no need to check if there haven't been enough moves | |
if (movesPerformed < 3) | |
return; | |
bool foundWin = false; | |
for (int i = PLAYER1; i <= PLAYER2; i++) | |
{ | |
//rows | |
if (board[0][0] == i and board[0][1] == i and board[0][2] == i) | |
{ | |
foundWin = true; | |
goto Board_CheckForWin_SkipFurtherChecking; | |
} | |
if (board[1][0] == i and board[1][1] == i and board[1][2] == i) | |
{ | |
foundWin = true; | |
goto Board_CheckForWin_SkipFurtherChecking; | |
} | |
if (board[2][0] == i and board[2][1] == i and board[2][2] == i) | |
{ | |
foundWin = true; | |
goto Board_CheckForWin_SkipFurtherChecking; | |
} | |
//columns | |
if (board[0][0] == i and board[1][0] == i and board[2][0] == i) | |
{ | |
foundWin = true; | |
goto Board_CheckForWin_SkipFurtherChecking; | |
} | |
if (board[0][1] == i and board[1][1] == i and board[2][1] == i) | |
{ | |
foundWin = true; | |
goto Board_CheckForWin_SkipFurtherChecking; | |
} | |
if (board[0][2] == i and board[1][2] == i and board[2][2] == i) | |
{ | |
foundWin = true; | |
goto Board_CheckForWin_SkipFurtherChecking; | |
} | |
//diagonals | |
if (board[0][0] == i and board[1][1] == i and board[2][2] == i) | |
{ | |
foundWin = true; | |
goto Board_CheckForWin_SkipFurtherChecking; | |
} | |
if (board[2][0] == i and board[1][1] == i and board[0][2] == i) | |
{ | |
foundWin = true; | |
//no need for the goto since it goes to the right line anyway | |
} | |
//resolve the checks | |
Board_CheckForWin_SkipFurtherChecking: | |
if (foundWin) | |
{ | |
winner = i; | |
movesPerformed = 9; //setting this to 9 closes off the board to other moves | |
return; | |
} | |
} | |
//if it exits the loop but 9 moves were performed, it is a cats-game. | |
if (movesPerformed == 9) | |
{ | |
/* | |
CreateNewBoard(); | |
movesPerformed = 0; | |
*/ | |
contestedBoard = this; | |
states->PushState(new Shooter()); | |
return; | |
} | |
} | |
void Board::DrawPieces() | |
{ | |
//Draw the x's and o's | |
for (int i = 0; i < 3; i++) | |
{ | |
for (int j = 0; j < 3; j++) | |
{ | |
int piece = board[i][j]; | |
if (piece == EMPTY) | |
{ | |
continue; //no need to draw anything for this, move on to the next one | |
} | |
else | |
{ | |
//Determine the size and location of the token | |
int px = x + i * w / 3; | |
int py = y + j * h / 3; | |
int dx = w / 3; | |
int dy = h / 3; | |
//draw the correct shape | |
if (piece == PLAYER1) | |
{ | |
DrawX(px, py, dx, dy); | |
} | |
else if (piece == PLAYER2) | |
{ | |
DrawO(px, py, dx, dy); | |
} | |
else | |
{ | |
throw new std::exception("ERROR: invalid piece in the game board"); | |
} | |
} | |
} | |
} | |
} | |
void Board::SetWinner(int player) | |
{ | |
movesPerformed = 9; | |
winner = player; | |
} |