diff --git a/Piezas.cpp b/Piezas.cpp index 088b709..75215ee 100644 --- a/Piezas.cpp +++ b/Piezas.cpp @@ -1,5 +1,9 @@ #include "Piezas.h" #include +#include + +using namespace std; + /** CLASS Piezas * Class for representing a Piezas vertical board, which is roughly based * on the game "Connect Four" where pieces are placed in a column and @@ -22,6 +26,8 @@ **/ Piezas::Piezas() { + vector> board(BOARD_ROWS,vector(BOARD_COLS, Blank)); + turn = X; } /** @@ -30,6 +36,11 @@ Piezas::Piezas() **/ void Piezas::reset() { + for(int i = 0; i < BOARD_ROWS; i++) { + for(int j = 0; j < BOARD_COLS; j++) { + board[i][j] = Blank; + } + } } /** @@ -42,7 +53,19 @@ void Piezas::reset() **/ Piece Piezas::dropPiece(int column) { - return Blank; + if(column < 0 || column >= BOARD_COLS) { + return Invalid; + } + + for(int i = 0; i < BOARD_ROWS; ++i) { + if(board[i][column] == Blank) { + board[i][column] = turn; + turn = (turn == X) ? O : X; + return board[i][column]; + } + } + + return Blank; } /** @@ -51,9 +74,46 @@ Piece Piezas::dropPiece(int column) **/ Piece Piezas::pieceAt(int row, int column) { - return Blank; + if(row < 0 || row >= BOARD_ROWS || column < 0 || column >= BOARD_COLS) { + return Invalid; + } + return board[row][column]; +} + +int Piezas::getMax(Piece piece) { + int maxLength = 0; + + // Check horizontally + for (int i = 0; i < BOARD_ROWS; ++i) { + int count = 0; + for (int j = 0; j < BOARD_COLS; ++j) { + if (board[i][j] == piece) { + count++; + maxLength = max(maxLength, count); + } else { + count = 0; + } + } + } + + // Check vertically + for (int j = 0; j < BOARD_COLS; ++j) { + int count = 0; + for (int i = 0; i < BOARD_ROWS; ++i) { + if (board[i][j] == piece) { + count++; + maxLength = max(maxLength, count); + } else { + count = 0; // reset count if the sequence breaks + } + } + } + + return maxLength; } + + /** * Returns which Piece has won, if there is a winner, Invalid if the game * is not over, or Blank if the board is filled and no one has won ("tie"). @@ -65,5 +125,26 @@ Piece Piezas::pieceAt(int row, int column) **/ Piece Piezas::gameState() { - return Blank; + bool full = true; + for(int i = 0; i < BOARD_ROWS; ++i) { + for(int j = 0; j < BOARD_COLS; ++j) { + if(board[i][j] == Blank) { + full = false; + } + } + } + if(!full) { + return Invalid; + } + + int max_X = getMax(X); + int max_O = getMax(O); + + if(max_X > max_O) { + return X; + } else if(max_O > max_X) { + return O; + } else { + return Blank; + } } \ No newline at end of file diff --git a/Piezas.cpp.gcov b/Piezas.cpp.gcov new file mode 100644 index 0000000..c2a40aa --- /dev/null +++ b/Piezas.cpp.gcov @@ -0,0 +1,239 @@ + -: 0:Source:Piezas.cpp + -: 0:Graph:Piezas.gcno + -: 0:Data:- + -: 0:Runs:0 + -: 1:#include "Piezas.h" + -: 2:#include + -: 3:#include + -: 4: + -: 5:using namespace std; + -: 6: + -: 7:/** CLASS Piezas + -: 8: * Class for representing a Piezas vertical board, which is roughly based + -: 9: * on the game "Connect Four" where pieces are placed in a column and + -: 10: * fall to the bottom of the column, or on top of other pieces already in + -: 11: * that column. For an illustration of the board, see: + -: 12: * https://en.wikipedia.org/wiki/Connect_Four + -: 13: * + -: 14: * Board coordinates [row,col] should match with: + -: 15: * [2,0][2,1][2,2][2,3] + -: 16: * [1,0][1,1][1,2][1,3] + -: 17: * [0,0][0,1][0,2][0,3] + -: 18: * So that a piece dropped in column 2 should take [0,2] and the next one + -: 19: * dropped in column 2 should take [1,2]. + -: 20:**/ + -: 21: + -: 22: + -: 23:/** + -: 24: * Constructor sets an empty board (default 3 rows, 4 columns) and + -: 25: * specifies it is X's turn first + -: 26:**/ +function _ZN6PiezasC2Ev called 0 returned 0% blocks executed 0% + #####: 27:Piezas::Piezas() +call 0 never executed + -: 28:{ + #####: 29: vector> board(BOARD_ROWS,vector(BOARD_COLS, Blank)); +call 0 never executed +branch 1 never executed (fallthrough) +branch 2 never executed (throw) +call 3 never executed +branch 4 never executed (fallthrough) +branch 5 never executed (throw) +call 6 never executed +call 7 never executed +call 8 never executed +call 9 never executed + #####: 30: turn = X; + #####: 31:} +call 0 never executed +call 1 never executed + -: 32: + -: 33:/** + -: 34: * Resets each board location to the Blank Piece value, with a board of the + -: 35: * same size as previously specified + -: 36:**/ +function _ZN6Piezas5resetEv called 0 returned 0% blocks executed 0% + #####: 37:void Piezas::reset() + -: 38:{ + #####: 39: for(int i = 0; i < BOARD_ROWS; i++) { +branch 0 never executed +branch 1 never executed (fallthrough) + #####: 40: for(int j = 0; j < BOARD_COLS; j++) { +branch 0 never executed +branch 1 never executed (fallthrough) + #####: 41: board[i][j] = Blank; +call 0 never executed +call 1 never executed + -: 42: } + -: 43: } + #####: 44:} + -: 45: + -: 46:/** + -: 47: * Places a piece of the current turn on the board, returns what + -: 48: * piece is placed, and toggles which Piece's turn it is. dropPiece does + -: 49: * NOT allow to place a piece in a location where a column is full. + -: 50: * In that case, placePiece returns Piece Blank value + -: 51: * Out of bounds coordinates return the Piece Invalid value + -: 52: * Trying to drop a piece where it cannot be placed loses the player's turn + -: 53:**/ +function _ZN6Piezas9dropPieceEi called 0 returned 0% blocks executed 0% + #####: 54:Piece Piezas::dropPiece(int column) + -: 55:{ + #####: 56: if(column < 0 || column >= BOARD_COLS) { +branch 0 never executed (fallthrough) +branch 1 never executed +branch 2 never executed (fallthrough) +branch 3 never executed + #####: 57: return Invalid; + -: 58: } + -: 59: + #####: 60: for(int i = 0; i < BOARD_ROWS; ++i) { +branch 0 never executed +branch 1 never executed (fallthrough) + #####: 61: if(board[i][column] == Blank) { +call 0 never executed +call 1 never executed +branch 2 never executed (fallthrough) +branch 3 never executed + #####: 62: board[i][column] = turn; +call 0 never executed +call 1 never executed + #####: 63: turn = (turn == X) ? O : X; +branch 0 never executed (fallthrough) +branch 1 never executed + #####: 64: return board[i][column]; +call 0 never executed +call 1 never executed + -: 65: } + -: 66: } + -: 67: + #####: 68: return Blank; + -: 69:} + -: 70: + -: 71:/** + -: 72: * Returns what piece is at the provided coordinates, or Blank if there + -: 73: * are no pieces there, or Invalid if the coordinates are out of bounds + -: 74:**/ +function _ZN6Piezas7pieceAtEii called 0 returned 0% blocks executed 0% + #####: 75:Piece Piezas::pieceAt(int row, int column) + -: 76:{ + #####: 77: if(row < 0 || row >= BOARD_ROWS || column < 0 || column >= BOARD_COLS) { +branch 0 never executed (fallthrough) +branch 1 never executed +branch 2 never executed (fallthrough) +branch 3 never executed +branch 4 never executed (fallthrough) +branch 5 never executed +branch 6 never executed (fallthrough) +branch 7 never executed + #####: 78: return Invalid; + -: 79: } + #####: 80: return board[row][column]; +call 0 never executed +call 1 never executed + -: 81:} + -: 82: +function _ZN6Piezas6getMaxE5Piece called 0 returned 0% blocks executed 0% + #####: 83:int Piezas::getMax(Piece piece) { + #####: 84: int maxLength = 0; + -: 85: + -: 86: // Check horizontally + #####: 87: for (int i = 0; i < BOARD_ROWS; ++i) { +branch 0 never executed +branch 1 never executed (fallthrough) + #####: 88: int count = 0; + #####: 89: for (int j = 0; j < BOARD_COLS; ++j) { +branch 0 never executed +branch 1 never executed (fallthrough) + #####: 90: if (board[i][j] == piece) { +call 0 never executed +call 1 never executed +branch 2 never executed (fallthrough) +branch 3 never executed + #####: 91: count++; + #####: 92: maxLength = max(maxLength, count); +call 0 never executed + -: 93: } else { + #####: 94: count = 0; + -: 95: } + -: 96: } + -: 97: } + -: 98: + -: 99: // Check vertically + #####: 100: for (int j = 0; j < BOARD_COLS; ++j) { +branch 0 never executed +branch 1 never executed (fallthrough) + #####: 101: int count = 0; + #####: 102: for (int i = 0; i < BOARD_ROWS; ++i) { +branch 0 never executed +branch 1 never executed (fallthrough) + #####: 103: if (board[i][j] == piece) { +call 0 never executed +call 1 never executed +branch 2 never executed (fallthrough) +branch 3 never executed + #####: 104: count++; + #####: 105: maxLength = max(maxLength, count); +call 0 never executed + -: 106: } else { + #####: 107: count = 0; // reset count if the sequence breaks + -: 108: } + -: 109: } + -: 110: } + -: 111: + #####: 112: return maxLength; + -: 113:} + -: 114: + -: 115: + -: 116: + -: 117:/** + -: 118: * Returns which Piece has won, if there is a winner, Invalid if the game + -: 119: * is not over, or Blank if the board is filled and no one has won ("tie"). + -: 120: * For a game to be over, all locations on the board must be filled with X's + -: 121: * and O's (i.e. no remaining Blank spaces). The winner is which player has + -: 122: * the most adjacent pieces in a single line. Lines can go either vertically + -: 123: * or horizontally. If both X's and O's have the same max number of pieces in a + -: 124: * line, it is a tie. + -: 125:**/ +function _ZN6Piezas9gameStateEv called 0 returned 0% blocks executed 0% + #####: 126:Piece Piezas::gameState() + -: 127:{ + #####: 128: bool full = true; + #####: 129: for(int i = 0; i < BOARD_ROWS; ++i) { +branch 0 never executed +branch 1 never executed (fallthrough) + #####: 130: for(int j = 0; j < BOARD_COLS; ++j) { +branch 0 never executed +branch 1 never executed (fallthrough) + #####: 131: if(board[i][j] == Blank) { +call 0 never executed +call 1 never executed +branch 2 never executed (fallthrough) +branch 3 never executed + #####: 132: full = false; + -: 133: } + -: 134: } + -: 135: } + #####: 136: if(!full) { +branch 0 never executed (fallthrough) +branch 1 never executed + #####: 137: return Invalid; + -: 138: } + -: 139: + #####: 140: int max_X = getMax(X); +call 0 never executed + #####: 141: int max_O = getMax(O); +call 0 never executed + -: 142: + #####: 143: if(max_X > max_O) { +branch 0 never executed (fallthrough) +branch 1 never executed + #####: 144: return X; + #####: 145: } else if(max_O > max_X) { +branch 0 never executed (fallthrough) +branch 1 never executed + #####: 146: return O; + -: 147: } else { + #####: 148: return Blank; + -: 149: } + -: 150:} diff --git a/Piezas.h b/Piezas.h index e5c2987..0a5e8ee 100644 --- a/Piezas.h +++ b/Piezas.h @@ -1,7 +1,7 @@ #ifndef _PIEZAS_H_ #define _PIEZAS_H_ #include - +#include const int BOARD_ROWS = 3; const int BOARD_COLS = 4; @@ -62,6 +62,8 @@ class Piezas **/ Piece pieceAt(int row, int column); + int getMax(Piece piece); + /** * Returns which Piece has won, if there is a winner, Invalid if the game * is not over, or Blank if the board is filled and no one has won ("tie"). diff --git a/PiezasTest b/PiezasTest new file mode 100755 index 0000000..8cf40c8 Binary files /dev/null and b/PiezasTest differ diff --git a/PiezasTest.cpp b/PiezasTest.cpp index c8fccd9..1d741ce 100644 --- a/PiezasTest.cpp +++ b/PiezasTest.cpp @@ -4,6 +4,9 @@ #include #include "Piezas.h" +#include + +using namespace std; class PiezasTest : public ::testing::Test { @@ -14,8 +17,68 @@ class PiezasTest : public ::testing::Test virtual void TearDown(){} //clean up after each test, (before destructor) }; -TEST(PiezasTest, smoke_test) //DELETE THIS TEST AFTER CONFIRMING IT RUNS -{ - Piezas board; - ASSERT_TRUE( true ); +TEST(PiezasTest, BoardInitialization) { + Piezas board; + for (int i = 0; i < BOARD_ROWS; i++) { + for (int j = 0; j < BOARD_COLS; j++) { + ASSERT_EQ(board.pieceAt(i, j), Blank); + } + } +} + +TEST(PiezasTest, DropPieceOnEmptyBoard) { + Piezas board; + ASSERT_EQ(board.dropPiece(0), X); + ASSERT_EQ(board.pieceAt(0, 0), X); +} + +TEST(PiezasTest, DropPieceOutOfBounds) { + Piezas board; + ASSERT_EQ(board.dropPiece(-1), Invalid); + ASSERT_EQ(board.dropPiece(BOARD_COLS), Invalid); +} + +TEST(PiezasTest, DropPieceColumnFull) { + Piezas board; + board.dropPiece(0); + board.dropPiece(0); + board.dropPiece(0); + ASSERT_EQ(board.dropPiece(0), Blank); +} + +TEST(PiezasTest, ResetBoard) { + Piezas board; + board.dropPiece(0); + board.reset(); + for (int i = 0; i < BOARD_ROWS; i++) { + for (int j = 0; j < BOARD_COLS; j++) { + ASSERT_EQ(board.pieceAt(i, j), Blank); + } + } +} + +TEST(PiezasTest, GameStateNotFinished) { + Piezas board; + ASSERT_EQ(board.gameState(), Invalid); +} + +TEST(PiezasTest, GameStateWin) { + Piezas board; + board.dropPiece(0); + board.dropPiece(1); + board.dropPiece(0); + board.dropPiece(1); + board.dropPiece(0); + ASSERT_EQ(board.gameState(), X); +} + +TEST(PiezasTest, GameStateTie) { + Piezas board; + + for (int j = 0; j < BOARD_COLS; j++) { + for (int i = 0; i < BOARD_ROWS; i++) { + board.dropPiece(j); + } + } + ASSERT_EQ(board.gameState(), Blank); }