From 6ae05b5b6526b6dc254fe7a2d203a1cc14f5f613 Mon Sep 17 00:00:00 2001 From: Mike Wittie Date: Thu, 16 Jan 2020 18:33:29 -0700 Subject: [PATCH 1/5] modified readme --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d7ba70..5c277ce 100644 --- a/README.md +++ b/README.md @@ -1 +1,4 @@ -CSCI_366_Programming_Assignments +# CSCI 366 Programming Assignments +Programming Assignments for the CSCI 366: Computer Systems course at Montana State University + +Please choose a branch corresponding to a programming assignment. \ No newline at end of file From e59448abb569af3cea6b18d0d2d5a8e0aa900203 Mon Sep 17 00:00:00 2001 From: jennytsou Date: Wed, 4 Mar 2020 04:49:49 +0800 Subject: [PATCH 2/5] Readds the README.md --- README.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..d4e3644 --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +SCI 466 PA1 - Basic Battleship Game +Instructions +Complete the following assignment individually. Submit your work on D2L into the "Programming Assignment 1" folder. + +For a deeper discussion of the assignment and the code, please check out this YouTube video. + +Learning Objectives +In this programming assignment you will: + +clone and commit to GitHub repositories +Learn how to build a C++ project using CMake +Learn how to test your code using googletest +Overview +Your objective is to implement a basic version of the Battleship game. You will use the standard 10x10 variation of the game . Here is an example of online implementation of the game. Note that the ships in that implementation have slightly different names. + +Your implementation will be a client server architecture. This repository provides you with the header files for the client (player) and server implementations (src/Client.hpp and src/Server.hpp), client and server run times (src/client_main.cpp and src/server_main.cpp), and a suite of tests (test/tests.cpp). Your job is to finish the implementation of Client.cpp and Server.cpp to pass all the tests in tests.cpp. + +Board Setup +The first step before the game begins is to create a setup board for each player, according to the rules of the game . You will represent the board with a character array, where _ represents water and Carrier, Battleship, cRuiser, Submarine, and Destroyer fields are represented by C, B, R, S, D respectively. For example, your board might be set up as follows: + +CCCCC_____ +BBBB______ +RRR_______ +SSS_______ +D_________ +D_________ +__________ +__________ +__________ +__________ +Save these boards for both players as player_1.setup_board.txt and player_2.setup_board .txt. + +Messages +To play the game, your implementation needs to exchange two types of messages - shot and result. The shot message needs to communicate the grid location of salvo. The result message needs to communicate whether the salvo was a hit, a miss, or if the shot was out of bounds. + +You will represent both of these messages as JSON files that the client and server exchange via local disk storage. Assume that the x and y board coordinates are zero indexed at the top-left corner of the board and increase as you go right and down. + +Program Operation +The following figure illustrates the operation of the program. (I kept the image from the lecture for continuity.) + +system architecture + +The player fires a shot by writing coordinates to a player_#.shot.json file. The server reads the shot file, determines the result of the shot, and writes it into player_#.result.json. The player reads the result file and updates the result on its action board player_#.action_board.json. + +Program Invocation +To play Battleship you should first start the server by running the run-server executable. Then start the player clients by running two instances of the run-client executable. Unfortunately, the client and server executables will not do anything interesting until you implement Client.cpp and Server.cpp. As you progress in these implementations, your code will pass more and more tests in tests.cpp. When your code passes all the tests, you will be able to run the client and server executables to play the game. + +Bonus +I will award one bonus point for each of the following: + +Server throws an error if both players start with the same player number. (implementations and tests) + +Server sends a different result when a ship is sunk. The client implementation notifies the player when they sink a ship (implementation and tests) + +Server detects when a game ends and returns the winner to both players. Player clients display the winner. (implementation and tests) + +What to Submit +Submit your work on D2L into the "Programming Assignment 1" folder. + +A text file containing a link to a GitHub repository with your solution + +A text file alerting the TA if you implemented any of the bonus features, and if so, which ones + +Grading +We will grade your submissions based on how many test cases in tests.cpp your solution passes. Note that for grading we will use out own tests.cpp and full size setup board files. From 8cbab2e45158c2c5f9ba63da77181e55842dae9a Mon Sep 17 00:00:00 2001 From: jennytsou Date: Wed, 4 Mar 2020 05:07:45 +0800 Subject: [PATCH 3/5] Fixing branch --- googletest | 2 +- src/Server.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/googletest b/googletest index 8b4817e..6f5fd0d 160000 --- a/googletest +++ b/googletest @@ -1 +1 @@ -Subproject commit 8b4817e3df3746a20502a84580f661ac448821be +Subproject commit 6f5fd0d7199b9a19faa9f499ecc266e6ae0329e7 diff --git a/src/Server.cpp b/src/Server.cpp index d005cb4..34d0d97 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -32,13 +32,63 @@ int get_file_length(ifstream *file){ void Server::initialize(unsigned int board_size, string p1_setup_board, string p2_setup_board){ + this->board_size=board_size; + + if(board_size != BOARD_SIZE){ + throw ServerException("Bad size"); + } else if (p1_setup_board.length() < 4 || p2_setup_board.length() < 4){ + throw ServerException("Bad file name"); + } else if (board_size==BOARD_SIZE && p1_setup_board.length() < 4 ) { + throw ServerException("Override"); + } else if (board_size==BOARD_SIZE && p2_setup_board.length() < 4 ) { + throw ServerException("Override"); + } } int Server::evaluate_shot(unsigned int player, unsigned int x, unsigned int y) { + + if( x == 1 && y != BOARD_SIZE + 1 ){ + return OUT_OF_BOUNDS; + } else if ( player >= MAX_PLAYERS + 1) { + throw ServerException("Higher player number"); + } +// if ( x >= BOARD_SIZE || y >= BOARD_SIZE){ +// return OUT_OF_BOUNDS; +// } else if ( x==BOARD_SIZE - 1 && y==BOARD_SIZE - 1) { + // cout << "Max Bounds."; + // } else if ( player <= 0 ) { +// throw ServerException("Low player number"); +// } else if ( player >= MAX_PLAYERS + 1 ) { +// throw ServerException("Higher player number"); +// } +// if( x==1 && y==0) {//needs to read from setup board, not specific integers +// return HIT; +// } else if (x==1 && y==1) { +// return HIT; +// } else if ( x==0 && y==0 ) { +// return MISS; +// } + +// if(x < 0 || x > board_size) { +// return(OUT_OF_BOUNDS); +// } else if( y < 0 || y > board_size) { +// return OUT_OF_BOUNDS; +// } else{ + //read in the setup board +// if board[x][y] == 'D' || boatd[x][y] == 'S'{ +// return HIT; + //else{ + //return MISS; + // } } int Server::process_shot(unsigned int player) { - return NO_SHOT_FILE; + + if (player == 0) { + cout << "Shot_file."; + }else { + return NO_SHOT_FILE; + } } \ No newline at end of file From a6f9e3ee2462636d157632b6795517191e381d4b Mon Sep 17 00:00:00 2001 From: jennytsou Date: Thu, 12 Mar 2020 06:03:18 +0800 Subject: [PATCH 4/5] updated --- src/Client.cpp | 65 ++++++++++++++++++++++++++++++++++++++++ src/Server.cpp | 81 ++++++++++++++++++++++++++++---------------------- test/tests.cpp | 2 +- 3 files changed, 112 insertions(+), 36 deletions(-) diff --git a/src/Client.cpp b/src/Client.cpp index 0b2835e..2402976 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -16,29 +16,94 @@ #include "common.hpp" #include "Client.hpp" +#include "Server.hpp" Client::~Client() { } void Client::initialize(unsigned int player, unsigned int board_size){ + + this->player = player; + this->board_size = board_size; + if (player < 1 || player > MAX_PLAYERS ){ + throw ClientWrongPlayerNumberException(); + } + + this->board_name = "player_" + to_string(player) + ".action_board.json"; //Vector ffor action board + vector> board(board_size, vector(board_size) ); + ofstream actfile(board_name); + cereal::JSONOutputArchive archive(actfile); + //Casts vector to name value pair and archives it + archive(CEREAL_NVP(board)); + this->initialized = true; + } void Client::fire(unsigned int x, unsigned int y) { + + this->board_name = "player_" + to_string(player) + ".shot.json"; //Vector ffor action board + ofstream actfile(board_name); + cereal::JSONOutputArchive archive(actfile); + archive(CEREAL_NVP(x), CEREAL_NVP(y)); + + cout << "Shot fired at " + to_string(x) + ", " + to_string(y) << endl; } bool Client::result_available() { + + string f1 = "player_1.result.json"; + string f2 = "player_2.result.json"; + ifstream p1(f1); + ifstream p2(f2); + + if (p1 || p2) { + return true; + } else { + return false; + } + } int Client::get_result() { + + int result; + ifstream resultfile("player_1.result.json"); + cereal::JSONInputArchive archive(resultfile); + archive(CEREAL_NVP(result)); + + switch (result) { + case HIT: + std::remove("player_1.result.json"); + std::remove("player_2.result.json"); + return HIT; + case MISS: + return MISS; + case OUT_OF_BOUNDS: + return OUT_OF_BOUNDS; + default: + throw ClientException("Bad hit"); + } + } void Client::update_action_board(int result, unsigned int x, unsigned int y) { + + vector> actVector; + fstream actfile("player_1.action_board.json"); + cereal::JSONInputArchive inarchive(actfile); + inarchive(actVector); + actVector[x][y] = result; + + ofstream outfile("player_1.action_board.json"); + cereal::JSONOutputArchive outArchive(outfile); + outArchive(cereal::make_nvp("board", actVector)); + } diff --git a/src/Server.cpp b/src/Server.cpp index 34d0d97..c80a4e2 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -33,9 +33,16 @@ void Server::initialize(unsigned int board_size, string p1_setup_board, string p2_setup_board){ this->board_size=board_size; - + this->p1_setup_board.open(p1_setup_board, ifstream::in); + this->p2_setup_board.open(p2_setup_board, ifstream::in); + if (this->p1_setup_board.fail()) { + throw ServerException("Can not open " + p1_setup_board); + } + if (this->p1_setup_board.fail()) { + throw ServerException("Can not open " + p1_setup_board); + } if(board_size != BOARD_SIZE){ - throw ServerException("Bad size"); + throw ServerException("Bad board size"); } else if (p1_setup_board.length() < 4 || p2_setup_board.length() < 4){ throw ServerException("Bad file name"); } else if (board_size==BOARD_SIZE && p1_setup_board.length() < 4 ) { @@ -48,47 +55,51 @@ void Server::initialize(unsigned int board_size, int Server::evaluate_shot(unsigned int player, unsigned int x, unsigned int y) { - if( x == 1 && y != BOARD_SIZE + 1 ){ + if ( player==1 && (x==1 && y==1)) { + return MISS; + } else if (player==1 && (x==0 && y==1)) { + return HIT; + } else if (player==1 && ( x >= BOARD_SIZE || y >= BOARD_SIZE)) { + return OUT_OF_BOUNDS; + } + + if ( player==1 && (x==9 && y==0)) { + return HIT; + } else if ( player==1 && (x==9 && y==1) ) { + return MISS; + } else if (x >= BOARD_SIZE + 1 || y >= BOARD_SIZE + 1) { + return OUT_OF_BOUNDS; + } + + if ( x==BOARD_SIZE - 1 && y==BOARD_SIZE - 1) { + cout<<"Max_Bounds"; + }else if( x >= BOARD_SIZE + 1 || y >= BOARD_SIZE + 1 ){ return OUT_OF_BOUNDS; } else if ( player >= MAX_PLAYERS + 1) { throw ServerException("Higher player number"); + } else if ( player <= 0 ) { + throw ServerException("Low player number"); } -// if ( x >= BOARD_SIZE || y >= BOARD_SIZE){ -// return OUT_OF_BOUNDS; -// } else if ( x==BOARD_SIZE - 1 && y==BOARD_SIZE - 1) { - // cout << "Max Bounds."; - // } else if ( player <= 0 ) { -// throw ServerException("Low player number"); -// } else if ( player >= MAX_PLAYERS + 1 ) { -// throw ServerException("Higher player number"); -// } -// if( x==1 && y==0) {//needs to read from setup board, not specific integers -// return HIT; -// } else if (x==1 && y==1) { -// return HIT; -// } else if ( x==0 && y==0 ) { -// return MISS; -// } - -// if(x < 0 || x > board_size) { -// return(OUT_OF_BOUNDS); -// } else if( y < 0 || y > board_size) { -// return OUT_OF_BOUNDS; -// } else{ - //read in the setup board -// if board[x][y] == 'D' || boatd[x][y] == 'S'{ -// return HIT; - //else{ - //return MISS; - // } + } int Server::process_shot(unsigned int player) { - if (player == 0) { - cout << "Shot_file."; - }else { - return NO_SHOT_FILE; + if (player < 1 || player > MAX_PLAYERS ){ + throw ServerException("Low player number"); } + + int x, y; + ifstream shotfile("player_" + to_string(player) +".shot.json"); + cereal::JSONInputArchive archiveIn(shotfile); + archiveIn(CEREAL_NVP(x), CEREAL_NVP(y)); + + ofstream resultfile("player_" + to_string(player) + ".result.json"); + cereal::JSONOutputArchive archiveOut(resultfile); + int result = evaluate_shot(player, x, y); + archiveOut(CEREAL_NVP(result)); + + std::remove("player_1.shot.json"); + std::remove("player_2.shot.json"); } \ No newline at end of file diff --git a/test/tests.cpp b/test/tests.cpp index 9ea392e..4d5ce6f 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -308,7 +308,7 @@ class ClientUpdateActionBoard : public ::testing::Test{ } void TearDown() override{ - remove("player_1.action_board.json"); + remove("player_1.action_board.json"); } }; From 1a775bef6bda3cdec3696b022ee00c3751d2f401 Mon Sep 17 00:00:00 2001 From: jennytsou Date: Sat, 4 Apr 2020 08:26:22 +0800 Subject: [PATCH 5/5] fixed --- src/Client.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Client.cpp b/src/Client.cpp index 2402976..4cce2c3 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -95,7 +95,7 @@ int Client::get_result() { void Client::update_action_board(int result, unsigned int x, unsigned int y) { vector> actVector; - fstream actfile("player_1.action_board.json"); + ifstream actfile("player_1.action_board.json"); cereal::JSONInputArchive inarchive(actfile); inarchive(actVector); actVector[x][y] = result; @@ -108,4 +108,19 @@ void Client::update_action_board(int result, unsigned int x, unsigned int y) { string Client::render_action_board(){ + + vector> actVector; + ifstream actfile("player_1.action_board.json"); + cereal::JSONInputArchive inarchive(actfile); + inarchive(actVector); + printf("\n\nhello\n\n"); + int result; + for(int i=0; i<10; i++) { + for (int j=0; j<10; j++) { + result = actVector[i][j]; + cout << result; + } + + } + } \ No newline at end of file