From 61eca48032cf83c6ac8f754004929236e38f68aa Mon Sep 17 00:00:00 2001 From: Suzu Tomo Date: Thu, 22 Sep 2022 00:38:54 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20API=E3=81=AE=E3=82=A2=E3=83=83?= =?UTF-8?q?=E3=83=97=E3=83=87=E3=83=BC=E3=83=88=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 19 ++- client_none.cpp | 9 -- kakomimasu.cpp | 186 ++++++++++++++++++-------- kakomimasu.h | 89 ++++++------ main.cpp | 70 ++++++++++ client_a1.cpp => sample/client_a1.cpp | 26 ++-- client_a2.cpp => sample/client_a2.cpp | 28 ++-- client_a4.cpp => sample/client_a4.cpp | 71 ++++++---- client_a5.cpp => sample/client_a5.cpp | 106 ++++++++++----- sample/client_none.cpp | 9 ++ 10 files changed, 426 insertions(+), 187 deletions(-) delete mode 100644 client_none.cpp create mode 100644 main.cpp rename client_a1.cpp => sample/client_a1.cpp (77%) rename client_a2.cpp => sample/client_a2.cpp (80%) rename client_a4.cpp => sample/client_a4.cpp (71%) rename client_a5.cpp => sample/client_a5.cpp (68%) create mode 100644 sample/client_none.cpp diff --git a/README.md b/README.md index f83a1c6..35cc10d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,17 @@ # 囲みマスC++クライアント -## Visual Studioでのビルドの手順 +## 使い方 + +`main.cpp`にサンプルのコードが書かれています。 +`main.cpp`は`sample/client_a1.cpp`の内容に加えオプション設定方法などが書かれています。 +何も設定しない状態では、ゲストユーザとして参加します。 + +ゲスト名を変える場合やAI対戦をする場合などにはコメント部分を解除して使用してください。 + + +## ビルド + +### Visual Studioでのビルドの手順 - Visual Studio Community 2019をインストールします - https://visualstudio.microsoft.com/ja/vs/community/ @@ -17,7 +28,7 @@ - 「全般」→「C++ 言語標準」→「ISO C++17 標準 (std:c++17)」を選択します - 「C++」→「SDLチェック」→「いいえ (/sdl-)」を選択します(sscanfに必要です) -## GCC(Windows)でのビルドの手順 +### GCC(Windows)でのビルドの手順 - MinGW-w64をインストールします - https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/installer/mingw-w64-install.exe/download @@ -32,9 +43,7 @@ - C:\Program Files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\i686-w64-mingw32\bin - curlをインストールします - https://curl.se/windows/ - - curl for 32 bit - - bin,include,libをmingw32のディレクトリに入れます - コンパイルします - - g++ -std=c++17 client_a1.cpp kakomimasu.cpp -lcurl + - g++ -std=c++17 main.cpp kakomimasu.cpp コンパイルできない場合は、環境変数の設定でMinGWの優先度を一番上にするとうまくいく場合があります。 diff --git a/client_none.cpp b/client_none.cpp deleted file mode 100644 index 926ed6d..0000000 --- a/client_none.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "kakomimasu.h" - -int main() { - // 自分のbearerTokenを書く - KakomimasuClient kc(""); - kc.waitMatching(); - - return 0; -} \ No newline at end of file diff --git a/kakomimasu.cpp b/kakomimasu.cpp index 6efba6d..23126ef 100644 --- a/kakomimasu.cpp +++ b/kakomimasu.cpp @@ -11,19 +11,15 @@ const int DIR[8][2] = { {1, 1}, }; -string host = "https://kakomimasu.website/api"; -void setHost(string s) { +string host = "https://api.kakomimasu.com"; +void setHost(string s) +{ host = s; } -static size_t callbackWrite(char *ptr, size_t size, size_t nmemb, string *stream) { - int dataLength = size * nmemb; - stream->append(ptr, dataLength); - return dataLength; -} - -string curlGet(string req, string token = "") { - // cout << "GET " << req << endl; +string curlGet(string req, string token = "") +{ + cout << "GET " << req << endl; const int sz = 102400; char buf[sz]; char cmdline[sz]; @@ -39,21 +35,25 @@ string curlGet(string req, string token = "") { return res; } -string curlPost(string req, string post_data, string bearer = "") { - // cout << "POST " << req << endl; +string curlPost(string req, string post_data, string auth = "") +{ + cout << "POST " << req << endl; + // cout << post_data << endl; const int sz = 102400; char buf[sz]; char cmdline[sz]; #ifdef _WIN64 - for (int i = 0; i < post_data.size(); ++i) { - if (post_data[i] == '"') { + for (int i = 0; i < post_data.size(); ++i) + { + if (post_data[i] == '"') + { post_data.insert(i, "\\"); i++; } } - snprintf(cmdline, sz, "curl -s -X POST -H \"Authorization:Bearer %s\" -H \"Content-Type: application/json\" -d %s \"%s%s\"", bearer.c_str(), post_data.c_str(), host.c_str(), req.c_str()); + snprintf(cmdline, sz, "curl -s -X POST -H \"Authorization:%s\" -H \"Content-Type: application/json\" -d %s \"%s%s\"", auth.c_str(), post_data.c_str(), host.c_str(), req.c_str()); #else - snprintf(cmdline, sz, "curl -s -X POST -H \"Authorization:Bearer %s\" -H \"Content-Type: application/json\" -d '%s' \"%s%s\"", bearer.c_str(), post_data.c_str(), host.c_str(), req.c_str()); + snprintf(cmdline, sz, "curl -s -X POST -H \"Authorization:%s\" -H \"Content-Type: application/json\" -d '%s' \"%s%s\"", auth.c_str(), post_data.c_str(), host.c_str(), req.c_str()); #endif #ifdef _MSC_VER @@ -68,40 +68,82 @@ string curlPost(string req, string post_data, string bearer = "") { return res; } -string userShow(string identifier) { - string res = curlGet("/users/show/" + identifier); - cout << res << endl; - return res; -} - random_device seed_gen; mt19937 engine(seed_gen()); -int rnd(int n) { +int rnd(int n) +{ return engine() % n; } -KakomimasuClient::KakomimasuClient(string bearer) { +KakomimasuClient::KakomimasuClient() +{ + m_guest_name = "cpp-guest"; +} + +void KakomimasuClient::setBearerToken(string bearer) +{ m_bearer = bearer; } -bool KakomimasuClient::getGameInfo() { - string res = curlGet("/match/" + m_game_id); +void KakomimasuClient::setAi(string ai_name, string ai_board = "") +{ + m_ai_name = ai_name; + m_ai_board = ai_board; +} + +void KakomimasuClient::setGuestName(string guest_name) +{ + m_guest_name = guest_name; +} + +bool KakomimasuClient::getGameInfo() +{ + string res = curlGet("/v1/match/" + m_game_id); picojson::value val; picojson::parse(val, res); picojson::object obj = val.get(); m_gameInfo = obj; - if (!m_gameInfo["board"].is()) { + if (!m_gameInfo["board"].is()) + { m_board = m_gameInfo["board"].get(); } return m_gameInfo["gaming"].get(); } -void KakomimasuClient::waitMatching() { +void KakomimasuClient::waitMatching() +{ + string auth = ""; + picojson::object send_obj; - string res = curlPost("/match", picojson::value(send_obj).serialize(), m_bearer); + + if (m_bearer.empty()) + { + picojson::object guest_obj; + guest_obj["name"] = picojson::value(m_guest_name); + send_obj["guest"] = picojson::value(guest_obj); + } + else + { + auth = "Bearer " + m_bearer; + } + + if (!m_ai_name.empty()) + { + picojson::object ai_obj; + ai_obj["aiName"] = picojson::value(m_ai_name); + if (!m_ai_board.empty()) + { + ai_obj["boardName"] = picojson::value(m_ai_board); + } + + send_obj["useAi"] = picojson::value(true); + send_obj["aiOption"] = picojson::value(ai_obj); + } + + string res = curlPost("/v1/match", picojson::value(send_obj).serialize(), auth); picojson::value val; picojson::parse(val, res); @@ -109,119 +151,153 @@ void KakomimasuClient::waitMatching() { m_game_id = obj["gameId"].get(); m_player_no = obj["index"].get(); + m_pic = obj["pic"].get(); + + cout << "gameId: " << m_game_id << endl; + cout << "playerNo: " << m_player_no << endl; - while (!getGameInfo()) { + while (!getGameInfo()) + { this_thread::sleep_for(chrono::milliseconds(500)); } cout << "maching!" << endl; } -int KakomimasuClient::getWidth() { +int KakomimasuClient::getWidth() +{ return (int)m_board["width"].get(); }; -int KakomimasuClient::getHeight() { +int KakomimasuClient::getHeight() +{ return (int)m_board["height"].get(); }; -int KakomimasuClient::getAgentCount() { +int KakomimasuClient::getAgentCount() +{ return (int)m_board["nAgent"].get(); }; -int KakomimasuClient::getPlayerNumber() { +int KakomimasuClient::getPlayerNumber() +{ return m_player_no; }; -int KakomimasuClient::getNextTurnUnixTime() { - return (int)m_gameInfo["nextTurnUnixTime"].get(); +int KakomimasuClient::getNextTurnUnixTime() +{ + int start_at_unix_time = (int)m_gameInfo["startedAtUnixTime"].get(); + int operation_sec = (int)m_gameInfo["operationSec"].get(); + int transition_sec = (int)m_gameInfo["transitionSec"].get(); + int turn = (int)m_gameInfo["turn"].get(); + int next_turn_unix_time = start_at_unix_time + (operation_sec + transition_sec) * turn; + cout << start_at_unix_time << " " << operation_sec << " " << transition_sec << " " << turn << " " << next_turn_unix_time << endl; + return next_turn_unix_time; }; -int KakomimasuClient::getTurn() { +int KakomimasuClient::getTurn() +{ return (int)m_gameInfo["turn"].get(); }; -int KakomimasuClient::getTotalTurn() { +int KakomimasuClient::getTotalTurn() +{ return (int)m_gameInfo["totalTurn"].get(); }; -vector> KakomimasuClient::getPoints() { +vector> KakomimasuClient::getPoints() +{ int height = getHeight(); int width = getWidth(); vector> res(height, vector(width)); picojson::array ary = m_board["points"].get(); int i = 0, j = 0; - for (auto &val : ary) { + for (auto &val : ary) + { res[i][j] = val.get(); j++; - if (j == width) j = 0, i++; + if (j == width) + j = 0, i++; } return res; } -vector> KakomimasuClient::getFiled() { +vector> KakomimasuClient::getFiled() +{ int height = getHeight(); int width = getWidth(); vector> res(height, vector(width)); picojson::array ary = m_board["points"].get(); int i = 0, j = 0; - for (auto &val : ary) { + for (auto &val : ary) + { res[i][j].point = val.get(); j++; - if (j == width) j = 0, i++; + if (j == width) + j = 0, i++; } i = j = 0; ary = m_gameInfo["tiled"].get(); - for (auto &val : ary) { + for (auto &val : ary) + { int type, pid; sscanf(val.serialize().c_str(), "[%d,%d]", &type, &pid); res[i][j].type = type; res[i][j].pid = pid; j++; - if (j == width) j = 0, i++; + if (j == width) + j = 0, i++; } return res; } -vector KakomimasuClient::getAgent() { +vector KakomimasuClient::getAgent() +{ vector res; picojson::array player = m_gameInfo["players"].get(); picojson::object obj = player[m_player_no].get(); picojson::array ary = obj["agents"].get(); - for (int i = 0; i < ary.size(); i++) { + for (int i = 0; i < ary.size(); i++) + { picojson::object pos = ary[i].get(); res.push_back({(int)pos["x"].get(), (int)pos["y"].get()}); } return res; }; -vector KakomimasuClient::getEnemyAgent() { +vector KakomimasuClient::getEnemyAgent() +{ vector res; picojson::array player = m_gameInfo["players"].get(); picojson::object obj = player[1 - m_player_no].get(); picojson::array ary = obj["agents"].get(); - for (int i = 0; i < ary.size(); i++) { + for (int i = 0; i < ary.size(); i++) + { picojson::object pos = ary[i].get(); res.push_back({(int)pos["x"].get(), (int)pos["y"].get()}); } return res; }; -void KakomimasuClient::waitNextTurn() { +void KakomimasuClient::waitNextTurn() +{ int next_time = getNextTurnUnixTime(); - while (time(NULL) < next_time) { + while (time(NULL) < next_time) + { this_thread::sleep_for(chrono::milliseconds(100)); } } -void KakomimasuClient::setAction(vector action) { +void KakomimasuClient::setAction(vector action) +{ picojson::array arr; - for (const auto &[agentId, type, x, y] : action) { + for (const auto &[agentId, type, x, y] : action) + { picojson::object obj; obj.emplace(make_pair("agentId", picojson::value((double)agentId))); obj.emplace(make_pair("type", type)); @@ -238,5 +314,5 @@ void KakomimasuClient::setAction(vector action) { picojson::value val(send_obj); string post_data = val.serialize(); - cout << curlPost("/match/" + m_game_id + "/action", post_data, m_bearer) << endl; + cout << curlPost("/v1/match/" + m_game_id + "/action", post_data, m_pic) << endl; }; \ No newline at end of file diff --git a/kakomimasu.h b/kakomimasu.h index 320dc50..cdc53d3 100644 --- a/kakomimasu.h +++ b/kakomimasu.h @@ -7,57 +7,62 @@ #include using namespace std; -struct Action { - int agentId; - string type; - int x; - int y; +struct Action +{ + int agentId; + string type; + int x; + int y; }; -struct Tile { - int type; - int pid; - int point; +struct Tile +{ + int type; + int pid; + int point; }; -struct Agent { - int x; - int y; +struct Agent +{ + int x; + int y; }; extern const int DIR[8][2]; void setHost(string s); -string userShow(string identifier); -void userRegist(string screenName, string name, string password); -static size_t callbackWrite(char *ptr, size_t size, size_t nmemb, string *stream); string curlGet(string req, string token); string curlPost(string req, string post_data, string token); int rnd(int n); -class KakomimasuClient { - public: - KakomimasuClient(string bearer); - bool getGameInfo(); - void waitMatching(); - int getWidth(); - int getHeight(); - int getAgentCount(); - int getPlayerNumber(); - int getNextTurnUnixTime(); - int getTurn(); - int getTotalTurn(); - vector> getPoints(); - vector> getFiled(); - vector getAgent(); - vector getEnemyAgent(); - void waitNextTurn(); - void setAction(vector action); +class KakomimasuClient +{ +public: + KakomimasuClient(); + void setBearerToken(string bearer); + void setAi(string ai_name, string ai_board); + void setGuestName(string guest_name); + bool getGameInfo(); + void waitMatching(); + int getWidth(); + int getHeight(); + int getAgentCount(); + int getPlayerNumber(); + int getNextTurnUnixTime(); + int getTurn(); + int getTotalTurn(); + vector> getPoints(); + vector> getFiled(); + vector getAgent(); + vector getEnemyAgent(); + void waitNextTurn(); + void setAction(vector action); - private: - string m_name; - string m_password; - string m_token; - string m_game_id; - string m_bearer; - int m_player_no; - picojson::object m_gameInfo; - picojson::object m_board; +private: + string m_game_id; + string m_guest_name; + string m_bearer; + string m_pic; + string m_ai_name; + string m_ai_board; + int m_player_no; + picojson::object m_gameInfo; + picojson::object m_board; }; \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..6f4f75f --- /dev/null +++ b/main.cpp @@ -0,0 +1,70 @@ +#include "kakomimasu.h" + +int main() +{ + KakomimasuClient kc; + + // ************** オプション設定 ここから ************** + + // APIの接続先を変える場合 + // setHost("http://localhost:8880"); + + // ゲスト名を変える場合(デフォルトはcpp-test) + // kc.setGuestName("kosen-taro"); + + // BearerTokenを設定する場合 + // kc.setBearerToken("xxxxxxxx"); + + // AI対戦する場合(ai名とボード名(省略可)を指定) + // kc.setAi("a1"); + + // ************** オプション設定 ここまで ************** + + kc.waitMatching(); + kc.getGameInfo(); + + const int pno = kc.getPlayerNumber(); + const vector> points = kc.getPoints(); + const int w = kc.getWidth(); + const int h = kc.getHeight(); + const int nagents = kc.getAgentCount(); + + // ポイントの高い順ソート + vector> pntall; + for (int i = 0; i < h; i++) + { + for (int j = 0; j < w; j++) + { + pntall.emplace_back(points[i][j], j, i); + } + } + sort(pntall.rbegin(), pntall.rend()); + + // ↓ここからがAIの中身↓ + while (kc.getGameInfo()) + { + // ランダムにずらしつつ置けるだけおく + // 置いたものはランダムに8方向に動かす + vector action; + const int offset = rnd(nagents); + for (int i = 0; i < nagents; i++) + { + const Agent agent = kc.getAgent()[i]; + if (agent.x == -1) + { + const auto [point, x, y] = pntall[i + offset]; + action.push_back({i, "PUT", x, y}); + } + else + { + const auto [dx, dy] = DIR[rnd(8)]; + action.push_back({i, "MOVE", agent.x + dx, agent.y + dy}); + } + } + kc.setAction(action); + // break; + kc.waitNextTurn(); + } + + return 0; +} \ No newline at end of file diff --git a/client_a1.cpp b/sample/client_a1.cpp similarity index 77% rename from client_a1.cpp rename to sample/client_a1.cpp index f152cba..c356710 100644 --- a/client_a1.cpp +++ b/sample/client_a1.cpp @@ -1,8 +1,8 @@ #include "kakomimasu.h" -int main() { - // 自分のbearerTokenを書く - KakomimasuClient kc(""); +int main() +{ + KakomimasuClient kc; kc.waitMatching(); kc.getGameInfo(); @@ -14,30 +14,38 @@ int main() { // ポイントの高い順ソート vector> pntall; - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { + for (int i = 0; i < h; i++) + { + for (int j = 0; j < w; j++) + { pntall.emplace_back(points[i][j], j, i); } } sort(pntall.rbegin(), pntall.rend()); // ↓ここからがAIの中身↓ - while (kc.getGameInfo()) { + while (kc.getGameInfo()) + { // ランダムにずらしつつ置けるだけおく // 置いたものはランダムに8方向に動かす vector action; const int offset = rnd(nagents); - for (int i = 0; i < nagents; i++) { + for (int i = 0; i < nagents; i++) + { const Agent agent = kc.getAgent()[i]; - if (agent.x == -1) { + if (agent.x == -1) + { const auto [point, x, y] = pntall[i + offset]; action.push_back({i, "PUT", x, y}); - } else { + } + else + { const auto [dx, dy] = DIR[rnd(8)]; action.push_back({i, "MOVE", agent.x + dx, agent.y + dy}); } } kc.setAction(action); + // break; kc.waitNextTurn(); } diff --git a/client_a2.cpp b/sample/client_a2.cpp similarity index 80% rename from client_a2.cpp rename to sample/client_a2.cpp index 952f543..41249ea 100644 --- a/client_a2.cpp +++ b/sample/client_a2.cpp @@ -1,8 +1,8 @@ #include "kakomimasu.h" -int main() { - // 自分のbearerTokenを書く - KakomimasuClient kc(""); +int main() +{ + KakomimasuClient kc; kc.waitMatching(); kc.getGameInfo(); @@ -14,27 +14,35 @@ int main() { // ポイントの高い順ソート vector> pntall; - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { + for (int i = 0; i < h; i++) + { + for (int j = 0; j < w; j++) + { pntall.emplace_back(points[i][j], j, i); } } sort(pntall.rbegin(), pntall.rend()); // ↓ここからがAIの中身↓ - while (kc.getGameInfo()) { + while (kc.getGameInfo()) + { // ランダムにずらしつつ置けるだけおく // 置いたものはランダムに8方向に動かす // 画面外にはでない判定を追加(a1 → a2) vector action; const int offset = rnd(nagents); - for (int i = 0; i < nagents; i++) { + for (int i = 0; i < nagents; i++) + { const Agent agent = kc.getAgent()[i]; - if (agent.x == -1) { + if (agent.x == -1) + { const auto [point, x, y] = pntall[i + offset]; action.push_back({i, "PUT", x, y}); - } else { - while (true) { + } + else + { + while (true) + { const auto [dx, dy] = DIR[rnd(8)]; const int x = agent.x + dx; const int y = agent.y + dy; diff --git a/client_a4.cpp b/sample/client_a4.cpp similarity index 71% rename from client_a4.cpp rename to sample/client_a4.cpp index 87d3a0f..2417c76 100644 --- a/client_a4.cpp +++ b/sample/client_a4.cpp @@ -1,20 +1,22 @@ // だいたい点数の高い順に置き、点数の高い順に壊しながら動くアルゴリズム #include "kakomimasu.h" -struct Tile_info { +struct Tile_info +{ int x, y; int type, pid; int point; // ポイントが高い順にソートできるように比較演算子の定義 - bool operator<(const Tile_info &right) const { + bool operator<(const Tile_info &right) const + { return point < right.point; } }; -int main() { - // 自分のbearerTokenを書く - KakomimasuClient kc(""); +int main() +{ + KakomimasuClient kc; kc.waitMatching(); kc.getGameInfo(); @@ -26,22 +28,27 @@ int main() { // ポイントの高い順ソート vector> pntall; - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { + for (int i = 0; i < h; i++) + { + for (int j = 0; j < w; j++) + { pntall.emplace_back(points[i][j], j, i); } } sort(pntall.rbegin(), pntall.rend()); // ↓ここからがAIの中身↓ - while (kc.getGameInfo()) { + while (kc.getGameInfo()) + { vector actions; vector> field = kc.getFiled(); const int offset = rnd(nagents); vector> poschk; // 動く予定の場所 - auto checkFree = [&](int x, int y) -> bool { - for (int i = 0; i < poschk.size(); i++) { + auto checkFree = [&](int x, int y) -> bool + { + for (int i = 0; i < poschk.size(); i++) + { const auto [px, py] = poschk[i]; if (px == x && py == y) return false; @@ -49,40 +56,58 @@ int main() { return true; }; - for (int i = 0; i < nagents; i++) { + for (int i = 0; i < nagents; i++) + { const Agent agent = kc.getAgent()[i]; - if (agent.x == -1) { // 置く前 + if (agent.x == -1) + { // 置く前 const auto [p_point, p_x, p_y] = pntall[i + offset]; actions.push_back({i, "PUT", p_x, p_y}); - } else { + } + else + { vector dirall; - for (const auto [dx, dy] : DIR) { + for (const auto [dx, dy] : DIR) + { const int x = agent.x + dx; const int y = agent.y + dy; - if (x >= 0 && x < w && y >= 0 && y < h && checkFree(x, y)) { + if (x >= 0 && x < w && y >= 0 && y < h && checkFree(x, y)) + { Tile f = field[y][x]; - if (f.type == 0 && f.pid != -1 && f.pid != pno) { + if (f.type == 0 && f.pid != -1 && f.pid != pno) + { dirall.push_back({x, y, f.type, f.pid, f.point + 10}); - } else if (f.type == 0 && f.pid == -1) { + } + else if (f.type == 0 && f.pid == -1) + { dirall.push_back({x, y, f.type, f.pid, f.point + 5}); - } else if (f.type == 1 && f.pid != pno) { + } + else if (f.type == 1 && f.pid != pno) + { dirall.push_back({x, y, f.type, f.pid, f.point}); } } } - if (dirall.size() > 0) { + if (dirall.size() > 0) + { sort(dirall.rbegin(), dirall.rend()); const Tile_info p = dirall[0]; - if (p.type == 0 || p.pid == -1) { + if (p.type == 0 || p.pid == -1) + { actions.push_back({i, "MOVE", p.x, p.y}); poschk.push_back({p.x, p.y}); poschk.push_back({agent.x, agent.y}); // 動けなかった時用 - } else { + } + else + { actions.push_back({i, "REMOVE", p.x, p.y}); poschk.push_back({agent.x, agent.y}); } - } else { - while (true) { + } + else + { + while (true) + { const auto [dx, dy] = DIR[rnd(8)]; const int x = agent.x + dx; const int y = agent.y + dy; diff --git a/client_a5.cpp b/sample/client_a5.cpp similarity index 68% rename from client_a5.cpp rename to sample/client_a5.cpp index 94a8b27..c1a71f6 100644 --- a/client_a5.cpp +++ b/sample/client_a5.cpp @@ -1,20 +1,22 @@ // だいたい点数の高い順に置き、点数の高い順に壊しながら動くアルゴリズム #include "kakomimasu.h" -struct Tile_info { +struct Tile_info +{ int x, y; int type, pid; int point; // ポイントが高い順にソートできるように比較演算子の定義 - bool operator<(const Tile_info &right) const { + bool operator<(const Tile_info &right) const + { return point < right.point; } }; -int main() { - // 自分のbearerTokenを書く - KakomimasuClient kc(""); +int main() +{ + KakomimasuClient kc; kc.waitMatching(); kc.getGameInfo(); @@ -27,22 +29,27 @@ int main() { // ポイントの高い順ソート // point, x, y vector> pntall; - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { + for (int i = 0; i < h; i++) + { + for (int j = 0; j < w; j++) + { pntall.emplace_back(points[i][j], j, i); } } sort(pntall.rbegin(), pntall.rend()); // ↓ここからがAIの中身↓ - while (kc.getGameInfo()) { + while (kc.getGameInfo()) + { vector actions; vector> field = kc.getFiled(); const int offset = rnd(nagents); vector> poschk; // 動く予定の場所 - auto checkFree = [&](int x, int y) -> bool { - for (int i = 0; i < poschk.size(); i++) { + auto checkFree = [&](int x, int y) -> bool + { + for (int i = 0; i < poschk.size(); i++) + { const auto [px, py] = poschk[i]; if (px == x && py == y) return false; @@ -50,78 +57,109 @@ int main() { return true; }; - for (int i = 0; i < nagents; i++) { + for (int i = 0; i < nagents; i++) + { const Agent agent = kc.getAgent()[i]; - if (agent.x == -1) { // 置く前 + if (agent.x == -1) + { // 置く前 const auto [p_point, p_x, p_y] = pntall[i + offset]; actions.push_back({i, "PUT", p_x, p_y}); - } else { + } + else + { vector dirall; - for (auto [dx, dy] : DIR) { + for (auto [dx, dy] : DIR) + { const int x = agent.x + dx; const int y = agent.y + dy; - if (x >= 0 && x < w && y >= 0 && y < h && checkFree(x, y)) { + if (x >= 0 && x < w && y >= 0 && y < h && checkFree(x, y)) + { const Tile f = field[y][x]; - if (f.type == 0 && f.pid != -1 && f.pid != pno && f.point > 0) { // 敵土地 + if (f.type == 0 && f.pid != -1 && f.pid != pno && f.point > 0) + { // 敵土地 dirall.push_back({x, y, f.type, f.pid, f.point + 10}); - } else if (f.type == 0 && f.pid == -1 && f.point > 0) { // 空き土地 + } + else if (f.type == 0 && f.pid == -1 && f.point > 0) + { // 空き土地 dirall.push_back({x, y, f.type, f.pid, f.point + 5}); - } else if (f.type == 1 && f.pid != pno) { // 敵壁 + } + else if (f.type == 1 && f.pid != pno) + { // 敵壁 dirall.push_back({x, y, f.type, f.pid, f.point}); } } } - if (dirall.size() > 0) { + if (dirall.size() > 0) + { sort(dirall.rbegin(), dirall.rend()); const Tile_info p = dirall[0]; - if (p.type == 0 || p.pid == -1) { + if (p.type == 0 || p.pid == -1) + { actions.push_back({i, "MOVE", p.x, p.y}); poschk.push_back({p.x, p.y}); - } else { + } + else + { actions.push_back({i, "REMOVE", p.x, p.y}); } poschk.push_back({agent.x, agent.y}); - } else { + } + else + { // 周りが全部埋まっていたら空いている高得点で一番近いところを目指す int dis = w * h; tuple target; bool target_flag = false; - for (const auto p : pntall) { + for (const auto p : pntall) + { const auto [p_point, p_x, p_y] = p; - if (field[p_y][p_x].type == 0 && field[p_y][p_x].pid == -1) { + if (field[p_y][p_x].type == 0 && field[p_y][p_x].pid == -1) + { const int dx = agent.x - p_x; const int dy = agent.y - p_y; const int d = dx * dx + dy * dy; - if (d < dis) { + if (d < dis) + { dis = d; target = p; target_flag = true; } } } - if (target_flag) { - auto sgn = [&](int n) -> int { - if (n < 0) return -1; - if (n > 0) return 1; + if (target_flag) + { + auto sgn = [&](int n) -> int + { + if (n < 0) + return -1; + if (n > 0) + return 1; return 0; }; auto [target_point, target_x, target_y] = target; const int x2 = agent.x + sgn(target_x - agent.x); const int y2 = agent.y + sgn(target_y - agent.y); const Tile p = field[y2][x2]; - if (p.type == 0 || p.pid == -1) { + if (p.type == 0 || p.pid == -1) + { actions.push_back({i, "MOVE", x2, y2}); poschk.push_back({x2, y2}); - } else { + } + else + { actions.push_back({i, "REMOVE", x2, y2}); } poschk.push_back({agent.x, agent.y}); - } else { - while (1) { + } + else + { + while (1) + { const auto [dx, dy] = DIR[rnd(8)]; const int x = agent.x + dx; const int y = agent.y + dy; - if (x < 0 || x >= w || y < 0 || y >= h) { + if (x < 0 || x >= w || y < 0 || y >= h) + { continue; } actions.push_back({i, "MOVE", x, y}); diff --git a/sample/client_none.cpp b/sample/client_none.cpp new file mode 100644 index 0000000..8656b6f --- /dev/null +++ b/sample/client_none.cpp @@ -0,0 +1,9 @@ +#include "kakomimasu.h" + +int main() +{ + KakomimasuClient kc; + kc.waitMatching(); + + return 0; +} \ No newline at end of file From 9834711778125ee08e548d72ba7e5d04ec79ee49 Mon Sep 17 00:00:00 2001 From: Suzu Tomo Date: Wed, 28 Sep 2022 23:00:23 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix:=2032bit=20minGW=E3=81=A7Windows?= =?UTF-8?q?=E5=88=A4=E5=AE=9A=E3=81=8C=E5=87=BA=E6=9D=A5=E3=81=AA=E3=81=84?= =?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kakomimasu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kakomimasu.cpp b/kakomimasu.cpp index 23126ef..9490a91 100644 --- a/kakomimasu.cpp +++ b/kakomimasu.cpp @@ -42,7 +42,7 @@ string curlPost(string req, string post_data, string auth = "") const int sz = 102400; char buf[sz]; char cmdline[sz]; -#ifdef _WIN64 +#if defined(_WIN64) || defined(_WIN32) for (int i = 0; i < post_data.size(); ++i) { if (post_data[i] == '"') From 56a8a2f6270cc0750d910d6a519e0589486ccf1e Mon Sep 17 00:00:00 2001 From: Suzu Tomo Date: Sun, 2 Oct 2022 23:27:05 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20Visual=20Studio=E3=81=AB=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 25 ++++++++++--------------- kakomimasu.cpp | 36 +++++++++++++++++++++++++++--------- kakomimasu.h | 2 +- main.cpp | 3 +-- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 35cc10d..b91c4de 100644 --- a/README.md +++ b/README.md @@ -9,24 +9,19 @@ ゲスト名を変える場合やAI対戦をする場合などにはコメント部分を解除して使用してください。 -## ビルド +## ビルド(Windows) ### Visual Studioでのビルドの手順 -- Visual Studio Community 2019をインストールします - - https://visualstudio.microsoft.com/ja/vs/community/ - - C++によるデスクトップ開発をインストールします - - 言語パックで英語をインストールします(Vcpkgで必要です) -- Vcpkgをインストールします - - https://github.com/microsoft/vcpkg/archive/master.zip - - 「bootstrap-vcpkg.bat」を実行します - - 「vcpkg install curl」を実行します - - 「vcpkg integrate install」を実行します -- Visual Studioで「C++ 空のプロジェクト」を作成します - - プロジェクトに追加します 「client_a1.cpp、kakomimasu.cpp、kakomimasu.h、picojson.h」 +- Visual Studioをインストールします + - https://visualstudio.microsoft.com/ja/ + - 「C++によるデスクトップ開発」がインストールされている必要があります。 +- curlをインストールします + - https://curl.se/windows/ +- Visual Studioで「空のプロジェクト(C++)」を作成します + - プロジェクトに次のファイルを追加します 「`main.cpp`、`kakomimasu.cpp`、`kakomimasu.h`、`picojson.h`」 - メニューバーの「プロジェクト」→「○○のプロパティ」→「構成プロパティ」を選びます - 「全般」→「C++ 言語標準」→「ISO C++17 標準 (std:c++17)」を選択します - - 「C++」→「SDLチェック」→「いいえ (/sdl-)」を選択します(sscanfに必要です) ### GCC(Windows)でのビルドの手順 @@ -41,8 +36,8 @@ - 以下にパスを通します - C:\Program Files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin - C:\Program Files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\i686-w64-mingw32\bin - - curlをインストールします - - https://curl.se/windows/ +- curlをインストールします + - https://curl.se/windows/ - コンパイルします - g++ -std=c++17 main.cpp kakomimasu.cpp diff --git a/kakomimasu.cpp b/kakomimasu.cpp index 9490a91..7a31753 100644 --- a/kakomimasu.cpp +++ b/kakomimasu.cpp @@ -1,4 +1,4 @@ -#include "kakomimasu.h" +#include "kakomimasu.h" const int DIR[8][2] = { {-1, -1}, @@ -21,8 +21,8 @@ string curlGet(string req, string token = "") { cout << "GET " << req << endl; const int sz = 102400; - char buf[sz]; - char cmdline[sz]; + char *buf = new char[sz]; + char *cmdline= new char[sz]; snprintf(cmdline, sz, "curl -s -H 'Authorization: %s' %s%s", token.c_str(), host.c_str(), req.c_str()); #ifdef _MSC_VER FILE *fp = _popen(cmdline, "r"); @@ -30,8 +30,18 @@ string curlGet(string req, string token = "") FILE *fp = popen(cmdline, "r"); #endif fgets(buf, sz, fp); + +#ifdef _MSC_VER + _pclose(fp); +#else + pclose(fp); +#endif + string res(buf); // cout << res << endl; + + delete[] buf; + delete[] cmdline; return res; } @@ -40,8 +50,8 @@ string curlPost(string req, string post_data, string auth = "") cout << "POST " << req << endl; // cout << post_data << endl; const int sz = 102400; - char buf[sz]; - char cmdline[sz]; + char *buf= new char[sz]; + char *cmdline = new char[sz]; #if defined(_WIN64) || defined(_WIN32) for (int i = 0; i < post_data.size(); ++i) { @@ -63,8 +73,16 @@ string curlPost(string req, string post_data, string auth = "") #endif fgets(buf, sz, fp); + +#ifdef _MSC_VER + _pclose(fp); +#else + pclose(fp); +#endif string res(buf); // cout << res << endl; + delete[] buf; + delete[] cmdline; return res; } @@ -85,7 +103,7 @@ void KakomimasuClient::setBearerToken(string bearer) m_bearer = bearer; } -void KakomimasuClient::setAi(string ai_name, string ai_board = "") +void KakomimasuClient::setAi(string ai_name, string ai_board) { m_ai_name = ai_name; m_ai_board = ai_board; @@ -150,7 +168,7 @@ void KakomimasuClient::waitMatching() picojson::object obj = val.get(); m_game_id = obj["gameId"].get(); - m_player_no = obj["index"].get(); + m_player_no = (int)obj["index"].get(); m_pic = obj["pic"].get(); cout << "gameId: " << m_game_id << endl; @@ -213,7 +231,7 @@ vector> KakomimasuClient::getPoints() int i = 0, j = 0; for (auto &val : ary) { - res[i][j] = val.get(); + res[i][j] = (int)val.get(); j++; if (j == width) @@ -232,7 +250,7 @@ vector> KakomimasuClient::getFiled() int i = 0, j = 0; for (auto &val : ary) { - res[i][j].point = val.get(); + res[i][j].point = (int)val.get(); j++; if (j == width) diff --git a/kakomimasu.h b/kakomimasu.h index cdc53d3..ddb655f 100644 --- a/kakomimasu.h +++ b/kakomimasu.h @@ -37,7 +37,7 @@ class KakomimasuClient public: KakomimasuClient(); void setBearerToken(string bearer); - void setAi(string ai_name, string ai_board); + void setAi(string ai_name, string ai_board = ""); void setGuestName(string guest_name); bool getGameInfo(); void waitMatching(); diff --git a/main.cpp b/main.cpp index 6f4f75f..26b81ab 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,4 @@ -#include "kakomimasu.h" +#include "kakomimasu.h" int main() { @@ -62,7 +62,6 @@ int main() } } kc.setAction(action); - // break; kc.waitNextTurn(); }