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