From 02eadae4caa8e7500d04f65f6673cebc7d13e8a2 Mon Sep 17 00:00:00 2001 From: szdytom Date: Tue, 30 Jan 2024 20:46:18 +0800 Subject: [PATCH] Add framework Signed-off-by: szdytom --- .gitignore | 9 ++++ Compete/Game.cpp | 86 ++++++++++++++++++++++++++++++++++++++ Compete/Game.h | 21 ++++++++++ Compete/main.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++ Strategy/Strategy.cpp | 59 ++++++++++++++++++++++++++ Strategy/Strategy.h | 11 +++++ Strategy/main.cpp | 70 +++++++++++++++++++++++++++++++ 7 files changed, 353 insertions(+) create mode 100644 .gitignore create mode 100644 Compete/Game.cpp create mode 100644 Compete/Game.h create mode 100644 Compete/main.cpp create mode 100644 Strategy/Strategy.cpp create mode 100644 Strategy/Strategy.h create mode 100644 Strategy/main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60bf255 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.out +*.exe +*.so +*.dll +*.sock +.vscode +*.swp +log.txt + diff --git a/Compete/Game.cpp b/Compete/Game.cpp new file mode 100644 index 0000000..1df4449 --- /dev/null +++ b/Compete/Game.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include "Game.h" + +using std::vector; + +GameState::GameState(int n) : n(n), cp(0), win(-1), B(n, vector(n)) { + C[0].resize(n); + C[1].resize(n); + assert(n % 2 == 1); +} + +bool GameState::_checkEnd() const { + int v = 0; + for (int i = 0; i < n; ++i) { + if (C[cp][i] >= (n + 1) / 2) + v += 1; + } + return v >= 4; +} + +bool GameState::move(int x, int y) { + if (x < 0 || x >= n || y < 0 || y >= n) { + return false; + } + + if (B[x][y] == -1) { + return false; + } + + const int dx[] = {0, 0, 1, -1}; + const int dy[] = {1, -1, 0, 0}; + for (int i = 0; i < 4; ++i) { + int xx = x + dx[i], yy = y + dy[i]; + if (xx < 0 || xx >= n || yy < 0 || yy >= n || B[xx][yy] == -1) + goto OK; + } + return false; + +OK: + C[cp][B[x][y]] += 1; + if (C[cp][B[x][y]] >= (n + 1) / 2) { + int t = B[x][y]; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + if (B[i][j] == t) + B[i][j] = -1; + } + } + if (_checkEnd()) + win = cp; + } + + B[x][y] = -1; + cp ^= 1; + return true; +} + +void GameState::randomBoard() { + using namespace std; + vector z; + mt19937 rng(random_device{}()); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) + z.push_back(i); + } + + shuffle(z.begin(), z.end(), rng); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) + B[i][j] = z[i * n + j]; + } +} + +std::string GameState::boardString() const { + std::string res; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + res += std::to_string(B[i][j]); + res += " \n"[j == n - 1]; + } + } + return res; +} + diff --git a/Compete/Game.h b/Compete/Game.h new file mode 100644 index 0000000..60e7f9f --- /dev/null +++ b/Compete/Game.h @@ -0,0 +1,21 @@ +#ifndef CQ4_GAME_H_ +#define CQ4_GAME_H_ + +#include +#include + +struct GameState { + int n; + int cp; + int win; + std::vector> B; + std::vector C[2]; + + GameState(int n); + std::string boardString() const; + bool _checkEnd() const; + bool move(int x, int y); + void randomBoard(); +}; + +#endif diff --git a/Compete/main.cpp b/Compete/main.cpp new file mode 100644 index 0000000..c645cbf --- /dev/null +++ b/Compete/main.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include "Game.h" +using namespace std; + +const int BOARD_SZ = 7; + +int sockfd; +void close_active_socket() { + close(sockfd); +} + +int main(int argc, char **argv) { + sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { + perror("socket()"); + return -1; + } + atexit(close_active_socket); + + sockaddr_in addr; + memset(&addr, 0, sizeof(sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(3030); + + if (bind(sockfd, (sockaddr*)&addr, sizeof(addr)) == -1) { + perror("bind()"); + return -1; + } + + if (listen(sockfd, 2) == -1) { + perror("listen()"); + return -1; + } + + FILE *logf = fopen("log.txt", "w"); + setvbuf(logf, nullptr, _IONBF, 0); + + GameState st(BOARD_SZ); + st.randomBoard(); + + fprintf(stderr, "Waiting for participants...\n"); + FILE *fplayerw[2], *fplayerr[2]; + for (int i = 0; i < 2; ++i) { + int playerfd = accept(sockfd, nullptr, nullptr); + if (playerfd == -1) { + perror("accept()"); + return -1; + } + + fplayerr[i] = fdopen(playerfd, "r"); + fplayerw[i] = fdopen(dup(playerfd), "w"); + fprintf(stderr, "Connected player %d.\n", i); + } + + fprintf(stderr, "Starting game...\n"); + auto b_str = st.boardString(); + fprintf(logf, "%s\n", b_str.c_str()); + for (int i = 0; i < 2; ++i) { + fprintf(fplayerw[i], "init %d\n%s", st.n, b_str.c_str()); + fflush(fplayerw[i]); + } + + fprintf(stderr, "Initial board sent\n"); + int lstX = -1, lstY = -1; + while (st.win == -1) { + if (fprintf(fplayerw[st.cp], "getMove %d %d\n", lstX, lstY) == -1) { + perror("fprintf(getMove)"); + fprintf(stderr, "Lost: %d(RPC Fail)\n", st.cp); + return -1; + } + fflush(fplayerw[st.cp]); + + if (fscanf(fplayerr[st.cp], "%d %d", &lstX, &lstY) == -1) { + perror("recv(getMove)"); + printf("Lost: %d(RPC Fail)\n", st.cp); + close(sockfd); + return -1; + } + + fprintf(logf, "Move(%d): %d %d\n", st.cp, lstX, lstY); + if (!st.move(lstX, lstY)) { + fprintf(stderr, "Lost: %d(Invalid Move)\n", st.cp); + fclose(logf); + return -1; + } + } + fprintf(stderr, "Win: %d\n", st.win); + fclose(logf); + return 0; +} + diff --git a/Strategy/Strategy.cpp b/Strategy/Strategy.cpp new file mode 100644 index 0000000..23b6395 --- /dev/null +++ b/Strategy/Strategy.cpp @@ -0,0 +1,59 @@ +#include "Strategy.h" +#include +using namespace std; + +int N; +vector> B; +int ctl[2][15]; + +void initStrategy(int n, const std::vector> &board) { + N = n; + B = board; + memset(ctl, 0, sizeof(ctl)); +} + +std::tuple getMove(int lstX, int lstY) { + if (lstX != -1) { + ctl[0][B[lstX][lstY]] += 1; + int t = B[lstX][lstY]; + if (ctl[0][B[lstX][lstY]] >= 4) { + for (int i = 0; i < N; ++i) { + for (int j = 0; j < N; ++j) { + if (B[i][j] == t) + B[i][j] = -1; + } + } + } + + B[lstX][lstY] = -1; + } + + for (int i = 0; i < N; ++i) { + for (int j = 0; j < N; ++j) { + bool flag = false; + if (i == 0 || i == N - 1 || j == 0 || j == N - 1) + flag = true; + if (flag || B[i - 1][j] == -1 || B[i + 1][j] == -1 + || B[i][j - 1] == -1 || B[i][j + 1] == -1) + flag = true; + + if (flag && B[i][j] != -1) { + ctl[1][B[i][j]] += 1; + + if (ctl[1][B[i][j]] >= 4) { + int t = B[i][j]; + for (int i = 0; i < N; ++i) { + for (int j = 0; j < N; ++j) { + if (B[i][j] == t) + B[i][j] = -1; + } + } + } + B[i][j] = -1; + return {i, j}; + } + } + } + return {-1, -1}; +} + diff --git a/Strategy/Strategy.h b/Strategy/Strategy.h new file mode 100644 index 0000000..a748cb7 --- /dev/null +++ b/Strategy/Strategy.h @@ -0,0 +1,11 @@ +#ifndef CQ4_STRATEGY_H_ +#define CQ4_STRATEGY_H_ + +#include +#include + +void initStrategy(int n, const std::vector> &B); +std::tuple getMove(int lstX, int lstY); + +#endif + diff --git a/Strategy/main.cpp b/Strategy/main.cpp new file mode 100644 index 0000000..62eb0ce --- /dev/null +++ b/Strategy/main.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Strategy.h" +using namespace std; + +int main(int argc, char **argv) { + int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { + perror("socket()"); + return -1; + } + + sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(3030); + addr.sin_addr.s_addr = inet_addr(argc >= 2 ? argv[1] : "127.0.0.1"); + + if (connect(sockfd, (sockaddr*)&addr, sizeof(addr)) == -1) { + perror("connect()"); + return -1; + } + + fprintf(stderr, "Connected to server.\n"); + FILE *fserverr = fdopen(sockfd, "r"); + FILE *fserverw = fdopen(dup(sockfd), "w"); + static char buf[128]; + while (true) { + if (fscanf(fserverr, "%s", buf) == -1) + break; + string method(buf); + + if (method == "init") { + int n; + fscanf(fserverr, "%d", &n); + vector> B(n, vector(n)); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) + fscanf(fserverr, "%d", &B[i][j]); + } + initStrategy(n, B); + fprintf(stderr, "init() called\n"); + } else if (method == "getMove") { + int lstX, lstY; + fscanf(fserverr, "%d %d", &lstX, &lstY); + fprintf(stderr, "getMove(%d, %d) called\n", lstX, lstY); + auto [x, y] = getMove(lstX, lstY); + if (fprintf(fserverw, "%d %d\n", x, y) == -1) { + perror("send(getMove)"); + return -1; + } + fflush(fserverw); + fprintf(stderr, "getMove(%d, %d): (%d, %d)\n", lstX, lstY, x, y); + } else { + fprintf(stderr, "Unknown method: %s\n", method.c_str()); + return -1; + } + } + + close(sockfd); + return 0; +} +