Add framework
Signed-off-by: szdytom <szdytom@qq.com>
This commit is contained in:
commit
02eadae4ca
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
*.out
|
||||||
|
*.exe
|
||||||
|
*.so
|
||||||
|
*.dll
|
||||||
|
*.sock
|
||||||
|
.vscode
|
||||||
|
*.swp
|
||||||
|
log.txt
|
||||||
|
|
86
Compete/Game.cpp
Normal file
86
Compete/Game.cpp
Normal 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
21
Compete/Game.h
Normal 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
97
Compete/main.cpp
Normal 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
59
Strategy/Strategy.cpp
Normal 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
11
Strategy/Strategy.h
Normal 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
70
Strategy/main.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user