Add framework

Signed-off-by: szdytom <szdytom@qq.com>
This commit is contained in:
方而静 2024-01-30 20:46:18 +08:00
commit 02eadae4ca
Signed by: szTom
GPG Key ID: 072D999D60C6473C
7 changed files with 353 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
*.out
*.exe
*.so
*.dll
*.sock
.vscode
*.swp
log.txt

86
Compete/Game.cpp Normal file
View File

@ -0,0 +1,86 @@
#include <cassert>
#include <algorithm>
#include <random>
#include "Game.h"
using std::vector;
GameState::GameState(int n) : n(n), cp(0), win(-1), B(n, vector<int>(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<int> 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;
}

21
Compete/Game.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef CQ4_GAME_H_
#define CQ4_GAME_H_
#include <vector>
#include <string>
struct GameState {
int n;
int cp;
int win;
std::vector<std::vector<int>> B;
std::vector<int> C[2];
GameState(int n);
std::string boardString() const;
bool _checkEnd() const;
bool move(int x, int y);
void randomBoard();
};
#endif

97
Compete/main.cpp Normal file
View File

@ -0,0 +1,97 @@
#include <cstdio>
#include <cstring>
#include <string>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#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;
}

59
Strategy/Strategy.cpp Normal file
View File

@ -0,0 +1,59 @@
#include "Strategy.h"
#include <cstring>
using namespace std;
int N;
vector<vector<int>> B;
int ctl[2][15];
void initStrategy(int n, const std::vector<std::vector<int>> &board) {
N = n;
B = board;
memset(ctl, 0, sizeof(ctl));
}
std::tuple<int, int> 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};
}

11
Strategy/Strategy.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef CQ4_STRATEGY_H_
#define CQ4_STRATEGY_H_
#include <vector>
#include <tuple>
void initStrategy(int n, const std::vector<std::vector<int>> &B);
std::tuple<int, int> getMove(int lstX, int lstY);
#endif

70
Strategy/main.cpp Normal file
View File

@ -0,0 +1,70 @@
#include <cstdio>
#include <format>
#include <string>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#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<vector<int>> B(n, vector<int>(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;
}