#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "constants.h" #include "server.h" #include "common.h" #include "func.h" #include #include #include #include //#define REGISTERED_USER_LIST_SIZE 100 #define REGISTERED_USER_LIST_SIZE 10 #define REGISTERED_USER_FILE "userlists.log" using std::multiset; using std::vector; pthread_mutex_t userlist_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t sessions_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t battles_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t default_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t items_lock[USER_CNT]; int server_fd = 0, port = 50000, port_range = 100; void check_user_status(int uid); void wrap_recv(int conn, client_message_t* pcm); void wrap_send(int conn, server_message_t* psm); void send_to_client(int uid, int message); void send_to_client(int uid, int message, char* str); void say_to_client(int uid, char* message); void send_to_client_with_username(int uid, int message, char* user_name); void close_session(int conn, int message); void terminate_process(int recved_signal); void load_user_list(); void save_user_list(); void save_user(int i); int query_session_built(uint32_t uid); void inform_all_user_battle_player(int bid); void user_quit_battle(uint32_t bid, uint32_t uid); void user_join_battle_common_part(uint32_t bid, uint32_t uid, uint32_t joined_state); void user_join_battle(uint32_t bid, uint32_t uid); void user_invited_to_join_battle(uint32_t bid, uint32_t uid); int find_uid_by_user_name(const char* user_name); int get_unalloced_battle(); int get_unused_session(); void inform_friends(int uid, int message); //void forced_generate_items(int bid, int x, int y, int kind, int count, int uid = -1); void random_generate_items(int bid); void move_bullets(int bid); void check_user_status(int uid); void check_all_user_status(int bid); void check_who_is_dead(int bid); void clear_items(int bid); void render_map_for_user(int uid, server_message_t* psm); void inform_all_user_battle_state(int bid); void* battle_ruler(void* args); int check_user_registered(char* user_name, char* password); void launch_battle(int bid); int admin_set_admin(int argc, char** argv); int admin_set_energy(int argc, char** argv); int admin_set_hp(int argc, char** argv); int admin_set_pos(int argc, char** argv); int admin_ban_user(int argc, char** argv); int client_command_admin_control(int uid); int client_message_fatal(int uid); void init_handler(); void* session_start(void* args); void* run_battle(void* args); int server_start(); void terminate_process(int signum); void terminate_entrance(int signum); void list_all_users(server_message_t* psm); int invite_friend_to_battle(int bid, int uid, char* friend_name); int client_command_user_login(int uid); int client_command_user_register(int uid); int client_command_launch_battle(int uid); int client_command_quit_battle(int uid); int client_command_invite_user(int uid); int client_command_send_message(int uid); int client_command_create_ffa(int uid); int client_command_launch_ffa(int uid); int client_command_accept_battle(int uid); int client_command_reject_battle(int uid); int client_command_quit(int uid); int client_command_move_up(int uid); int client_command_move_down(int uid); int client_command_move_left(int uid); int client_command_move_right(int uid); int client_command_put_landmine(int uid); int client_command_fire(int uid, int delta_x, int delta_y, int dir); int client_command_fire_up(int uid); int client_command_fire_down(int uid); int client_command_fire_left(int uid); int client_command_fire_right(int uid); int client_command_fire_up_left(int uid); int client_command_fire_up_right(int uid); int client_command_fire_down_left(int uid); int client_command_fire_down_right(int uid); int client_command_fire_aoe(int uid, int dir); int client_command_fire_aoe_up(int uid); int client_command_fire_aoe_down(int uid); int client_command_fire_aoe_left(int uid); int client_command_fire_aoe_right(int uid); int client_command_melee(int uid); int client_command_user_logout(int uid); int client_command_fetch_all_users(int uid); int client_command_fetch_all_friends(int uid); static int user_list_size = 0; //static uint64_t sum_delay_time = 0, prev_time; struct { char user_name[USERNAME_SIZE]; char password[PASSWORD_SIZE]; } registered_user_list[REGISTERED_USER_LIST_SIZE]; struct session_t { char user_name[USERNAME_SIZE]; char ip_addr[IPADDR_SIZE]; int conn; int state; int is_admin; int score; int kill; int death; uint32_t bid; uint32_t inviter_id; client_message_t cm; } sessions[USER_CNT]; struct session_args_t { int conn; char ip_addr[IPADDR_SIZE]; }; typedef struct session_args_t session_args_t; class item_t { public: int id; int dir; int owner; uint64_t time; int count; int kind; pos_t pos; item_t(const item_t &it) : id(it.id), dir(it.dir), owner(it.owner), time(it.time), count(it.count), kind(it.kind), pos(it.pos) {} item_t() { id = 0; dir = owner = time = count = kind = 0; pos.x = pos.y = 0; } friend const bool operator < (const item_t it1, const item_t it2) { return it1.time < it2.time; } }; class battle_t { public: int is_alloced; size_t alive_users; size_t all_users; class user_t { public: int battle_state; int energy; int dir; int life; int killby; pos_t pos; pos_t last_pos; } users[USER_CNT]; int num_of_other; // number of other alloced item except for bullet int item_count; uint64_t global_time; std::list items; void reset() { is_alloced = all_users = alive_users = num_of_other = item_count = 0; global_time = 0; items.clear(); } battle_t() { reset(); } } battles[USER_CNT]; void load_user_list() { FILE* userlist = fopen(REGISTERED_USER_FILE, "r"); if (userlist == NULL) { log("can not find " REGISTERED_USER_FILE ""); return; } #define LOAD_FAIL \ log("failed to load users, try to delete " REGISTERED_USER_FILE "."), \ user_list_size = 0, memset(registered_user_list, 0, sizeof(registered_user_list)), \ fclose(userlist); for (int i = 0; i < REGISTERED_USER_LIST_SIZE; i++) { cout<<"asdad:"<user_name; char* password = pcm->password; char* ip_addr = sessions[uid].ip_addr; log("user #%d %s\033[2m(%s)\033[0m try to login", uid, user_name, ip_addr); int message = check_user_registered(user_name, password); if (query_session_built(uid)) { log("user #%d %s\033[2m(%s)\033[0m has logined", uid, sessions[uid].user_name, sessions[uid].ip_addr); send_to_client(uid, SERVER_RESPONSE_YOU_HAVE_LOGINED); return 0; } for (int i = 0; i < USER_CNT; i++) { if (query_session_built(i)) { logi("check dup user id: %s vs. %s", user_name, sessions[i].user_name); if (strncmp(user_name, sessions[i].user_name, USERNAME_SIZE - 1) == 0) { log("user #%d %s duplicate with %dth user %s\033[2m(%s)\033[0m", uid, user_name, i, sessions[i].user_name, sessions[i].ip_addr); is_dup = 1; break; } } } // no duplicate user ids found cout<<"dup: "<= MAX_OTHER) return; if (x < 0 || x >= BATTLE_W) return; //60 if (y < 0 || y >= BATTLE_H) return; //21 battles[bid].item_count++; item_t new_item; new_item.id = battles[bid].item_count; new_item.kind = kind; new_item.pos.x = x; new_item.pos.y = y; new_item.time = battles[bid].global_time + count; new_item.owner = uid; if (kind == ITEM_MAGMA) { new_item.count = MAGMA_INIT_TIMES; } /* battles[bid].items.push_back(new_item); log("new %s #%d (%d,%d)", item_s[new_item.kind], new_item.id, new_item.pos.x, new_item.pos.y); */ } void random_generate_items(int bid) { int random_kind; //if (!probability(1, 100)) return; // rand 退出 if (battles[bid].num_of_other >= MAX_OTHER) return; /* delete random_kind = rand() % (ITEM_END - 1) + 1; if (random_kind == ITEM_BLOOD_VIAL && probability(1, 2)) random_kind = ITEM_MAGAZINE; */ random_kind = ITEM_MAGAZINE; battles[bid].item_count++; item_t new_item; new_item.id = battles[bid].item_count; new_item.kind = random_kind; new_item.pos.x = (rand() & 0x7FFF) % BATTLE_W; new_item.pos.y = (rand() & 0x7FFF) % BATTLE_H; new_item.time = battles[bid].global_time + OTHER_ITEM_LASTS_TIME; battles[bid].num_of_other++; /* delete log("new %s #%d (%d,%d)", item_s[new_item.kind], new_item.id, new_item.pos.x, new_item.pos.y); */ /* delete if (random_kind == ITEM_MAGMA) { new_item.count = MAGMA_INIT_TIMES; } */ //battles[bid].items.push_back(new_item); //delete //for (int i = 0; i < USER_CNT; i++) { // if (battles[bid].users[i].battle_state != BATTLE_STATE_LIVE) // continue; // check_user_status(i); //} } void move_bullets(int bid) { for (auto& cur : battles[bid].items) { //for (int i = 0; i < MAX_ITEM; i++) { if (cur.kind != ITEM_BULLET) continue; // log("try to move bullet %d with dir %d", i, cur.dir); switch (cur.dir) { case DIR_UP: { if (cur.pos.y > 0) { (cur.pos.y)--; break; } else { cur.dir = DIR_DOWN; break; } } case DIR_DOWN: { if (cur.pos.y < BATTLE_H - 1) { (cur.pos.y)++; break; } else { cur.dir = DIR_UP; break; } } case DIR_LEFT: { if (cur.pos.x > 0) { (cur.pos.x)--; break; } else { cur.dir = DIR_RIGHT; break; } } case DIR_RIGHT: { if (cur.pos.x < BATTLE_W - 1) { (cur.pos.x)++; break; } else { cur.dir = DIR_LEFT; break; } } case DIR_UP_LEFT: { if (cur.pos.y > 0) { (cur.pos.y)--; } else { cur.dir = DIR_DOWN_LEFT; break; } if (cur.pos.x > 1) { (cur.pos.x) -= 2; } else { cur.dir = DIR_UP_RIGHT; break; } break; } case DIR_UP_RIGHT: { if (cur.pos.y > 0) { (cur.pos.y)--; } else { cur.dir = DIR_DOWN_RIGHT; break; } if (cur.pos.x < BATTLE_W - 2) { (cur.pos.x) += 2; } else { cur.dir = DIR_UP_LEFT; break; } break; } case DIR_DOWN_LEFT: { if (cur.pos.y < BATTLE_H - 2) { (cur.pos.y)++; } else { cur.dir = DIR_UP_LEFT; break; } if (cur.pos.x > 1) { (cur.pos.x) -= 2; } else { cur.dir = DIR_DOWN_RIGHT; break; } break; } case DIR_DOWN_RIGHT: { if (cur.pos.y < BATTLE_H - 2) { (cur.pos.y)++; } else { cur.dir = DIR_UP_RIGHT; break; } if (cur.pos.x < BATTLE_W - 2) { (cur.pos.x) += 2; } else { cur.dir = DIR_DOWN_LEFT; break; } break; } } } } void check_user_status(int uid) { //log("checking..."); //auto start_time = myclock(); int bid = sessions[uid].bid; int ux = battles[bid].users[uid].pos.x; int uy = battles[bid].users[uid].pos.y; //for (int i = 0; i < MAX_ITEM; i++) { auto& items = battles[bid].items; if (battles[bid].users[uid].battle_state != BATTLE_STATE_LIVE) { return; } for (auto it = items.begin(); it != items.end(); it++) { //next = std::next(it);, next = std::next(it) => it++ int ix = it->pos.x; int iy = it->pos.y; if (ix == ux && iy == uy) { switch (it->kind) { case ITEM_MAGAZINE: { battles[bid].users[uid].energy += BULLETS_PER_MAGAZINE; //log("user #%d %s\033[2m(%s)\033[0m is got magazine", uid, sessions[uid].user_name, sessions[uid].ip_addr); if (battles[bid].users[uid].energy > MAX_BULLETS) { //log("user #%d %s\033[2m(%s)\033[0m 's bullets exceeds max value", uid, sessions[uid].user_name, sessions[uid].ip_addr); battles[bid].users[uid].energy = MAX_BULLETS; } //send_to_client(uid, SERVER_MESSAGE_YOU_GOT_MAGAZINE); it = items.erase(it); //log("current item size: %ld", items.size()); break; } case ITEM_MAGMA: { if (it->owner != uid) { battles[bid].users[uid].life = max(battles[bid].users[uid].life - 1, 0); battles[bid].users[uid].killby = it->owner; it->count--; //log("user #%d %s\033[2m(%s)\033[0m is trapped in magma", uid, sessions[uid].user_name, sessions[uid].ip_addr); //send_to_client(uid, SERVER_MESSAGE_YOU_ARE_TRAPPED_IN_MAGMA); if (it->count <= 0) { //log("magma #%d is exhausted", it->id); battles[bid].num_of_other--; it = items.erase(it); //log("current item size: %ld", items.size()); } } break; } case ITEM_BLOOD_VIAL: { battles[bid].users[uid].life += LIFE_PER_VIAL; //log("user #%d %s\033[2m(%s)\033[0m got blood vial", uid, sessions[uid].user_name, sessions[uid].ip_addr); if (battles[bid].users[uid].life > MAX_LIFE) { //log("user #%d %s\033[2m(%s)\033[0m life exceeds max value", uid, sessions[uid].user_name, sessions[uid].ip_addr); battles[bid].users[uid].life = MAX_LIFE; } //log("current item size: %ld", items.size()); battles[bid].num_of_other--; //send_to_client(uid, SERVER_MESSAGE_YOU_GOT_BLOOD_VIAL); it = items.erase(it); break; } case ITEM_BULLET: { if (it->owner != uid) { battles[bid].users[uid].life = max(battles[bid].users[uid].life - 1, 0); battles[bid].users[uid].killby = it->owner; //log("user #%d %s\033[2m(%s)\033[0m is shooted", uid, sessions[uid].user_name, sessions[uid].ip_addr); //log("current item size: %ld", items.size()); //send_to_client(uid, SERVER_MESSAGE_YOU_ARE_SHOOTED); it = items.erase(it); break; } break; } case ITEM_LANDMINE: { if (it->owner != uid) { it->time = battles[bid].global_time; forced_generate_items(bid, ix, iy, ITEM_MAGMA, 7, it->owner); forced_generate_items(bid, ix - 1, iy, ITEM_MAGMA, 7, it->owner); forced_generate_items(bid, ix + 1, iy, ITEM_MAGMA, 7, it->owner); forced_generate_items(bid, ix, iy - 1, ITEM_MAGMA, 7, it->owner); forced_generate_items(bid, ix, iy + 1, ITEM_MAGMA, 7, it->owner); } break; } } } } //auto end_time = myclock(); //log("completed."); } void check_all_user_status(int bid) { //for (int i = 0; i < MAX_ITEM; i++) { //log("checking..."); //log("completed."); for (int i = 0; i < USER_CNT; i++) { if (battles[bid].users[i].battle_state != BATTLE_STATE_LIVE) continue; check_user_status(i); } } void check_who_is_dead(int bid) { for (int i = 0; i < USER_CNT; i++) { if (battles[bid].users[i].battle_state == BATTLE_STATE_LIVE && battles[bid].users[i].life <= 0) { log("user #%d %s\033[2m(%s)\033[0m is dead", i, sessions[i].user_name, sessions[i].ip_addr); battles[bid].users[i].battle_state = BATTLE_STATE_DEAD; battles[bid].alive_users--; log("send dead info to user #%d %s\033[2m(%s)\033[0m", i, sessions[i].user_name, sessions[i].ip_addr); send_to_client(i, SERVER_MESSAGE_YOU_ARE_DEAD); sessions[i].death++; log("death of user #%d %s\033[2m(%s)\033[0m: %d", i, sessions[i].user_name, sessions[i].ip_addr, sessions[i].death); if (battles[bid].users[i].killby != -1) { int by = battles[bid].users[i].killby; sessions[by].kill++; log("kill of user #%d %s\033[2m(%s)\033[0m: %d", i, sessions[by].user_name, sessions[by].ip_addr, sessions[by].kill); double delta = (double)sessions[i].score / sessions[by].score; delta = delta * delta; if (delta > 4) delta = 4; if (delta < 0.2) delta = 0.2; int d = min(round(5. * delta), sessions[i].score); sessions[i].score -= d; sessions[by].score += d; battles[bid].users[by].energy += battles[bid].users[i].energy; } else { sessions[i].score = max(sessions[i].score - 5, 0); } } else if (battles[bid].users[i].battle_state == BATTLE_STATE_DEAD) { battles[bid].users[i].battle_state = BATTLE_STATE_WITNESS; battles[bid].users[i].energy = 0; battles[bid].users[i].life = 0; } } } void clear_items(int bid) { //log("call func %s", __func__); //for (int i = 0; i < MAX_ITEM; i++) { // if (battles[bid].items[i].times) { // battles[bid].items[i].times--; // if (!battles[bid].items[i].times) { // log("free item #%d", i); // battles[bid].items[i].is_used = false; // if (battles[bid].items[i].kind < ITEM_END) { // battles[bid].num_of_other--; // } // //battles[bid].items[i].kind = ITEM_BLANK; // } // } //} //log("check completed..."); auto& items = battles[bid].items; size_t cnt[ITEM_SIZE] = {0}; // 有修改 可能会有bug for (auto cur = items.begin(); cur != items.end(); cur++) { //next = std::next(cur); , next = std::next(cur) if (cur->time <= battles[bid].global_time) { if (cur->kind < ITEM_END) { battles[bid].num_of_other--; } cnt[cur->kind]++; //next = battles[bid].items.erase(cur); cur = battles[bid].items.erase(cur); } } //int cleared = 0; for (int i = 0; i < ITEM_SIZE; i++) { if (cnt[i]) { //log("clear %ld %s(s)", cnt[i], item_s[i]); //cleared = 1; } } //if (cleared) log("current item size: %ld", items.size()); } void render_map_for_user(int uid, server_message_t* psm) { int bid = sessions[uid].bid; int map[BATTLE_H][BATTLE_W] = {0}; int cur, x, y; //for (int i = 0, x, y; i < MAX_ITEM; i++) { for (auto it : battles[bid].items) { x = it.pos.x; y = it.pos.y; switch (it.kind) { case ITEM_BULLET: { if (it.owner == uid) { map[y][x] = max(map[y][x], MAP_ITEM_MY_BULLET); } else { map[y][x] = max(map[y][x], MAP_ITEM_OTHER_BULLET); } break; } case ITEM_LANDMINE: { if (it.owner != uid) break; map[y][x] = max(map[y][x], item_to_map[ITEM_LANDMINE]); } default: { cur = item_to_map[it.kind]; map[y][x] = max(map[y][x], cur); } } //sm.item_kind[i] = it.kind; //sm.item_pos[i].x = it.pos.x; //sm.item_pos[i].y = it.pos.y; } for (int i = 0; i < BATTLE_H; i++) { for (int j = 0; j < BATTLE_W; j += 2) { //psm->map[i][j] = map[i][j]; //if (psm->map[i][j] != 0) log("set item #%d", psm->map[i][j]); psm->map[i][j >> 1] = (map[i][j]) | (map[i][j + 1] << 4); } } } void inform_all_user_battle_player(int bid) { server_message_t sm; sm.message = SERVER_MESSAGE_BATTLE_PLAYER; for (int i = 0; i < USER_CNT; i++) { if (battles[bid].users[i].battle_state == BATTLE_STATE_LIVE && battles[bid].users[i].life > 0) { strncpy(sm.users[i].name, sessions[i].user_name, USERNAME_SIZE - 1); sm.users[i].namecolor = i % color_s_size + 1; sm.users[i].life = battles[bid].users[i].life; sm.users[i].score = sessions[i].score; sm.users[i].death = sessions[i].death; sm.users[i].kill = sessions[i].kill; } else { strcpy(sm.users[i].name, (char*)""); sm.users[i].namecolor = 0; sm.users[i].life = 0; sm.users[i].score = 0; sm.users[i].death = 0; sm.users[i].kill = 0; } } for (int i = 0; i < USER_CNT; i++) { for (int j = i + 1; j < USER_CNT; j++) { if (sm.users[i].score < sm.users[j].score) { std::swap(sm.users[i], sm.users[j]); } } } for (int i = 0; i < USER_CNT; i++) { if (battles[bid].users[i].battle_state != BATTLE_STATE_UNJOINED) { //wrap_send(sessions[i].conn, &sm); //log("inform user #%d %s\033[2m(%s)\033[0m", i, sessions[i].user_name, sessions[i].ip_addr); } } } void inform_all_user_battle_state(int bid) { server_message_t sm; sm.message = SERVER_MESSAGE_BATTLE_INFORMATION; for (int i = 0; i < USER_CNT; i++) { if (battles[bid].users[i].battle_state == BATTLE_STATE_LIVE) { sm.user_pos[i].x = battles[bid].users[i].pos.x; sm.user_pos[i].y = battles[bid].users[i].pos.y; sm.user_color[i] = i % color_s_size + 1; } else { sm.user_pos[i].x = -1; sm.user_pos[i].y = -1; sm.user_color[i] = 0; } } for (int i = 0; i < USER_CNT; i++) { if (battles[bid].users[i].battle_state != BATTLE_STATE_UNJOINED) { render_map_for_user(i, &sm); sm.index = i; sm.life = battles[bid].users[i].life; sm.bullets_num = battles[bid].users[i].energy; sm.color = i % color_s_size + 1; //wrap_send(sessions[i].conn, &sm); } } } void* battle_ruler(void* args) { int bid = (int)(uintptr_t)args; //log("battle ruler for battle #%d", bid); // FIXME: battle re-alloced before exiting loop for (int i = 0; i < INIT_GRASS; i++) { forced_generate_items(bid, (rand() & 0x7FFF) % BATTLE_W, (rand() & 0x7FFF) % BATTLE_H, ITEM_GRASS, 10000); } uint64_t t[2]; while (battles[bid].is_alloced) { battles[bid].global_time++; t[0] = myclock(); move_bullets(bid); check_all_user_status(bid); //check_who_is_dead(bid); inform_all_user_battle_state(bid); if (battles[bid].global_time % 10 == 0) { inform_all_user_battle_player(bid); } clear_items(bid); random_generate_items(bid); t[1] = myclock(); /* 时间种子 不测 if (t[1] - t[0] >= 5) //logw("current delay %lums", t[1] - t[0]); //sum_delay_time += t[1] - t[0]; while (myclock() < t[0] + GLOBAL_SPEED) usleep(1000); */ } return NULL; } int check_user_registered(char* user_name, char* password) { for (int i = 0; i < REGISTERED_USER_LIST_SIZE; i++) { if (strncmp(user_name, registered_user_list[i].user_name, USERNAME_SIZE - 1) != 0) continue; if (strncmp(password, registered_user_list[i].password, PASSWORD_SIZE - 1) != 0) { logi("user name %s sent error password", user_name); return SERVER_RESPONSE_LOGIN_FAIL_ERROR_PASSWORD; } else { return SERVER_RESPONSE_LOGIN_SUCCESS; } } logi("user name %s hasn't been registered", user_name); return SERVER_RESPONSE_LOGIN_FAIL_UNREGISTERED_USERID; } void launch_battle(int bid) { pthread_t thread; pthread_create(&thread, NULL, battle_ruler, (void*)(uintptr_t)bid); /* log("try to create battle_ruler thread"); if (pthread_create(&thread, NULL, battle_ruler, (void*)(uintptr_t)bid) == -1) { eprintf("fail to launch battle"); } */ } void list_all_users(server_message_t* psm) { for (int i = 0; i < USER_CNT; i++) { if (query_session_built(i)) { //log("%s: found %s %s", __func__, sessions[i].user_name, //sessions[i].state == USER_STATE_BATTLE ? "in battle" : ""); psm->all_users[i].user_state = sessions[i].state; strncpy(psm->all_users[i].user_name, sessions[i].user_name, USERNAME_SIZE - 1); } } } int client_command_fetch_all_users(int uid) { char* user_name = sessions[uid].user_name; //log("user #%d %s\033[2m(%s)\033[0m tries to fetch all users's info", uid, user_name, sessions[uid].user_name); if (!query_session_built(uid)) { //logi("user #%d %s\033[2m(%s)\033[0m who tries to list users hasn't login", uid, user_name, sessions[uid].user_name); //send_to_client(uid, SERVER_RESPONSE_YOU_HAVE_NOT_LOGIN); return 0; } server_message_t sm; memset(&sm, 0, sizeof(server_message_t)); //list_all_users(&sm); sm.response = SERVER_RESPONSE_ALL_USERS_INFO; //wrap_send(sessions[uid].conn, &sm); return 0; } int client_command_fetch_all_friends(int uid) { char *user_name = sessions[uid].user_name; //log("user %s tries to fetch info", user_name); if (!query_session_built(uid)) { //logi("user %s who tries to list users hasn't login", user_name); //send_to_client(uid, SERVER_RESPONSE_YOU_HAVE_NOT_LOGIN); return 0; } server_message_t sm; memset(&sm, 0, sizeof(server_message_t)); list_all_users(&sm); sm.all_users[uid].user_state = USER_STATE_UNUSED; sm.response = SERVER_RESPONSE_ALL_FRIENDS_INFO; //wrap_send(sessions[uid].conn, &sm); return 0; } int invite_friend_to_battle(int bid, int uid, char* friend_name) { int friend_id = find_uid_by_user_name(friend_name); if (friend_id == -1) { // fail to find friend logi("friend %s hasn't login", friend_name); send_to_client(uid, SERVER_MESSAGE_FRIEND_NOT_LOGIN); } else if (friend_id == uid) { logi("launch battle %d for %s", bid, sessions[uid].user_name); sessions[uid].inviter_id = uid; send_to_client(uid, SERVER_RESPONSE_INVITATION_SENT); } else if (sessions[friend_id].state == USER_STATE_BATTLE) { // friend already in battle logi("friend %s already in battle", friend_name); send_to_client(uid, SERVER_MESSAGE_FRIEND_ALREADY_IN_BATTLE); } else { // invite friend logi("friend #%d %s found", friend_id, friend_name); user_invited_to_join_battle(bid, friend_id); // WARNING: can't move this statement sessions[friend_id].inviter_id = uid; send_to_client_with_username(friend_id, SERVER_MESSAGE_INVITE_TO_BATTLE, sessions[uid].user_name); } return 0; } int client_command_launch_battle(int uid) { if (sessions[uid].state == USER_STATE_BATTLE) { log("user %s who tries to launch battle has been in battle", sessions[uid].user_name); send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE); return 0; } else { log("user %s tries to launch battle", sessions[uid].user_name); } int bid = get_unalloced_battle(); client_message_t* pcm = &sessions[uid].cm; log("%s launch battle with %s", sessions[uid].user_name, pcm->user_name); if (bid == -1) { loge("fail to create battle for %s and %s", sessions[uid].user_name, pcm->user_name); send_to_client(uid, SERVER_RESPONSE_LAUNCH_BATTLE_FAIL); return 0; } else { logi("launch battle %d for %s, invite %s", bid, sessions[uid].user_name, pcm->user_name); user_join_battle(bid, uid); cout<<"test:"<user_name<user_name, "")) invite_friend_to_battle(bid, uid, pcm->user_name); launch_battle(bid); send_to_client(uid, SERVER_RESPONSE_LAUNCH_BATTLE_SUCCESS); } return 0; } int client_command_quit_battle(int uid) { log("user %s tries to quit battle", sessions[uid].user_name); if (sessions[uid].state != USER_STATE_BATTLE) { logi("but he hasn't join battle"); send_to_client(uid, SERVER_RESPONSE_YOURE_NOT_IN_BATTLE); } else { logi("call user_quit_battle to quit"); user_quit_battle(sessions[uid].bid, uid); } return 0; } int client_command_invite_user(int uid) { client_message_t* pcm = &sessions[uid].cm; int bid = sessions[uid].bid; int friend_id = find_uid_by_user_name(pcm->user_name); log("user #%d %s\033[2m(%s)\033[0m tries to invite friend", uid, sessions[uid].user_name, sessions[uid].ip_addr); if (sessions[uid].state != USER_STATE_BATTLE) { log("user %s\033[2m(%s)\033[0m who invites friend %s wasn't in battle", sessions[uid].user_name, sessions[uid].ip_addr, pcm->user_name); send_to_client(uid, SERVER_RESPONSE_YOURE_NOT_IN_BATTLE); } else { logi("invite user %s\033[2m(%s)\033[0m to battle #%d", sessions[friend_id].user_name, sessions[uid].ip_addr, bid); invite_friend_to_battle(bid, uid, pcm->user_name); } return 0; } int client_command_send_message(int uid) { client_message_t* pcm = &sessions[uid].cm; server_message_t sm; memset(&sm, 0, sizeof(server_message_t)); sm.message = SERVER_MESSAGE_FRIEND_MESSAGE; strncpy(sm.from_user, sessions[uid].user_name, USERNAME_SIZE); strncpy(sm.msg, pcm->message, MSG_SIZE); if (pcm->user_name[0] == '\0') { //logi("user %d:%s\033[2m(%s)\033[0m yells at all users: %s", uid, sessions[uid].user_name, sessions[uid].ip_addr, pcm->message); int i; for (i = 0; i < USER_CNT; i++) { if (uid == i) continue; //wrap_send(sessions[i].conn, &sm); int w = -1; // test } } else { return 0; // test /* int friend_id = find_uid_by_user_name(pcm->user_name); if (friend_id == -1 || friend_id == uid) { logi("user %d:%s\033[2m(%s)\033[0m fails to speak to %s:`%s`", uid, sessions[uid].user_name, sessions[uid].ip_addr, pcm->user_name, pcm->message); } else { logi("user %d:%s\033[2m(%s)\033[0m speaks to %d:%s : `%s`", uid, sessions[uid].user_name, sessions[uid].ip_addr, friend_id, pcm->user_name, pcm->message); wrap_send(sessions[friend_id].conn, &sm); } */ } return 0; } int client_command_create_ffa(int uid) { if (sessions[uid].state == USER_STATE_BATTLE) { log("user %s who tries to launch battle has been in battle", sessions[uid].user_name); send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE); return 0; } else { log("user %s tries to create ffa sessions #0", sessions[uid].user_name); } int bid = 0; client_message_t* pcm = &sessions[uid].cm; log("%s launch battle with %s", sessions[uid].user_name, pcm->user_name); cout<<"state: "<user_name); send_to_client(uid, SERVER_RESPONSE_LAUNCH_BATTLE_FAIL); return 0; } else { logi("launch battle #0 for ffa"); battles[bid].is_alloced = true; user_join_battle(bid, uid); if (strcmp(pcm->user_name, "")) invite_friend_to_battle(bid, uid, pcm->user_name); launch_battle(bid); send_to_client(uid, SERVER_RESPONSE_LAUNCH_BATTLE_SUCCESS); } return 0; } int client_command_launch_ffa(int uid) { log("user %s\033[2m(%s)\033[0m try ffa", sessions[uid].user_name, sessions[uid].ip_addr); if (sessions[uid].state == USER_STATE_BATTLE) { logi("already in battle"); send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE); } else { int bid = 0; if (battles[bid].is_alloced) { user_join_battle(bid, uid); logi("accept success"); } else { logi("user %s created ffa session #0", sessions[uid].user_name); client_command_create_ffa(uid); } } return 0; } int client_command_accept_battle(int uid) { log("user %s\033[2m(%s)\033[0m accept battle #%d", sessions[uid].user_name, sessions[uid].ip_addr, sessions[uid].bid); if (sessions[uid].state == USER_STATE_BATTLE) { logi("already in battle"); send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE); } else if (sessions[uid].state == USER_STATE_WAIT_TO_BATTLE) { int inviter_id = sessions[uid].inviter_id; int bid = sessions[uid].bid; if (battles[bid].is_alloced) { send_to_client_with_username(inviter_id, SERVER_MESSAGE_FRIEND_ACCEPT_BATTLE, sessions[inviter_id].user_name); user_join_battle(bid, uid); logi("accept success"); } else { logi("user %s\033[2m(%s)\033[0m accept battle which didn't exist", sessions[uid].user_name, sessions[uid].ip_addr); send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE); } } else { logi("hasn't been invited"); send_to_client(uid, SERVER_RESPONSE_NOBODY_INVITE_YOU); } return 0; } int client_command_reject_battle(int uid) { log("user %s\033[2m(%s)\033[0m reject battle #%d", sessions[uid].user_name, sessions[uid].ip_addr, sessions[uid].bid); if (sessions[uid].state == USER_STATE_BATTLE) { logi("user already in battle"); send_to_client(uid, SERVER_RESPONSE_YOURE_ALREADY_IN_BATTLE); } else if (sessions[uid].state == USER_STATE_WAIT_TO_BATTLE) { logi("reject success"); int bid = sessions[uid].bid; send_to_client(sessions[uid].inviter_id, SERVER_MESSAGE_FRIEND_REJECT_BATTLE); sessions[uid].state = USER_STATE_LOGIN; battles[bid].users[uid].battle_state = BATTLE_STATE_UNJOINED; } else { logi("hasn't been invited"); send_to_client(uid, SERVER_RESPONSE_NOBODY_INVITE_YOU); } return 0; } int client_command_quit(int uid) { int conn = sessions[uid].conn; if (sessions[uid].state == USER_STATE_BATTLE || sessions[uid].state == USER_STATE_WAIT_TO_BATTLE) { log("user #%d %s tries to quit client was in battle", uid, sessions[uid].user_name); user_quit_battle(sessions[uid].bid, uid); } if (sessions[uid].conn >= 0) { sessions[uid].conn = -1; log("user #%d %s quit", uid, sessions[uid].user_name); sessions[uid].state = USER_STATE_UNUSED; close(conn); } return -1; } int client_command_move_up(int uid) { log("user #%d %s\033[2m(%s)\033[0m move up", uid, sessions[uid].user_name, sessions[uid].ip_addr); int bid = sessions[uid].bid; battles[bid].users[uid].dir = DIR_UP; if (battles[bid].users[uid].pos.y > 0) { battles[bid].users[uid].pos.y--; check_user_status(uid); } return 0; } int client_command_move_down(int uid) { log("user #%d %s\033[2m(%s)\033[0m move down", uid, sessions[uid].user_name, sessions[uid].ip_addr); int bid = sessions[uid].bid; battles[bid].users[uid].dir = DIR_DOWN; if (battles[bid].users[uid].pos.y < BATTLE_H - 1) { battles[bid].users[uid].pos.y++; check_user_status(uid); } return 0; } int client_command_move_left(int uid) { log("user #%d %s\033[2m(%s)\033[0m move left", uid, sessions[uid].user_name, sessions[uid].ip_addr); int bid = sessions[uid].bid; battles[bid].users[uid].dir = DIR_LEFT; if (battles[bid].users[uid].pos.x > 0) { battles[bid].users[uid].pos.x--; check_user_status(uid); } return 0; } int client_command_move_right(int uid) { log("user #%d %s\033[2m(%s)\033[0m move right", uid, sessions[uid].user_name, sessions[uid].ip_addr); int bid = sessions[uid].bid; battles[bid].users[uid].dir = DIR_RIGHT; if (battles[bid].users[uid].pos.x < BATTLE_W - 1) { battles[bid].users[uid].pos.x++; check_user_status(uid); } return 0; } int client_command_put_landmine(int uid) { int bid = sessions[uid].bid; if (battles[bid].users[uid].energy < LANDMINE_COST) { //send_to_client(uid, SERVER_MESSAGE_YOUR_MAGAZINE_IS_EMPTY); return 0; } int x = battles[bid].users[uid].pos.x; int y = battles[bid].users[uid].pos.y; /* if (x < 0 || x >= BATTLE_W) return 1; if (y < 0 || y >= BATTLE_H) return 1; */ if ( x >= BATTLE_W) return 1; if ( y >= BATTLE_H) return 1; //log("user #%d %s\033[2m(%s)\033[0m put at (%d, %d)", uid, sessions[uid].user_name, sessions[uid].ip_addr, x, y); item_t new_item; new_item.id = ++battles[bid].item_count; new_item.kind = ITEM_LANDMINE; new_item.owner = uid; new_item.pos.x = x; new_item.pos.y = y; new_item.time = battles[bid].global_time + INF; battles[bid].users[uid].energy -= LANDMINE_COST; //battles[bid].items.push_back(new_item); //log("current item size: %ld", battles[bid].items.size()); return 0; } int client_command_fire(int uid, int delta_x, int delta_y, int dir) { int bid = sessions[uid].bid; if (battles[bid].users[uid].energy <= 0) { //send_to_client(uid, SERVER_MESSAGE_YOUR_MAGAZINE_IS_EMPTY); return 0; } int x = battles[bid].users[uid].pos.x + delta_x; int y = battles[bid].users[uid].pos.y + delta_y; if (x < 0 || x >= BATTLE_W) return 1; if (y < 0 || y >= BATTLE_H) return 1; //log("user #%d %s\033[2m(%s)\033[0m fire %s", uid, sessions[uid].user_name, sessions[uid].ip_addr, dir_s[dir]); item_t new_item; new_item.id = ++battles[bid].item_count; new_item.kind = ITEM_BULLET; new_item.dir = dir; new_item.owner = uid; new_item.pos.x = x; new_item.pos.y = y; new_item.time = battles[bid].global_time + BULLETS_LASTS_TIME; battles[bid].users[uid].energy--; //battles[bid].items.push_back(new_item); // 奇怪的分支 先注释掉 //log("current item size: %ld", battles[bid].items.size()); return 0; } int client_command_fire_up(int uid) { logi("client_command_fire"); client_command_fire(uid, 0, 0, DIR_UP); return 0; } int client_command_fire_down(int uid) { logi("client_command_fire"); client_command_fire(uid, 0, 0, DIR_DOWN); return 0; } int client_command_fire_left(int uid) { logi("client_command_fire"); client_command_fire(uid, 0, 0, DIR_LEFT); return 0; } int client_command_fire_right(int uid) { logi("client_command_fire"); client_command_fire(uid, 0, 0, DIR_RIGHT); return 0; } int client_command_fire_up_left(int uid) { logi("client_command_fire"); client_command_fire(uid, 0, 0, DIR_UP_LEFT); return 0; } int client_command_fire_up_right(int uid) { logi("client_command_fire"); client_command_fire(uid, 0, 0, DIR_UP_RIGHT); return 0; } int client_command_fire_down_left(int uid) { logi("client_command_fire"); client_command_fire(uid, 0, 0, DIR_DOWN_LEFT); return 0; } int client_command_fire_down_right(int uid) { logi("client_command_fire"); client_command_fire(uid, 0, 0, DIR_DOWN_RIGHT); return 0; } int client_command_fire_aoe(int uid, int dir) { log("user #%d %s\033[2m(%s)\033[0m fire(aoe) %s", uid, sessions[uid].user_name, sessions[uid].ip_addr, dir_s[dir]); logi("call client_command_fire"); int limit = battles[sessions[uid].bid].users[uid].energy / 2, cnt = 0; for (int i = 0; limit; i++) { for (int j = -i; j <= i && limit; j++) { switch (dir) { case DIR_UP: { if (client_command_fire(uid, j, -i + abs(j), dir) == 0) cnt++; break; } case DIR_DOWN: { if (client_command_fire(uid, j, i - abs(j), dir) == 0) cnt++; break; } case DIR_LEFT: { if (client_command_fire(uid, -i + abs(j), j, dir) == 0) cnt++; break; } case DIR_RIGHT: { if (client_command_fire(uid, i - abs(j), j, dir) == 0) cnt++; break; } } limit--; } } log("created %d bullets", cnt); return 0; } int client_command_fire_aoe_up(int uid) { logi("call client_command_fire_aoe"); return client_command_fire_aoe(uid, DIR_UP); } int client_command_fire_aoe_down(int uid) { logi("call client_command_fire_aoe"); return client_command_fire_aoe(uid, DIR_DOWN); } int client_command_fire_aoe_left(int uid) { logi("call client_command_fire_aoe"); return client_command_fire_aoe(uid, DIR_LEFT); } int client_command_fire_aoe_right(int uid) { logi("call client_command_fire_aoe"); return client_command_fire_aoe(uid, DIR_RIGHT); } int client_command_melee(int uid) { int bid = sessions[uid].bid; if (battles[bid].users[uid].life <= 0) return 0; int dir = battles[bid].users[uid].dir; int x = battles[bid].users[uid].pos.x; int y = battles[bid].users[uid].pos.y; log("user #%d %s\033[2m(%s)\033[0m melee %s", uid, sessions[uid].user_name, sessions[uid].ip_addr, dir_s[dir]); for (int i = 1; i <= 3; i++) { forced_generate_items(bid, x + dir_offset[dir].x * i, y + dir_offset[dir].y * i, ITEM_MAGMA, 3, uid); } return 0; } int admin_set_admin(int argc, char** argv) { if (argc < 3) return -1; cout<<"username: "<= USER_CNT || sessions[uid].conn < 0) { return -1; } if (status) log("admin set user #%d admin", uid); else log("admin set user #%d non-admin", uid); sessions[uid].is_admin = status; for (int i = 0; i < USER_CNT; i++) { if (sessions[i].conn >= 0) { if (status) { say_to_client(i, sformat("admin set user #%d %s to admin", uid, sessions[uid].user_name)); } else { say_to_client(i, sformat("admin set user #%d %s to non-admin", uid, sessions[uid].user_name)); } } } return 0; } int admin_set_energy(int argc, char** argv) { if (argc < 3) return -1; int uid = find_uid_by_user_name(argv[1]), energy = atoi(argv[2]); log("admin set user #%d's energy", uid); cout<<"uid:"<= USER_CNT || sessions[uid].conn < 0 || energy < 0) { return -1; } log("admin set user #%d %s's energy to %d", uid, sessions[uid].user_name, energy); battles[sessions[uid].bid].users[uid].energy = energy; for (int i = 0; i < USER_CNT; i++) { if (sessions[i].conn >= 0) { say_to_client(i, sformat("admin set user #%d %s's energy to %d", uid, sessions[uid].user_name, energy)); } } return 0; } int admin_set_hp(int argc, char** argv) { if (argc < 3) return -1; int uid = find_uid_by_user_name(argv[1]), hp = atoi(argv[2]); if (uid < 0 || //uid >= USER_CNT|| sessions[uid].conn < 0 || hp < 0) { return -1; } log("admin set user #%d %s's hp to %d", uid, sessions[uid].user_name, hp); battles[sessions[uid].bid].users[uid].life = hp; for (int i = 0; i < USER_CNT; i++) { if (sessions[i].conn >= 0) { say_to_client(i, sformat("admin set user #%d %s's hp to %d", uid, sessions[uid].user_name, hp)); } } return 0; } int admin_set_pos(int argc, char** argv) { if (argc < 4) return -1; int uid = find_uid_by_user_name(argv[1]); int x = atoi(argv[2]), y = atoi(argv[3]); cout<<"x:"<= USER_CNT || sessions[uid].conn < 0) { return -1; } cout<<"x:"<= BATTLE_W) return -1; if (y < 0 || y >= BATTLE_H) return -1; log("admin set user #%d %s's pos to (%d, %d)", uid, sessions[uid].user_name, x, y); battles[sessions[uid].bid].users[uid].pos.x = x; battles[sessions[uid].bid].users[uid].pos.y = y; return 0; } int admin_ban_user(int argc, char** argv) { if (argc < 2) return -1; int uid = find_uid_by_user_name(argv[1]); log("admin ban user #%d", uid); if (uid < 0 // || uid >= USER_CNT ) { logi("fail"); return -1; } if (sessions[uid].conn >= 0) { log("admin banned user #%d %s\033[2m(%s)\033[0m", uid, sessions[uid].user_name, sessions[uid].ip_addr); send_to_client( uid, SERVER_STATUS_QUIT, (char*)" (you were banned by admin)"); client_command_quit(uid); for (int i = 0; i < USER_CNT; i++) { if (sessions[i].conn >= 0) { say_to_client(i, sformat("admin banned user #%d %s\033[2m(%s)\033[0m", uid, sessions[uid].user_name, sessions[uid].ip_addr)); } } } return 0; } static struct { const char* cmd; int (*func)(int argc, char** argv); } admin_handler[] = { {"ban", admin_ban_user}, {"eng", admin_set_energy}, {"energy", admin_set_energy}, {"hp", admin_set_hp}, {"setadmin", admin_set_admin}, {"pos", admin_set_pos}, }; #define NR_HANDLER ((int)sizeof(admin_handler) / (int)sizeof(admin_handler[0])) int client_command_admin_control(int uid) { if (!sessions[uid].is_admin) { //say_to_client(uid, (char*)"you are not admin"); return 0; } client_message_t* pcm = &sessions[uid].cm; char *buff = (char*)pcm->message; //log("analysis command `%s`", buff); /* char *go = buff, *argv[ADMIN_COMMAND_LEN]; int argc = 0; while (*go != 0) { if (!isspace(*go)) { argv[argc] = go; argc++; char c = (*go == '"') ? '"' : ' '; while ((*go != 0) && (*go != c)) go++; if (*go == 0) break; *go = 0; } go++; } if (argc) { argv[argc] = NULL; for (int i = 0; i < NR_HANDLER; i++) { if (strcmp(argv[0], admin_handler[i].cmd) == 0) { if (admin_handler[i].func(argc, argv)) { int s = 0; //say_to_client(uid, (char*)"invalid command!"); } return 0; } } } */ //say_to_client(uid, (char*)"invalid command!"); return 0; } int client_message_fatal(int uid) { loge("received FATAL from user #%d %s\033[2m(%s)\033[0m ", uid, sessions[uid].user_name, sessions[uid].ip_addr); for (int i = 0; i < USER_CNT; i++) { if (sessions[i].conn >= 0) { send_to_client(i, SERVER_STATUS_FATAL); log("send FATAL to user #%d %s\033[2m(%s)\033[0m", i, sessions[i].user_name, sessions[i].ip_addr); } } //terminate_process(0); return 0; } static int (*handler[256])(int); void init_handler() { handler[CLIENT_MESSAGE_FATAL] = client_message_fatal, handler[CLIENT_COMMAND_USER_QUIT] = client_command_quit, handler[CLIENT_COMMAND_USER_REGISTER] = client_command_user_register, handler[CLIENT_COMMAND_USER_LOGIN] = client_command_user_login, handler[CLIENT_COMMAND_USER_LOGOUT] = client_command_user_logout, handler[CLIENT_COMMAND_FETCH_ALL_USERS] = client_command_fetch_all_users, handler[CLIENT_COMMAND_FETCH_ALL_FRIENDS] = client_command_fetch_all_friends, handler[CLIENT_COMMAND_LAUNCH_BATTLE] = client_command_launch_battle, handler[CLIENT_COMMAND_QUIT_BATTLE] = client_command_quit_battle, handler[CLIENT_COMMAND_ACCEPT_BATTLE] = client_command_accept_battle, handler[CLIENT_COMMAND_LAUNCH_FFA] = client_command_launch_ffa, handler[CLIENT_COMMAND_REJECT_BATTLE] = client_command_reject_battle, handler[CLIENT_COMMAND_INVITE_USER] = client_command_invite_user, handler[CLIENT_COMMAND_SEND_MESSAGE] = client_command_send_message, handler[CLIENT_COMMAND_MOVE_UP] = client_command_move_up, handler[CLIENT_COMMAND_MOVE_DOWN] = client_command_move_down, handler[CLIENT_COMMAND_MOVE_LEFT] = client_command_move_left, handler[CLIENT_COMMAND_MOVE_RIGHT] = client_command_move_right, handler[CLIENT_COMMAND_PUT_LANDMINE] = client_command_put_landmine, handler[CLIENT_COMMAND_MELEE] = client_command_melee, handler[CLIENT_COMMAND_FIRE_UP] = client_command_fire_up, handler[CLIENT_COMMAND_FIRE_DOWN] = client_command_fire_down, handler[CLIENT_COMMAND_FIRE_LEFT] = client_command_fire_left, handler[CLIENT_COMMAND_FIRE_RIGHT] = client_command_fire_right, handler[CLIENT_COMMAND_FIRE_UP_LEFT] = client_command_fire_up_left, handler[CLIENT_COMMAND_FIRE_UP_RIGHT] = client_command_fire_up_right, handler[CLIENT_COMMAND_FIRE_DOWN_LEFT] = client_command_fire_down_left, handler[CLIENT_COMMAND_FIRE_DOWN_RIGHT] = client_command_fire_down_right, handler[CLIENT_COMMAND_FIRE_AOE_UP] = client_command_fire_aoe_up, handler[CLIENT_COMMAND_FIRE_AOE_DOWN] = client_command_fire_aoe_down, handler[CLIENT_COMMAND_FIRE_AOE_LEFT] = client_command_fire_aoe_left, handler[CLIENT_COMMAND_FIRE_AOE_RIGHT] = client_command_fire_aoe_right; handler[CLIENT_COMMAND_ADMIN_CONTROL] = client_command_admin_control; } /* void wrap_recv(int conn, client_message_t* pcm) { size_t total_len = 0; while (total_len < sizeof(client_message_t)) { size_t len = recv(conn, pcm + total_len, sizeof(client_message_t) - total_len, 0); if (len < 0) { loge("broken pipe"); } total_len += len; } } void wrap_send(int conn, server_message_t* psm) { size_t total_len = 0; while (total_len < sizeof(server_message_t)) { size_t len = send(conn, psm + total_len, sizeof(server_message_t) - total_len, 0); if (len < 0) { loge("broken pipe"); } total_len += len; } } */ void send_to_client(int uid, int message) { int conn = sessions[uid].conn; if (conn < 0) return; server_message_t sm; memset(&sm, 0, sizeof(server_message_t)); sm.response = message; //wrap_send(conn, &sm); } void send_to_client(int uid, int message, char* str) { int conn = sessions[uid].conn; if (conn < 0) return; server_message_t sm; memset(&sm, 0, sizeof(server_message_t)); sm.response = message; strncpy(sm.msg, str, MSG_SIZE - 1); //wrap_send(conn, &sm); } void say_to_client(int uid, char *message) { //log("say `%s` to user #%d %s", message, uid, sessions[uid].user_name); int conn = sessions[uid].conn; if (conn < 0) { //logi("fail"); return; } server_message_t sm; memset(&sm, 0, sizeof(server_message_t)); sm.message = SERVER_MESSAGE; strncpy(sm.msg, message, MSG_SIZE - 1); //wrap_send(conn, &sm); } void send_to_client_with_username(int uid, int message, char* user_name) { int conn = sessions[uid].conn; if (conn < 0) return; server_message_t sm; memset(&sm, 0, sizeof(server_message_t)); sm.response = message; strncpy(sm.friend_name, user_name, USERNAME_SIZE - 1); //wrap_send(conn, &sm); } void close_session(int conn, int message) { send_to_client(conn, message); close(conn); } void* session_start(void* args) { int uid = -1; session_args_t info = *(session_args_t*)(uintptr_t)args; client_message_t* pcm = NULL; /* if ((uid = get_unused_session()) < 0) { close_session(info.conn, SERVER_RESPONSE_LOGIN_FAIL_SERVER_LIMITS); return NULL; } else { */ uid = 0; sessions[uid].conn = info.conn; strncpy(sessions[uid].user_name, "", USERNAME_SIZE - 1); strncpy(sessions[uid].ip_addr, info.ip_addr, IPADDR_SIZE - 1); if (strncmp(sessions[uid].ip_addr, "", IPADDR_SIZE) == 0) { strncpy(sessions[uid].ip_addr, "unknown", IPADDR_SIZE - 1); } pcm = &sessions[uid].cm; memset(pcm, 0, sizeof(client_message_t)); //log("build session #%d", uid); if (strncmp(info.ip_addr, "127.0.0.1", IPADDR_SIZE) == 0) { //log("admin login!"); sessions[uid].is_admin = 1; } sessions[uid].death = sessions[uid].kill = 0; sessions[uid].score = 50; //} /* while (1) { //wrap_recv(info.conn, pcm); if (pcm->command >= CLIENT_COMMAND_END) continue; int ret_code = handler[pcm->command](uid); if (ret_code < 0) { //log("close session #%d", uid); break; }} */ return NULL; } void* run_battle(void* args) { // TODO: return NULL; } int server_start() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); /* if (sockfd < 0) { eprintf("create Socket Failed!"); } */ struct sockaddr_in servaddr; bool binded = false; for (int cur_port = port; cur_port <= port + port_range; cur_port++) { memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(cur_port); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* if (bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) { logw("can not bind to port %d!", cur_port); } else { binded = true; port = cur_port; break; } } if (!binded) { eprintf("can not start server."); } if (listen(sockfd, USER_CNT) == -1) { eprintf("fail to listen on socket."); } else { log("listen on port %d.", port); } */ bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); } return sockfd; } void terminate_process(int signum) { for (int i = 0; i < USER_CNT; i++) { if (sessions[i].conn >= 0) { log("send quit to user #%d %s\033[2m(%s)\033[0m", i, sessions[i].user_name, sessions[i].ip_addr); if (signum) { send_to_client( i, SERVER_STATUS_QUIT, sformat(" (runtime error: %s)", signal_name_s[signum])); } else { send_to_client(i, SERVER_STATUS_QUIT); } log("close conn:%d", sessions[i].conn); //close(sessions[i].conn); sessions[i].conn = -1; } } if (server_fd) { //close(server_fd); log("close server fd:%d", server_fd); } pthread_mutex_destroy(&sessions_lock); pthread_mutex_destroy(&battles_lock); for (int i = 0; i < USER_CNT; i++) { pthread_mutex_destroy(&items_lock[i]); } log("exit(%d)", signum); //exit(signum); } void terminate_entrance(int signum) { loge("received signal %s, terminate.", signal_name_s[signum]); terminate_process(signum == SIGINT ? 0 : signum); } void init_handlers(char* url) { handler[CLIENT_MESSAGE_FATAL] = client_message_fatal, handler[CLIENT_COMMAND_USER_QUIT] = client_command_quit, handler[CLIENT_COMMAND_USER_REGISTER] = client_command_user_register, handler[CLIENT_COMMAND_USER_LOGIN] = client_command_user_login, handler[CLIENT_COMMAND_USER_LOGOUT] = client_command_user_logout, handler[CLIENT_COMMAND_FETCH_ALL_USERS] = client_command_fetch_all_users, handler[CLIENT_COMMAND_FETCH_ALL_FRIENDS] = client_command_fetch_all_friends, handler[CLIENT_COMMAND_LAUNCH_BATTLE] = client_command_launch_battle, handler[CLIENT_COMMAND_QUIT_BATTLE] = client_command_quit_battle, handler[CLIENT_COMMAND_ACCEPT_BATTLE] = client_command_accept_battle, handler[CLIENT_COMMAND_LAUNCH_FFA] = client_command_launch_ffa, handler[CLIENT_COMMAND_REJECT_BATTLE] = client_command_reject_battle, handler[CLIENT_COMMAND_INVITE_USER] = client_command_invite_user, handler[CLIENT_COMMAND_SEND_MESSAGE] = client_command_send_message, handler[CLIENT_COMMAND_MOVE_UP] = client_command_move_up, handler[CLIENT_COMMAND_MOVE_DOWN] = client_command_move_down, handler[CLIENT_COMMAND_MOVE_LEFT] = client_command_move_left, handler[CLIENT_COMMAND_MOVE_RIGHT] = client_command_move_right, handler[CLIENT_COMMAND_PUT_LANDMINE] = client_command_put_landmine, handler[CLIENT_COMMAND_MELEE] = client_command_melee, handler[CLIENT_COMMAND_FIRE_UP] = client_command_fire_up, handler[CLIENT_COMMAND_FIRE_DOWN] = client_command_fire_down, handler[CLIENT_COMMAND_FIRE_LEFT] = client_command_fire_left, handler[CLIENT_COMMAND_FIRE_RIGHT] = client_command_fire_right, handler[CLIENT_COMMAND_FIRE_UP_LEFT] = client_command_fire_up_left, handler[CLIENT_COMMAND_FIRE_UP_RIGHT] = client_command_fire_up_right, handler[CLIENT_COMMAND_FIRE_DOWN_LEFT] = client_command_fire_down_left, handler[CLIENT_COMMAND_FIRE_DOWN_RIGHT] = client_command_fire_down_right, handler[CLIENT_COMMAND_FIRE_AOE_UP] = client_command_fire_aoe_up, handler[CLIENT_COMMAND_FIRE_AOE_DOWN] = client_command_fire_aoe_down, handler[CLIENT_COMMAND_FIRE_AOE_LEFT] = client_command_fire_aoe_left, handler[CLIENT_COMMAND_FIRE_AOE_RIGHT] = client_command_fire_aoe_right; handler[CLIENT_COMMAND_ADMIN_CONTROL] = client_command_admin_control; } void init_constant() { item_s[ITEM_NONE] = (char*)"none"; item_s[ITEM_MAGAZINE] = (char*)"magazine"; item_s[ITEM_MAGMA] = (char*)"magma"; item_s[ITEM_GRASS] = (char*)"grass"; item_s[ITEM_BLOOD_VIAL] = (char*)"blood_vial"; item_s[ITEM_END] = (char*)"end"; item_s[ITEM_BULLET] = (char*)"bullet"; item_s[ITEM_LANDMINE] = (char*)"landmine"; dir_s[DIR_UP] = (char*)"up"; dir_s[DIR_DOWN] = (char*)"down"; dir_s[DIR_LEFT] = (char*)"left"; dir_s[DIR_RIGHT] = (char*)"right"; dir_s[DIR_UP_LEFT] = (char*)"up&left"; dir_s[DIR_UP_RIGHT] = (char*)"up&right"; dir_s[DIR_DOWN_LEFT] = (char*)"down&left"; dir_s[DIR_DOWN_RIGHT] = (char*)"down&right"; map_s[MAP_ITEM_NONE] = (char*)" "; map_s[MAP_ITEM_MAGAZINE] = (char*)"+"; map_s[MAP_ITEM_MAGMA] = (char*)"X"; map_s[MAP_ITEM_GRASS] = (char*)"\033[2;37m█\033[0m"; map_s[MAP_ITEM_BLOOD_VIAL] = (char*)"*"; map_s[MAP_ITEM_MY_BULLET] = (char*)"."; map_s[MAP_ITEM_OTHER_BULLET] = (char*)"."; map_s[MAP_ITEM_USER] = (char*)"A"; map_s[MAP_ITEM_LANDMINE] = (char*)"o"; map_s[MAP_ITEM_END] = (char*)" "; item_to_map[ITEM_NONE] = MAP_ITEM_NONE; item_to_map[ITEM_MAGAZINE] = MAP_ITEM_MAGAZINE; item_to_map[ITEM_MAGMA] = MAP_ITEM_MAGMA; item_to_map[ITEM_GRASS] = MAP_ITEM_GRASS; item_to_map[ITEM_BLOOD_VIAL] = MAP_ITEM_BLOOD_VIAL; item_to_map[ITEM_LANDMINE] = MAP_ITEM_LANDMINE; item_to_map[ITEM_END] = MAP_ITEM_END; signal_name_s[SIGHUP ] = (char*)"SIGHUP"; signal_name_s[SIGINT ] = (char*)"SIGINT"; signal_name_s[SIGQUIT ] = (char*)"SIGQUIT"; signal_name_s[SIGILL ] = (char*)"SIGILL" ; signal_name_s[SIGABRT ] = (char*)"SIGABRT"; signal_name_s[SIGFPE ] = (char*)"SIGFPE" ; signal_name_s[SIGKILL ] = (char*)"SIGKILL"; signal_name_s[SIGSEGV ] = (char*)"SIGSEGV"; signal_name_s[SIGPIPE ] = (char*)"SIGPIPE"; signal_name_s[SIGALRM ] = (char*)"SIGALRM"; signal_name_s[SIGTERM ] = (char*)"SIGTERM"; signal_name_s[SIGUSR1 ] = (char*)"SIGUSR1"; signal_name_s[SIGUSR2 ] = (char*)"SIGUSR2"; signal_name_s[SIGCHLD ] = (char*)"SIGCHLD"; signal_name_s[SIGCONT ] = (char*)"SIGCONT"; signal_name_s[SIGSTOP ] = (char*)"SIGSTOP"; signal_name_s[SIGTSTP ] = (char*)"SIGTSTP"; signal_name_s[SIGTTIN ] = (char*)"SIGTTIN"; signal_name_s[SIGTTOU ] = (char*)"SIGTTOU"; signal_name_s[SIGBUS ] = (char*)"SIGBUS" ; signal_name_s[SIGPOLL ] = (char*)"SIGPOLL"; signal_name_s[SIGPROF ] = (char*)"SIGPROF"; signal_name_s[SIGSYS ] = (char*)"SIGSYS" ; signal_name_s[SIGTRAP ] = (char*)"SIGTRAP"; signal_name_s[SIGURG ] = (char*)"SIGURG" ; signal_name_s[SIGVTALRM] = (char*)"SIGVTALRM"; signal_name_s[SIGXCPU ] = (char*)"SIGXCPU"; signal_name_s[SIGXFSZ ] = (char*)"SIGXFSZ"; color_s[0] = (char*)NONE; color_s[1] = (char*)L_GREEN; color_s[2] = (char*)L_RED; color_s[3] = (char*)YELLOW; color_s[4] = (char*)L_BLUE; color_s[5] = (char*)L_PURPLE; color_s[6] = (char*)L_CYAN; color_s[7] = (char*)(RED UNDERLINE); color_s[8] = (char*)(GREEN UNDERLINE); color_s[9] = (char*)(BROWN UNDERLINE); color_s[10] = (char*)(BLUE UNDERLINE); color_s[11] = (char*)(PURPLE UNDERLINE); color_s[12] = (char*)(CYAN UNDERLINE); color_s_size = 12; } /* int main0(int argc, char* argv[]) { init_constants(); init_handler(); if (argc == 2) { port = atoi(argv[1]); } srand(time(NULL)); pthread_t thread; if (signal(SIGINT, terminate_entrance) == SIG_ERR) { eprintf("an error occurred while setting a signal handler."); } if (signal(SIGSEGV, terminate_entrance) == SIG_ERR) { eprintf("an error occurred while setting a signal handler."); } if (signal(SIGABRT, terminate_entrance) == SIG_ERR) { eprintf("an error occurred while setting a signal handler."); } if (signal(SIGTERM, terminate_entrance) == SIG_ERR) { eprintf("an error occurred while setting a signal handler."); } if (signal(SIGTRAP, terminate_entrance) == SIG_ERR) { eprintf("an error occurred while setting a signal handler."); } for (int i = 0; i < USER_CNT; i++) { pthread_mutex_init(&items_lock[i], NULL); } log("server %s", version); if (sizeof(server_message_t) >= 1000) logw("message_size = %ldB", sizeof(server_message_t)); server_fd = server_start(); load_user_list(); for (int i = 0; i < USER_CNT; i++) sessions[i].conn = -1; struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); while (1) { static session_args_t info; info.conn = accept(server_fd, (struct sockaddr*)&client_addr, &length); strncpy(info.ip_addr, inet_ntoa(client_addr.sin_addr), IPADDR_SIZE - 1); log("connected by %s:%d , conn:%d", info.ip_addr, client_addr.sin_port, info.conn); if (info.conn < 0) { loge("fail to accept client."); } else if (pthread_create(&thread, NULL, session_start, (void*)(uintptr_t)&info) != 0) { loge("fail to create thread."); } logi("bind thread #%lu", thread); } return 0; } */ int EightQueen(int n) { //函数返回八皇后问题的解法个数 int *p = new int[n]; //p[8]用来存储八皇后的位置,下标表示行号,数值表示列号 //例如p[2]=3表示落在(2,3)这个点上,行号列号均为0~8 memset(p, 0, n * sizeof(int));//初始化所有p[i]=0 int k = 0; //k用来记录行号 int count = 0; //count用来记录解法个数,函数最终返回该值 while (k >= 0) { //最后一次回溯k=-1跳出循环,从而找到全部解法 while (p[k] < n) { int i; for (i = 0; i < k; i++)//找一下K行之前的几行有没有与p[k]在同一列或者同一对角线上 if (p[i] == p[k] || p[i] - p[k] == i - k || p[i] - p[k] == k - i) break; //如果有,就跳出循环,此时i= 0)p[k]++; //如果还没到最后的解法,即如果不是0行找不到解的话,就可以开始回溯,将上一行的位置++ } } return count; //函数返回count解法数量 } int data[ 8 ][ 8 ]; //chess(double dimensional array) int a[ 8 ]; //column(列) int b[ 15 ]; //主对角线(左上至右下) int c[ 15 ]; //从对角线(右上至左下) int cnt = 0; void eightQueens( int ); void output( const int [][ 8 ], int ); int EightQueen1() { int i, j; for( i = 0; i < 15; ++i ) //主、从对角线 b[ i ] = c[ i ] = 0; //表示安全 for( i = 0; i < 8; ++i )//chess { a[ i ] = 0; //i列安全 for( j = 0; j < 8; ++j ) data[ i ][ j ] = 0; } eightQueens( 0 ); cout << "/ncount = " << cnt << endl; return 0; } void eightQueens( int line ) { if( 8 == line )//八个皇后安置就位,输出 { output( data, 8 ); cout << endl; return; } for( int column = 0; column < 8; ++column ) { if( 0 == a[ column ] && 0 == b[ line - column + 7 ] && 0 == c[ line + column ] ) { data[ line ][ column ] = 1; //安置皇后 a[ column ] = 1; //此列被占 b[ line - column + 7 ] = 1; //主对角线被占 c[ line + column ] = 1; //从对角线被占 eightQueens( line + 1 ); //下一个皇后 //重置 data[ line ][ column ] = 0; a[ column ] = 0; b[ line - column + 7 ] = 0; c[ line + column ] = 0; } } } //output chess void output( const int data[][ 8 ], int size ) { for( int i = 0; i < size; ++i ) { for( int j = 0; j < size; ++j ) cout << data[ i ][ j ] << ' '; cout << endl; } ++cnt; } namespace floyd_algorithm{ #include #include #define MAXV 7 //最大顶点个数 #define INF 32767 //定义 ∞ //∞ == 32767 ,int 型的最大范围(2位)= 2^(2*8-1),TC告诉我们int占用2个字节,而VC和LGCC告诉我们int占用4个字节 //图:Graph //顶点:Vertex //邻接:Adjacency //矩阵:Matrix //表:List //边:Edge typedef struct vertex { int number; //顶点的编号 }VertexType; //别名,顶点的类型 typedef struct matrix { int n; //顶点个数 int e; //边数 int adjMat[MAXV][MAXV]; //邻接矩阵数组 VertexType ver[MAXV]; //存放顶点信息 }MatGraph; //别名,完整的图邻接矩阵类型 typedef struct eNode { int adjVer; //该边的邻接点编号 int weiLGht; //该边的的信息,如权值 struct eNode* nextEdLGe; //指向下一条边的指针 }EdgeNode; //别名,边结点的类型 typedef struct vNode { EdgeNode* firstEdLGe; //指向第一个边结点 }VNode; //别名,邻接表的头结点类型 typedef struct list { int n; //顶点个数 int e; //边数 VNode adjList[MAXV]; //邻接表的头结点数组 }ListGraph; //别名,完整的图邻接表类型 //创建图的邻接表 void createAdjListGraph(ListGraph*& LG, int A[MAXV][MAXV], int n, int e) { int i, j; EdgeNode* p; LG = (ListGraph*)malloc(sizeof(ListGraph)); for (i = 0; i < n; i++) { LG->adjList[i].firstEdLGe = NULL; //给邻接表中所有头结点指针域置初值 } for (i = 0; i < n; i++) { //检查邻接矩阵中的每个元素 for (j = n - 1; j >= 0; j--) { if (A[i][j] != 0) { //存在一条边 p = (EdgeNode*)malloc(sizeof(EdgeNode)); //申请一个结点内存 p->adjVer = j; //存放邻接点 p->weiLGht = A[i][j]; //存放权值 p->nextEdLGe = NULL; p->nextEdLGe = LG->adjList[i].firstEdLGe; //头插法 LG->adjList[i].firstEdLGe = p; } } } LG->n = n; LG->e = e; } //输出邻接表 void displayAdjList(ListGraph* LG) { int i; EdgeNode* p; for (i = 0; i < MAXV; i++) { p = LG->adjList[i].firstEdLGe; printf("%d:", i); while (p != NULL) { if (p->weiLGht != 32767) { printf("%2d[%d]->", p->adjVer, p->weiLGht); } p = p->nextEdLGe; } printf(" NULL\n"); } } //输出邻接矩阵 void displayAdjMat(MatGraph MG) { int i, j; for (i = 0; i < MAXV; i++) { for (j = 0; j < MAXV; j++) { if (MG.adjMat[i][j] == 0) { printf("%4s", "0"); } else if (MG.adjMat[i][j] == 32767) { printf("%4s", "∞"); } else { printf("%4d", MG.adjMat[i][j]); } } printf("\n"); } } //邻接表转换为邻接矩阵 void ListToMat(ListGraph* LG, MatGraph& MG) { int i, j; EdgeNode* p; for (i = 0; i < MAXV; i++) { for (j = 0; j < MAXV; j++) { MG.adjMat[i][j] = 0; } } for (i = 0; i < LG->n; i++) { p = LG->adjList[i].firstEdLGe; while (p != NULL) { MG.adjMat[i][p->adjVer] = p->weiLGht; p = p->nextEdLGe; } } MG.n = LG->n; MG.e = LG->e; } //输出多源最短路径 void displayPath(MatGraph MG, int A[MAXV][MAXV], int path[MAXV][MAXV]) { int i, j, k; int s; int aPath[MAXV]; //存放一条最短路径(逆向) int d; //顶点个数 for (i = 0; i < MG.n; i++) { for (j = 0; j < MG.n; j++) { if (A[i][j] != INF && i != j) { //若顶点 i 和 顶点 j 之间存在路径 //printf("从 %d 到 %d 的路径为:", i, j); k = path[i][j]; d = 0; aPath[d] = j; //路径上添加终点 while (//k != -1 && k != i) { //路劲上添加中间点 d++; aPath[d] = k; k = path[i][k]; } d++; aPath[d] = i; //路径上添加起点 //printf("%d", aPath[d]); //输出起点 for (s = d - 1; s >= 0; s--) { //输出路径上其他顶点 //printf("->%d", aPath[s]); } //printf("\t\t"); //printf("路径长度为:%d\n", A[i][j]); } } } } //Floyd算法 void Floyd(MatGraph MG) { int i, j, k; int A[MAXV][MAXV]; int path[MAXV][MAXV]; for (i = 0; i < MG.n; i++) { for (j = 0; j < MG.n; j++) { A[i][j] = MG.adjMat[i][j]; if (i != j && MG.adjMat[i][j] < INF) { path[i][j] = i; //顶点 i 到顶点 j 有边时 } else { path[i][j] = -1; //顶点 i 到顶点 j 无边时 } } } for (k = 0; k < MG.n; k++) { //一次考察所有顶点 for (i = 0; i < MG.n; i++) { for (j = 0; j < MG.n; j++) { if (A[i][j] > A[i][k] + A[k][j]) { A[i][j] = A[i][k] + A[k][j]; //修改最短路径长度 path[i][j] = path[k][j]; //修改最短路径 } } } } displayPath(MG, A, path); //输出最短路径 } int floyd() { ListGraph* LG; MatGraph MG; int array[MAXV][MAXV] = { { 0, 4, 6, 6,INF,INF,INF}, {INF, 0, 1,INF, 7,INF,INF}, {INF,INF, 0,INF, 6, 4,INF}, {INF,INF, 2, 0,INF, 5,INF}, {INF,INF,INF,INF, 0,INF, 6}, {INF,INF,INF,INF, 1, 0, 8}, {INF,INF,INF,INF,INF,INF, 0} }; int e = 12; createAdjListGraph(LG, array, MAXV, e); //displayAdjList(LG); //printf("\n"); ListToMat(LG, MG); //displayAdjMat(MG); //printf("\n"); Floyd(MG); //printf("\n"); return 0; } } namespace __floyd{ #include #include #define MAXV 7 //最大顶点个数 #define INF 32767 //定义 ∞ //∞ == 32767 ,int 型的最大范围(2位)= 2^(2*8-1),TC告诉我们int占用2个字节,而VC和LGCC告诉我们int占用4个字节 //图:Graph //顶点:Vertex //邻接:Adjacency //矩阵:Matrix //表:List //边:Edge typedef struct vertex { int number; //顶点的编号 }VertexType; //别名,顶点的类型 typedef struct matrix { int n; //顶点个数 int e; //边数 int adjMat[MAXV][MAXV]; //邻接矩阵数组 VertexType ver[MAXV]; //存放顶点信息 }MatGraph; //别名,完整的图邻接矩阵类型 typedef struct eNode { int adjVer; //该边的邻接点编号 int weiLGht; //该边的的信息,如权值 struct eNode* nextEdLGe; //指向下一条边的指针 }EdgeNode; //别名,边结点的类型 typedef struct vNode { EdgeNode* firstEdLGe; //指向第一个边结点 }VNode; //别名,邻接表的头结点类型 typedef struct list { int n; //顶点个数 int e; //边数 VNode adjList[MAXV]; //邻接表的头结点数组 }ListGraph; //别名,完整的图邻接表类型 //创建图的邻接表 void createAdjListGraph(ListGraph*& LG, int A[MAXV][MAXV], int n, int e) { int i, j; EdgeNode* p; LG = (ListGraph*)malloc(sizeof(ListGraph)); for (i = 0; i < n; i++) { LG->adjList[i].firstEdLGe = NULL; //给邻接表中所有头结点指针域置初值 } for (i = 0; i < n; i++) { //检查邻接矩阵中的每个元素 for (j = n - 1; j >= 0; j--) { if (A[i][j] != 0) { //存在一条边 p = (EdgeNode*)malloc(sizeof(EdgeNode)); //申请一个结点内存 p->adjVer = j; //存放邻接点 p->weiLGht = A[i][j]; //存放权值 p->nextEdLGe = NULL; p->nextEdLGe = LG->adjList[i].firstEdLGe; //头插法 LG->adjList[i].firstEdLGe = p; } } } LG->n = n; LG->e = e; } //输出邻接表 void displayAdjList(ListGraph* LG) { int i; EdgeNode* p; for (i = 0; i < MAXV; i++) { p = LG->adjList[i].firstEdLGe; printf("%d:", i); while (p != NULL) { if (p->weiLGht != 32767) { printf("%2d[%d]->", p->adjVer, p->weiLGht); } p = p->nextEdLGe; } printf(" NULL\n"); } } //输出邻接矩阵 void displayAdjMat(MatGraph MG) { int i, j; for (i = 0; i < MAXV; i++) { for (j = 0; j < MAXV; j++) { if (MG.adjMat[i][j] == 0) { printf("%4s", "0"); } else if (MG.adjMat[i][j] == 32767) { printf("%4s", "∞"); } else { printf("%4d", MG.adjMat[i][j]); } } printf("\n"); } } //邻接表转换为邻接矩阵 void ListToMat(ListGraph* LG, MatGraph& MG) { int i, j; EdgeNode* p; for (i = 0; i < MAXV; i++) { for (j = 0; j < MAXV; j++) { MG.adjMat[i][j] = 0; } } for (i = 0; i < LG->n; i++) { p = LG->adjList[i].firstEdLGe; while (p != NULL) { MG.adjMat[i][p->adjVer] = p->weiLGht; p = p->nextEdLGe; } } MG.n = LG->n; MG.e = LG->e; } //输出多源最短路径 void displayPath(MatGraph MG, int A[MAXV][MAXV], int path[MAXV][MAXV]) { int i, j, k; int s; int aPath[MAXV]; //存放一条最短路径(逆向) int d; //顶点个数 for (i = 0; i < MG.n; i++) { for (j = 0; j < MG.n; j++) { if (A[i][j] != INF && i != j) { //若顶点 i 和 顶点 j 之间存在路径 //printf("从 %d 到 %d 的路径为:", i, j); k = path[i][j]; d = 0; aPath[d] = j; //路径上添加终点 while (//k != -1 && k != i) { //路劲上添加中间点 d++; aPath[d] = k; k = path[i][k]; } d++; aPath[d] = i; //路径上添加起点 //printf("%d", aPath[d]); //输出起点 for (s = d - 1; s >= 0; s--) { //输出路径上其他顶点 //printf("->%d", aPath[s]); } //printf("\t\t"); //printf("路径长度为:%d\n", A[i][j]); } } } } //Floyd算法 void Floyd(MatGraph MG) { int i, j, k; int A[MAXV][MAXV]; int path[MAXV][MAXV]; for (i = 0; i < MG.n; i++) { for (j = 0; j < MG.n; j++) { A[i][j] = MG.adjMat[i][j]; if (i != j && MG.adjMat[i][j] < INF) { path[i][j] = i; //顶点 i 到顶点 j 有边时 } else { path[i][j] = -1; //顶点 i 到顶点 j 无边时 } } } for (k = 0; k < MG.n; k++) { //一次考察所有顶点 for (i = 0; i < MG.n; i++) { for (j = 0; j < MG.n; j++) { if (A[i][j] > A[i][k] + A[k][j]) { A[i][j] = A[i][k] + A[k][j]; //修改最短路径长度 path[i][j] = path[k][j]; //修改最短路径 } } } } displayPath(MG, A, path); //输出最短路径 } int floyd() { ListGraph* LG; MatGraph MG; int array[MAXV][MAXV] = { { 0, 4, 6, 6,INF,INF,INF}, {INF, 0, 1,INF, 7,INF,INF}, {INF,INF, 0,INF, 6, 4,INF}, {INF,INF, 2, 0,INF, 5,INF}, {INF,INF,INF,INF, 0,INF, 6}, {INF,INF,INF,INF, 1, 0, 8}, {INF,INF,INF,INF,INF,INF, 0} }; int e = 12; createAdjListGraph(LG, array, MAXV, e); //displayAdjList(LG); //printf("\n"); ListToMat(LG, MG); //displayAdjMat(MG); //printf("\n"); Floyd(MG); //printf("\n"); return 0; } } namespace Queue{ int data[ 8 ][ 8 ]; //chess(double dimensional array) int a[ 8 ]; //column(列) int b[ 15 ]; //主对角线(左上至右下) int c[ 15 ]; //从对角线(右上至左下) int cnt = 0; void eightQueens( int ); void output( const int [][ 8 ], int ); int EightQueen1() { int i, j; for( i = 0; i < 15; ++i ) //主、从对角线 b[ i ] = c[ i ] = 0; //表示安全 for( i = 0; i < 8; ++i )//chess { a[ i ] = 0; //i列安全 for( j = 0; j < 8; ++j ) data[ i ][ j ] = 0; } eightQueens( 0 ); cout << "/ncount = " << cnt << endl; return 0; } void eightQueens( int line ) { if( 8 == line )//八个皇后安置就位,输出 { output( data, 8 ); cout << endl; return; } for( int column = 0; column < 8; ++column ) { if( 0 == a[ column ] && 0 == b[ line - column + 7 ] && 0 == c[ line + column ] ) { data[ line ][ column ] = 1; //安置皇后 a[ column ] = 1; //此列被占 b[ line - column + 7 ] = 1; //主对角线被占 c[ line + column ] = 1; //从对角线被占 eightQueens( line + 1 ); //下一个皇后 //重置 data[ line ][ column ] = 0; a[ column ] = 0; b[ line - column + 7 ] = 0; c[ line + column ] = 0; } } } //output chess void output( const int data[][ 8 ], int size ) { for( int i = 0; i < size; ++i ) { for( int j = 0; j < size; ++j ) cout << data[ i ][ j ] << ' '; cout << endl; } ++cnt; } }