diff --git a/Board.cpp b/Board.cpp index d13ccc2..397dc48 100644 --- a/Board.cpp +++ b/Board.cpp @@ -1,3 +1,4 @@ +<<<<<<< HEAD #include #include #include "Board.h" @@ -568,3 +569,578 @@ int Board::evaluate(char max, char min){ +======= +#include +#include +#include "Board.h" + +using namespace std; + +Board::Board() { + Piece* temp; + bool valid = false; + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 8; ++j) { + temp = new Piece(i, j, 'X'); + xpieces.push_back(temp); + pieces.push_back(temp); + } + } + + for (int i = 6; i < 8; ++i) { + for (int j = 0; j < 8; ++j) { + temp = new Piece(i, j, 'O'); + opieces.push_back(temp); + pieces.push_back(temp); + } + } +} + +Board::Board(const Board& b) { + vector xp = b.getXPieces(); + vector op = b.getOPieces(); + Piece* temp; + //bool valid = false; + char tempturn = b.getTurnPls(); + turn = tempturn; + + for (int i = 0; i < xp.size(); ++i) { + temp = new Piece(xp[i]->getX(), xp[i]->getY(), 'X'); + xpieces.push_back(temp); + pieces.push_back(temp); + } + + for (int i = 0; i < op.size(); ++i) { + temp = new Piece(op[i]->getX(), op[i]->getY(), 'O'); + opieces.push_back(temp); + pieces.push_back(temp); + } +} + +void Board::setValidFalse() { + valid = false; +} + +void Board::setValidTrue() { + valid = true; +} + +bool Board::isValid() { + return valid; +} + +//make this efficient! +bool Board::isPiece(int r, int c){ + for (int i = 0; i < pieces.size(); ++i){ + if (pieces[i]->getX() == r && pieces[i]->getY() == c){ + return true; + } + } + + return false; +} + +void Board::isTaken(int r, int c) { + for (int i = 0; i < pieces.size(); ++i){ + if (pieces[i]->getX() == r && pieces[i]->getY() == c){ + if(pieces[i]->getType() == 'O') { + for(int x = 0; x < opieces.size(); ++x) { + if (opieces[x]->getX() == r && opieces[x]->getY() == c) { + opieces.erase(opieces.begin() + x); + //break; + } + } + } + else { + for(int x = 0; x < xpieces.size(); ++x) { + if (xpieces[x]->getX() == r && xpieces[x]->getY() == c) { + xpieces.erase(xpieces.begin() + x); + //break; + } + } + } + pieces.erase(pieces.begin() + i); + break; + } + } +} + +//make this efficient! +Piece* Board::getPiece(int r, int c){ + for (int i = 0; i < pieces.size(); ++i){ + if (pieces[i]->getX() == r && pieces[i]->getY() == c){ + return pieces[i]; + } + } + + return new Piece(); +} + +moves Board::parse(string input){ + input = myToUpper(input); + + int temp1; + int temp2; + string temp3; + + temp2 = input[0] - 'A'; + temp1 = input[1] - '0'; + + if (input[3] == 'L') + { + temp3 = "LEFT"; + } + + else if (input[3] == 'R') + { + temp3 = "RIGHT"; + } + + else + { + temp3 = "FWD"; + } + + moves output(temp1, temp2, temp3); + + return output; +} + +bool Board::isGameOver(){ + for (int i = 0; i < xpieces.size(); ++i){ + if (xpieces[i]->getX() == 7){ + cout<<"\n\n\nPlayer X wins!\n\n\n"<getX() == 0){ + cout<<"\n\n\nPlayer O wins!\n\n\n"<getX() << " " << pieces[i]->getY() << " " << pieces[i]->getType() << "\t"; + } + cout << "Debugging:\n\n"; + */ + cout << "; A B C D E F G H"<getType() == 'X') + cout << "|" << "X"; + else + cout << "|" << "O"; + else + cout << "|" << "_"; + } + + cout<<"|\n"; + } + + cout<<'\n'<getType() == 'X') + output += "|X"; + else + output += "|O"; + else + output += "|_"; + } + + output += "|\n"; + } + + output += "\n\nturn: "; + output += turn; + output += "\n"; + + return output; +} + +int Board::charToIntColumn(char input){ + int kolumn; + + switch (input) + { + case 'A': kolumn = 0; break; + case 'B': kolumn = 1; break; + case 'C': kolumn = 2; break; + case 'D': kolumn = 3; break; + case 'E': kolumn = 4; break; + case 'F': kolumn = 5; break; + case 'G': kolumn = 6; break; + case 'H': kolumn = 7; break; + } + + return kolumn; +} + +char Board::intToCharColumn(int input){ + char kolumn; + + switch (input) + { + case 1: kolumn = 'A'; break; + case 2: kolumn = 'B'; break; + case 3: kolumn = 'C'; break; + case 4: kolumn = 'D'; break; + case 5: kolumn = 'E'; break; + case 6: kolumn = 'F'; break; + case 7: kolumn = 'G'; break; + case 8: kolumn = 'H'; break; + } + + return kolumn; +} + +void Board::move(string inputMove){ + moves m = parse(inputMove); + cout << "MOVE: " << m.row << " " << m.column << " " << m.moveType << "\n\n"; + move(m); +} + +void Board::move(moves m){ + int row = 8 - (m.row); + int column = m.column; + + //cout << "INSIDE MOVE: " << row << " " << column << " " << m.moveType << "\n\n"; + + if (row > 8 || row < 0 || column > 8 || column < 0) { + cout<<"ERROR: index out of bound."<getX() << piece->getY() << "\n\n"; + if (piece->getType() != turn) { + cout<<"ERROR: attempting to move the wrong side's piece.\n"; + } + + else { + if(isThisMovePossible(row, column, m.moveType)) + { + if (m.moveType == "FWD") { + piece->moveFwd(); + } + + else if (m.moveType == "LEFT") { + //add error checking + if(piece->getType() == 'O') { + row--; + column--; + } + else { + row++; + column--; + } + if(isPiece(row, column)) { + if(getPiece(row, column)->getType() != piece->getType()) { + isTaken(row, column); + piece->moveLeft(); + } + } + else { + piece->moveLeft(); + } + } + + else if (m.moveType == "RIGHT") { + //add error checking + //cout << "TESTING??\n\n"; + if(piece->getType() == 'O') { + row--; + column++; + } + else { + row++; + column++; + } + if(isPiece(row, column)) { + if(getPiece(row, column)->getType() != piece->getType()) { + isTaken(row, column); + piece->moveRight(); + } + } + else { + //cout << piece->getX() << " " << piece->getY() << "\n\n"; + piece->moveRight(); + //cout << piece->getX() << " " << piece->getY() << "\n\n"; + } + } + setValidTrue(); + } + else + { + cout << "Invalid move.\n\n"; + setValidFalse(); + } + } +} + +bool Board::isThisMovePossible(int r, int c, string moveType){ + Piece* piece; + Piece* temp; + if (isPiece(r, c)) + piece = getPiece(r, c); + else + return false; + + if (piece->getType() != turn) { + cout << "Error in Board::isThisMovePossible: trying to move a piece outside your turn.\n"; + return false; + } + + else{ + int reflector = 1; + + if (piece->getType() == 'O') + reflector = -1; + + if (moveType == "FWD"){ + if (!isPiece(r + reflector, c)) + return true; + else + return false; + } + + else if (moveType == "RIGHT"){ + temp = getPiece(r + reflector, c+1); + if(c < 7) { + if (!isPiece(r+reflector, c+1) && (r+reflector >= 0) && (r+reflector <= 7) && (c+1 <= 7)) { + //cout << "What.\n\n"; + return true; + } + else if(temp->getType() != piece->getType()) { + char a = temp->getType(); + char b = piece->getType(); + //cout << a << " " << b << "\n\n"; + return true; + } + else { + return false; + } + } + else { + return false; + } + } + + else if (moveType == "LEFT"){ + temp = getPiece(r + reflector, c-1); + if(c > 0) { + if (!isPiece(r+reflector, c-1) && (r+reflector >= 0) && (r+reflector <= 7)) { + //cout << "What.\n\n"; + return true; + } + else if(temp->getType() != piece->getType()) { + char a = temp->getType(); + char b = piece->getType(); + //cout << a << " " << b << "\n\n"; + return true; + } + else { + return false; + } + } + else { + return false; + } + } + + else return false; + } +} + +vector Board::viewPossibleMoves(){ + int r, c = -1; + vector output; + + if (turn == 'X'){ + for (int i = 0; i < xpieces.size(); ++i){ + r = xpieces[i]->getX(); + c = xpieces[i]->getY(); + if (isThisMovePossible(r, c, "FWD")) + { + moves temp(8-r,c, "FWD"); + output.push_back(temp); + } + + if (isThisMovePossible(r,c,"LEFT")) + { + moves temp(8-r,c, "LEFT"); + output.push_back(temp); + } + + if (isThisMovePossible(r,c,"RIGHT")) + { + moves temp(8-r,c, "RIGHT"); + output.push_back(temp); + } + } + } + + else if (turn == 'O') { + //cout << "\nTESTING\n\n"; + for (int i = 0; i < opieces.size(); ++i){ + r = opieces[i]->getX(); + c = opieces[i]->getY(); + if (isThisMovePossible(r, c, "FWD")) + { + moves temp(8-r,c, "FWD"); + output.push_back(temp); + } + + if (isThisMovePossible(r,c,"LEFT")) + { + moves temp(8-r,c, "LEFT"); + output.push_back(temp); + } + + if (isThisMovePossible(r,c,"RIGHT")) + { + moves temp(8-r,c, "RIGHT"); + output.push_back(temp); + } + } + } + + return output; +} + +string Board::myToUpper(string input){ + string output; + + for (int i = 0 ; i < input.size(); ++i) + { + int numeric; + + if ((input[i] - 0 >= 97) && (input[i] - 0 <= 122)) + { + numeric = input[i] - 32; + output.push_back((char)numeric);// = 'Q';//(char) numeric; + } + else output.push_back(input[i]); + } + + return output; + +} + +void Board::undo(Board& tablero){ + vector record; + + if (record.size() < 2) + { + cout<<"nothing to undo"< record; + input = myToUpper(input); + //cout << "MOVE: " << input << "\n\n"; + + if (input == "UNDO") + { + undo(tablero); + } + + else if (input == "DISPLAYRECORD") //for debugging purposes + { + cout<<"record: "<& inputVec, Board inputBoard){ + if (inputVec.size() == 10) + { + inputVec.erase(inputVec.begin()); + } + + else if (inputVec.size() > 10) + { + cout<<"QUEUE OVERFLOW!"<>>>>>> master diff --git a/Board.h b/Board.h index 44becfc..6f3d67c 100644 --- a/Board.h +++ b/Board.h @@ -1,3 +1,4 @@ +<<<<<<< HEAD #pragma once #include @@ -55,3 +56,63 @@ public: void snapshot(vector& inputVec, Board inputBoard); int evaluate(char max, char min); }; +======= +#pragma once + +#include +#include +#include "Piece.h" + +using namespace std; + +struct moves { + int row; + int column; + string moveType; + + moves(int linea, int columna, string m) { + row = linea; + column = columna; + moveType = m; + } +}; + +class Board { + vector xpieces; + vector opieces; + vector pieces; + char turn = 'O'; + bool valid = false; + +public: + Board(); + Board(const Board& b); + void setValidFalse(); + void setValidTrue(); + bool isValid(); + bool isPiece(int r, int c); + void isTaken(int r, int c); + Piece* getPiece(int r, int c); + vector getXPieces() const { return xpieces; } + vector getOPieces() const { return opieces; } + char getTurnPls() const { return turn; } + moves parse(string input); + char getTurn() { return turn; } + bool isGameOver(); + void changeTurns(); + void displayBoard(); + string boardToString(); + int charToIntColumn(char input); + char intToCharColumn(int input); + void move(string inputMove); + void move(moves jugada); + void moveWOPrint(moves jugada); + bool isThisMovePossible(int r, int c, string moveType); + vector viewPossibleMoves(); + string myToUpper(string input); + void undo(Board& tablero); + void interpret(string input, Board& tablero); + void snapshot(vector& inputVec, Board inputBoard); + int evaluate(char max, char min); +}; +>>>>>>> master diff --git a/Client.class b/Client.class new file mode 100644 index 0000000..042ed8e Binary files /dev/null and b/Client.class differ diff --git a/Engine.cpp b/Engine.cpp index d05e61a..ca2ce59 100644 --- a/Engine.cpp +++ b/Engine.cpp @@ -1,3 +1,4 @@ +<<<<<<< HEAD #include #include #include @@ -212,3 +213,149 @@ moves Engine::minMax(moves m, int c){ return m; }*/ } +======= +#include +#include +#include +#include +#include "Engine.h" + +Engine::Engine(){ + Board* brd = new Board(); + b = brd; +} + +void Engine::startGame(){ + cout<<"WELCOME\n"; + + cout<<"1. Play against AI?\n"; + cout<<"2. Play against a human?\n"; + cout<<"Enter choice: \n"; + + int choice = -1; + cin >> choice; + cout << "OK" << endl; + + string move; + + bool gameOver = false; + vector record; + b->snapshot(record, *b); + + while (gameOver != true) + { + gameOver = b->isGameOver(); + + while(b->getTurn() == 'O' && !b->isValid()) + { + b->displayBoard(); + cout<<"\nEnter command: "; + cin>>move; + cout << "\n"; + b->interpret(move, *b); + if(b->isValid()) { + b->changeTurns(); + b->setValidFalse(); + } + } + + //if(b->isValid()) cout << b->getTurn(); + + while(b->getTurn() == 'X' ) + { + AI(); + } + + gameOver = b->isGameOver(); + b->setValidFalse(); + + b->snapshot(record, *b); + } +} + +void Engine::easyAI() +{ + vector listOfMoves = b->viewPossibleMoves(); + /* + for(int x = 0; x < listOfMoves.size(); ++x) { + cout << listOfMoves[x].row << " " << listOfMoves[x].column << " " << listOfMoves[x].moveType << "\n\n"; + } + */ + srand(time(NULL)); + int randomChoice = rand() % (listOfMoves.size()-1) - 0; + + //int temp = randomChoice; + cout << "easy AI move: " << listOfMoves[randomChoice].row << listOfMoves[randomChoice].column << listOfMoves[randomChoice].moveType << "\n"; + b->move(listOfMoves[randomChoice]); + b->changeTurns(); +} + +void Engine::AI(){ + //cout << "----------------------BEGIN AI FUNCTION----------------------\n"; + vector listOfMoves = b->viewPossibleMoves(); + Board* temp = new Board(*b); + + //probably not needed, check later + /* + if (b->getTurn() != 'X'){ + cout << "a changing of turns is needed. \n"; + b->changeTurns(); + } + */ + //only doing 1 branch right now because testing + /*for (int i = 0; i < listOfMoves.size(); ++i){ + minMax(b, listOfMoves[i]); + }*/ + + b->move(minMax(temp, listOfMoves[0], 0, 0)); + b->changeTurns(); + + //verification of correct turn + /* + if (b->getTurn() != 'O'){ + cout << "ERROR in Engine::AI: b is on the wrong turn. \n"; + } + */ + b->displayBoard(); + //cout << "----------------------END AI FUNCTION----------------------\n"; +} + +moves Engine::minMax(Board* temp, moves m, int c, int r){ + //testing purposes only, c = finite depth + //cout << "c: " << c << "\n\n"; + //cout << "current turn: " << temp->getTurn() << "\n"; + vector listOfMoves = temp->viewPossibleMoves(); + //cout << "listOfMoves size: " << listOfMoves.size() << "\n\n"; + /* + if (c > 5){ + return m; + } + */ + if (temp->isGameOver() == true){ + //cout << "END OF PATH REACHED\n"; + return m; + } + + else { + if(temp->getPiece(8 - m.row, m.column)->getType() == temp->getTurn() && temp->isThisMovePossible(8 - m.row, m.column, m.moveType)){ + //cout << "piece has been moved in minMax\n"; + temp->move(m); + temp->evaluate('X', 'O'); + temp->changeTurns(); + //temp->displayBoard(); + } + else { + //cout << m.row << " " << m.column << "\n\n"; + m = minMax(temp, listOfMoves[++r], c, r); + } + + //temp->displayBoard(); + vector listOfMoves = temp->viewPossibleMoves(); + //cout << "listOfMoves size: " << listOfMoves.size() << "\n\n"; + minMax(temp, listOfMoves[0], 0, 0); + + //testing + return m; + } +} +>>>>>>> master diff --git a/Engine.h b/Engine.h index 66f8843..48c989a 100644 --- a/Engine.h +++ b/Engine.h @@ -1,3 +1,4 @@ +<<<<<<< HEAD #pragma once #include "Board.h" @@ -13,4 +14,22 @@ public: void easyAI(); void AI(); moves minMax(moves m, int c); +======= +#pragma once + +#include "Board.h" + +using namespace std; + +class Engine { + Board* b; + +public: + Engine(); + void startGame(); + void easyAI(); + void AI(); + Board* getBoard() { return b; } + moves minMax(Board* temp, moves m, int c, int r); +>>>>>>> master }; diff --git a/Piece.cpp b/Piece.cpp index 6848914..659b3fa 100644 --- a/Piece.cpp +++ b/Piece.cpp @@ -1,3 +1,4 @@ +<<<<<<< HEAD #include #include "Piece.h" @@ -67,3 +68,74 @@ void Piece::moveRight(){ void Piece::isTaken(){ cout << getX() << " " << getY() << "\n\n"; } +======= +#include +#include "Piece.h" + +using namespace std; + +Piece::Piece(){ + x = -1; + y = -1; + type = '?'; +} + +Piece::Piece(int r, int c){ + x = r; + y = c; + type = '_'; +} + +Piece::Piece(int r, int c, char t){ + x = r; + y = c; + type = t; +} + +void Piece::moveFwd(){ + if (type == 'X'){ + x++; + } + + else if (type == 'O'){ + x--; + } + + else + cout << "Error: trying to move an empty piece forward."; +} + +void Piece::moveLeft(){ + if (type == 'X'){ + x++; + y--; + } + + else if (type == 'O'){ + x--; + y--; + } + + else + cout << "Error: trying to move an empty piece left."; +} + +void Piece::moveRight(){ + if (type == 'X'){ + x++; + y++; + } + + else if (type == 'O'){ + x--; + y++; + } + + else + cout << "Error: trying to move an empty piece left."; +} + +void Piece::isTaken(){ + cout << getX() << " " << getY() << "\n\n"; +} +>>>>>>> master diff --git a/Piece.h b/Piece.h index 245c7cc..31dc42f 100644 --- a/Piece.h +++ b/Piece.h @@ -1,3 +1,4 @@ +<<<<<<< HEAD #pragma once using namespace std; @@ -22,3 +23,29 @@ public: void makeEmpty(){ type = '_'; } void isTaken(); }; +======= +#pragma once + +using namespace std; + +class Piece { + int x; + int y; + char type; + +public: + Piece(); + Piece(int r, int c); + Piece(int r, int c, char t); + void moveFwd(); + void moveLeft(); + void moveRight(); + int getX(){ return x; } + void setX(int r){ x = r; } + int getY(){ return y; } + void setY(int c){ y = c; } + char getType(){ return type; } + void makeEmpty(){ type = '_'; } + void isTaken(); +}; +>>>>>>> master diff --git a/README.md b/README.md index 112f16e..4115f48 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Breakthrough Reposity for the second CSCE 315 project +<<<<<<< HEAD To compile everything: g++ -std=c++11 test.cpp Engine.cpp Board.cpp Piece.cpp -o runner or, alternatively if you delete the Parser.h, Parser.cpp, and Client.cpp (there's no need for them currently) g++ -std=c++11 *.cpp -o runner To launch the server: ./runner @@ -8,3 +9,17 @@ To launch the server: ./runner Enter a port number when prompted, then the server is launched and waiting for a client to join. Client can simply join via telnet: telnet linux.cse.tamu.edu +======= +To compile everything: + make + or make all + +To run test: + ./test + +To launch the server: +./server [port #] + +Client can simply join via telnet: + telnet linux.cse.tamu.edu +>>>>>>> master diff --git a/test.cpp b/test.cpp index e697fbe..2dd8313 100644 --- a/test.cpp +++ b/test.cpp @@ -4,11 +4,22 @@ using namespace std; int main() { +<<<<<<< HEAD Engine e; +======= + //Board b; + Engine e; + /* +>>>>>>> master int pn = 0; cout << "Welcome to Breakthrough server launcher, please enter a host port number: \n"; cin >> pn; cin.clear(); cin.ignore(10000,'\n'); +<<<<<<< HEAD e.startGame(pn); +======= + */ + e.startGame(); +>>>>>>> master } diff --git a/test.txt b/test.txt deleted file mode 100644 index e69de29..0000000