123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- #ifndef __ROOM_HPP__
- #define __ROOM_HPP__
- #include "util.hpp"
- #include "db.hpp"
- #include "online.hpp"
- #include <vector>
- #define BOARD_ROW 15
- #define BOARD_COL 15
- #define CHESS_WHITE 1
- #define CHESS_BLACK 2
- typedef enum {
- GAME_START,
- GAME_OVER
- } room_status;
- class room {
- private:
-
- bool five_piece(int row, int col, int row_off, int col_off, int color) {
- int count = 1;
-
- int search_row = row + row_off;
- int search_col = col + col_off;
- while((search_row >= 0 && search_row < BOARD_ROW) && (search_col >= 0 && search_col < BOARD_COL)
- && (_board[search_row][search_col] == color)) {
- ++count;
- search_row += row_off;
- search_col += col_off;
- }
-
- search_row = row - row_off;
- search_col = col - col_off;
- while((search_row >= 0 && search_row < BOARD_ROW) && (search_col >= 0 && search_col < BOARD_COL)
- && (_board[search_row][search_col] == color)) {
- ++count;
- search_row -= row_off;
- search_col -= col_off;
- }
- return count >= 5;
- }
-
- uint64_t check_win(int chess_row, int chess_col, int cur_color) {
- uint64_t winner_id = cur_color == CHESS_WHITE ? _white_user_id : _black_user_id;
-
- if(five_piece(chess_row, chess_col, 0, 1, cur_color)) return winner_id;
-
- if(five_piece(chess_row, chess_col, 1, 0, cur_color)) return winner_id;
-
- if(five_piece(chess_row, chess_col, 1, -1, cur_color)) return winner_id;
-
- if(five_piece(chess_row, chess_col, 1, 1, cur_color)) return winner_id;
-
- return 0;
- }
-
- void update_db_info(uint64_t winner_id, uint64_t loser_id) {
- _tb_user->win(winner_id);
- _tb_user->lose(loser_id);
- }
- public:
- room(uint64_t room_id, user_table *tb_user, online_manager *online_user)
- : _room_id(room_id), _statu(GAME_START), _tb_user(tb_user), _online_user(online_user), _board(BOARD_ROW, std::vector<int>(BOARD_COL, 0))
- {
- LOG(DEBUG, "%d号房间创建成功", _room_id);
- }
- ~room() { LOG(DEBUG, "%d号房间已被销毁", _room_id); }
-
- void add_white_user(uint64_t id) {
- _white_user_id = id;
- ++_player_count;
- }
-
- void add_black_user(uint64_t id) {
- _black_user_id = id;
- ++_player_count;
- }
-
- Json::Value handler_chess(Json::Value &req) {
- Json::Value resp = req;
-
- if(_online_user->is_in_game_room(_white_user_id) == false) {
- resp["result"] = true;
- resp["reason"] = "对方已掉线,游戏获胜";
- resp["winner"] = (Json::UInt64)_black_user_id;
- }
- if(_online_user->is_in_game_room(_black_user_id) == false) {
- resp["result"] = true;
- resp["reason"] = "对方已掉线,游戏胜利";
- resp["winner"] = (Json::UInt64)_white_user_id;
- }
-
- uint64_t cur_uid = req["uid"].asUInt64();
- int chess_row = req["row"].asInt();
- int chess_col = req["col"].asInt();
- if(_board[chess_row][chess_col] != 0) {
- resp["result"] = false;
- resp["reason"] = "该位置已被占用";
- return resp;
- }
- int cur_color = (cur_uid == _white_user_id ? CHESS_WHITE : CHESS_BLACK);
- _board[chess_row][chess_col] = cur_color;
-
- uint64_t winner_id = check_win(chess_row, chess_col, cur_color);
- resp["result"] = true;
- resp["reason"] = "下棋成功";
- resp["winner"] = (Json::UInt64)winner_id;
- if(winner_id != 0) { resp["reason"] = "五星连珠,游戏胜利"; }
- return resp;
- }
-
- Json::Value handler_chat(Json::Value &req) {
- Json::Value resp = req;
-
- std::string msg = req["message"].asString();
- size_t pos = msg.find("垃圾");
- if(pos != std::string::npos) {
- resp["result"] = false;
- resp["reason"] = "消息中包含敏感词";
- return resp;
- }
- resp["reslut"] = true;
- return resp;
- }
-
- void handler_exit(uint64_t uid) {
-
- if(_statu == GAME_START) {
- Json::Value resp;
- resp["optype"] = "put_chess";
- resp["result"] = true;
- resp["reason"] = "对方已退出,游戏胜利";
- resp["room_id"] = (Json::UInt64)_room_id;
- resp["uid"] = (Json::UInt64)uid;
- resp["row"] = -1;
- resp["col"] = -1;
- resp["winner"] = (Json::UInt64)(uid == _white_user_id ? _black_user_id : _white_user_id);
-
- uint64_t loser_id = uid;
- uint64_t winner_id = loser_id == _white_user_id ? _black_user_id : _white_user_id;
- update_db_info(winner_id, loser_id);
- _statu = GAME_OVER;
-
- broadcast(resp);
- }
-
- --_player_count;
- }
-
-
- void handler(Json::Value &req) {
- Json::Value resp;
-
- if(_room_id != req["room_id"].asUInt64()) {
- resp["optype"] = req["optype"].asString();
- resp["result"] = false;
- resp["reason"] = "房间号不匹配";
- broadcast(resp);
- return;
- }
-
- std::string type = req["optype"].asString();
- if(type == "put_chess") {
- resp = handler_chess(req);
-
- if(resp["winner"].asUInt64() != 0) {
- uint64_t winner_id = resp["winner"].asUInt64();
- uint64_t loser_id = (winner_id == _white_user_id ? _black_user_id : _white_user_id);
- update_db_info(winner_id, loser_id);
- _statu = GAME_OVER;
- }
- } else if(type == "chat") {
- resp = handler_chat(req);
- } else {
- resp["optype"] = req["optype"].asString();
- resp["result"] = false;
- resp["reason"] = "位置请求类型";
- }
-
- broadcast(resp);
- }
-
- void broadcast(Json::Value &resp) {
-
- std::string body;
- json_util::serialize(resp, body);
-
- wsserver_t::connection_ptr conn_white = _online_user->get_conn_from_room(_white_user_id);
- wsserver_t::connection_ptr conn_black = _online_user->get_conn_from_room(_black_user_id);
-
- if(conn_white.get() != nullptr) {
- conn_white->send(body);
- }
- if(conn_black.get() != nullptr) {
- conn_black->send(body);
- }
- }
- public:
-
- uint64_t _room_id;
- room_status _statu;
- int _player_count;
- uint64_t _white_user_id;
- uint64_t _black_user_id;
- private:
- user_table *_tb_user;
- online_manager *_online_user;
- std::vector<std::vector<int>> _board;
- };
- using room_ptr = std::shared_ptr<room>;
- class room_manager {
- public:
- room_manager(user_table *tb_user, online_manager *online_user)
- : _next_rid(1), _tb_user(tb_user), _online_user(online_user) {
- LOG(DEBUG, "游戏房间管理模块初始化成功");
- }
- ~room_manager() { LOG(NORMAL, "游戏房间管理模块已被销毁"); }
-
- room_ptr create_room(uint64_t uid1, uint64_t uid2) {
-
- if(_online_user->is_in_game_hall(uid1) == false || _online_user->is_in_game_hall(uid2) == false) {
- LOG(DEBUG, "玩家不在游戏大厅中,匹配失败");
- return room_ptr();
- }
-
- std::unique_lock<std::mutex> lock(_mutex);
- room_ptr rp(new room(_next_rid, _tb_user, _online_user));
- rp->add_white_user(uid1);
- rp->add_black_user(uid2);
-
- _rooms[_next_rid] = rp;
- _users[uid1] = _next_rid;
- _users[uid2] = _next_rid;
-
- ++_next_rid;
-
- return rp;
- }
-
- room_ptr get_room_by_rid(uint64_t rid) {
- std::unique_lock<std::mutex> lock(_mutex);
- auto it = _rooms.find(rid);
- if(it == _rooms.end()) return room_ptr();
- return _rooms[rid];
- }
-
- room_ptr get_room_by_uid(uint64_t uid) {
- std::unique_lock<std::mutex> lock(_mutex);
-
- auto it1 = _users.find(uid);
- if(it1 == _users.end()) return room_ptr();
- uint64_t rid = _users[uid];
-
- auto it2 = _rooms.find(rid);
- if(it2 == _rooms.end()) return room_ptr();
- return _rooms[rid];
- }
-
- void remove_room(uint64_t rid) {
-
- room_ptr rp = get_room_by_rid(rid);
- if(rp.get() == nullptr) return;
-
- uint64_t white_user_id = rp->_white_user_id;
- uint64_t black_user_id = rp->_black_user_id;
-
- std::unique_lock<std::mutex> lock(_mutex);
- _users.erase(white_user_id);
- _users.erase(black_user_id);
-
- _rooms.erase(rid);
- }
-
- void remove_room_user(uint64_t uid) {
-
- room_ptr rp = get_room_by_uid(uid);
- if(rp.get() == nullptr) return;
-
- rp->handler_exit(uid);
-
- if(rp->_player_count == 0) remove_room(rp->_room_id);
- }
- private:
- uint64_t _next_rid;
- std::mutex _mutex;
- user_table *_tb_user;
- online_manager *_online_user;
- std::unordered_map<uint64_t, room_ptr> _rooms;
- std::unordered_map<uint64_t, uint64_t> _users;
- };
- #endif
|