├── .gitattributes ├── ClientSocket.cpp ├── ClientSocket.h ├── Define.h ├── Einstein.cpp ├── Einstein.h ├── EinsteinChessTestServer ├── TestServer.py ├── Twoplayers-BattleServer (胜率曲线).py ├── Twoplayers-BattleServer.py ├── einstein双人对战平台 │ ├── 2PlayersServer.mp4 │ ├── Twoplayers-BattleServer.py │ └── 双人对战平台使用说明.txt ├── picture │ ├── black │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── AYST.png │ │ ├── B1.png │ │ ├── B2.png │ │ ├── B3.png │ │ ├── B4.png │ │ ├── B5.png │ │ ├── B6.png │ │ ├── BLUEWIN.png │ │ ├── R1.png │ │ ├── R2.png │ │ ├── R3.png │ │ ├── R4.png │ │ ├── R5.png │ │ ├── R6.png │ │ ├── REDWIN.png │ │ ├── Y1.png │ │ ├── Y2.png │ │ ├── Y3.png │ │ ├── Y4.png │ │ ├── Y5.png │ │ ├── Y6.png │ │ ├── equation.jpeg │ │ └── shy.png │ └── white │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── AYST.png │ │ ├── B1.png │ │ ├── B2.png │ │ ├── B3.png │ │ ├── B4.png │ │ ├── B5.png │ │ ├── B6.png │ │ ├── BLUEWIN.png │ │ ├── R1.png │ │ ├── R2.png │ │ ├── R3.png │ │ ├── R4.png │ │ ├── R5.png │ │ ├── R6.png │ │ ├── REDWIN.png │ │ ├── Y1.png │ │ ├── Y2.png │ │ ├── Y3.png │ │ ├── Y4.png │ │ ├── Y5.png │ │ └── Y6.png ├── 示例图片 │ ├── macos运行示例.png │ ├── ubuntu运行示例.png │ ├── windows运行示例.png │ └── 如何打开cmd.png └── 配置环境.txt ├── README.md └── main.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | *.py linguist-language=C++ 2 | -------------------------------------------------------------------------------- /ClientSocket.cpp: -------------------------------------------------------------------------------- 1 | #include "ClientSocket.h" 2 | 3 | #pragma comment(lib, "Ws2_32.lib") 4 | 5 | 6 | ClientSocket::ClientSocket() 7 | { 8 | 9 | } 10 | 11 | 12 | ClientSocket::~ClientSocket(void) 13 | { 14 | //close(); 15 | } 16 | 17 | /** connect to the server 18 | * return 0 means that connect to the server successfully 19 | * return >0 means that an error happened. 20 | */ 21 | int ClientSocket::connectServer() 22 | { 23 | std::cout << "Connect server: " << SERVER_IP << ":" << SERVER_PORT << std::endl; 24 | int rtn = 0, err = 0; 25 | WSADATA wsaData; 26 | // initialize windows socket library 27 | err = WSAStartup(0x0202, &wsaData); 28 | if (err != NO_ERROR) 29 | { 30 | std::cout << "Failed with WSAStartup error: " << err << std::endl; 31 | rtn = 1; 32 | return rtn; 33 | } 34 | // creat socket 35 | clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 36 | if (clientSocket == INVALID_SOCKET) 37 | { 38 | std::cout << "Socket failed with error: " << WSAGetLastError() << std::endl; 39 | rtn = 2; 40 | return rtn; 41 | } 42 | // server address 43 | memset(&server, 0, sizeof(SOCKADDR_IN)); 44 | server.sin_family = PF_INET; 45 | server.sin_port = htons(SERVER_PORT); 46 | server.sin_addr.s_addr = inet_addr(SERVER_IP); 47 | // connect 48 | err = connect(clientSocket, (struct sockaddr *) &server, sizeof(SOCKADDR_IN)); 49 | if (err < 0) 50 | { 51 | std::cout << "Connect failed with error: " << err << std::endl; 52 | // printf("%d\n", WSAGetLastError); 53 | rtn = 3; 54 | return rtn; 55 | } 56 | return rtn; 57 | } 58 | 59 | 60 | /* send message to the server 61 | * input the message that you want to send to the message 62 | * return 0 means that send message successfully 63 | * return 1 means that an error happened 64 | */ 65 | int ClientSocket::sendMsg(const char* msg) 66 | { 67 | int rtn = 0, err = 0; 68 | 69 | //set length 70 | int len = strlen(msg); 71 | len = len < BUFSIZE ? len + 1 : BUFSIZE; 72 | 73 | //set sendBuf 74 | //memset(sendBuf, 0, BUFSIZE); 75 | //memset(sendBuf, 0, sizeof(sendBuf)); 76 | //memcpy(sendBuf, msg, len); 77 | char *bufsend = new char[len]; 78 | memcpy(bufsend, msg, len); 79 | 80 | //send message to the server 81 | err = send(clientSocket, bufsend, len, 0); 82 | if (err < 0) 83 | { 84 | std::cout << "Send msg failed with error: " << err << std::endl; 85 | rtn = 1; 86 | return rtn; 87 | } 88 | return rtn; 89 | } 90 | 91 | 92 | /* receive message from the server 93 | * return 0 means that receives message successfully 94 | * return 1 means that an error happened 95 | */ 96 | int ClientSocket::recvMsg() 97 | { 98 | int rtn = 0, err = 0; 99 | memset(recvBuf, 0, BUFSIZE); 100 | 101 | //receive message 102 | err = recv(clientSocket, recvBuf, BUFSIZE, 0); 103 | if (err < 0) 104 | { 105 | std::cout << "Receive msg failed with error: " << err << std::endl; 106 | rtn = 1; 107 | return rtn; 108 | } 109 | return rtn; 110 | 111 | } 112 | 113 | //get the received message 114 | char* ClientSocket::getRecvMsg() { 115 | return this->recvBuf; 116 | } 117 | 118 | /*close client socket*/ 119 | void ClientSocket::close() { 120 | closesocket(clientSocket); 121 | 122 | std::cout << "Close socket" << std::endl; 123 | } -------------------------------------------------------------------------------- /ClientSocket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Define.h" 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #define BUFSIZE 128 9 | 10 | 11 | 12 | class ClientSocket 13 | { 14 | private: 15 | //server address 16 | SOCKADDR_IN server; 17 | 18 | //client SOCKET that connect to the server 19 | SOCKET clientSocket; 20 | 21 | //the message buffer that is received from the server 22 | char recvBuf[BUFSIZE]; 23 | 24 | //the message buffer that is sent to the server 25 | char sendBuf[BUFSIZE]; 26 | 27 | public: 28 | ClientSocket(); 29 | ~ClientSocket(void); 30 | 31 | //connect to the server 32 | int connectServer(); 33 | 34 | //receive message from server 35 | int recvMsg(); 36 | 37 | //send message to server 38 | int sendMsg(const char* msg); 39 | 40 | //close socket 41 | void close(); 42 | 43 | 44 | //get the received message 45 | char* getRecvMsg(); 46 | 47 | }; 48 | 49 | -------------------------------------------------------------------------------- /Define.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define ID "111111110" //your id 3 | #define SERVER_IP "127.0.0.1" //server ip 4 | #define SERVER_PORT 50006 //server port 5 | -------------------------------------------------------------------------------- /Einstein.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include "Einstein.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | time_t now_time; 10 | time_t begin_time; 11 | time_t end_time; 12 | struct tm* pt; 13 | const double coe = 1.38; 14 | 15 | class Board 16 | { 17 | public: 18 | std::shared_ptr parent; 19 | std::vector validchess; //可以走的棋子 20 | int chess[2] = { 0,-1 }; //导致这个棋局要走的棋子和方向 21 | std::vector posStep[2]; //可能的走法的个数,要分种类,0水平走位、1垂直走位、2对角走位 22 | int color; //红色为0,蓝色为1 23 | int board[5][5] = {}; //棋盘 24 | int visit_times = 0; 25 | int win_time = 0; 26 | double quality = 0.0; 27 | std::vector> child; 28 | 29 | Board() {}; 30 | Board(std::shared_ptr par, int col, int a[5][5], int pos[2]) { 31 | parent = par; 32 | color = col; 33 | chess[0] = pos[0]; 34 | chess[1] = pos[1]; 35 | if (col == 0) 36 | { 37 | for (int i = 0; i < 5; i++) 38 | for (int j = 0; j < 5; j++) 39 | { 40 | int temp = a[i][j]; 41 | board[i][j] = temp; 42 | if (temp >= 1 && temp <= 6) 43 | validchess.push_back(temp); 44 | } 45 | } 46 | else 47 | { 48 | for (int i = 0; i < 5; i++) 49 | for (int j = 0; j < 5; j++) 50 | { 51 | int temp = a[i][j]; 52 | board[i][j] = temp; 53 | if (temp >= 7) 54 | validchess.push_back(temp - 6); 55 | } 56 | } 57 | com_posStep(); 58 | } 59 | void com_posStep() { 60 | if (color == 0) 61 | { 62 | for (int i = 0; i < validchess.size(); i++) 63 | { 64 | int x, y; 65 | for (int j = 0; j < 5; j++) 66 | for (int k = 0; k < 5; k++) 67 | { 68 | if (board[j][k] == validchess[i]) 69 | { 70 | x = j; 71 | y = k; 72 | break; 73 | } 74 | } 75 | if (x == 4) 76 | { 77 | posStep[0].push_back(validchess[i]); 78 | posStep[1].push_back(0); 79 | } 80 | else if (y == 4) 81 | { 82 | posStep[0].push_back(validchess[i]); 83 | posStep[1].push_back(1); 84 | } 85 | else 86 | { 87 | posStep[0].push_back(validchess[i]); 88 | posStep[1].push_back(0); 89 | posStep[0].push_back(validchess[i]); 90 | posStep[1].push_back(1); 91 | posStep[0].push_back(validchess[i]); 92 | posStep[1].push_back(2); 93 | } 94 | } 95 | } 96 | else 97 | { 98 | for (int i = 0; i < validchess.size(); i++) 99 | { 100 | int x, y; 101 | for (int j = 0; j < 5; j++) 102 | for (int k = 0; k < 5; k++) 103 | { 104 | if (board[j][k] == validchess[i] + 6) 105 | { 106 | x = j; 107 | y = k; 108 | //break; 109 | } 110 | } 111 | if (x == 0) 112 | { 113 | posStep[0].push_back(validchess[i]); 114 | posStep[1].push_back(0); 115 | } 116 | else if (y == 0) 117 | { 118 | posStep[0].push_back(validchess[i]); 119 | posStep[1].push_back(1); 120 | } 121 | else 122 | { 123 | posStep[0].push_back(validchess[i]); 124 | posStep[1].push_back(0); 125 | posStep[0].push_back(validchess[i]); 126 | posStep[1].push_back(1); 127 | posStep[0].push_back(validchess[i]); 128 | posStep[1].push_back(2); 129 | } 130 | } 131 | } 132 | } 133 | Board(std::shared_ptr par, int col, int a[5][5], int dice) { 134 | parent = par; 135 | color = col; 136 | int ch[7] = { 0 }; 137 | if (col == 0) 138 | { 139 | for (int i = 0; i < 5; i++) 140 | for (int j = 0; j < 5; j++) 141 | { 142 | int temp = a[i][j]; 143 | board[i][j] = temp; 144 | if (temp >= 1 && temp <= 6) 145 | ch[temp]++; 146 | } 147 | if (ch[dice] == 1) 148 | validchess.push_back(dice); 149 | else 150 | { 151 | for (int i = dice - 1; i > 0; i--) 152 | { 153 | if (ch[i] == 1) 154 | { 155 | validchess.push_back(i); 156 | break; 157 | } 158 | } 159 | for (int i = dice + 1; i < 7; i++) 160 | { 161 | if (ch[i] == 1) 162 | { 163 | validchess.push_back(i); 164 | break; 165 | } 166 | } 167 | } 168 | } 169 | else 170 | { 171 | for (int i = 0; i < 5; i++) 172 | for (int j = 0; j < 5; j++) 173 | { 174 | int temp = a[i][j]; 175 | board[i][j] = temp; 176 | if (temp >= 7) 177 | ch[temp - 6]++; 178 | } 179 | if (ch[dice - 6] == 1) 180 | validchess.push_back(dice - 6); 181 | else 182 | { 183 | for (int i = dice - 7; i > 0; i--) 184 | { 185 | if (ch[i] == 1) 186 | { 187 | validchess.push_back(i); 188 | break; 189 | } 190 | } 191 | for (int i = dice - 5; i < 7; i++) 192 | { 193 | if (ch[i] == 1) 194 | { 195 | validchess.push_back(i); 196 | break; 197 | } 198 | } 199 | } 200 | } 201 | com_posStep(); 202 | } 203 | ~Board() {}; 204 | }; 205 | 206 | std::shared_ptr BestChild(std::shared_ptr v, double c); 207 | std::shared_ptr MostWin(std::shared_ptr v); 208 | std::shared_ptr Expand(std::shared_ptr v); 209 | bool is_Terminal(std::shared_ptr v); 210 | bool is_Expanded(std::shared_ptr v); 211 | std::shared_ptr Treepolicy(std::shared_ptr v); 212 | void oneMove(std::shared_ptr v, int newboard[5][5], int chess, int direction); 213 | int simulate(std::shared_ptr v); 214 | bool RandomMove(std::shared_ptr v, bool col); 215 | void Backup(std::shared_ptr v, int result); 216 | 217 | void to_int(std::string s, int begin, int end, int* a, int line) 218 | { 219 | int i = begin; 220 | int j = begin + 1; 221 | int t = 0; 222 | while (j < end + 1) 223 | { 224 | if (s[j] == ',' || s[j] == ']') 225 | { 226 | std::string x = s.substr(i, j - i); 227 | a[line * 5 + t] = atoi(x.c_str()); 228 | t++; 229 | i = j + 2; 230 | } 231 | j++; 232 | } 233 | } 234 | 235 | Einstein::Einstein() 236 | { 237 | this->clientsocket.connectServer(); 238 | clientsocket.sendMsg(ID); 239 | } 240 | 241 | Einstein::~Einstein() 242 | { 243 | this->clientsocket.close(); 244 | } 245 | 246 | int Einstein::parse(std::string s) 247 | { 248 | int k = s.find("], [", 0); 249 | int l = s.find("], [", k + 4); 250 | int m = s.find("], [", l + 4); 251 | int n = s.find("], [", m + 4); 252 | int p = s.find("]]|", n + 4); 253 | to_int(s, 2, k, chessboard, 0); 254 | to_int(s, k + 4, l, chessboard, 1); 255 | to_int(s, l + 4, m, chessboard, 2); 256 | to_int(s, m + 4, n, chessboard, 3); 257 | to_int(s, n + 4, p, chessboard, 4); 258 | std::string d = s.substr(p + 3, s.length() - p - 3); 259 | dice = atoi(d.c_str()); 260 | if (logger.size() == 0) 261 | { 262 | begin_time = clock(); 263 | return 0; 264 | } 265 | else 266 | { 267 | std::string g = logger.back(); 268 | int last[25]; 269 | int f = g.find("[[", 0); 270 | int k = g.find("], [", f + 2); 271 | int l = g.find("], [", k + 4); 272 | int m = g.find("], [", l + 4); 273 | int n = g.find("], [", m + 4); 274 | int p = g.find("]]|", n + 4); 275 | to_int(g, f + 2, k, last, 0); 276 | to_int(g, k + 4, l, last, 1); 277 | to_int(g, l + 4, m, last, 2); 278 | to_int(g, m + 4, n, last, 3); 279 | to_int(g, n + 4, p, last, 4); 280 | int diff = 0; 281 | for (int i = 0; i < 25; i++) 282 | if (chessboard[i] != last[i]) 283 | diff++; 284 | if (diff <= 4) 285 | return 0; 286 | else 287 | { 288 | int ze = g.rfind(" "); 289 | int pr = g.rfind("|"); 290 | int chess = std::stoi(g.substr(ze + 1, pr - ze - 1)); 291 | std::string operation = g.substr(pr + 1, g.length() - pr - 1); 292 | int t = 0; 293 | while (last[t] != chess) 294 | t++; 295 | if (operation == "up") 296 | { 297 | last[t - 5] = chess; 298 | last[t] = 0; 299 | } 300 | else if (operation == "left") 301 | { 302 | last[t - 1] = chess; 303 | last[t] = 0; 304 | } 305 | else if (operation == "leftup") 306 | { 307 | last[t - 6] = chess; 308 | last[t] = 0; 309 | } 310 | else if (operation == "down") 311 | { 312 | last[t + 5] = chess; 313 | last[t] = 0; 314 | } 315 | else if (operation == "right") 316 | { 317 | last[t + 1] = chess; 318 | last[t] = 0; 319 | } 320 | else 321 | { 322 | last[t + 6] = chess; 323 | last[t] = 0; 324 | } 325 | end_time = clock(); 326 | double lasting = difftime(end_time, begin_time) / (double)CLOCKS_PER_SEC; 327 | begin_time = clock(); 328 | if (chess >= 7) 329 | { 330 | int red = 0; 331 | for (int i = 0; i < 25; i++) 332 | if (last[i] >= 1 && last[i] <= 6) 333 | red++; 334 | if (red == 0 || last[0] == chess) 335 | { 336 | logging("Game over! Blue wins! Time: " + std::to_string(lasting) + "s"); 337 | return 0; 338 | } 339 | else 340 | { 341 | logging("Game over! Red wins! Time: " + std::to_string(lasting) + "s"); 342 | return 0; 343 | } 344 | } 345 | else 346 | { 347 | int blue = 0; 348 | for (int i = 0; i < 25; i++) 349 | if (last[i] >= 7 && last[i] <= 12) 350 | blue++; 351 | if (blue == 0 || last[24] == chess) 352 | { 353 | logging("Game over! Red wins! Time: " + std::to_string(lasting) + "s"); 354 | return 0; 355 | } 356 | else 357 | { 358 | logging("Game over! Blue wins! Time: " + std::to_string(lasting) + "s"); 359 | return 0; 360 | } 361 | } 362 | } 363 | } 364 | } 365 | 366 | //莽夫算法 367 | std::string fool(int dice, int board[5][5]); 368 | 369 | //UCT 370 | 371 | //返回最佳子节点 372 | std::shared_ptr BestChild(std::shared_ptr v, double c) 373 | { 374 | std::shared_ptr q; 375 | double max = -1.0; 376 | for (int i = 0; i < v->child.size(); i++) 377 | { 378 | double UCB = v->child[i]->quality / (double)v->child[i]->visit_times + c * sqrt(2 * log((double)v->visit_times) / (double)v->child[i]->visit_times); 379 | if (UCB - max > 0.0) 380 | { 381 | q = v->child[i]; 382 | max = UCB; 383 | } 384 | } 385 | return q; 386 | } 387 | 388 | std::shared_ptr MostWin(std::shared_ptr v) 389 | { 390 | std::shared_ptr p; 391 | double max = -1.0; 392 | for (int i = 0; i < v->child.size(); i++) 393 | { 394 | if (v->child[i]->quality - max > 0.0) 395 | { 396 | max = v->child[i]->quality; 397 | p = v->child[i]; 398 | } 399 | } 400 | return p; 401 | } 402 | 403 | //拓展 404 | std::shared_ptr Expand(std::shared_ptr v) 405 | { 406 | std::vector posChess[2]; 407 | bool flag; 408 | for (int i = 0; i < v->posStep->size(); i++) 409 | { 410 | flag = false; 411 | for (int j = 0; j < v->child.size(); j++) 412 | { 413 | if (v->child[j]->chess[0] == v->posStep[0][i] && v->child[j]->chess[1] == v->posStep[1][i]) 414 | { 415 | flag = true; 416 | break; 417 | } 418 | } 419 | if (!flag) 420 | { 421 | posChess[0].push_back(v->posStep[0][i]); 422 | posChess[1].push_back(v->posStep[1][i]); 423 | } 424 | } 425 | int index = rand() % posChess[0].size(); 426 | int newBoard[5][5]; 427 | for (int i = 0; i < 5; i++) 428 | for (int j = 0; j < 5; j++) 429 | newBoard[i][j] = v->board[i][j]; 430 | oneMove(v, newBoard, posChess[0][index], posChess[1][index]); 431 | int pos[2]; 432 | pos[0] = posChess[0][index]; 433 | pos[1] = posChess[1][index]; 434 | std::shared_ptr newChild(new Board(v, !(bool)v->color, newBoard, pos)); 435 | v->child.push_back(newChild); 436 | return newChild; 437 | } 438 | 439 | void oneMove(std::shared_ptr v, int newboard[5][5], int chess, int direction) 440 | { 441 | int x, y; 442 | if (v->color == 0) 443 | { 444 | for (int i = 0; i < 5; i++) 445 | for (int j = 0; j < 5; j++) 446 | if (newboard[i][j] == chess) 447 | { 448 | x = i; 449 | y = j; 450 | //break; 451 | } 452 | if (direction == 0) 453 | { 454 | newboard[x][y + 1] = chess; 455 | newboard[x][y] = 0; 456 | } 457 | else if (direction == 1) 458 | { 459 | newboard[x + 1][y] = chess; 460 | newboard[x][y] = 0; 461 | } 462 | else 463 | { 464 | newboard[x + 1][y + 1] = chess; 465 | newboard[x][y] = 0; 466 | } 467 | } 468 | else 469 | { 470 | for (int i = 0; i < 5; i++) 471 | for (int j = 0; j < 5; j++) 472 | if (newboard[i][j] == chess + 6) 473 | { 474 | x = i; 475 | y = j; 476 | //break; 477 | } 478 | if (direction == 0) 479 | { 480 | newboard[x][y - 1] = chess + 6; 481 | newboard[x][y] = 0; 482 | } 483 | else if (direction == 1) 484 | { 485 | newboard[x - 1][y] = chess + 6; 486 | newboard[x][y] = 0; 487 | } 488 | else 489 | { 490 | newboard[x - 1][y - 1] = chess + 6; 491 | newboard[x][y] = 0; 492 | } 493 | } 494 | } 495 | 496 | //搜索策略 497 | //判断是否为终止节点 498 | bool is_Terminal(std::shared_ptr v) 499 | { 500 | int blue, red; 501 | blue = red = 0; 502 | for (int i = 0; i < 5; i++) 503 | for (int j = 0; j < 5; j++) 504 | { 505 | if (v->board[i][j] >= 1 && v->board[i][j] <= 6) 506 | red++; 507 | else if (v->board[i][j] >= 7) 508 | blue++; 509 | } 510 | if (red == 0 || blue == 0 || v->board[0][0] >= 7 || (v->board[4][4] >= 1 && v->board[4][4] <= 6)) 511 | return true; 512 | else 513 | return false; 514 | } 515 | 516 | bool is_Expanded(std::shared_ptr v) 517 | { 518 | if (v->posStep[0].size() > v->child.size()) 519 | return false; 520 | else 521 | return true; 522 | } 523 | 524 | std::shared_ptr Treepolicy(std::shared_ptr v) 525 | { 526 | while (!is_Terminal(v)) 527 | { 528 | if (!is_Expanded(v)) 529 | return Expand(v); 530 | else 531 | v = BestChild(v, coe); 532 | } 533 | return v; 534 | } 535 | 536 | //模拟函数 537 | bool RandomMove(std::shared_ptr v, bool col) 538 | { 539 | int ch[7] = { 0 }; 540 | int x, y; 541 | srand((unsigned int)clock()); 542 | int DICE = rand() % 6 + 1; 543 | if (col == 0) 544 | { 545 | for (int i = 0; i < 5; i++) 546 | for (int j = 0; j < 5; j++) 547 | { 548 | int temp = v->board[i][j]; 549 | if (temp >= 1 && temp <= 6) 550 | ch[temp]++; 551 | } 552 | if (ch[DICE] == 1) 553 | { 554 | for (int i = 0; i < 5; i++) 555 | for (int j = 0; j < 5; j++) 556 | if (v->board[i][j] == DICE) 557 | { 558 | x = i; 559 | y = j; 560 | break; 561 | } 562 | if (x == 4) 563 | { 564 | v->board[x][y + 1] = DICE; 565 | v->board[x][y] = 0; 566 | } 567 | else if (y == 4) 568 | { 569 | v->board[x + 1][y] = DICE; 570 | v->board[x][y] = 0; 571 | } 572 | else 573 | { 574 | srand((unsigned int)clock()); 575 | int direct = rand() % 3; 576 | if (direct == 0) 577 | { 578 | v->board[x][y + 1] = DICE; 579 | v->board[x][y] = 0; 580 | } 581 | else if (direct == 1) 582 | { 583 | v->board[x + 1][y] = DICE; 584 | v->board[x][y] = 0; 585 | } 586 | else 587 | { 588 | v->board[x + 1][y + 1] = DICE; 589 | v->board[x][y] = 0; 590 | } 591 | } 592 | } 593 | else 594 | { 595 | int cand_1, cand_2; 596 | cand_1 = cand_2 = 9; 597 | for (int i = DICE - 1; i > 0; i--) 598 | { 599 | if (ch[i] == 1) 600 | { 601 | cand_1 = i; 602 | break; 603 | } 604 | } 605 | for (int i = DICE + 1; i < 7; i++) 606 | { 607 | if (ch[i] == 1) 608 | { 609 | cand_2 = i; 610 | break; 611 | } 612 | } 613 | int choice; 614 | if (cand_1 != 9 && cand_2 != 9) 615 | { 616 | srand((unsigned int)clock()); 617 | int cand = rand() % 2; 618 | if (cand == 0) 619 | choice = cand_1; 620 | else 621 | choice = cand_2; 622 | } 623 | else if (cand_1 == 9) 624 | choice = cand_2; 625 | else if (cand_2 == 9) 626 | choice = cand_1; 627 | for (int i = 0; i < 5; i++) 628 | for (int j = 0; j < 5; j++) 629 | if (v->board[i][j] == choice) 630 | { 631 | x = i; 632 | y = j; 633 | break; 634 | } 635 | if (x == 4) 636 | { 637 | v->board[x][y + 1] = choice; 638 | v->board[x][y] = 0; 639 | } 640 | else if (y == 4) 641 | { 642 | v->board[x + 1][y] = choice; 643 | v->board[x][y] = 0; 644 | } 645 | else 646 | { 647 | srand((unsigned int)clock()); 648 | int direct = rand() % 3; 649 | if (direct == 0) 650 | { 651 | v->board[x][y + 1] = choice; 652 | v->board[x][y] = 0; 653 | } 654 | else if (direct == 1) 655 | { 656 | v->board[x + 1][y] = choice; 657 | v->board[x][y] = 0; 658 | } 659 | else 660 | { 661 | v->board[x + 1][y + 1] = choice; 662 | v->board[x][y] = 0; 663 | } 664 | } 665 | } 666 | } 667 | else 668 | { 669 | for (int i = 0; i < 5; i++) 670 | for (int j = 0; j < 5; j++) 671 | { 672 | int temp = v->board[i][j]; 673 | if (temp >= 7) 674 | ch[temp - 6]++; 675 | } 676 | if (ch[DICE] == 1) 677 | { 678 | for (int i = 0; i < 5; i++) 679 | for (int j = 0; j < 5; j++) 680 | if (v->board[i][j] == DICE + 6) 681 | { 682 | x = i; 683 | y = j; 684 | break; 685 | } 686 | if (x == 0) 687 | { 688 | v->board[x][y - 1] = DICE + 6; 689 | v->board[x][y] = 0; 690 | } 691 | else if (y == 0) 692 | { 693 | v->board[x - 1][y] = DICE + 6; 694 | v->board[x][y] = 0; 695 | } 696 | else 697 | { 698 | srand((unsigned int)clock()); 699 | int direct = rand() % 3; 700 | if (direct == 0) 701 | { 702 | v->board[x][y - 1] = DICE + 6; 703 | v->board[x][y] = 0; 704 | } 705 | else if (direct == 1) 706 | { 707 | v->board[x - 1][y] = DICE + 6; 708 | v->board[x][y] = 0; 709 | } 710 | else 711 | { 712 | v->board[x - 1][y - 1] = DICE + 6; 713 | v->board[x][y] = 0; 714 | } 715 | } 716 | } 717 | else 718 | { 719 | int cand_1, cand_2; 720 | cand_1 = cand_2 = 19; 721 | for (int i = DICE - 1; i > 0; i--) 722 | { 723 | if (ch[i] == 1) 724 | { 725 | cand_1 = i + 6; 726 | break; 727 | } 728 | } 729 | for (int i = DICE + 1; i < 7; i++) 730 | { 731 | if (ch[i] == 1) 732 | { 733 | cand_2 = i + 6; 734 | break; 735 | } 736 | } 737 | int choice; 738 | if (cand_1 != 19 && cand_2 != 19) 739 | { 740 | srand((unsigned int)clock()); 741 | int cand = rand() % 2; 742 | if (cand == 0) 743 | choice = cand_1; 744 | else 745 | choice = cand_2; 746 | } 747 | else if (cand_1 == 19) 748 | choice = cand_2; 749 | else if (cand_2 == 19) 750 | choice = cand_1; 751 | for (int i = 0; i < 5; i++) 752 | for (int j = 0; j < 5; j++) 753 | if (v->board[i][j] == choice) 754 | { 755 | x = i; 756 | y = j; 757 | break; 758 | } 759 | if (x == 0) 760 | { 761 | v->board[x][y - 1] = choice; 762 | v->board[x][y] = 0; 763 | } 764 | else if (y == 0) 765 | { 766 | v->board[x - 1][y] = choice; 767 | v->board[x][y] = 0; 768 | } 769 | else 770 | { 771 | srand((unsigned int)clock()); 772 | int direct = rand() % 3; 773 | if (direct == 0) 774 | { 775 | v->board[x][y - 1] = choice; 776 | v->board[x][y] = 0; 777 | } 778 | else if (direct == 1) 779 | { 780 | v->board[x - 1][y] = choice; 781 | v->board[x][y] = 0; 782 | } 783 | else 784 | { 785 | v->board[x - 1][y - 1] = choice; 786 | v->board[x][y] = 0; 787 | } 788 | } 789 | } 790 | } 791 | return !col; 792 | } 793 | 794 | int simulate(std::shared_ptr v) 795 | { 796 | int origin[5][5]; 797 | for (int i = 0; i < 5; i++) 798 | for (int j = 0; j < 5; j++) 799 | origin[i][j] = v->board[i][j]; 800 | bool tempColor = v->color; 801 | while (!is_Terminal(v)) 802 | { 803 | tempColor = RandomMove(v, tempColor); 804 | } 805 | //返回模拟结果 806 | int result; 807 | int blue, red; 808 | blue = red = 0; 809 | for (int i = 0; i < 5; i++) 810 | for (int j = 0; j < 5; j++) 811 | { 812 | if (v->board[i][j] >= 1 && v->board[i][j] <= 6) 813 | red++; 814 | else if (v->board[i][j] >= 7) 815 | blue++; 816 | } 817 | if (blue == 0 || (v->board[4][4] >= 1 && v->board[4][4] <= 6)) 818 | result = 0; 819 | else 820 | result = 1; 821 | for (int i = 0; i < 5; i++) 822 | for (int j = 0; j < 5; j++) 823 | v->board[i][j] = origin[i][j]; 824 | return result; 825 | } 826 | 827 | void Backup(std::shared_ptr v, int result) 828 | { 829 | while (v) 830 | { 831 | v->visit_times++; //到底是谁的visit次数? 832 | if ((v->color ^ result)) 833 | v->win_time++; 834 | v->quality = double(v->win_time) / double(v->visit_times); //到底是谁的visit次数? 835 | v = v->parent; 836 | } 837 | } 838 | 839 | 840 | void DeleteAll(std::shared_ptr v) 841 | { 842 | for (int i = 0; i < v->child.size(); i++) 843 | { 844 | DeleteAll(v->child[i]); 845 | } 846 | std::vector>().swap(v->child); 847 | } 848 | 849 | std::shared_ptr UCT(int dice, int board[5][5]) 850 | { 851 | std::shared_ptr root; 852 | std::shared_ptr none; 853 | if (dice <= 6) 854 | root=std::make_shared(none, 0, board, dice); 855 | else 856 | root = std::make_shared(none, 1, board, dice); 857 | time_t begin = clock(); 858 | time_t end = clock(); 859 | while (double(end - begin)/CLOCKS_PER_SEC < 5) 860 | { 861 | std::shared_ptr p; 862 | p = Treepolicy(root); 863 | int result = simulate(p); 864 | Backup(p, result); 865 | end = clock(); 866 | } 867 | std::shared_ptr best; 868 | best = MostWin(root); 869 | return best; 870 | } 871 | 872 | int Einstein::handle() 873 | { 874 | int t = clientsocket.recvMsg(); 875 | if (t == 0) 876 | { 877 | char* a = clientsocket.getRecvMsg(); 878 | std::string rec = a; 879 | parse(rec); 880 | int board[5][5]; 881 | for (int i = 0; i < 5; i++) 882 | for (int j = 0; j < 5; j++) 883 | board[i][j] = chessboard[i * 5 + j]; 884 | //std::string str = fool(dice, board); 885 | std::shared_ptr best; 886 | best = UCT(dice, board); 887 | std::string str; 888 | if (dice <= 6) 889 | { 890 | if (best->chess[1] == 0) 891 | str = std::to_string(best->chess[0]) + "|right"; 892 | else if (best->chess[1] == 1) 893 | str = std::to_string(best->chess[0]) + "|down"; 894 | else if (best->chess[1] == 2) 895 | str = std::to_string(best->chess[0]) + "|rightdown"; 896 | } 897 | else 898 | { 899 | if (best->chess[1] == 0) 900 | str = std::to_string(best->chess[0] + 6) + "|left"; 901 | else if (best->chess[1] == 1) 902 | str = std::to_string(best->chess[0] + 6) + "|up"; 903 | else if (best->chess[1] == 2) 904 | str = std::to_string(best->chess[0] + 6) + "|leftup"; 905 | } 906 | now_time = time(NULL); 907 | clientsocket.sendMsg(str.c_str()); 908 | std::string m = rec + " operation " + str; 909 | pt = localtime(&now_time); 910 | std::string log = std::to_string(pt->tm_year + 1900) + "-" + std::to_string(pt->tm_mon + 1) + "-" + std::to_string(pt->tm_mday) + " " + std::to_string(pt->tm_hour) + "-" + std::to_string(pt->tm_min) + "-" + std::to_string(pt->tm_sec) + " : " + m; 911 | logging(log); 912 | std::cout << best->quality * 100.0 << "%" << std::endl << std::endl; 913 | DeleteAll(best->parent); 914 | return 1; 915 | } 916 | else 917 | { 918 | std::string g = logger.back(); 919 | int last[25]; 920 | int f = g.find("[[", 0); 921 | int k = g.find("], [", f + 2); 922 | int l = g.find("], [", k + 4); 923 | int m = g.find("], [", l + 4); 924 | int n = g.find("], [", m + 4); 925 | int p = g.find("]]|", n + 4); 926 | to_int(g, f + 2, k, last, 0); 927 | to_int(g, k + 4, l, last, 1); 928 | to_int(g, l + 4, m, last, 2); 929 | to_int(g, m + 4, n, last, 3); 930 | to_int(g, n + 4, p, last, 4); 931 | int diff = 0; 932 | for (int i = 0; i < 25; i++) 933 | if (chessboard[i] != last[i]) 934 | diff++; 935 | if (diff <= 4) 936 | return 0; 937 | else 938 | { 939 | int ze = g.rfind(" "); 940 | int pr = g.rfind("|"); 941 | int chess = std::stoi(g.substr(ze + 1, pr - ze - 1)); 942 | std::string operation = g.substr(pr + 1, g.length() - pr - 1); 943 | int t = 0; 944 | while (last[t] != chess) 945 | t++; 946 | if (operation == "up") 947 | { 948 | last[t - 5] = chess; 949 | last[t] = 0; 950 | } 951 | else if (operation == "left") 952 | { 953 | last[t - 1] = chess; 954 | last[t] = 0; 955 | } 956 | else if (operation == "leftup") 957 | { 958 | last[t - 6] = chess; 959 | last[t] = 0; 960 | } 961 | else if (operation == "down") 962 | { 963 | last[t + 5] = chess; 964 | last[t] = 0; 965 | } 966 | else if (operation == "right") 967 | { 968 | last[t + 1] = chess; 969 | last[t] = 0; 970 | } 971 | else 972 | { 973 | last[t + 6] = chess; 974 | last[t] = 0; 975 | } 976 | end_time = clock(); 977 | double lasting = difftime(end_time, begin_time) / (double)CLOCKS_PER_SEC; 978 | if (chess >= 7) 979 | { 980 | int red = 0; 981 | for (int i = 0; i < 25; i++) 982 | if (last[i] >= 1 && last[i] <= 6) 983 | red++; 984 | if (red == 0 || last[0] == chess) 985 | { 986 | logging("Game over! Blue wins! Time: " + std::to_string(lasting) + "s"); 987 | return 0; 988 | } 989 | else 990 | { 991 | logging("Game over! Red wins! Time: " + std::to_string(lasting) + "s"); 992 | return 0; 993 | } 994 | } 995 | else 996 | { 997 | int blue = 0; 998 | for (int i = 0; i < 25; i++) 999 | if (last[i] >= 7 && last[i] <= 12) 1000 | blue++; 1001 | if (blue == 0 || last[24] == chess) 1002 | { 1003 | logging("Game over! Red wins! Time: " + std::to_string(lasting) + "s"); 1004 | return 0; 1005 | } 1006 | else 1007 | { 1008 | logging("Game over! Blue wins! Time: " + std::to_string(lasting) + "s"); 1009 | return 0; 1010 | } 1011 | } 1012 | } 1013 | return 0; 1014 | } 1015 | } 1016 | 1017 | int Einstein::logging(std::string s) 1018 | { 1019 | logger.push_back(s); 1020 | std::cout << s << std::endl; 1021 | return 0; 1022 | } 1023 | 1024 | int Einstein::writelog() 1025 | { 1026 | std::ofstream fout; 1027 | filename = std::to_string(pt->tm_year + 1900) + "-" + std::to_string(pt->tm_mon + 1) + "-" + std::to_string(pt->tm_mday) + "-181860013.log"; 1028 | fout.open(filename); 1029 | std::list::iterator itor; 1030 | itor = logger.begin(); 1031 | while (itor != logger.end()) 1032 | fout << *itor++ << std::endl; 1033 | return 0; 1034 | } 1035 | 1036 | std::string fool(int dice, int board[5][5]) 1037 | { 1038 | int chess[7] = { 0 }; 1039 | if (dice <= 6) 1040 | { 1041 | for (int i = 0; i < 5; i++) 1042 | for (int j = 0; j < 5; j++) 1043 | if (board[i][j] >= 1 && board[i][j] <= 6) 1044 | chess[board[i][j]]++; 1045 | int x, y; 1046 | if (chess[dice] == 1) 1047 | { 1048 | for (int i = 0; i < 5; i++) 1049 | for (int j = 0; j < 5; j++) 1050 | if (board[i][j] == dice) 1051 | { 1052 | x = i; 1053 | y = j; 1054 | } 1055 | } 1056 | else 1057 | { 1058 | //从中间向两边找 1059 | int x1, x2, y1, y2; 1060 | x1 = x2 = y1 = y2 = 9; 1061 | for (int k = dice - 1; k > 0; k--) 1062 | if (chess[k] == 1) 1063 | { 1064 | for (int i = 0; i < 5; i++) 1065 | for (int j = 0; j < 5; j++) 1066 | if (board[i][j] == k) 1067 | { 1068 | x1 = i; 1069 | y1 = j; 1070 | } 1071 | break; 1072 | } 1073 | for (int k = dice + 1; k < 7; k++) 1074 | if (chess[k] == 1) 1075 | { 1076 | for (int i = 0; i < 5; i++) 1077 | for (int j = 0; j < 5; j++) 1078 | if (board[i][j] == k) 1079 | { 1080 | x2 = i; 1081 | y2 = j; 1082 | } 1083 | break; 1084 | } 1085 | if ((4 - x1) * (4 - x1) + (4 - y1) * (4 - y1) > (4 - x2) * (4 - x2) + (4 - y2) * (4 - y2)) 1086 | { 1087 | x = x2; 1088 | y = y2; 1089 | } 1090 | else 1091 | { 1092 | x = x1; 1093 | y = y1; 1094 | } 1095 | } 1096 | if (x == 4) 1097 | { 1098 | std::string a = std::to_string(board[x][y]) + "|right"; 1099 | return a; 1100 | } 1101 | else if (y == 4) 1102 | { 1103 | std::string a = std::to_string(board[x][y]) + "|down"; 1104 | return a; 1105 | } 1106 | else 1107 | { 1108 | std::string a = std::to_string(board[x][y]) + "|rightdown"; 1109 | return a; 1110 | } 1111 | } 1112 | else 1113 | { 1114 | for (int i = 0; i < 5; i++) 1115 | for (int j = 0; j < 5; j++) 1116 | if (board[i][j] >= 7 && board[i][j] <= 12) 1117 | chess[board[i][j] - 6]++; 1118 | int x, y; 1119 | if (chess[dice - 6] == 1) 1120 | { 1121 | for (int i = 0; i < 5; i++) 1122 | for (int j = 0; j < 5; j++) 1123 | if (board[i][j] == dice) 1124 | { 1125 | x = i; 1126 | y = j; 1127 | } 1128 | } 1129 | else 1130 | { 1131 | //从中间向两边找 1132 | int x1, x2, y1, y2; 1133 | x1 = x2 = y1 = y2 = 9; 1134 | for (int k = dice - 6 - 1; k > 0; k--) 1135 | if (chess[k] == 1) 1136 | { 1137 | for (int i = 0; i < 5; i++) 1138 | for (int j = 0; j < 5; j++) 1139 | if (board[i][j] == k + 6) 1140 | { 1141 | x1 = i; 1142 | y1 = j; 1143 | } 1144 | break; 1145 | } 1146 | for (int k = dice - 6 + 1; k < 7; k++) 1147 | if (chess[k] == 1) 1148 | { 1149 | for (int i = 0; i < 5; i++) 1150 | for (int j = 0; j < 5; j++) 1151 | if (board[i][j] == k + 6) 1152 | { 1153 | x2 = i; 1154 | y2 = j; 1155 | } 1156 | break; 1157 | } 1158 | if (x1 * x1 + y1 * y1 > x2 * x2 + y2 * y2) 1159 | { 1160 | x = x2; 1161 | y = y2; 1162 | } 1163 | else 1164 | { 1165 | x = x1; 1166 | y = y1; 1167 | } 1168 | } 1169 | if (x == 0) 1170 | { 1171 | std::string a = std::to_string(board[x][y]) + "|left"; 1172 | return a; 1173 | } 1174 | else if (y == 0) 1175 | { 1176 | std::string a = std::to_string(board[x][y]) + "|up"; 1177 | return a; 1178 | } 1179 | else 1180 | { 1181 | std::string a = std::to_string(board[x][y]) + "|leftup"; 1182 | return a; 1183 | } 1184 | } 1185 | } 1186 | -------------------------------------------------------------------------------- /Einstein.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ClientSocket.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Einstein 10 | { 11 | private: 12 | ClientSocket clientsocket; 13 | std::list logger; 14 | std::string filename; // log filename 15 | int chessboard[25]; 16 | int dice; 17 | 18 | public: 19 | Einstein(); 20 | ~Einstein(); 21 | int parse(std::string s); 22 | int handle(); 23 | int logging(std::string s); 24 | int writelog(); 25 | }; 26 | -------------------------------------------------------------------------------- /EinsteinChessTestServer/TestServer.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import os 3 | import sys 4 | import random 5 | import copy 6 | import socket 7 | import logging 8 | from pygame.locals import * 9 | from sys import exit 10 | from time import ctime, sleep 11 | WINDOWSIZE = (1400, 680) # 游戏窗口大小 12 | LINECOLOR = (0, 0, 0) # 棋盘线的颜色 13 | TEXTCOLOR = (0, 0, 0) # 标题文本颜色 14 | BLACKGROUND = (255, 255, 255) # 游戏背景颜色 15 | BLACK = (0, 0, 0) 16 | BLUE = (0, 191, 255) 17 | YELLOW = (255, 255, 0) 18 | RED = (255, 0, 0) 19 | GREEN = (0, 255, 0) 20 | WHITE = (255, 255, 255) 21 | SIZE = (50, 50) # 棋子大小 22 | AYSTSIZE = (240, 240) # 爱因斯坦背景头像图片大小 23 | POSAYST = (365, 0) # 爱因斯坦头像位置 24 | STEP = 60 # 步长:棋子走一步移动的距离 25 | TEXTSIZE = 30 # 标题文字大小 26 | TIPSIZE = 15 # 提示文字大小 27 | COUNT = -1 # 记录当前回合 28 | START = 65 # 棋盘左上角起始点(70,70) 29 | REDWIN = 1 # 代表RED方赢 30 | BLUEWIN = 2 # 代表玩家BLUE方赢 31 | LEFT = 'left' 32 | RIGHT = 'right' 33 | UP = 'up' 34 | DOWN = 'down' 35 | LEFTUP = 'leftup' 36 | RIGHTDOWN = 'rightdown' 37 | ID = 'ID' 38 | RESULT = [0, 0] # 记录比赛结果 39 | WINSIZE = (530, 130) # 显示比赛结果窗口大小 40 | INFTY = 10000 41 | SLEEPTIME = 0 42 | logging.basicConfig(level=logging.INFO, format='%(asctime)s %(name)s- %(levelname)s - %(message)s', filename='TestServer.log') 43 | logger = logging.getLogger() 44 | ch = logging.StreamHandler() #日志输出到屏幕控制台 45 | ch.setLevel(logging.INFO) #设置日志等级 46 | formatter = logging.Formatter('%(asctime)s %(name)s- %(levelname)s - %(message)s') #定义日志输出格式 47 | ch.setFormatter(formatter) #选择一个格式 48 | logger.addHandler(ch) #增加指定的handler 49 | 50 | 51 | class Status(object): 52 | def __init__(self): 53 | self.map = None 54 | self.value = None 55 | self.pawn = None 56 | self.pro = None 57 | self.parent = None 58 | self.pPawn = None 59 | self.pMove = None 60 | self.pDice = None 61 | self.cPawn = None 62 | self.cPawnSecond = None 63 | self.cPM = [[],[],[],[],[],[]] 64 | self.cPMSecond = [[],[],[],[],[],[]] 65 | def print(self): 66 | print(self.cPM) 67 | def init(): 68 | global IMAGE,tip,screen,font,maplib,Lyr,Lyb,Lx,S,matchPro 69 | pygame.init() 70 | S = Status() 71 | screen = pygame.display.set_mode(WINDOWSIZE, 0, 32) # 设置游戏窗口 72 | pygame.display.set_caption('EinStein wurfelt nicht') # 设置Caption 73 | font = pygame.font.SysFont("Cambria Math", TEXTSIZE, 74 | bold=False, italic=False) # 设置标题字体格式 75 | tip = pygame.font.SysFont("arial", TIPSIZE, bold=False, italic=False) # 设置提示字体 76 | IMAGE = { 77 | 'R1': pygame.transform.scale(pygame.image.load('picture/white/R1.png').convert(), SIZE), 78 | 'R2': pygame.transform.scale(pygame.image.load('picture/white/R2.png').convert(), SIZE), 79 | 'R3': pygame.transform.scale(pygame.image.load('picture/white/R3.png').convert(), SIZE), 80 | 'R4': pygame.transform.scale(pygame.image.load('picture/white/R4.png').convert(), SIZE), 81 | 'R5': pygame.transform.scale(pygame.image.load('picture/white/R5.png').convert(), SIZE), 82 | 'R6': pygame.transform.scale(pygame.image.load('picture/white/R6.png').convert(), SIZE), 83 | 'B1': pygame.transform.scale(pygame.image.load('picture/white/B1.png').convert(), SIZE), 84 | 'B2': pygame.transform.scale(pygame.image.load('picture/white/B2.png').convert(), SIZE), 85 | 'B3': pygame.transform.scale(pygame.image.load('picture/white/B3.png').convert(), SIZE), 86 | 'B4': pygame.transform.scale(pygame.image.load('picture/white/B4.png').convert(), SIZE), 87 | 'B5': pygame.transform.scale(pygame.image.load('picture/white/B5.png').convert(), SIZE), 88 | 'B6': pygame.transform.scale(pygame.image.load('picture/white/B6.png').convert(), SIZE), 89 | 'Y1': pygame.transform.scale(pygame.image.load('picture/white/Y1.png').convert(), SIZE), 90 | 'Y2': pygame.transform.scale(pygame.image.load('picture/white/Y2.png').convert(), SIZE), 91 | 'Y3': pygame.transform.scale(pygame.image.load('picture/white/Y3.png').convert(), SIZE), 92 | 'Y4': pygame.transform.scale(pygame.image.load('picture/white/Y4.png').convert(), SIZE), 93 | 'Y5': pygame.transform.scale(pygame.image.load('picture/white/Y5.png').convert(), SIZE), 94 | 'Y6': pygame.transform.scale(pygame.image.load('picture/white/Y6.png').convert(), SIZE), 95 | '1': pygame.transform.scale(pygame.image.load('picture/white/1.png').convert(), SIZE), 96 | '2': pygame.transform.scale(pygame.image.load('picture/white/2.png').convert(), SIZE), 97 | '3': pygame.transform.scale(pygame.image.load('picture/white/3.png').convert(), SIZE), 98 | '4': pygame.transform.scale(pygame.image.load('picture/white/4.png').convert(), SIZE), 99 | '5': pygame.transform.scale(pygame.image.load('picture/white/5.png').convert(), SIZE), 100 | '6': pygame.transform.scale(pygame.image.load('picture/white/6.png').convert(), SIZE), 101 | 'BLUEWIN': pygame.transform.scale(pygame.image.load('picture/white/BLUEWIN.png').convert(), WINSIZE), 102 | 'REDWIN': pygame.transform.scale(pygame.image.load('picture/white/REDWIN.png').convert(), WINSIZE), 103 | } 104 | # 布局库 105 | maplib = [[6, 2, 4, 1, 5, 3], 106 | [6, 5, 2, 1, 4, 3], 107 | [1, 5, 4, 6, 2, 3], 108 | [1, 6, 3, 5, 2, 4], 109 | [1, 6, 4, 3, 2, 5], 110 | [6, 1, 2, 5, 4, 3], 111 | [6, 1, 3, 5, 4, 2], 112 | [1, 6, 4, 2, 3, 5], 113 | [1, 5, 2, 6, 3, 4], 114 | [1, 6, 5, 2, 3, 4], 115 | [1, 2, 5, 6, 3, 4], 116 | [6, 2, 5, 1, 4, 3], 117 | [1, 6, 3, 2, 4, 5], 118 | [6, 2, 3, 1, 5, 4], 119 | [1, 6, 3, 4, 2, 5], 120 | [1, 5, 4, 6, 3, 2] 121 | ] 122 | resetInfo() 123 | Lyr = [] 124 | Lyb = [] 125 | Lx = [] 126 | matchPro = 0.85 127 | 128 | 129 | def loadImage(name, pos, size=SIZE): 130 | filename = "picture/white/" + name 131 | screen.blit(pygame.transform.scale( 132 | pygame.image.load(filename).convert(), size), pos) 133 | def waitForPlayerToPressKey(): # 等待按键 134 | while True: 135 | for event in pygame.event.get(): 136 | if event.type == QUIT: 137 | terminate() 138 | if event.type == KEYDOWN: 139 | if event.key == K_ESCAPE: 140 | terminate() 141 | return 142 | 143 | 144 | def drawStartScreen(): # 开始界面 145 | screen.fill(WHITE) 146 | loadImage("AYST.png", (190, 40), AYSTSIZE) 147 | drawText('127.0.0.1:50006 IS WAITING FOR CONNECTION', font, TEXTCOLOR, screen, 6.5, 2) 148 | pygame.display.update() 149 | 150 | 151 | # waitForPlayerToPressKey() 152 | def drawWinScreen(result): # 比赛结束,显示结果界面 153 | if result == BLUEWIN: 154 | loadImage("BLUEWIN.png", (50, 500), WINSIZE) 155 | if result == REDWIN: 156 | loadImage("REDWIN.png", (50, 500), WINSIZE) 157 | # waitForPlayerToPressKey() 158 | pygame.display.update() 159 | sleep(SLEEPTIME) 160 | 161 | def showWinRate(RedWinRate, BlueWinRate, x): 162 | global Lyr, Lyb, Lx 163 | yr = (100 - RedWinRate)/(100/3.0) + 0.6 164 | yb = (100 - BlueWinRate)/(100/3.0) + 0.6 165 | x = x/(1000/5) + 4.2 166 | Lyr.append(copy.deepcopy(yr)) 167 | Lyb.append(copy.deepcopy(yb)) 168 | Lx.append(copy.deepcopy(x)) 169 | for i in range(0, len(Lyr)-1): 170 | pygame.draw.line( 171 | screen, RED, (100*Lx[i], 100*Lyr[i]), (100*Lx[i], 100*Lyr[i+1])) 172 | pygame.draw.line( 173 | screen, BLUE, (100*Lx[i], 100*Lyb[i]), (100*Lx[i], 100*Lyb[i+1])) 174 | def drawGameScreen(Red, Blue): # 游戏比赛界面 175 | global S 176 | screen.fill(WHITE) 177 | # 画棋盘 178 | for i in range(6): 179 | x = y = 60*(i+1) 180 | pygame.draw.line(screen, LINECOLOR, (60, y), (360, y)) 181 | pygame.draw.line(screen, LINECOLOR, (x, 60), (x, 360)) 182 | # 加载提示文字 183 | drawText('Winning Percentage Dynamic Figure', font, BLACK, screen, 0, 7.2) 184 | drawText(Red + ' Vs ' + Blue, font, BLACK, screen, 0.5, 7.2) 185 | drawText('matchPro : '+ str(round(100*matchPro,4))+'%',font,BLACK,screen,1,7.2) 186 | 187 | 188 | # 胜率坐标轴 189 | pygame.draw.line(screen, LINECOLOR, (415, 55), (420, 50)) 190 | pygame.draw.line(screen, LINECOLOR, (425, 55), (420, 50)) 191 | pygame.draw.line(screen, LINECOLOR, (420, 360), (420, 50)) 192 | pygame.draw.line(screen, LINECOLOR, (420, 360), (1200, 360)) 193 | pygame.draw.line(screen, LINECOLOR, (1195, 355), (1200, 360)) 194 | pygame.draw.line(screen, LINECOLOR, (1195, 365), (1200, 360)) 195 | 196 | 197 | drawText('You can move: ', font, BLACK, screen, 0.1, 0.2) 198 | drawText('A : down', tip, BLACK, screen, 6, 1) 199 | drawText('W : right', tip, BLACK, screen, 6, 2.5) 200 | drawText('S : right-down', tip, BLACK, screen, 6, 4) 201 | drawText('U : up', tip, BLACK, screen, 6.5, 1) 202 | drawText('H : left', tip, BLACK, screen, 6.5, 2.5) 203 | drawText('Y : left-up', tip, BLACK, screen, 6.5, 4) 204 | drawText('RED : '+str(RESULT[0]), font, RED, screen, 6, 7) 205 | drawText('BLUE : '+str(RESULT[1]), font, BLUE, screen, 6.5, 7) 206 | drawText('RED : ' + Red, font,RED, screen, 7.5, 2) 207 | drawText('BLUE: ' + Blue, font,BLUE, screen, 8, 2) 208 | if(sum(RESULT)): 209 | RedWinRate = round(100*float(RESULT[0])/sum(RESULT), 2) 210 | BlueWinRate = round(100*float(RESULT[1])/sum(RESULT), 2) 211 | drawText('RedWinRate:'+str(round(100 * 212 | float(RESULT[0])/sum(RESULT), 2)), font, RED, screen, 6, 9.5) 213 | drawText('BlueWinRate:'+str(round(100 * 214 | float(RESULT[1])/sum(RESULT), 2)), font, BLUE, screen, 6.5, 9.5) 215 | x = sum(RESULT) 216 | showWinRate(RedWinRate, BlueWinRate, x) 217 | # 画棋子 218 | for i in range(5): 219 | for j in range(5): 220 | if S.map[i][j] != 0: 221 | drawPawn(S.map[i][j], i, j) 222 | 223 | pygame.display.update() 224 | 225 | def drawMovePawn(n, ans): # 可选择移动的棋子 226 | x = -1 227 | y = 2 228 | for v in ans: 229 | drawPawn(v, x, y) 230 | y += 1 231 | if n <= 6: 232 | loadImage(str(n)+'.png', (310, 5)) 233 | else: 234 | loadImage(str(n-6)+'.png', (310, 5)) 235 | pygame.display.update() 236 | 237 | 238 | def drawPawn(value, row, col, size=SIZE): # 在(row,col)处,画值为value的棋子 239 | pos_x = col * STEP + START 240 | pos_y = row * STEP + START 241 | Pos = (pos_x, pos_y) 242 | if value <= 6: 243 | s = 'R' + str(value) 244 | elif value > 6: 245 | s = 'B' + str(value-6) 246 | loadImage(s+'.png', Pos, size) 247 | 248 | def drawText(text, font, color, surface, row, col): # 处理需要描绘的文字:text:文本;font:格式; 249 | row += 0.2 250 | x = col * STEP 251 | y = row * STEP 252 | textobj = font.render(text, True, color, WHITE) 253 | textrect = textobj.get_rect() 254 | textrect.topleft = (x, y) 255 | surface.blit(textobj, textrect) 256 | 257 | 258 | def selectPawn(S,n=0): # 掷骰子,挑选可以移动的棋子 259 | global COUNT 260 | if n == 0: 261 | COUNT += 1 262 | if COUNT % 2 == 0: 263 | n = random.randint(1, 6) 264 | else: 265 | n = random.randint(7, 12) 266 | ans = findNearby(n, S.pawn) 267 | else: 268 | ans = findNearby(n, S.pawn) 269 | return n, ans 270 | 271 | 272 | def terminate(): # 退出游戏 273 | pygame.quit() 274 | sys.exit() 275 | 276 | 277 | def makeMove(p, PawnMoveTo): # 移动棋子,更新地图信息,和棋子存活情况 278 | row, col = getLocation(p, S.map) 279 | x = y = 0 280 | if PawnMoveTo == LEFT: 281 | y = -1 282 | elif PawnMoveTo == RIGHT: 283 | y = +1 284 | elif PawnMoveTo == UP: 285 | x = -1 286 | elif PawnMoveTo == DOWN: 287 | x = +1 288 | elif PawnMoveTo == LEFTUP: 289 | x = -1 290 | y = -1 291 | elif PawnMoveTo == RIGHTDOWN: 292 | x = +1 293 | y = +1 294 | else: 295 | return False 296 | # 移动无效 297 | if notInMap(row+x, col+y): 298 | return False 299 | S.map[row][col] = 0 300 | row = row + x 301 | col = col + y 302 | # 是否吃掉自己或对方的棋 303 | if S.map[row][col] != 0: 304 | i = S.pawn.index(S.map[row][col]) 305 | S.pawn[i] = 0 306 | S.map[row][col] = p 307 | return True 308 | def notInMap(x, y): # 检测棋子是否在棋盘内移动 309 | if x in range(0, 5) and y in range(0, 5): 310 | return False 311 | return True 312 | 313 | 314 | def showSelected(p): # 用红色标记,显示被挑选的棋子 315 | row, col = getLocation(p, S.map) 316 | pos_x = col * STEP + START 317 | pos_y = row * STEP + START 318 | Pos = (pos_x, pos_y) 319 | if p > 6: 320 | s = 'Y' + str(p-6) 321 | else: 322 | s = 'Y' + str(p) 323 | loadImage(s+'.png', Pos) 324 | pygame.display.update() 325 | 326 | 327 | def isEnd(S): # 检测比赛是否结束 328 | if S.map[0][0] > 6: 329 | return BLUEWIN 330 | elif S.map[4][4] > 0 and S.map[4][4] <= 6: 331 | return REDWIN 332 | cnt = 0 333 | for i in range(0, 6): 334 | if S.pawn[i] == 0: 335 | cnt += 1 336 | if cnt == 6: 337 | return BLUEWIN 338 | cnt = 0 339 | for i in range(6, 12): 340 | if S.pawn[i] == 0: 341 | cnt += 1 342 | if cnt == 6: 343 | return REDWIN 344 | return False 345 | 346 | 347 | def resetInfo(): # 重置比赛信息 348 | S.map = getNewMap() 349 | S.pawn = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] # 棋子初始化 350 | S.pro = [1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0 / 351 | 6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6] 352 | value = getLocValue(S) 353 | S.value = getPawnValue(S.pro, value) 354 | 355 | 356 | def getNewMap(): # 换新图 357 | r = random.sample(maplib, 1)[0] 358 | b = random.sample(maplib, 1)[0] 359 | newMap = [ 360 | [r[0], r[3], r[5], 0, 0], 361 | [r[1], r[4], 0, 0, 0], 362 | [r[2], 0, 0, 0, b[2]+6], 363 | [0, 0, 0, b[4]+6, b[1]+6], 364 | [0, 0, b[5]+6, b[3]+6, b[0]+6] 365 | ] 366 | return newMap 367 | 368 | 369 | def getLocValue(S): # 棋子所在位置的价值 370 | blueValue = [[99, 10, 6, 3, 1], 371 | [10, 8, 4, 2, 1], 372 | [6, 4, 4, 2, 1], 373 | [3, 2, 2, 2, 1], 374 | [1, 1, 1, 1, 1]] 375 | redValue = [[1, 1, 1, 1, 1], 376 | [1, 2, 2, 2, 3], 377 | [1, 2, 4, 4, 6], 378 | [1, 2, 4, 8, 10], 379 | [1, 3, 6, 10, 99]] 380 | V = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 381 | for p in range(1, 13): 382 | if S.pawn[p-1] != 0: 383 | row, col = getLocation(p, S.map) 384 | if p <= 6: 385 | V[p-1] = redValue[row][col] 386 | else: 387 | V[p-1] = blueValue[row][col] 388 | return V 389 | 390 | def getPawnValue(pro, value): # 棋子价值 391 | V = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 392 | for i in range(0, 12): 393 | V[i] = pro[i] * value[i] 394 | return V 395 | 396 | def searchNearbyBlueMaxValue(p, S): # 搜索附近蓝方最有价值的棋子 397 | nearby = [] 398 | row, col = getLocation(p, S.map) 399 | if row+1 < 5: 400 | if S.map[row+1][col] > 6: 401 | nearby.append(S.value[S.map[row+1][col]-1]) 402 | if col+1 < 5: 403 | if S.map[row][col+1] > 6: 404 | nearby.append(S.value[S.map[row][col+1]-1]) 405 | if row+1 < 5 and col+1 < 5: 406 | if S.map[row+1][col+1] > 6: 407 | nearby.append(S.value[S.map[row+1][col+1]-1]) 408 | if nearby == []: 409 | return 0 410 | 411 | expValue = 0 412 | for v in nearby: 413 | expValue += v/sum(nearby) 414 | return expValue 415 | 416 | def searchNearbyRedMaxValue(p, S): # 搜索附近红方最有价值的棋子 417 | nearby = [] 418 | row, col = getLocation(p, S.map) 419 | if row-1 >= 0: 420 | if S.map[row-1][col] <= 6 and S.map[row-1][col] > 0: 421 | nearby.append(S.value[S.map[row-1][col]-1]) 422 | if col-1 >= 0: 423 | if S.map[row][col-1] <= 6 and S.map[row][col-1] > 0: 424 | nearby.append(S.value[S.map[row][col-1]-1]) 425 | if row-1 >= 0 and col-1 >= 0: 426 | if S.map[row-1][col-1] <= 6 and S.map[row-1][col-1] > 0: 427 | nearby.append(S.value[S.map[row-1][col-1]-1]) 428 | if nearby == []: 429 | return 0 430 | expValue = 0 431 | for v in nearby: 432 | expValue += v/sum(nearby) 433 | return expValue 434 | 435 | def getThread(S): # 获得红方对蓝方的威胁值,蓝方对红方的威胁值 436 | redToBlueOfThread = 0 437 | blueToRedOfThread = 0 438 | for p in range(1, 13): 439 | if S.pawn[p-1] != 0: 440 | if p <= 6: 441 | nearbyBlueMaxValue = searchNearbyBlueMaxValue(p, S) 442 | redToBlueOfThread += S.pro[p-1] * nearbyBlueMaxValue 443 | else: 444 | nearbyRedMaxValue = searchNearbyRedMaxValue(p, S) 445 | blueToRedOfThread += S.pro[p-1] * nearbyRedMaxValue 446 | return redToBlueOfThread, blueToRedOfThread 447 | 448 | def findNearby(n, nowPawn): # 寻找可以移动的棋子 449 | ans = [] 450 | # 如果有对应棋子 451 | if nowPawn[n-1] != 0: 452 | ans.append(n) 453 | #没有对应棋子 454 | elif n > 6: 455 | for i in range(n-1, 6, -1): 456 | if i in nowPawn: 457 | ans.append(i) 458 | break 459 | for i in range(n+1, 13): 460 | if i in nowPawn: 461 | ans.append(i) 462 | break 463 | elif n <= 6: 464 | for i in range(n-1, 0, -1): 465 | if i in nowPawn: 466 | ans.append(i) 467 | break 468 | for i in range(n+1, 7): 469 | if i in nowPawn: 470 | ans.append(i) 471 | break 472 | return ans 473 | 474 | 475 | def getLocation(p, Map): # 返回传入地图下,棋子p的坐标 476 | for i in range(5): 477 | for j in range(5): 478 | if Map[i][j] == p: 479 | return i, j 480 | 481 | 482 | def tryMakeMove(p, PawnMoveTo, S): # 尝试移动,并且返回移动后的棋局地图与棋子存活情况 483 | newS = copy.deepcopy(S) 484 | row, col = getLocation(p, newS.map) 485 | x = y = 0 486 | if PawnMoveTo == LEFT: 487 | y = -1 488 | elif PawnMoveTo == RIGHT: 489 | y = +1 490 | elif PawnMoveTo == UP: 491 | x = -1 492 | elif PawnMoveTo == DOWN: 493 | x = +1 494 | elif PawnMoveTo == LEFTUP: 495 | x = -1 496 | y = -1 497 | elif PawnMoveTo == RIGHTDOWN: 498 | x = +1 499 | y = +1 500 | # 移动无效 501 | if notInMap(row+x, col+y): 502 | return False 503 | newS.map[row][col] = 0 504 | row = row + x 505 | col = col + y 506 | if newS.map[row][col] != 0: 507 | i = newS.pawn.index(newS.map[row][col]) 508 | newS.pawn[i] = 0 509 | newS.map[row][col] = p 510 | # value = getLocValue(newS) # 获取所有棋子的位置价值 511 | # newS.pro = getPawnPro(newS) # 获取所有棋子被摇到的概率 512 | # newS.value = getPawnValue(value, newS.pro) 513 | newS.parent = S 514 | newS.pPawn = p 515 | newS.pMove = PawnMoveTo 516 | if p < 7: 517 | newS.cPawn = [INFTY,INFTY,INFTY,INFTY,INFTY,INFTY] 518 | newS.cPawnSecond = [INFTY,INFTY,INFTY,INFTY,INFTY,INFTY] 519 | else: 520 | newS.cPawn = [-INFTY,-INFTY,-INFTY,-INFTY,-INFTY,-INFTY] 521 | newS.cPawnSecond = [-INFTY,-INFTY,-INFTY,-INFTY,-INFTY,-INFTY] 522 | return newS 523 | 524 | def decideBlueHowToMove(ans): 525 | p = 0 526 | while True: 527 | PawnMoveTo = None 528 | for event in pygame.event.get(): 529 | if event.type == QUIT: 530 | terminate() 531 | elif event.type == KEYDOWN: 532 | if len(ans) > 1: 533 | if event.key == K_1: 534 | p = 7 535 | elif event.key == K_2: 536 | p = 8 537 | elif event.key == K_3: 538 | p = 9 539 | elif event.key == K_4: 540 | p = 10 541 | elif event.key == K_5: 542 | p = 11 543 | elif event.key == K_6: 544 | p = 12 545 | else: 546 | p = ans[0] 547 | if p != 0: 548 | if p in ans: 549 | showSelected(p) 550 | if event.key == K_h: 551 | PawnMoveTo = LEFT 552 | elif event.key == K_u: 553 | PawnMoveTo = UP 554 | elif event.key == K_y: 555 | PawnMoveTo = LEFTUP 556 | if PawnMoveTo != None: 557 | newS = tryMakeMove(p, PawnMoveTo, S) 558 | if newS is not False: 559 | return p, PawnMoveTo 560 | def blueByBraveOfMan(ans): 561 | moveTo = ['leftup', 'up', 'left'] 562 | bestp = 0 563 | bestm = '' 564 | for p in ans: 565 | for m in moveTo: 566 | newS = tryMakeMove(p, m, S) 567 | if newS is not False: 568 | bestp = p 569 | bestm = m 570 | break 571 | return bestp, bestm 572 | def redByBraveOfMan(ans): 573 | moveTo = ['rightdown', 'down', 'right'] 574 | bestp = 0 575 | bestm = '' 576 | for p in ans: 577 | for m in moveTo: 578 | newS = tryMakeMove(p, m, S) 579 | if newS is not False: 580 | bestp = p 581 | bestm = m 582 | break 583 | return bestp, bestm 584 | def getScore(S, k=2.2, lam=5): 585 | redToBlueOfThread, blueToRedOfThread = getThread(S) 586 | expRed = expBlue = 0 587 | for i in range(0, 12): 588 | if i < 6: 589 | expRed += S.value[i] 590 | else: 591 | expBlue += S.value[i] 592 | theValue = lam * ( k * expRed - expBlue) - blueToRedOfThread + redToBlueOfThread 593 | return theValue 594 | def blueByDemo(ans, k=2.2, lam=5): 595 | maxValue = theValue = -INFTY 596 | bestp = 0 597 | bestm = '' 598 | move = ['left','up','leftup'] 599 | for p in ans: 600 | for m in move: 601 | newStatus = tryMakeMove(p,m,S) 602 | if newStatus is not False: 603 | theValue = getDemoValue(newStatus) 604 | if theValue > maxValue: 605 | maxValue,bestp,bestm = theValue,p,m 606 | return bestp,bestm 607 | def blueByDemo2(ans, k=2.2, lam=5): 608 | maxValue = theValue = -INFTY 609 | bestp = 0 610 | bestm = '' 611 | move = ['left','up','leftup'] 612 | for p in ans: 613 | for m in move: 614 | newStatus = tryMakeMove(p,m,S) 615 | if newStatus is not False: 616 | theValue = getDemoValue2(newStatus) 617 | if theValue > maxValue: 618 | maxValue,bestp,bestm = theValue,p,m 619 | return bestp,bestm 620 | def getDemoValue2(S,k=2.2,lam=5): 621 | move = ['right','down','rightdown'] 622 | exp = 0 623 | for p in range(1,7): 624 | if p in S.pawn: 625 | theValue = maxValue = -INFTY 626 | for m in move: 627 | newStatus = tryMakeMove(p,m,S) 628 | if newStatus is not False: 629 | theValue = getScore(newStatus) 630 | if theValue > maxValue: 631 | maxValue = theValue 632 | exp += S.pro[p-1] * maxValue 633 | return -exp 634 | def getDemoValue(S, k=2.2, lam=5): 635 | redToBlueOfThread, blueToRedOfThread = getThread(S) 636 | expRed = expBlue = 0 637 | for i in range(0, 12): 638 | if i < 6: 639 | expRed += S.value[i] 640 | else: 641 | expBlue += S.value[i] 642 | theValue = lam * ( k * expBlue - expRed) + blueToRedOfThread - redToBlueOfThread 643 | return theValue 644 | def redByMinimax(ans, k=2.2, lam=5, STEP=2): 645 | maxValue = theValue = -INFTY 646 | bestp = 0; 647 | bestm = ''; 648 | move = ['right','down','rightdown'] 649 | KL = [] 650 | SL = [] 651 | for p in ans: 652 | for m in move: 653 | newStatus = tryMakeMove(p,m,S); 654 | if newStatus is not False: 655 | SL.append(newStatus) 656 | if isEnd(newStatus): 657 | return p,m 658 | STEP -= 1 659 | if len(SL) == 1: 660 | bestp,bestm = SL[0].pPawn,SL[0].pMove 661 | else: 662 | KL.append(SL) 663 | for i in range(STEP): 664 | NL = getTheNextStepStatus(KL[-1]) 665 | KL.append(NL) 666 | KL = MinimaxGoBack(KL) 667 | for s in KL: 668 | theValue = getSum(s.cPawn) 669 | if theValue > maxValue: 670 | maxValue,bestp,bestm = theValue,s.pPawn,s.pMove 671 | return bestp,bestm 672 | def getTheNextStepStatus(SL): 673 | NL = [] 674 | if SL[0].pPawn > 6: 675 | move = ['right','down','rightdown'] 676 | o = 0 677 | else: 678 | move = ['left','up','leftup'] 679 | o = 6 680 | for s in SL: 681 | for i in range(1,7): 682 | n,ans = selectPawn(s,i+o) 683 | for p in ans: 684 | for m in move: 685 | newStatus = tryMakeMove(p,m,s); 686 | if newStatus is not False: 687 | newStatus.pDice = i 688 | NL.append(newStatus) 689 | return NL 690 | def getSum(L): 691 | value = 0 692 | for i in L: 693 | if i != INFTY and i != -INFTY: 694 | value += i 695 | return (1/6)*value 696 | def MinimaxGoBack(KL): 697 | for s in KL[-1]: 698 | score = getScore(s) 699 | if s.pPawn > 6: 700 | if score < s.parent.cPawn[(s.pDice%6)-1]: 701 | s.parent.cPawn[s.pDice%6 - 1] = score 702 | else: 703 | if score > s.parent.cPawn[s.pDice-1]: 704 | s.parent.cPawn[s.pDice-1] = score 705 | for i in range(len(KL)-2,0,-1): 706 | for s in KL[i]: 707 | score = getSum(s.cPawn) 708 | if s.pPawn > 6: 709 | if score < s.parent.cPawn[s.pDice%6-1]: 710 | s.parent.cPawn[s.pDice%6 -1] = score 711 | else: 712 | if score > s.parent.cPawn[s.pDice-1]: 713 | s.parent.cPawn[s.pDice-1] = score 714 | return KL[0] 715 | def BeyesGoBack(KL, rPro=1, bPro=1): 716 | for s in KL[-1]: 717 | score = getScore(s) 718 | if s.pPawn > 6: 719 | if score < s.parent.cPawn[(s.pDice%6)-1]: 720 | s.parent.cPawnSecond[s.pDice%6-1] = s.parent.cPawn[s.pDice%6 - 1] 721 | s.parent.cPawn[s.pDice%6 - 1] = score 722 | if len(KL) == 2: 723 | s.parent.cPMSecond[s.pDice%6 -1] = s.parent.cPM[(s.pDice%6) - 1] 724 | s.parent.cPM[(s.pDice%6) - 1] = [s.pPawn,s.pMove] 725 | else: 726 | if score > s.parent.cPawn[s.pDice-1]: 727 | s.parent.cPawn[s.pDice%6 - 1] = score 728 | if len(KL) == 2: 729 | s.parent.cPM[(s.pDice%6) - 1] = [s.pPawn,s.pMove] 730 | for s in KL[-2]: 731 | if s.pPawn > 6: 732 | break; 733 | for d in range(1,7): 734 | if abs(s.cPawnSecond[d-1]) != INFTY: 735 | if random.random() + bPro*0.90 < 1: 736 | s.cPawn[d-1] = s.cPawnSecond[d-1] 737 | s.cPM[d-1] = s.cPMSecond[d-1] 738 | for i in range(len(KL)-2,0,-1): 739 | for s in KL[i]: 740 | score = getSum(s.cPawn) 741 | if s.pPawn > 6: 742 | if score < s.parent.cPawn[(s.pDice%6)-1]: 743 | s.parent.cPawnSecond[s.pDice%6-1] = s.parent.cPawn[s.pDice%6 - 1] 744 | s.parent.cPawn[s.pDice%6 - 1] = score 745 | if i == 1: 746 | s.parent.cPMSecond[s.pDice%6 -1] = s.parent.cPM[(s.pDice%6) - 1] 747 | s.parent.cPM[(s.pDice%6) - 1] = [s.pPawn,s.pMove] 748 | else: 749 | if score > s.parent.cPawn[s.pDice-1]: 750 | s.parent.cPawnSecond[s.pDice%6-1] = s.parent.cPawn[s.pDice%6 - 1] 751 | s.parent.cPawn[s.pDice%6 - 1] = score 752 | if i == 1: 753 | s.parent.cPMSecond[s.pDice%6 -1] = s.parent.cPM[(s.pDice%6) - 1] 754 | s.parent.cPM[(s.pDice%6) - 1] = [s.pPawn,s.pMove] 755 | for s in KL[i]: 756 | if s.pPawn > 6: 757 | break; 758 | for d in range(1,7): 759 | if abs(s.cPawnSecond[d-1]) != INFTY: 760 | if random.random() + bPro*0.90 < 1: 761 | s.cPawn[d-1] = s.cPMSecond[d-1] 762 | s.cPM[d-1] = s.cPMSecond[d-1] 763 | return KL[0] 764 | def redByBeyes(ans, lastInfo, k=2.2, lam=5, STEP=2): 765 | global myGuess,matchPro 766 | if lastInfo != []: 767 | if check(lastInfo): 768 | matchPro = updatePro(matchPro,1) 769 | else: 770 | matchPro = updatePro(matchPro,0) 771 | #print(matchPro) 772 | maxValue = theValue = -INFTY 773 | bestp = 0; 774 | bestm = ''; 775 | move = ['right','down','rightdown'] 776 | KL = [] 777 | SL = [] 778 | for p in ans: 779 | for m in move: 780 | newStatus = tryMakeMove(p,m,S); 781 | if newStatus is not False: 782 | SL.append(newStatus) 783 | STEP -= 1 784 | if len(SL) == 1: 785 | bestp,bestm = SL[0].pPawn, SL[0].pMove 786 | else: 787 | KL.append(SL) 788 | for i in range(STEP): 789 | NL = getTheNextStepStatus(KL[-1]) 790 | KL.append(NL) 791 | KL = BeyesGoBack(KL, rPro=1, bPro=1) 792 | for s in KL: 793 | theValue = getSum(s.cPawn) 794 | if theValue > maxValue: 795 | maxValue,bestp,bestm = theValue,s.pPawn,s.pMove 796 | myGuess = s 797 | return bestp,bestm 798 | def check(lastInfo): 799 | n,p,m = lastInfo 800 | if myGuess.cPM[n%6-1] == []: 801 | return False 802 | if myGuess.cPM[n%6-1][0] == p and myGuess.cPM[n%6-1][1] == m: 803 | return True 804 | return False 805 | def updatePro(matchPro,flag): 806 | Pb = matchPro 807 | Pfb = 1-matchPro 808 | Pab = 0.90 809 | Pfab = 1-Pab 810 | Pafb = 0.55 811 | Pfafb = 1-Pafb 812 | if flag: 813 | Pa = Pab * Pb + Pafb * Pfb 814 | Pb = (Pab * Pb)/Pa 815 | else: 816 | Pfa = Pfab * Pb + Pfafb * Pfb 817 | Pb = (Pfab * Pb)/Pfa 818 | Pb = min(0.9645,max(Pb,0.6555)) 819 | return Pb 820 | 821 | 822 | def decideRedHowToMove(ans): # 人类选手决定如何行棋 823 | p = 0 824 | while True: 825 | PawnMoveTo = None 826 | for event in pygame.event.get(): 827 | if event.type == QUIT: 828 | terminate() 829 | elif event.type == KEYDOWN: 830 | if len(ans) > 1: 831 | if event.key == K_1: 832 | p = 1 833 | elif event.key == K_2: 834 | p = 2 835 | elif event.key == K_3: 836 | p = 3 837 | elif event.key == K_4: 838 | p = 4 839 | elif event.key == K_5: 840 | p = 5 841 | elif event.key == K_6: 842 | p = 6 843 | else: 844 | p = ans[0] 845 | if p != 0: 846 | if p in ans: 847 | showSelected(p) 848 | if event.key == K_w: 849 | PawnMoveTo = RIGHT 850 | elif event.key == K_a: 851 | PawnMoveTo = DOWN 852 | elif event.key == K_s: 853 | PawnMoveTo = RIGHTDOWN 854 | if PawnMoveTo != None: 855 | newS = tryMakeMove(p, PawnMoveTo, S) 856 | if newS is not False: 857 | return p, PawnMoveTo 858 | 859 | 860 | # 20190302 socket 移动棋子,如果走错直接输 861 | def socketToMove(conn,n, ans, S): 862 | message = str(S.map) + '|' + str(n) 863 | conn.sendall(message.encode('UTF-8')) 864 | try: 865 | conn.settimeout(5) 866 | data, address = conn.recvfrom(1024) 867 | except socket.error as e: 868 | logger.info(str(e)) 869 | return -1, 'timeout' 870 | 871 | # 对战 872 | text = (data.decode()[:-1]).split('|') 873 | # 调试 874 | # text = (data.decode()).split('|') 875 | p = int(text[0]) 876 | moveTo = text[1] 877 | if (p in ans): 878 | if p > 0 and p < 7: 879 | if moveTo == DOWN or moveTo == RIGHT or moveTo == RIGHTDOWN: 880 | newS = tryMakeMove(p, moveTo, S) 881 | if newS is not False: 882 | return p, moveTo 883 | elif p > 6 and p < 13: 884 | if moveTo == UP or moveTo == LEFT or moveTo == LEFTUP: 885 | newS = tryMakeMove(p, moveTo, S) 886 | if newS is not False: 887 | return p, moveTo 888 | return -1, 'not move' 889 | 890 | 891 | def playGame(Red, Blue, detail, conn): 892 | 893 | lastInfo = [] 894 | mapNeedRedraw = True # 是否需要重新绘制地图 895 | 896 | if detail: 897 | drawGameScreen(Red, Blue) 898 | while True: 899 | moveTo = None # 棋子移动方向 900 | mapNeedRedraw = False 901 | 902 | # correct = 0 #游戏结果 903 | 904 | n, ans = selectPawn(S) 905 | if detail: 906 | drawMovePawn(n, ans) 907 | 908 | # GUI control here 909 | for event in pygame.event.get(): 910 | if event.type == QUIT: 911 | terminate() 912 | 913 | 914 | if COUNT % 2 == 0: 915 | if Red == 'BetaCat1.0': 916 | p, moveTo = redByMinimax(ans) 917 | if Red == 'Socket': 918 | try: 919 | p, moveTo = socketToMove(conn=conn,n=n, ans=ans, S=S) 920 | if p == -1: 921 | logger.info('RESULT : BLUEWIN') 922 | return BLUEWIN 923 | except socket.error as e: 924 | logger.info('RESULT : BLUEWIN') 925 | return BLUEWIN 926 | except ValueError as e1: 927 | logger.info('RESULT : BLUEWIN') 928 | return BLUEWIN 929 | 930 | if COUNT % 2 == 1: 931 | 932 | if Blue == 'Socket': 933 | try: 934 | p, moveTo = socketToMove(conn=conn, n=n, ans=ans, S=S) 935 | if p == -1: 936 | logger.info('RESULT : REDWIN') 937 | return REDWIN 938 | except socket.error as e: 939 | logger.info('RESULT : REDWIN') 940 | return REDWIN 941 | except ValueError as e1: 942 | logger.info('RESULT : REDWIN') 943 | return BLUEWIN 944 | 945 | 946 | if Blue == 'Demo': 947 | p, moveTo = blueByDemo(ans) 948 | 949 | if moveTo != None: 950 | moved = makeMove(p, moveTo) 951 | lastInfo = [n, p, moveTo] 952 | if moved: 953 | mapNeedRedraw = True 954 | if mapNeedRedraw and detail: # 如果需要重绘棋局界面,则: 955 | sleep(SLEEPTIME) 956 | drawGameScreen(Red, Blue) # 重绘棋局界面 957 | logger.info(str(S.map)+' |chess: '+str(p)+' |move : '+moveTo) 958 | pass 959 | 960 | result = isEnd(S) # 检查游戏是否结束,返回游戏结果 961 | 962 | 963 | if result: 964 | lastInfo = [] 965 | logger.info('RESULT : REDWIN' if result == 1 else 'RESULT : BLUEWIN') 966 | return result 967 | 968 | 969 | def startGame(Red, Blue, n, filename, detail=True): 970 | global COUNT 971 | init() 972 | if detail: 973 | drawStartScreen() # 游戏开始界面 974 | RESULT[0] = 0 975 | RESULT[1] = 0 976 | cnt = n 977 | rateline = [] 978 | if Blue == 'Socket' or Red == 'Socket': 979 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 980 | sock.bind(('0.0.0.0', 50006)) 981 | sock.listen(1) 982 | conn, addr = sock.accept() 983 | #获取ID 984 | ID = conn.recv(1024).decode()[:-1] 985 | print("CONNECT CLIENT ID : " + str(ID)) 986 | else: 987 | conn = 0 988 | print(' connected') 989 | while cnt: 990 | resetInfo() 991 | result = playGame(Red, Blue, detail, conn) # 游戏开始,返回比赛结果 992 | if detail: 993 | #pass 994 | drawWinScreen(result) 995 | 996 | 997 | RESULT[result-1] += 1 # 更新比分 998 | cnt -= 1 999 | COUNT = 2000 - cnt - 1 # 先手方交替 1000 | rateline.append(float(RESULT[0])/sum(RESULT)) 1001 | 1002 | drawText('RED : ' + str(RESULT[0]), font, RED, screen, 6, 7) 1003 | drawText('BLUE : ' + str(RESULT[1]), font, BLUE, screen, 6.5, 7) 1004 | pygame.display.update() 1005 | 1006 | if cnt % 5 == 0: 1007 | print(sum(RESULT),'\t',round(100*RESULT[0]/sum(RESULT),4)) 1008 | 1009 | if Blue == 'Socket' or Red == 'Socket': 1010 | try: 1011 | conn.sendall('close'.encode('utf8')) 1012 | conn.close() 1013 | except socket.error as e: 1014 | print('Test Game Over : %s' % e) 1015 | return RESULT[0] 1016 | 1017 | 1018 | if __name__ == '__main__': 1019 | ''' 1020 | 可选测试对象 1021 | Red :BetaCat1.0 | Socket | 1022 | Blue :Demo | Socket ' 1023 | BetaCat1.0 Demo 分别为红方或蓝方AI 1024 | Socket 为用户选择红方或蓝方连接客户端,不能同时连接客户端 1025 | 当前示例表示红方为服务器,蓝方为客户端 1026 | 首先启动此程序 1027 | ''' 1028 | Red = 'BetaCat1.0' 1029 | Blue = 'Socket' 1030 | filename = os.getcwd() + "\\data\\" + Red + 'Vs' + Blue 1031 | print(filename) 1032 | # 测试局数 1033 | cnt = 500 1034 | result = startGame(Red, Blue, cnt, filename, detail=True) 1035 | input('wait') 1036 | -------------------------------------------------------------------------------- /EinsteinChessTestServer/Twoplayers-BattleServer (胜率曲线).py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import os 3 | import sys 4 | import random 5 | import copy 6 | import socket 7 | import logging 8 | from pygame.locals import * 9 | from sys import exit 10 | from time import ctime, sleep 11 | import logging 12 | 13 | WINDOWSIZE = (1200, 680) # 游戏窗口大小 14 | LINECOLOR = (0, 0, 0) # 棋盘线的颜色 15 | TEXTCOLOR = (0, 0, 0) # 标题文本颜色 16 | BLACKGROUND = (255, 255, 255) # 游戏背景颜色 17 | BLACK = (0, 0, 0) 18 | BLUE = (0, 191, 255) 19 | YELLOW = (255, 255, 0) 20 | RED = (255, 0, 0) 21 | GREEN = (0, 255, 0) 22 | WHITE = (255, 255, 255) 23 | SIZE = (50, 50) # 棋子大小 24 | AYSTSIZE = (240, 240) # 爱因斯坦背景头像图片大小 25 | POSAYST = (365, 0) # 爱因斯坦头像位置 26 | STEP = 60 # 步长:棋子走一步移动的距离 27 | TEXTSIZE = 30 # 标题文字大小 28 | TIPSIZE = 15 # 提示文字大小 29 | COUNT = -1 # 记录当前回合 30 | START = 65 # 棋盘左上角起始点(70,70) 31 | REDWIN = 1 # 代表RED方赢 32 | BLUEWIN = 2 # 代表玩家BLUE方赢 33 | LEFT = 'left' 34 | RIGHT = 'right' 35 | UP = 'up' 36 | DOWN = 'down' 37 | LEFTUP = 'leftup' 38 | RIGHTDOWN = 'rightdown' 39 | RESULT = [0, 0] # 记录比赛结果 40 | WINSIZE = (400, 90) # 显示比赛结果窗口大小 41 | INFTY = 10000 42 | SLEEPTIME = 0 43 | clock = pygame.time.Clock() 44 | clients = list() 45 | logging.basicConfig(level=logging.INFO, format='%(asctime)s %(name)s- %(levelname)s - %(message)s', filename='battle.log') 46 | logger = logging.getLogger() 47 | 48 | ch = logging.StreamHandler() #日志输出到屏幕控制台 49 | ch.setLevel(logging.INFO) #设置日志等级 50 | formatter = logging.Formatter('%(asctime)s %(name)s- %(levelname)s - %(message)s') #定义日志输出格式 51 | ch.setFormatter(formatter) #选择一个格式 52 | logger.addHandler(ch) #增加指定的handler 53 | playernum = 2 54 | currentnum = 0 55 | start = 0 56 | 57 | 58 | class Status(object): 59 | def __init__(self): 60 | self.map = None 61 | self.value = None 62 | self.pawn = None 63 | self.pro = None 64 | self.parent = None 65 | self.pPawn = None 66 | self.pMove = None 67 | self.pDice = None 68 | self.cPawn = None 69 | self.cPawnSecond = None 70 | self.cPM = [[],[],[],[],[],[]] 71 | self.cPMSecond = [[],[],[],[],[],[]] 72 | def print(self): 73 | print(self.cPM) 74 | 75 | class Player: 76 | 77 | ID = 'ID' 78 | wins = 0 79 | def __init__(self, id, sock): 80 | self.ID = id 81 | self.clientsock = sock 82 | 83 | def init(): 84 | global IMAGE,tip,screen,font,maplib,Lyr,Lyb,Lx,S,matchPro 85 | pygame.init() 86 | S = Status() 87 | screen = pygame.display.set_mode(WINDOWSIZE, 0, 32) # 设置游戏窗口 88 | pygame.display.set_caption('Einstein Chess-Player 0 VS Player 1') # 设置Caption 89 | font = pygame.font.SysFont("Cambria Math", TEXTSIZE, 90 | bold=False, italic=False) # 设置标题字体格式 91 | tip = pygame.font.SysFont("arial", TIPSIZE, bold=False, italic=False) # 设置提示字体 92 | IMAGE = { 93 | 'R1': pygame.transform.scale(pygame.image.load('picture/white/R1.png').convert(), SIZE), 94 | 'R2': pygame.transform.scale(pygame.image.load('picture/white/R2.png').convert(), SIZE), 95 | 'R3': pygame.transform.scale(pygame.image.load('picture/white/R3.png').convert(), SIZE), 96 | 'R4': pygame.transform.scale(pygame.image.load('picture/white/R4.png').convert(), SIZE), 97 | 'R5': pygame.transform.scale(pygame.image.load('picture/white/R5.png').convert(), SIZE), 98 | 'R6': pygame.transform.scale(pygame.image.load('picture/white/R6.png').convert(), SIZE), 99 | 'B1': pygame.transform.scale(pygame.image.load('picture/white/B1.png').convert(), SIZE), 100 | 'B2': pygame.transform.scale(pygame.image.load('picture/white/B2.png').convert(), SIZE), 101 | 'B3': pygame.transform.scale(pygame.image.load('picture/white/B3.png').convert(), SIZE), 102 | 'B4': pygame.transform.scale(pygame.image.load('picture/white/B4.png').convert(), SIZE), 103 | 'B5': pygame.transform.scale(pygame.image.load('picture/white/B5.png').convert(), SIZE), 104 | 'B6': pygame.transform.scale(pygame.image.load('picture/white/B6.png').convert(), SIZE), 105 | 'Y1': pygame.transform.scale(pygame.image.load('picture/white/Y1.png').convert(), SIZE), 106 | 'Y2': pygame.transform.scale(pygame.image.load('picture/white/Y2.png').convert(), SIZE), 107 | 'Y3': pygame.transform.scale(pygame.image.load('picture/white/Y3.png').convert(), SIZE), 108 | 'Y4': pygame.transform.scale(pygame.image.load('picture/white/Y4.png').convert(), SIZE), 109 | 'Y5': pygame.transform.scale(pygame.image.load('picture/white/Y5.png').convert(), SIZE), 110 | 'Y6': pygame.transform.scale(pygame.image.load('picture/white/Y6.png').convert(), SIZE), 111 | '1': pygame.transform.scale(pygame.image.load('picture/white/1.png').convert(), SIZE), 112 | '2': pygame.transform.scale(pygame.image.load('picture/white/2.png').convert(), SIZE), 113 | '3': pygame.transform.scale(pygame.image.load('picture/white/3.png').convert(), SIZE), 114 | '4': pygame.transform.scale(pygame.image.load('picture/white/4.png').convert(), SIZE), 115 | '5': pygame.transform.scale(pygame.image.load('picture/white/5.png').convert(), SIZE), 116 | '6': pygame.transform.scale(pygame.image.load('picture/white/6.png').convert(), SIZE), 117 | 'BLUEWIN': pygame.transform.scale(pygame.image.load('picture/white/BLUEWIN.png').convert(), WINSIZE), 118 | 'REDWIN': pygame.transform.scale(pygame.image.load('picture/white/REDWIN.png').convert(), WINSIZE), 119 | } 120 | # 布局库 121 | maplib = [[6, 2, 4, 1, 5, 3], 122 | [6, 5, 2, 1, 4, 3], 123 | [1, 5, 4, 6, 2, 3], 124 | [1, 6, 3, 5, 2, 4], 125 | [1, 6, 4, 3, 2, 5], 126 | [6, 1, 2, 5, 4, 3], 127 | [6, 1, 3, 5, 4, 2], 128 | [1, 6, 4, 2, 3, 5], 129 | [1, 5, 2, 6, 3, 4], 130 | [1, 6, 5, 2, 3, 4], 131 | [1, 2, 5, 6, 3, 4], 132 | [6, 2, 5, 1, 4, 3], 133 | [1, 6, 3, 2, 4, 5], 134 | [6, 2, 3, 1, 5, 4], 135 | [1, 6, 3, 4, 2, 5], 136 | [1, 5, 4, 6, 3, 2] 137 | ] 138 | resetInfo() 139 | Lyr = [] 140 | Lyb = [] 141 | Lx = [] 142 | matchPro = 0.85 143 | 144 | 145 | def loadImage(name, pos, size=SIZE): 146 | filename = "picture/white/" + name 147 | screen.blit(pygame.transform.scale( 148 | pygame.image.load(filename).convert(), size), pos) 149 | def waitForPlayerToPressKey(): # 等待按键 150 | while True: 151 | for event in pygame.event.get(): 152 | if event.type == QUIT: 153 | terminate() 154 | if event.type == KEYDOWN: 155 | if event.key == K_ESCAPE: 156 | terminate() 157 | return 158 | 159 | 160 | def drawStartScreen(): # 开始界面 161 | screen.fill(WHITE) 162 | loadImage("AYST.png", (100, 40), AYSTSIZE) 163 | # drawText('EinStein wurfelt nicht', font, GREEN, screen, 260, 200) 164 | drawText('PORT 50006 IS WAITING FOR CONNECTION', font, TEXTCOLOR, screen, 5.5, 0.1) 165 | pygame.display.update() 166 | 167 | 168 | # waitForPlayerToPressKey() 169 | def drawWinScreen(result): # 比赛结束,显示结果界面 170 | if result == BLUEWIN: 171 | loadImage("BLUEWIN.png", (50, 500), WINSIZE) 172 | if result == REDWIN: 173 | loadImage("REDWIN.png", (50, 5000), WINSIZE) 174 | # waitForPlayerToPressKey() 175 | pygame.display.update() 176 | sleep(SLEEPTIME) 177 | 178 | def showWinRate(RedWinRate, BlueWinRate, x): 179 | global Lyr, Lyb, Lx 180 | yr = (100 - RedWinRate)/(100/3.0) + 0.6 181 | yb = (100 - BlueWinRate)/(100/3.0) + 0.6 182 | x = x/(1000/5) + 4.2 183 | Lyr.append(copy.deepcopy(yr)) 184 | Lyb.append(copy.deepcopy(yb)) 185 | Lx.append(copy.deepcopy(x)) 186 | for i in range(0, len(Lyr)-1): 187 | pygame.draw.line( 188 | screen, RED, (100*Lx[i], 100*Lyr[i]), (100*Lx[i], 100*Lyr[i+1])) 189 | pygame.draw.line( 190 | screen, BLUE, (100*Lx[i], 100*Lyb[i]), (100*Lx[i], 100*Lyb[i+1])) 191 | def drawGameScreen(conn0, conn1): # 游戏比赛界面 192 | global S 193 | 194 | screen.fill(WHITE) 195 | # 画棋盘 196 | for i in range(6): 197 | x = y = 60*(i+1) 198 | pygame.draw.line(screen, LINECOLOR, (60, y), (360, y)) 199 | pygame.draw.line(screen, LINECOLOR, (x, 60), (x, 360)) 200 | 201 | 202 | drawText('RED : '+str(conn0.ID), font, RED, screen, 6, 1) 203 | drawText('BLUE : '+str(conn1.ID), font, BLUE, screen, 6.5, 1) 204 | 205 | # 加载提示文字 206 | drawText('Winning Percentage Dynamic Figure', font, BLACK, screen, 0, 7.2) 207 | drawText(str(conn0.ID) + ' Vs ' + str(conn1.ID), font, BLACK, screen, 0.5, 7.2) 208 | #drawText('matchPro : '+ str(round(100*matchPro,4))+'%',font,BLACK,screen,1,7.2) 209 | 210 | 211 | # 胜率坐标轴 212 | pygame.draw.line(screen, LINECOLOR, (415, 55), (420, 50)) 213 | pygame.draw.line(screen, LINECOLOR, (425, 55), (420, 50)) 214 | pygame.draw.line(screen, LINECOLOR, (420, 360), (420, 50)) 215 | pygame.draw.line(screen, LINECOLOR, (420, 360), (1000, 360)) 216 | pygame.draw.line(screen, LINECOLOR, (995, 355), (1000, 360)) 217 | pygame.draw.line(screen, LINECOLOR, (995, 365), (1000, 360)) 218 | 219 | 220 | drawText('RED : '+str(RESULT[0]), font, RED, screen, 6, 7) 221 | drawText('BLUE : '+str(RESULT[1]), font, BLUE, screen, 6.5, 7) 222 | 223 | if(sum(RESULT)): 224 | RedWinRate = round(100*float(RESULT[0])/sum(RESULT), 2) 225 | BlueWinRate = round(100*float(RESULT[1])/sum(RESULT), 2) 226 | drawText('RedWinRate:'+str(round(100 * 227 | float(RESULT[0])/sum(RESULT), 2)), font, RED, screen, 6, 9.5) 228 | drawText('BlueWinRate:'+str(round(100 * 229 | float(RESULT[1])/sum(RESULT), 2)), font, BLUE, screen, 6.5, 9.5) 230 | x = sum(RESULT) 231 | showWinRate(RedWinRate, BlueWinRate, x) 232 | 233 | # 画棋子 234 | for i in range(5): 235 | for j in range(5): 236 | if S.map[i][j] != 0: 237 | drawPawn(S.map[i][j], i, j) 238 | pygame.display.update() 239 | pygame.display.update() 240 | 241 | 242 | def drawMovePawn(n, ans): # 可选择移动的棋子 243 | x = -1 244 | y = 2 245 | for v in ans: 246 | drawPawn(v, x, y) 247 | y += 1 248 | if n <= 6: 249 | loadImage(str(n)+'.png', (310, 5)) 250 | else: 251 | loadImage(str(n-6)+'.png', (310, 5)) 252 | pygame.display.update() 253 | 254 | 255 | def drawPawn(value, row, col, size=SIZE): # 在(row,col)处,画值为value的棋子 256 | pos_x = col * STEP + START 257 | pos_y = row * STEP + START 258 | Pos = (pos_x, pos_y) 259 | if value <= 6: 260 | s = 'R' + str(value) 261 | elif value > 6: 262 | s = 'B' + str(value-6) 263 | loadImage(s+'.png', Pos, size) 264 | 265 | def drawText(text, font, color, surface, row, col): # 处理需要描绘的文字:text:文本;font:格式; 266 | row += 0.2 267 | x = col * STEP 268 | y = row * STEP 269 | textobj = font.render(text, True, color, WHITE) 270 | textrect = textobj.get_rect() 271 | textrect.topleft = (x, y) 272 | surface.blit(textobj, textrect) 273 | 274 | 275 | def selectPawn(S,n=0): # 掷骰子,挑选可以移动的棋子 276 | global COUNT 277 | if n == 0: 278 | COUNT += 1 279 | if COUNT % 2 == 0: 280 | n = random.randint(1, 6) 281 | else: 282 | n = random.randint(7, 12) 283 | ans = findNearby(n, S.pawn) 284 | else: 285 | ans = findNearby(n, S.pawn) 286 | return n, ans 287 | 288 | 289 | def terminate(): # 退出游戏 290 | pygame.quit() 291 | sys.exit() 292 | 293 | 294 | def makeMove(p, PawnMoveTo): # 移动棋子,更新地图信息,和棋子存活情况 295 | row, col = getLocation(p, S.map) 296 | x = y = 0 297 | if PawnMoveTo == LEFT: 298 | y = -1 299 | elif PawnMoveTo == RIGHT: 300 | y = +1 301 | elif PawnMoveTo == UP: 302 | x = -1 303 | elif PawnMoveTo == DOWN: 304 | x = +1 305 | elif PawnMoveTo == LEFTUP: 306 | x = -1 307 | y = -1 308 | elif PawnMoveTo == RIGHTDOWN: 309 | x = +1 310 | y = +1 311 | else: 312 | return False 313 | # 移动无效 314 | if notInMap(row+x, col+y): 315 | return False 316 | S.map[row][col] = 0 317 | row = row + x 318 | col = col + y 319 | # 是否吃掉自己或对方的棋 320 | if S.map[row][col] != 0: 321 | i = S.pawn.index(S.map[row][col]) 322 | S.pawn[i] = 0 323 | S.map[row][col] = p 324 | return True 325 | def notInMap(x, y): # 检测棋子是否在棋盘内移动 326 | if x in range(0, 5) and y in range(0, 5): 327 | return False 328 | return True 329 | 330 | 331 | def showSelected(p): # 用红色标记,显示被挑选的棋子 332 | row, col = getLocation(p, S.map) 333 | pos_x = col * STEP + START 334 | pos_y = row * STEP + START 335 | Pos = (pos_x, pos_y) 336 | if p > 6: 337 | s = 'Y' + str(p-6) 338 | else: 339 | s = 'Y' + str(p) 340 | loadImage(s+'.png', Pos) 341 | # screen.blit(IMAGE[s],Pos) 342 | pygame.display.update() 343 | 344 | 345 | def isEnd(S): # 检测比赛是否结束 346 | if S.map[0][0] > 6: 347 | return BLUEWIN 348 | elif S.map[4][4] > 0 and S.map[4][4] <= 6: 349 | return REDWIN 350 | cnt = 0 351 | for i in range(0, 6): 352 | if S.pawn[i] == 0: 353 | cnt += 1 354 | if cnt == 6: 355 | return BLUEWIN 356 | cnt = 0 357 | for i in range(6, 12): 358 | if S.pawn[i] == 0: 359 | cnt += 1 360 | if cnt == 6: 361 | return REDWIN 362 | return False 363 | 364 | 365 | def resetInfo(): # 重置比赛信息 366 | S.map = getNewMap() 367 | S.pawn = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] # 棋子初始化 368 | S.pro = [1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0 / 369 | 6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6] 370 | value = getLocValue(S) 371 | S.value = getPawnValue(S.pro, value) 372 | 373 | 374 | def getNewMap(): # 换新图 375 | r = random.sample(maplib, 1)[0] 376 | b = random.sample(maplib, 1)[0] 377 | newMap = [ 378 | [r[0], r[3], r[5], 0, 0], 379 | [r[1], r[4], 0, 0, 0], 380 | [r[2], 0, 0, 0, b[2]+6], 381 | [0, 0, 0, b[4]+6, b[1]+6], 382 | [0, 0, b[5]+6, b[3]+6, b[0]+6] 383 | ] 384 | return newMap 385 | 386 | 387 | def getLocValue(S): # 棋子所在位置的价值 388 | blueValue = [[99, 10, 6, 3, 1], 389 | [10, 8, 4, 2, 1], 390 | [6, 4, 4, 2, 1], 391 | [3, 2, 2, 2, 1], 392 | [1, 1, 1, 1, 1]] 393 | redValue = [[1, 1, 1, 1, 1], 394 | [1, 2, 2, 2, 3], 395 | [1, 2, 4, 4, 6], 396 | [1, 2, 4, 8, 10], 397 | [1, 3, 6, 10, 99]] 398 | V = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 399 | for p in range(1, 13): 400 | if S.pawn[p-1] != 0: 401 | row, col = getLocation(p, S.map) 402 | if p <= 6: 403 | V[p-1] = redValue[row][col] 404 | else: 405 | V[p-1] = blueValue[row][col] 406 | return V 407 | def getPawnValue(pro, value): # 棋子价值 408 | V = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 409 | for i in range(0, 12): 410 | V[i] = pro[i] * value[i] 411 | return V 412 | 413 | def findNearby(n, nowPawn): # 寻找可以移动的棋子 414 | ans = [] 415 | # 如果有对应棋子 416 | if nowPawn[n-1] != 0: 417 | ans.append(n) 418 | #没有对应棋子 419 | elif n > 6: 420 | for i in range(n-1, 6, -1): 421 | if i in nowPawn: 422 | ans.append(i) 423 | break 424 | for i in range(n+1, 13): 425 | if i in nowPawn: 426 | ans.append(i) 427 | break 428 | elif n <= 6: 429 | for i in range(n-1, 0, -1): 430 | if i in nowPawn: 431 | ans.append(i) 432 | break 433 | for i in range(n+1, 7): 434 | if i in nowPawn: 435 | ans.append(i) 436 | break 437 | return ans 438 | 439 | 440 | def getLocation(p, Map): # 返回传入地图下,棋子p的坐标 441 | for i in range(5): 442 | for j in range(5): 443 | if Map[i][j] == p: 444 | return i, j 445 | 446 | 447 | def tryMakeMove(p, PawnMoveTo, S): # 尝试移动,并且返回移动后的棋局地图与棋子存活情况 448 | newS = copy.deepcopy(S) 449 | row, col = getLocation(p, newS.map) 450 | x = y = 0 451 | if PawnMoveTo == LEFT: 452 | y = -1 453 | elif PawnMoveTo == RIGHT: 454 | y = +1 455 | elif PawnMoveTo == UP: 456 | x = -1 457 | elif PawnMoveTo == DOWN: 458 | x = +1 459 | elif PawnMoveTo == LEFTUP: 460 | x = -1 461 | y = -1 462 | elif PawnMoveTo == RIGHTDOWN: 463 | x = +1 464 | y = +1 465 | # 移动无效 466 | if notInMap(row+x, col+y): 467 | return False 468 | newS.map[row][col] = 0 469 | row = row + x 470 | col = col + y 471 | if newS.map[row][col] != 0: 472 | i = newS.pawn.index(newS.map[row][col]) 473 | newS.pawn[i] = 0 474 | newS.map[row][col] = p 475 | # value = getLocValue(newS) # 获取所有棋子的位置价值 476 | # newS.pro = getPawnPro(newS) # 获取所有棋子被摇到的概率 477 | # newS.value = getPawnValue(value, newS.pro) 478 | newS.parent = S 479 | newS.pPawn = p 480 | newS.pMove = PawnMoveTo 481 | if p < 7: 482 | newS.cPawn = [INFTY,INFTY,INFTY,INFTY,INFTY,INFTY] 483 | newS.cPawnSecond = [INFTY,INFTY,INFTY,INFTY,INFTY,INFTY] 484 | else: 485 | newS.cPawn = [-INFTY,-INFTY,-INFTY,-INFTY,-INFTY,-INFTY] 486 | newS.cPawnSecond = [-INFTY,-INFTY,-INFTY,-INFTY,-INFTY,-INFTY] 487 | return newS 488 | 489 | 490 | 491 | # 20190302 socket 移动棋子,如果走错直接输 492 | def socketToMove(conn,n, ans, S): 493 | message = str(S.map) + '|' + str(n) 494 | conn.sendall(message.encode('UTF-8')) 495 | try: 496 | conn.settimeout(15) 497 | data, address = conn.recvfrom(1024) 498 | except socket.error as e: 499 | logger.info(str(e)) 500 | return -1, 'timeout' 501 | text = (data.decode('UTF-8')[:-1]).split('|') 502 | try: 503 | p = int(text[0]) 504 | moveTo = text[1] 505 | except TypeError as tp: 506 | return -1, 'not move' 507 | 508 | if (p in ans): 509 | if p > 0 and p < 7: 510 | if moveTo == DOWN or moveTo == RIGHT or moveTo == RIGHTDOWN: 511 | newS = tryMakeMove(p, moveTo, S) 512 | if newS is not False: 513 | return p, moveTo 514 | elif p > 6 and p < 13: 515 | if moveTo == UP or moveTo == LEFT or moveTo == LEFTUP: 516 | newS = tryMakeMove(p, moveTo, S) 517 | if newS is not False: 518 | return p, moveTo 519 | return -1, 'not move' 520 | 521 | 522 | def outputResult(): 523 | global clients 524 | rank = clients.copy() 525 | if currentnum == playernum: 526 | for i in range(playernum - 1): 527 | for j in range(playernum - i - 1): 528 | if (rank[j].wins < rank[j + 1].wins): 529 | rank[j], rank[j + 1] = rank[j + 1], rank[j] 530 | with open('BATTLERESULT.txt',mode='w', encoding='utf8') as f: 531 | for c in rank: 532 | f.writelines(str(c.ID) + ' WINTIMES : ' + str(c.wins)+str('\n')) 533 | logger.info('WRITE INTO BATTLERESULT') 534 | 535 | 536 | def startgame(port, n, detail=True): 537 | global COUNT 538 | global playernum 539 | global clients 540 | global currentnum 541 | wins = [0 for i in range(playernum)] 542 | init() 543 | if detail: 544 | drawStartScreen() # 游戏开始界面 545 | RESULT[0] = 0 546 | RESULT[1] = 0 547 | cnt = n 548 | rateline = [] 549 | 550 | # while(playernum == 0): 551 | # sleep(1) 552 | 553 | #客户端 554 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 555 | sock.bind(('0.0.0.0', port)) 556 | 557 | for i in range(playernum): 558 | sock.listen() 559 | conn, addr = sock.accept() 560 | # 获取用户ID 561 | playerID = conn.recv(1024).decode('utf8')[:-1] 562 | clients.append(Player(playerID, conn)) 563 | print('client_{} connected: {}'.format(i, addr)) 564 | logger.info('client_'+str(i)+' connected: '+str(addr)) 565 | currentnum = i+1 566 | # app.refresh() 567 | 568 | 569 | 570 | for i in range(0, playernum-1): 571 | for j in range(i+1, playernum): 572 | count = cnt 573 | while count: 574 | resetInfo() 575 | #result = playGame(Red, Blue, detail) # 游戏开始,返回比赛结果 576 | result = battle(clients[i], clients[j], detail) 577 | if detail: 578 | # pass 579 | drawWinScreen(result) 580 | if result == REDWIN: 581 | clients[i].wins = clients[i].wins+1 582 | else: 583 | clients[j].wins = clients[j].wins+1 584 | # app.refresh() 585 | 586 | RESULT[result - 1] += 1 # 更新比分 587 | count -= 1 588 | COUNT = 2000 - count - 1 # 先手方交替 589 | rateline.append(float(RESULT[0]) / sum(RESULT)) 590 | if count % 5 == 0: 591 | # pass 592 | print(sum(RESULT), '\t', round(100 * RESULT[0] / sum(RESULT), 4)) 593 | for i in range(playernum): 594 | try: 595 | # logger.info('rank : '+str(i)+' '+ clients[i].ID + ' wins '+str( clients[i].wins)) 596 | clients[i].clientsock.sendall('close'.encode('utf8')) 597 | except socket.error as e: 598 | logger.info(str('ERRORS ') + str(e)) 599 | rank = clients.copy() 600 | if currentnum == playernum: 601 | for i in range(playernum - 1): 602 | for j in range(playernum - i - 1): 603 | if (rank[j].wins < rank[j + 1].wins): 604 | rank[j], rank[j + 1] = rank[j + 1], rank[j] 605 | for i in range(playernum): 606 | logger.info('rank : ' + str(i+1) + ' ' + rank[i].ID + ' wins ' + str(rank[i].wins)) 607 | 608 | sock.close() 609 | 610 | 611 | def battle(client0, client1, detail): 612 | lastInfo = [] 613 | mapNeedRedraw = True # 是否需要重新绘制地图 614 | if detail: 615 | drawGameScreen(client0, client1) 616 | while True: 617 | 618 | moveTo = None # 棋子移动方向 619 | mapNeedRedraw = False 620 | n, ans = selectPawn(S) 621 | if detail: 622 | drawMovePawn(n, ans) 623 | for event in pygame.event.get(): 624 | if event.type == QUIT: 625 | terminate() 626 | try: 627 | sleep(SLEEPTIME) 628 | if COUNT % 2 == 0: 629 | p, moveTo = socketToMove(conn=client0.clientsock, n=n, ans=ans, S=S) 630 | if p == -1: 631 | logger.info(str('RESULT : '+client1.ID+' WIN')) 632 | return BLUEWIN 633 | except socket.error as e: 634 | logger.info(str('ERRORS ')+str(e) ) 635 | logger.info(str('RESULT : ' + client1.ID + ' WIN')) 636 | return BLUEWIN 637 | except ValueError as e1: 638 | logger.info(str('ERRORS ')+str(e1)) 639 | logger.info(str('RESULT : ' + client1.ID + ' WIN')) 640 | return BLUEWIN 641 | 642 | 643 | try: 644 | if COUNT % 2 == 1: 645 | p, moveTo = socketToMove(conn=client1.clientsock, n=n, ans=ans, S=S) 646 | if p == -1: 647 | str('RESULT : ' + client0.ID + ' WIN') 648 | return REDWIN 649 | except socket.error as e: 650 | logger.info(str('ERRORS ') + str(e)) 651 | logger.info(str('RESULT : ' + client0.ID + ' WIN')) 652 | return REDWIN 653 | except ValueError as e1: 654 | logger.info(str('ERRORS ') + str(e1)) 655 | logger.info(str('RESULT : ' + client0.ID + ' WIN')) 656 | return REDWIN 657 | 658 | 659 | if moveTo != None: 660 | moved = makeMove(p, moveTo) 661 | lastInfo = [n, p, moveTo] 662 | if moved: 663 | mapNeedRedraw = True 664 | if mapNeedRedraw and detail: # 如果需要重绘棋局界面,则: 665 | drawGameScreen(client0, client1) # 重绘棋局界面 666 | logger.info(str(S.map) + ' |id: ' + str(p) + ' |move : ' + moveTo) 667 | pass 668 | result = isEnd(S) # 检查游戏是否结束,返回游戏结果 669 | if result: 670 | lastInfo = [] 671 | logger.info(str('RESULT : '+client0.ID+' WIN') if result == 1 else str('RESULT : '+client1.ID+' WIN')) 672 | return result 673 | 674 | 675 | 676 | if __name__ == '__main__': 677 | # 测试局数 678 | cnt = 100 679 | result = startgame(port=50006, n=cnt) 680 | outputResult() 681 | input('enter any key to stop\n') 682 | sys.exit() 683 | -------------------------------------------------------------------------------- /EinsteinChessTestServer/Twoplayers-BattleServer.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import os 3 | import sys 4 | import random 5 | import copy 6 | import socket 7 | import logging 8 | from pygame.locals import * 9 | from sys import exit 10 | from time import ctime, sleep 11 | import logging 12 | 13 | WINDOWSIZE = (450, 450) # 游戏窗口大小 14 | LINECOLOR = (0, 0, 0) # 棋盘线的颜色 15 | TEXTCOLOR = (0, 0, 0) # 标题文本颜色 16 | BLACKGROUND = (255, 255, 255) # 游戏背景颜色 17 | BLACK = (0, 0, 0) 18 | BLUE = (0, 191, 255) 19 | YELLOW = (255, 255, 0) 20 | RED = (255, 0, 0) 21 | GREEN = (0, 255, 0) 22 | WHITE = (255, 255, 255) 23 | SIZE = (50, 50) # 棋子大小 24 | AYSTSIZE = (240, 240) # 爱因斯坦背景头像图片大小 25 | POSAYST = (365, 0) # 爱因斯坦头像位置 26 | STEP = 60 # 步长:棋子走一步移动的距离 27 | TEXTSIZE = 30 # 标题文字大小 28 | TIPSIZE = 15 # 提示文字大小 29 | COUNT = -1 # 记录当前回合 30 | START = 65 # 棋盘左上角起始点(70,70) 31 | REDWIN = 1 # 代表RED方赢 32 | BLUEWIN = 2 # 代表玩家BLUE方赢 33 | LEFT = 'left' 34 | RIGHT = 'right' 35 | UP = 'up' 36 | DOWN = 'down' 37 | LEFTUP = 'leftup' 38 | RIGHTDOWN = 'rightdown' 39 | RESULT = [0, 0] # 记录比赛结果 40 | WINSIZE = (400, 90) # 显示比赛结果窗口大小 41 | INFTY = 10000 42 | SLEEPTIME = 0 43 | clock = pygame.time.Clock() 44 | clients = list() 45 | logging.basicConfig(level=logging.INFO, format='%(asctime)s %(name)s- %(levelname)s - %(message)s', filename='battle.log') 46 | logger = logging.getLogger() 47 | 48 | ch = logging.StreamHandler() #日志输出到屏幕控制台 49 | ch.setLevel(logging.INFO) #设置日志等级 50 | formatter = logging.Formatter('%(asctime)s %(name)s- %(levelname)s - %(message)s') #定义日志输出格式 51 | ch.setFormatter(formatter) #选择一个格式 52 | logger.addHandler(ch) #增加指定的handler 53 | playernum = 2 54 | currentnum = 0 55 | start = 0 56 | 57 | 58 | class Status(object): 59 | def __init__(self): 60 | self.map = None 61 | self.value = None 62 | self.pawn = None 63 | self.pro = None 64 | self.parent = None 65 | self.pPawn = None 66 | self.pMove = None 67 | self.pDice = None 68 | self.cPawn = None 69 | self.cPawnSecond = None 70 | self.cPM = [[],[],[],[],[],[]] 71 | self.cPMSecond = [[],[],[],[],[],[]] 72 | def print(self): 73 | print(self.cPM) 74 | 75 | class Player: 76 | 77 | ID = 'ID' 78 | wins = 0 79 | def __init__(self, id, sock): 80 | self.ID = id 81 | self.clientsock = sock 82 | 83 | def init(): 84 | global IMAGE,tip,screen,font,maplib,Lyr,Lyb,Lx,S,matchPro 85 | pygame.init() 86 | S = Status() 87 | screen = pygame.display.set_mode(WINDOWSIZE, 0, 32) # 设置游戏窗口 88 | pygame.display.set_caption('Einstein Chess-Player 0 VS Player 1') # 设置Caption 89 | font = pygame.font.SysFont("Cambria Math", TEXTSIZE, 90 | bold=False, italic=False) # 设置标题字体格式 91 | tip = pygame.font.SysFont("arial", TIPSIZE, bold=False, italic=False) # 设置提示字体 92 | IMAGE = { 93 | 'R1': pygame.transform.scale(pygame.image.load('picture/white/R1.png').convert(), SIZE), 94 | 'R2': pygame.transform.scale(pygame.image.load('picture/white/R2.png').convert(), SIZE), 95 | 'R3': pygame.transform.scale(pygame.image.load('picture/white/R3.png').convert(), SIZE), 96 | 'R4': pygame.transform.scale(pygame.image.load('picture/white/R4.png').convert(), SIZE), 97 | 'R5': pygame.transform.scale(pygame.image.load('picture/white/R5.png').convert(), SIZE), 98 | 'R6': pygame.transform.scale(pygame.image.load('picture/white/R6.png').convert(), SIZE), 99 | 'B1': pygame.transform.scale(pygame.image.load('picture/white/B1.png').convert(), SIZE), 100 | 'B2': pygame.transform.scale(pygame.image.load('picture/white/B2.png').convert(), SIZE), 101 | 'B3': pygame.transform.scale(pygame.image.load('picture/white/B3.png').convert(), SIZE), 102 | 'B4': pygame.transform.scale(pygame.image.load('picture/white/B4.png').convert(), SIZE), 103 | 'B5': pygame.transform.scale(pygame.image.load('picture/white/B5.png').convert(), SIZE), 104 | 'B6': pygame.transform.scale(pygame.image.load('picture/white/B6.png').convert(), SIZE), 105 | 'Y1': pygame.transform.scale(pygame.image.load('picture/white/Y1.png').convert(), SIZE), 106 | 'Y2': pygame.transform.scale(pygame.image.load('picture/white/Y2.png').convert(), SIZE), 107 | 'Y3': pygame.transform.scale(pygame.image.load('picture/white/Y3.png').convert(), SIZE), 108 | 'Y4': pygame.transform.scale(pygame.image.load('picture/white/Y4.png').convert(), SIZE), 109 | 'Y5': pygame.transform.scale(pygame.image.load('picture/white/Y5.png').convert(), SIZE), 110 | 'Y6': pygame.transform.scale(pygame.image.load('picture/white/Y6.png').convert(), SIZE), 111 | '1': pygame.transform.scale(pygame.image.load('picture/white/1.png').convert(), SIZE), 112 | '2': pygame.transform.scale(pygame.image.load('picture/white/2.png').convert(), SIZE), 113 | '3': pygame.transform.scale(pygame.image.load('picture/white/3.png').convert(), SIZE), 114 | '4': pygame.transform.scale(pygame.image.load('picture/white/4.png').convert(), SIZE), 115 | '5': pygame.transform.scale(pygame.image.load('picture/white/5.png').convert(), SIZE), 116 | '6': pygame.transform.scale(pygame.image.load('picture/white/6.png').convert(), SIZE), 117 | 'BLUEWIN': pygame.transform.scale(pygame.image.load('picture/white/BLUEWIN.png').convert(), WINSIZE), 118 | 'REDWIN': pygame.transform.scale(pygame.image.load('picture/white/REDWIN.png').convert(), WINSIZE), 119 | } 120 | # 布局库 121 | maplib = [[6, 2, 4, 1, 5, 3], 122 | [6, 5, 2, 1, 4, 3], 123 | [1, 5, 4, 6, 2, 3], 124 | [1, 6, 3, 5, 2, 4], 125 | [1, 6, 4, 3, 2, 5], 126 | [6, 1, 2, 5, 4, 3], 127 | [6, 1, 3, 5, 4, 2], 128 | [1, 6, 4, 2, 3, 5], 129 | [1, 5, 2, 6, 3, 4], 130 | [1, 6, 5, 2, 3, 4], 131 | [1, 2, 5, 6, 3, 4], 132 | [6, 2, 5, 1, 4, 3], 133 | [1, 6, 3, 2, 4, 5], 134 | [6, 2, 3, 1, 5, 4], 135 | [1, 6, 3, 4, 2, 5], 136 | [1, 5, 4, 6, 3, 2] 137 | ] 138 | resetInfo() 139 | Lyr = [] 140 | Lyb = [] 141 | Lx = [] 142 | matchPro = 0.85 143 | 144 | 145 | def loadImage(name, pos, size=SIZE): 146 | filename = "picture/white/" + name 147 | screen.blit(pygame.transform.scale( 148 | pygame.image.load(filename).convert(), size), pos) 149 | def waitForPlayerToPressKey(): # 等待按键 150 | while True: 151 | for event in pygame.event.get(): 152 | if event.type == QUIT: 153 | terminate() 154 | if event.type == KEYDOWN: 155 | if event.key == K_ESCAPE: 156 | terminate() 157 | return 158 | 159 | 160 | def drawStartScreen(): # 开始界面 161 | screen.fill(WHITE) 162 | loadImage("AYST.png", (100, 40), AYSTSIZE) 163 | # drawText('EinStein wurfelt nicht', font, GREEN, screen, 260, 200) 164 | drawText('PORT 50006 IS WAITING FOR CONNECTION', font, TEXTCOLOR, screen, 5.5, 0.1) 165 | pygame.display.update() 166 | 167 | 168 | # waitForPlayerToPressKey() 169 | def drawWinScreen(result): # 比赛结束,显示结果界面 170 | if result == BLUEWIN: 171 | loadImage("BLUEWIN.png", (20, 130), WINSIZE) 172 | if result == REDWIN: 173 | loadImage("REDWIN.png", (20, 130), WINSIZE) 174 | # waitForPlayerToPressKey() 175 | pygame.display.update() 176 | sleep(SLEEPTIME) 177 | 178 | def showWinRate(RedWinRate, BlueWinRate, x): 179 | global Lyr, Lyb, Lx 180 | yr = (100 - RedWinRate)/(100/3.0) + 0.6 181 | yb = (100 - BlueWinRate)/(100/3.0) + 0.6 182 | x = x/(1000/5) + 4.2 183 | Lyr.append(copy.deepcopy(yr)) 184 | Lyb.append(copy.deepcopy(yb)) 185 | Lx.append(copy.deepcopy(x)) 186 | for i in range(0, len(Lyr)-1): 187 | pygame.draw.line( 188 | screen, RED, (100*Lx[i], 100*Lyr[i]), (100*Lx[i], 100*Lyr[i+1])) 189 | pygame.draw.line( 190 | screen, BLUE, (100*Lx[i], 100*Lyb[i]), (100*Lx[i], 100*Lyb[i+1])) 191 | def drawGameScreen(conn0, conn1): # 游戏比赛界面 192 | global S 193 | 194 | screen.fill(WHITE) 195 | # 画棋盘 196 | for i in range(6): 197 | x = y = 60*(i+1) 198 | pygame.draw.line(screen, LINECOLOR, (60, y), (360, y)) 199 | pygame.draw.line(screen, LINECOLOR, (x, 60), (x, 360)) 200 | 201 | 202 | drawText('RED : '+str(conn0.ID), font, RED, screen, 6, 1) 203 | drawText('BLUE : '+str(conn1.ID), font, BLUE, screen, 6.5, 1) 204 | 205 | 206 | # 画棋子 207 | for i in range(5): 208 | for j in range(5): 209 | if S.map[i][j] != 0: 210 | drawPawn(S.map[i][j], i, j) 211 | pygame.display.update() 212 | pygame.display.update() 213 | 214 | 215 | def drawMovePawn(n, ans): # 可选择移动的棋子 216 | x = -1 217 | y = 2 218 | for v in ans: 219 | drawPawn(v, x, y) 220 | y += 1 221 | if n <= 6: 222 | loadImage(str(n)+'.png', (310, 5)) 223 | else: 224 | loadImage(str(n-6)+'.png', (310, 5)) 225 | pygame.display.update() 226 | 227 | 228 | def drawPawn(value, row, col, size=SIZE): # 在(row,col)处,画值为value的棋子 229 | pos_x = col * STEP + START 230 | pos_y = row * STEP + START 231 | Pos = (pos_x, pos_y) 232 | if value <= 6: 233 | s = 'R' + str(value) 234 | elif value > 6: 235 | s = 'B' + str(value-6) 236 | loadImage(s+'.png', Pos, size) 237 | 238 | def drawText(text, font, color, surface, row, col): # 处理需要描绘的文字:text:文本;font:格式; 239 | row += 0.2 240 | x = col * STEP 241 | y = row * STEP 242 | textobj = font.render(text, True, color, WHITE) 243 | textrect = textobj.get_rect() 244 | textrect.topleft = (x, y) 245 | surface.blit(textobj, textrect) 246 | 247 | 248 | def selectPawn(S,n=0): # 掷骰子,挑选可以移动的棋子 249 | global COUNT 250 | if n == 0: 251 | COUNT += 1 252 | if COUNT % 2 == 0: 253 | n = random.randint(1, 6) 254 | else: 255 | n = random.randint(7, 12) 256 | ans = findNearby(n, S.pawn) 257 | else: 258 | ans = findNearby(n, S.pawn) 259 | return n, ans 260 | 261 | 262 | def terminate(): # 退出游戏 263 | pygame.quit() 264 | sys.exit() 265 | 266 | 267 | def makeMove(p, PawnMoveTo): # 移动棋子,更新地图信息,和棋子存活情况 268 | row, col = getLocation(p, S.map) 269 | x = y = 0 270 | if PawnMoveTo == LEFT: 271 | y = -1 272 | elif PawnMoveTo == RIGHT: 273 | y = +1 274 | elif PawnMoveTo == UP: 275 | x = -1 276 | elif PawnMoveTo == DOWN: 277 | x = +1 278 | elif PawnMoveTo == LEFTUP: 279 | x = -1 280 | y = -1 281 | elif PawnMoveTo == RIGHTDOWN: 282 | x = +1 283 | y = +1 284 | else: 285 | return False 286 | # 移动无效 287 | if notInMap(row+x, col+y): 288 | return False 289 | S.map[row][col] = 0 290 | row = row + x 291 | col = col + y 292 | # 是否吃掉自己或对方的棋 293 | if S.map[row][col] != 0: 294 | i = S.pawn.index(S.map[row][col]) 295 | S.pawn[i] = 0 296 | S.map[row][col] = p 297 | return True 298 | def notInMap(x, y): # 检测棋子是否在棋盘内移动 299 | if x in range(0, 5) and y in range(0, 5): 300 | return False 301 | return True 302 | 303 | 304 | def showSelected(p): # 用红色标记,显示被挑选的棋子 305 | row, col = getLocation(p, S.map) 306 | pos_x = col * STEP + START 307 | pos_y = row * STEP + START 308 | Pos = (pos_x, pos_y) 309 | if p > 6: 310 | s = 'Y' + str(p-6) 311 | else: 312 | s = 'Y' + str(p) 313 | loadImage(s+'.png', Pos) 314 | # screen.blit(IMAGE[s],Pos) 315 | pygame.display.update() 316 | 317 | 318 | def isEnd(S): # 检测比赛是否结束 319 | if S.map[0][0] > 6: 320 | return BLUEWIN 321 | elif S.map[4][4] > 0 and S.map[4][4] <= 6: 322 | return REDWIN 323 | cnt = 0 324 | for i in range(0, 6): 325 | if S.pawn[i] == 0: 326 | cnt += 1 327 | if cnt == 6: 328 | return BLUEWIN 329 | cnt = 0 330 | for i in range(6, 12): 331 | if S.pawn[i] == 0: 332 | cnt += 1 333 | if cnt == 6: 334 | return REDWIN 335 | return False 336 | 337 | 338 | def resetInfo(): # 重置比赛信息 339 | S.map = getNewMap() 340 | S.pawn = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] # 棋子初始化 341 | S.pro = [1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0 / 342 | 6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6] 343 | value = getLocValue(S) 344 | S.value = getPawnValue(S.pro, value) 345 | 346 | 347 | def getNewMap(): # 换新图 348 | r = random.sample(maplib, 1)[0] 349 | b = random.sample(maplib, 1)[0] 350 | newMap = [ 351 | [r[0], r[3], r[5], 0, 0], 352 | [r[1], r[4], 0, 0, 0], 353 | [r[2], 0, 0, 0, b[2]+6], 354 | [0, 0, 0, b[4]+6, b[1]+6], 355 | [0, 0, b[5]+6, b[3]+6, b[0]+6] 356 | ] 357 | return newMap 358 | 359 | 360 | def getLocValue(S): # 棋子所在位置的价值 361 | blueValue = [[99, 10, 6, 3, 1], 362 | [10, 8, 4, 2, 1], 363 | [6, 4, 4, 2, 1], 364 | [3, 2, 2, 2, 1], 365 | [1, 1, 1, 1, 1]] 366 | redValue = [[1, 1, 1, 1, 1], 367 | [1, 2, 2, 2, 3], 368 | [1, 2, 4, 4, 6], 369 | [1, 2, 4, 8, 10], 370 | [1, 3, 6, 10, 99]] 371 | V = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 372 | for p in range(1, 13): 373 | if S.pawn[p-1] != 0: 374 | row, col = getLocation(p, S.map) 375 | if p <= 6: 376 | V[p-1] = redValue[row][col] 377 | else: 378 | V[p-1] = blueValue[row][col] 379 | return V 380 | def getPawnValue(pro, value): # 棋子价值 381 | V = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 382 | for i in range(0, 12): 383 | V[i] = pro[i] * value[i] 384 | return V 385 | 386 | def findNearby(n, nowPawn): # 寻找可以移动的棋子 387 | ans = [] 388 | # 如果有对应棋子 389 | if nowPawn[n-1] != 0: 390 | ans.append(n) 391 | #没有对应棋子 392 | elif n > 6: 393 | for i in range(n-1, 6, -1): 394 | if i in nowPawn: 395 | ans.append(i) 396 | break 397 | for i in range(n+1, 13): 398 | if i in nowPawn: 399 | ans.append(i) 400 | break 401 | elif n <= 6: 402 | for i in range(n-1, 0, -1): 403 | if i in nowPawn: 404 | ans.append(i) 405 | break 406 | for i in range(n+1, 7): 407 | if i in nowPawn: 408 | ans.append(i) 409 | break 410 | return ans 411 | 412 | 413 | def getLocation(p, Map): # 返回传入地图下,棋子p的坐标 414 | for i in range(5): 415 | for j in range(5): 416 | if Map[i][j] == p: 417 | return i, j 418 | 419 | 420 | def tryMakeMove(p, PawnMoveTo, S): # 尝试移动,并且返回移动后的棋局地图与棋子存活情况 421 | newS = copy.deepcopy(S) 422 | row, col = getLocation(p, newS.map) 423 | x = y = 0 424 | if PawnMoveTo == LEFT: 425 | y = -1 426 | elif PawnMoveTo == RIGHT: 427 | y = +1 428 | elif PawnMoveTo == UP: 429 | x = -1 430 | elif PawnMoveTo == DOWN: 431 | x = +1 432 | elif PawnMoveTo == LEFTUP: 433 | x = -1 434 | y = -1 435 | elif PawnMoveTo == RIGHTDOWN: 436 | x = +1 437 | y = +1 438 | # 移动无效 439 | if notInMap(row+x, col+y): 440 | return False 441 | newS.map[row][col] = 0 442 | row = row + x 443 | col = col + y 444 | if newS.map[row][col] != 0: 445 | i = newS.pawn.index(newS.map[row][col]) 446 | newS.pawn[i] = 0 447 | newS.map[row][col] = p 448 | # value = getLocValue(newS) # 获取所有棋子的位置价值 449 | # newS.pro = getPawnPro(newS) # 获取所有棋子被摇到的概率 450 | # newS.value = getPawnValue(value, newS.pro) 451 | newS.parent = S 452 | newS.pPawn = p 453 | newS.pMove = PawnMoveTo 454 | if p < 7: 455 | newS.cPawn = [INFTY,INFTY,INFTY,INFTY,INFTY,INFTY] 456 | newS.cPawnSecond = [INFTY,INFTY,INFTY,INFTY,INFTY,INFTY] 457 | else: 458 | newS.cPawn = [-INFTY,-INFTY,-INFTY,-INFTY,-INFTY,-INFTY] 459 | newS.cPawnSecond = [-INFTY,-INFTY,-INFTY,-INFTY,-INFTY,-INFTY] 460 | return newS 461 | 462 | 463 | 464 | # 20190302 socket 移动棋子,如果走错直接输 465 | def socketToMove(conn,n, ans, S): 466 | message = str(S.map) + '|' + str(n) 467 | conn.sendall(message.encode('UTF-8')) 468 | try: 469 | conn.settimeout(5) 470 | data, address = conn.recvfrom(1024) 471 | except socket.error as e: 472 | logger.info(str(e)) 473 | return -1, 'timeout' 474 | text = (data.decode('UTF-8')[:-1]).split('|') 475 | try: 476 | p = int(text[0]) 477 | moveTo = text[1] 478 | except TypeError as tp: 479 | return -1, 'not move' 480 | 481 | if (p in ans): 482 | if p > 0 and p < 7: 483 | if moveTo == DOWN or moveTo == RIGHT or moveTo == RIGHTDOWN: 484 | newS = tryMakeMove(p, moveTo, S) 485 | if newS is not False: 486 | return p, moveTo 487 | elif p > 6 and p < 13: 488 | if moveTo == UP or moveTo == LEFT or moveTo == LEFTUP: 489 | newS = tryMakeMove(p, moveTo, S) 490 | if newS is not False: 491 | return p, moveTo 492 | return -1, 'not move' 493 | 494 | 495 | def outputResult(): 496 | global clients 497 | rank = clients.copy() 498 | if currentnum == playernum: 499 | for i in range(playernum - 1): 500 | for j in range(playernum - i - 1): 501 | if (rank[j].wins < rank[j + 1].wins): 502 | rank[j], rank[j + 1] = rank[j + 1], rank[j] 503 | with open('BATTLERESULT.txt',mode='w', encoding='utf8') as f: 504 | for c in rank: 505 | f.writelines(str(c.ID) + ' WINTIMES : ' + str(c.wins)+str('\n')) 506 | logger.info('WRITE INTO BATTLERESULT') 507 | 508 | 509 | def startgame(port, n, detail=True): 510 | global COUNT 511 | global playernum 512 | global clients 513 | global currentnum 514 | wins = [0 for i in range(playernum)] 515 | init() 516 | if detail: 517 | drawStartScreen() # 游戏开始界面 518 | RESULT[0] = 0 519 | RESULT[1] = 0 520 | cnt = n 521 | rateline = [] 522 | 523 | # while(playernum == 0): 524 | # sleep(1) 525 | 526 | #客户端 527 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 528 | sock.bind(('0.0.0.0', port)) 529 | 530 | for i in range(playernum): 531 | sock.listen() 532 | conn, addr = sock.accept() 533 | # 获取用户ID 534 | playerID = conn.recv(1024).decode('utf8')[:-1] 535 | clients.append(Player(playerID, conn)) 536 | print('client_{} connected: {}'.format(i, addr)) 537 | logger.info('client_'+str(i)+' connected: '+str(addr)) 538 | currentnum = i+1 539 | # app.refresh() 540 | 541 | 542 | 543 | for i in range(0, playernum-1): 544 | for j in range(i+1, playernum): 545 | count = cnt 546 | while count: 547 | resetInfo() 548 | #result = playGame(Red, Blue, detail) # 游戏开始,返回比赛结果 549 | result = battle(clients[i], clients[j], detail) 550 | if detail: 551 | # pass 552 | drawWinScreen(result) 553 | if result == REDWIN: 554 | clients[i].wins = clients[i].wins+1 555 | else: 556 | clients[j].wins = clients[j].wins+1 557 | # app.refresh() 558 | 559 | RESULT[result - 1] += 1 # 更新比分 560 | count -= 1 561 | COUNT = 2000 - count - 1 # 先手方交替 562 | rateline.append(float(RESULT[0]) / sum(RESULT)) 563 | if count % 5 == 0: 564 | # pass 565 | print(sum(RESULT), '\t', round(100 * RESULT[0] / sum(RESULT), 4)) 566 | for i in range(playernum): 567 | try: 568 | # logger.info('rank : '+str(i)+' '+ clients[i].ID + ' wins '+str( clients[i].wins)) 569 | clients[i].clientsock.sendall('close'.encode('utf8')) 570 | except socket.error as e: 571 | logger.info(str('ERRORS ') + str(e)) 572 | rank = clients.copy() 573 | if currentnum == playernum: 574 | for i in range(playernum - 1): 575 | for j in range(playernum - i - 1): 576 | if (rank[j].wins < rank[j + 1].wins): 577 | rank[j], rank[j + 1] = rank[j + 1], rank[j] 578 | for i in range(playernum): 579 | logger.info('rank : ' + str(i+1) + ' ' + rank[i].ID + ' wins ' + str(rank[i].wins)) 580 | 581 | sock.close() 582 | 583 | 584 | def battle(client0, client1, detail): 585 | lastInfo = [] 586 | mapNeedRedraw = True # 是否需要重新绘制地图 587 | if detail: 588 | drawGameScreen(client0, client1) 589 | while True: 590 | 591 | moveTo = None # 棋子移动方向 592 | mapNeedRedraw = False 593 | n, ans = selectPawn(S) 594 | if detail: 595 | drawMovePawn(n, ans) 596 | for event in pygame.event.get(): 597 | if event.type == QUIT: 598 | terminate() 599 | try: 600 | sleep(SLEEPTIME) 601 | if COUNT % 2 == 0: 602 | p, moveTo = socketToMove(conn=client0.clientsock, n=n, ans=ans, S=S) 603 | if p == -1: 604 | logger.info(str('RESULT : '+client1.ID+' WIN')) 605 | return BLUEWIN 606 | except socket.error as e: 607 | logger.info(str('ERRORS ')+str(e) ) 608 | logger.info(str('RESULT : ' + client1.ID + ' WIN')) 609 | return BLUEWIN 610 | except ValueError as e1: 611 | logger.info(str('ERRORS ')+str(e1)) 612 | logger.info(str('RESULT : ' + client1.ID + ' WIN')) 613 | return BLUEWIN 614 | 615 | 616 | try: 617 | if COUNT % 2 == 1: 618 | p, moveTo = socketToMove(conn=client1.clientsock, n=n, ans=ans, S=S) 619 | if p == -1: 620 | str('RESULT : ' + client0.ID + ' WIN') 621 | return REDWIN 622 | except socket.error as e: 623 | logger.info(str('ERRORS ') + str(e)) 624 | logger.info(str('RESULT : ' + client0.ID + ' WIN')) 625 | return REDWIN 626 | except ValueError as e1: 627 | logger.info(str('ERRORS ') + str(e1)) 628 | logger.info(str('RESULT : ' + client0.ID + ' WIN')) 629 | return REDWIN 630 | 631 | 632 | if moveTo != None: 633 | moved = makeMove(p, moveTo) 634 | lastInfo = [n, p, moveTo] 635 | if moved: 636 | mapNeedRedraw = True 637 | if mapNeedRedraw and detail: # 如果需要重绘棋局界面,则: 638 | drawGameScreen(client0, client1) # 重绘棋局界面 639 | logger.info(str(S.map) + ' |id: ' + str(p) + ' |move : ' + moveTo) 640 | pass 641 | result = isEnd(S) # 检查游戏是否结束,返回游戏结果 642 | if result: 643 | lastInfo = [] 644 | logger.info(str('RESULT : '+client0.ID+' WIN') if result == 1 else str('RESULT : '+client1.ID+' WIN')) 645 | return result 646 | 647 | 648 | 649 | if __name__ == '__main__': 650 | # 测试局数 651 | cnt = 100 652 | result = startgame(port=50006, n=cnt) 653 | outputResult() 654 | input('enter any key to stop\n') 655 | sys.exit() 656 | -------------------------------------------------------------------------------- /EinsteinChessTestServer/einstein双人对战平台/2PlayersServer.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/einstein双人对战平台/2PlayersServer.mp4 -------------------------------------------------------------------------------- /EinsteinChessTestServer/einstein双人对战平台/Twoplayers-BattleServer.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import os 3 | import sys 4 | import random 5 | import copy 6 | import socket 7 | import logging 8 | from pygame.locals import * 9 | from sys import exit 10 | from time import ctime, sleep 11 | import logging 12 | 13 | WINDOWSIZE = (450, 450) # 游戏窗口大小 14 | LINECOLOR = (0, 0, 0) # 棋盘线的颜色 15 | TEXTCOLOR = (0, 0, 0) # 标题文本颜色 16 | BLACKGROUND = (255, 255, 255) # 游戏背景颜色 17 | BLACK = (0, 0, 0) 18 | BLUE = (0, 191, 255) 19 | YELLOW = (255, 255, 0) 20 | RED = (255, 0, 0) 21 | GREEN = (0, 255, 0) 22 | WHITE = (255, 255, 255) 23 | SIZE = (50, 50) # 棋子大小 24 | AYSTSIZE = (240, 240) # 爱因斯坦背景头像图片大小 25 | POSAYST = (365, 0) # 爱因斯坦头像位置 26 | STEP = 60 # 步长:棋子走一步移动的距离 27 | TEXTSIZE = 30 # 标题文字大小 28 | TIPSIZE = 15 # 提示文字大小 29 | COUNT = -1 # 记录当前回合 30 | START = 65 # 棋盘左上角起始点(70,70) 31 | REDWIN = 1 # 代表RED方赢 32 | BLUEWIN = 2 # 代表玩家BLUE方赢 33 | LEFT = 'left' 34 | RIGHT = 'right' 35 | UP = 'up' 36 | DOWN = 'down' 37 | LEFTUP = 'leftup' 38 | RIGHTDOWN = 'rightdown' 39 | RESULT = [0, 0] # 记录比赛结果 40 | WINSIZE = (400, 90) # 显示比赛结果窗口大小 41 | INFTY = 10000 42 | SLEEPTIME = 0 43 | clock = pygame.time.Clock() 44 | clients = list() 45 | logging.basicConfig(level=logging.INFO, format='%(asctime)s %(name)s- %(levelname)s - %(message)s', filename='battle.log') 46 | logger = logging.getLogger() 47 | 48 | ch = logging.StreamHandler() #日志输出到屏幕控制台 49 | ch.setLevel(logging.INFO) #设置日志等级 50 | formatter = logging.Formatter('%(asctime)s %(name)s- %(levelname)s - %(message)s') #定义日志输出格式 51 | ch.setFormatter(formatter) #选择一个格式 52 | logger.addHandler(ch) #增加指定的handler 53 | playernum = 2 54 | currentnum = 0 55 | start = 0 56 | 57 | 58 | class Status(object): 59 | def __init__(self): 60 | self.map = None 61 | self.value = None 62 | self.pawn = None 63 | self.pro = None 64 | self.parent = None 65 | self.pPawn = None 66 | self.pMove = None 67 | self.pDice = None 68 | self.cPawn = None 69 | self.cPawnSecond = None 70 | self.cPM = [[],[],[],[],[],[]] 71 | self.cPMSecond = [[],[],[],[],[],[]] 72 | def print(self): 73 | print(self.cPM) 74 | 75 | class Player: 76 | 77 | ID = 'ID' 78 | wins = 0 79 | def __init__(self, id, sock): 80 | self.ID = id 81 | self.clientsock = sock 82 | 83 | def init(): 84 | global IMAGE,tip,screen,font,maplib,Lyr,Lyb,Lx,S,matchPro 85 | pygame.init() 86 | S = Status() 87 | screen = pygame.display.set_mode(WINDOWSIZE, 0, 32) # 设置游戏窗口 88 | pygame.display.set_caption('Einstein Chess-Player 0 VS Player 1') # 设置Caption 89 | font = pygame.font.SysFont("Cambria Math", TEXTSIZE, 90 | bold=False, italic=False) # 设置标题字体格式 91 | tip = pygame.font.SysFont("arial", TIPSIZE, bold=False, italic=False) # 设置提示字体 92 | IMAGE = { 93 | 'R1': pygame.transform.scale(pygame.image.load('picture/white/R1.png').convert(), SIZE), 94 | 'R2': pygame.transform.scale(pygame.image.load('picture/white/R2.png').convert(), SIZE), 95 | 'R3': pygame.transform.scale(pygame.image.load('picture/white/R3.png').convert(), SIZE), 96 | 'R4': pygame.transform.scale(pygame.image.load('picture/white/R4.png').convert(), SIZE), 97 | 'R5': pygame.transform.scale(pygame.image.load('picture/white/R5.png').convert(), SIZE), 98 | 'R6': pygame.transform.scale(pygame.image.load('picture/white/R6.png').convert(), SIZE), 99 | 'B1': pygame.transform.scale(pygame.image.load('picture/white/B1.png').convert(), SIZE), 100 | 'B2': pygame.transform.scale(pygame.image.load('picture/white/B2.png').convert(), SIZE), 101 | 'B3': pygame.transform.scale(pygame.image.load('picture/white/B3.png').convert(), SIZE), 102 | 'B4': pygame.transform.scale(pygame.image.load('picture/white/B4.png').convert(), SIZE), 103 | 'B5': pygame.transform.scale(pygame.image.load('picture/white/B5.png').convert(), SIZE), 104 | 'B6': pygame.transform.scale(pygame.image.load('picture/white/B6.png').convert(), SIZE), 105 | 'Y1': pygame.transform.scale(pygame.image.load('picture/white/Y1.png').convert(), SIZE), 106 | 'Y2': pygame.transform.scale(pygame.image.load('picture/white/Y2.png').convert(), SIZE), 107 | 'Y3': pygame.transform.scale(pygame.image.load('picture/white/Y3.png').convert(), SIZE), 108 | 'Y4': pygame.transform.scale(pygame.image.load('picture/white/Y4.png').convert(), SIZE), 109 | 'Y5': pygame.transform.scale(pygame.image.load('picture/white/Y5.png').convert(), SIZE), 110 | 'Y6': pygame.transform.scale(pygame.image.load('picture/white/Y6.png').convert(), SIZE), 111 | '1': pygame.transform.scale(pygame.image.load('picture/white/1.png').convert(), SIZE), 112 | '2': pygame.transform.scale(pygame.image.load('picture/white/2.png').convert(), SIZE), 113 | '3': pygame.transform.scale(pygame.image.load('picture/white/3.png').convert(), SIZE), 114 | '4': pygame.transform.scale(pygame.image.load('picture/white/4.png').convert(), SIZE), 115 | '5': pygame.transform.scale(pygame.image.load('picture/white/5.png').convert(), SIZE), 116 | '6': pygame.transform.scale(pygame.image.load('picture/white/6.png').convert(), SIZE), 117 | 'BLUEWIN': pygame.transform.scale(pygame.image.load('picture/white/BLUEWIN.png').convert(), WINSIZE), 118 | 'REDWIN': pygame.transform.scale(pygame.image.load('picture/white/REDWIN.png').convert(), WINSIZE), 119 | } 120 | # 布局库 121 | maplib = [[6, 2, 4, 1, 5, 3], 122 | [6, 5, 2, 1, 4, 3], 123 | [1, 5, 4, 6, 2, 3], 124 | [1, 6, 3, 5, 2, 4], 125 | [1, 6, 4, 3, 2, 5], 126 | [6, 1, 2, 5, 4, 3], 127 | [6, 1, 3, 5, 4, 2], 128 | [1, 6, 4, 2, 3, 5], 129 | [1, 5, 2, 6, 3, 4], 130 | [1, 6, 5, 2, 3, 4], 131 | [1, 2, 5, 6, 3, 4], 132 | [6, 2, 5, 1, 4, 3], 133 | [1, 6, 3, 2, 4, 5], 134 | [6, 2, 3, 1, 5, 4], 135 | [1, 6, 3, 4, 2, 5], 136 | [1, 5, 4, 6, 3, 2] 137 | ] 138 | resetInfo() 139 | Lyr = [] 140 | Lyb = [] 141 | Lx = [] 142 | matchPro = 0.85 143 | 144 | 145 | def loadImage(name, pos, size=SIZE): 146 | filename = "picture/white/" + name 147 | screen.blit(pygame.transform.scale( 148 | pygame.image.load(filename).convert(), size), pos) 149 | def waitForPlayerToPressKey(): # 等待按键 150 | while True: 151 | for event in pygame.event.get(): 152 | if event.type == QUIT: 153 | terminate() 154 | if event.type == KEYDOWN: 155 | if event.key == K_ESCAPE: 156 | terminate() 157 | return 158 | 159 | 160 | def drawStartScreen(): # 开始界面 161 | screen.fill(WHITE) 162 | loadImage("AYST.png", (100, 40), AYSTSIZE) 163 | # drawText('EinStein wurfelt nicht', font, GREEN, screen, 260, 200) 164 | drawText('PORT 50006 IS WAITING FOR CONNECTION', font, TEXTCOLOR, screen, 5.5, 0.1) 165 | pygame.display.update() 166 | 167 | 168 | # waitForPlayerToPressKey() 169 | def drawWinScreen(result): # 比赛结束,显示结果界面 170 | if result == BLUEWIN: 171 | loadImage("BLUEWIN.png", (20, 130), WINSIZE) 172 | if result == REDWIN: 173 | loadImage("REDWIN.png", (20, 130), WINSIZE) 174 | # waitForPlayerToPressKey() 175 | pygame.display.update() 176 | sleep(SLEEPTIME) 177 | 178 | def showWinRate(RedWinRate, BlueWinRate, x): 179 | global Lyr, Lyb, Lx 180 | yr = (100 - RedWinRate)/(100/3.0) + 0.6 181 | yb = (100 - BlueWinRate)/(100/3.0) + 0.6 182 | x = x/(1000/5) + 4.2 183 | Lyr.append(copy.deepcopy(yr)) 184 | Lyb.append(copy.deepcopy(yb)) 185 | Lx.append(copy.deepcopy(x)) 186 | for i in range(0, len(Lyr)-1): 187 | pygame.draw.line( 188 | screen, RED, (100*Lx[i], 100*Lyr[i]), (100*Lx[i], 100*Lyr[i+1])) 189 | pygame.draw.line( 190 | screen, BLUE, (100*Lx[i], 100*Lyb[i]), (100*Lx[i], 100*Lyb[i+1])) 191 | def drawGameScreen(conn0, conn1): # 游戏比赛界面 192 | global S 193 | 194 | screen.fill(WHITE) 195 | # 画棋盘 196 | for i in range(6): 197 | x = y = 60*(i+1) 198 | pygame.draw.line(screen, LINECOLOR, (60, y), (360, y)) 199 | pygame.draw.line(screen, LINECOLOR, (x, 60), (x, 360)) 200 | 201 | 202 | drawText('RED : '+str(conn0.ID), font, RED, screen, 6, 1) 203 | drawText('BLUE : '+str(conn1.ID), font, BLUE, screen, 6.5, 1) 204 | 205 | 206 | # 画棋子 207 | for i in range(5): 208 | for j in range(5): 209 | if S.map[i][j] != 0: 210 | drawPawn(S.map[i][j], i, j) 211 | pygame.display.update() 212 | pygame.display.update() 213 | 214 | 215 | def drawMovePawn(n, ans): # 可选择移动的棋子 216 | x = -1 217 | y = 2 218 | for v in ans: 219 | drawPawn(v, x, y) 220 | y += 1 221 | if n <= 6: 222 | loadImage(str(n)+'.png', (310, 5)) 223 | else: 224 | loadImage(str(n-6)+'.png', (310, 5)) 225 | pygame.display.update() 226 | 227 | 228 | def drawPawn(value, row, col, size=SIZE): # 在(row,col)处,画值为value的棋子 229 | pos_x = col * STEP + START 230 | pos_y = row * STEP + START 231 | Pos = (pos_x, pos_y) 232 | if value <= 6: 233 | s = 'R' + str(value) 234 | elif value > 6: 235 | s = 'B' + str(value-6) 236 | loadImage(s+'.png', Pos, size) 237 | 238 | def drawText(text, font, color, surface, row, col): # 处理需要描绘的文字:text:文本;font:格式; 239 | row += 0.2 240 | x = col * STEP 241 | y = row * STEP 242 | textobj = font.render(text, True, color, WHITE) 243 | textrect = textobj.get_rect() 244 | textrect.topleft = (x, y) 245 | surface.blit(textobj, textrect) 246 | 247 | 248 | def selectPawn(S,n=0): # 掷骰子,挑选可以移动的棋子 249 | global COUNT 250 | if n == 0: 251 | COUNT += 1 252 | if COUNT % 2 == 0: 253 | n = random.randint(1, 6) 254 | else: 255 | n = random.randint(7, 12) 256 | ans = findNearby(n, S.pawn) 257 | else: 258 | ans = findNearby(n, S.pawn) 259 | return n, ans 260 | 261 | 262 | def terminate(): # 退出游戏 263 | pygame.quit() 264 | sys.exit() 265 | 266 | 267 | def makeMove(p, PawnMoveTo): # 移动棋子,更新地图信息,和棋子存活情况 268 | row, col = getLocation(p, S.map) 269 | x = y = 0 270 | if PawnMoveTo == LEFT: 271 | y = -1 272 | elif PawnMoveTo == RIGHT: 273 | y = +1 274 | elif PawnMoveTo == UP: 275 | x = -1 276 | elif PawnMoveTo == DOWN: 277 | x = +1 278 | elif PawnMoveTo == LEFTUP: 279 | x = -1 280 | y = -1 281 | elif PawnMoveTo == RIGHTDOWN: 282 | x = +1 283 | y = +1 284 | else: 285 | return False 286 | # 移动无效 287 | if notInMap(row+x, col+y): 288 | return False 289 | S.map[row][col] = 0 290 | row = row + x 291 | col = col + y 292 | # 是否吃掉自己或对方的棋 293 | if S.map[row][col] != 0: 294 | i = S.pawn.index(S.map[row][col]) 295 | S.pawn[i] = 0 296 | S.map[row][col] = p 297 | return True 298 | def notInMap(x, y): # 检测棋子是否在棋盘内移动 299 | if x in range(0, 5) and y in range(0, 5): 300 | return False 301 | return True 302 | 303 | 304 | def showSelected(p): # 用红色标记,显示被挑选的棋子 305 | row, col = getLocation(p, S.map) 306 | pos_x = col * STEP + START 307 | pos_y = row * STEP + START 308 | Pos = (pos_x, pos_y) 309 | if p > 6: 310 | s = 'Y' + str(p-6) 311 | else: 312 | s = 'Y' + str(p) 313 | loadImage(s+'.png', Pos) 314 | # screen.blit(IMAGE[s],Pos) 315 | pygame.display.update() 316 | 317 | 318 | def isEnd(S): # 检测比赛是否结束 319 | if S.map[0][0] > 6: 320 | return BLUEWIN 321 | elif S.map[4][4] > 0 and S.map[4][4] <= 6: 322 | return REDWIN 323 | cnt = 0 324 | for i in range(0, 6): 325 | if S.pawn[i] == 0: 326 | cnt += 1 327 | if cnt == 6: 328 | return BLUEWIN 329 | cnt = 0 330 | for i in range(6, 12): 331 | if S.pawn[i] == 0: 332 | cnt += 1 333 | if cnt == 6: 334 | return REDWIN 335 | return False 336 | 337 | 338 | def resetInfo(): # 重置比赛信息 339 | S.map = getNewMap() 340 | S.pawn = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] # 棋子初始化 341 | S.pro = [1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0 / 342 | 6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6] 343 | value = getLocValue(S) 344 | S.value = getPawnValue(S.pro, value) 345 | 346 | 347 | def getNewMap(): # 换新图 348 | r = random.sample(maplib, 1)[0] 349 | b = random.sample(maplib, 1)[0] 350 | newMap = [ 351 | [r[0], r[3], r[5], 0, 0], 352 | [r[1], r[4], 0, 0, 0], 353 | [r[2], 0, 0, 0, b[2]+6], 354 | [0, 0, 0, b[4]+6, b[1]+6], 355 | [0, 0, b[5]+6, b[3]+6, b[0]+6] 356 | ] 357 | return newMap 358 | 359 | 360 | def getLocValue(S): # 棋子所在位置的价值 361 | blueValue = [[99, 10, 6, 3, 1], 362 | [10, 8, 4, 2, 1], 363 | [6, 4, 4, 2, 1], 364 | [3, 2, 2, 2, 1], 365 | [1, 1, 1, 1, 1]] 366 | redValue = [[1, 1, 1, 1, 1], 367 | [1, 2, 2, 2, 3], 368 | [1, 2, 4, 4, 6], 369 | [1, 2, 4, 8, 10], 370 | [1, 3, 6, 10, 99]] 371 | V = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 372 | for p in range(1, 13): 373 | if S.pawn[p-1] != 0: 374 | row, col = getLocation(p, S.map) 375 | if p <= 6: 376 | V[p-1] = redValue[row][col] 377 | else: 378 | V[p-1] = blueValue[row][col] 379 | return V 380 | def getPawnValue(pro, value): # 棋子价值 381 | V = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 382 | for i in range(0, 12): 383 | V[i] = pro[i] * value[i] 384 | return V 385 | 386 | def findNearby(n, nowPawn): # 寻找可以移动的棋子 387 | ans = [] 388 | # 如果有对应棋子 389 | if nowPawn[n-1] != 0: 390 | ans.append(n) 391 | #没有对应棋子 392 | elif n > 6: 393 | for i in range(n-1, 6, -1): 394 | if i in nowPawn: 395 | ans.append(i) 396 | break 397 | for i in range(n+1, 13): 398 | if i in nowPawn: 399 | ans.append(i) 400 | break 401 | elif n <= 6: 402 | for i in range(n-1, 0, -1): 403 | if i in nowPawn: 404 | ans.append(i) 405 | break 406 | for i in range(n+1, 7): 407 | if i in nowPawn: 408 | ans.append(i) 409 | break 410 | return ans 411 | 412 | 413 | def getLocation(p, Map): # 返回传入地图下,棋子p的坐标 414 | for i in range(5): 415 | for j in range(5): 416 | if Map[i][j] == p: 417 | return i, j 418 | 419 | 420 | def tryMakeMove(p, PawnMoveTo, S): # 尝试移动,并且返回移动后的棋局地图与棋子存活情况 421 | newS = copy.deepcopy(S) 422 | row, col = getLocation(p, newS.map) 423 | x = y = 0 424 | if PawnMoveTo == LEFT: 425 | y = -1 426 | elif PawnMoveTo == RIGHT: 427 | y = +1 428 | elif PawnMoveTo == UP: 429 | x = -1 430 | elif PawnMoveTo == DOWN: 431 | x = +1 432 | elif PawnMoveTo == LEFTUP: 433 | x = -1 434 | y = -1 435 | elif PawnMoveTo == RIGHTDOWN: 436 | x = +1 437 | y = +1 438 | # 移动无效 439 | if notInMap(row+x, col+y): 440 | return False 441 | newS.map[row][col] = 0 442 | row = row + x 443 | col = col + y 444 | if newS.map[row][col] != 0: 445 | i = newS.pawn.index(newS.map[row][col]) 446 | newS.pawn[i] = 0 447 | newS.map[row][col] = p 448 | # value = getLocValue(newS) # 获取所有棋子的位置价值 449 | # newS.pro = getPawnPro(newS) # 获取所有棋子被摇到的概率 450 | # newS.value = getPawnValue(value, newS.pro) 451 | newS.parent = S 452 | newS.pPawn = p 453 | newS.pMove = PawnMoveTo 454 | if p < 7: 455 | newS.cPawn = [INFTY,INFTY,INFTY,INFTY,INFTY,INFTY] 456 | newS.cPawnSecond = [INFTY,INFTY,INFTY,INFTY,INFTY,INFTY] 457 | else: 458 | newS.cPawn = [-INFTY,-INFTY,-INFTY,-INFTY,-INFTY,-INFTY] 459 | newS.cPawnSecond = [-INFTY,-INFTY,-INFTY,-INFTY,-INFTY,-INFTY] 460 | return newS 461 | 462 | 463 | 464 | # 20190302 socket 移动棋子,如果走错直接输 465 | def socketToMove(conn,n, ans, S): 466 | message = str(S.map) + '|' + str(n) 467 | conn.sendall(message.encode('UTF-8')) 468 | try: 469 | conn.settimeout(5) 470 | data, address = conn.recvfrom(1024) 471 | except socket.error as e: 472 | logger.info(str(e)) 473 | return -1, 'timeout' 474 | text = (data.decode('UTF-8')[:-1]).split('|') 475 | try: 476 | p = int(text[0]) 477 | moveTo = text[1] 478 | except TypeError as tp: 479 | return -1, 'not move' 480 | 481 | if (p in ans): 482 | if p > 0 and p < 7: 483 | if moveTo == DOWN or moveTo == RIGHT or moveTo == RIGHTDOWN: 484 | newS = tryMakeMove(p, moveTo, S) 485 | if newS is not False: 486 | return p, moveTo 487 | elif p > 6 and p < 13: 488 | if moveTo == UP or moveTo == LEFT or moveTo == LEFTUP: 489 | newS = tryMakeMove(p, moveTo, S) 490 | if newS is not False: 491 | return p, moveTo 492 | return -1, 'not move' 493 | 494 | 495 | def outputResult(): 496 | global clients 497 | rank = clients.copy() 498 | if currentnum == playernum: 499 | for i in range(playernum - 1): 500 | for j in range(playernum - i - 1): 501 | if (rank[j].wins < rank[j + 1].wins): 502 | rank[j], rank[j + 1] = rank[j + 1], rank[j] 503 | with open('BATTLERESULT.txt',mode='w', encoding='utf8') as f: 504 | for c in rank: 505 | f.writelines(str(c.ID) + ' WINTIMES : ' + str(c.wins)+str('\n')) 506 | logger.info('WRITE INTO BATTLERESULT') 507 | 508 | 509 | def startgame(port, n, detail=True): 510 | global COUNT 511 | global playernum 512 | global clients 513 | global currentnum 514 | wins = [0 for i in range(playernum)] 515 | init() 516 | if detail: 517 | drawStartScreen() # 游戏开始界面 518 | RESULT[0] = 0 519 | RESULT[1] = 0 520 | cnt = n 521 | rateline = [] 522 | 523 | # while(playernum == 0): 524 | # sleep(1) 525 | 526 | #客户端 527 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 528 | sock.bind(('0.0.0.0', port)) 529 | 530 | for i in range(playernum): 531 | sock.listen() 532 | conn, addr = sock.accept() 533 | # 获取用户ID 534 | playerID = conn.recv(1024).decode('utf8')[:-1] 535 | clients.append(Player(playerID, conn)) 536 | print('client_{} connected: {}'.format(i, addr)) 537 | logger.info('client_'+str(i)+' connected: '+str(addr)) 538 | currentnum = i+1 539 | # app.refresh() 540 | 541 | 542 | 543 | for i in range(0, playernum-1): 544 | for j in range(i+1, playernum): 545 | count = cnt 546 | while count: 547 | resetInfo() 548 | #result = playGame(Red, Blue, detail) # 游戏开始,返回比赛结果 549 | result = battle(clients[i], clients[j], detail) 550 | if detail: 551 | # pass 552 | drawWinScreen(result) 553 | if result == REDWIN: 554 | clients[i].wins = clients[i].wins+1 555 | else: 556 | clients[j].wins = clients[j].wins+1 557 | # app.refresh() 558 | 559 | RESULT[result - 1] += 1 # 更新比分 560 | count -= 1 561 | COUNT = 2000 - count - 1 # 先手方交替 562 | rateline.append(float(RESULT[0]) / sum(RESULT)) 563 | if count % 5 == 0: 564 | # pass 565 | print(sum(RESULT), '\t', round(100 * RESULT[0] / sum(RESULT), 4)) 566 | for i in range(playernum): 567 | try: 568 | # logger.info('rank : '+str(i)+' '+ clients[i].ID + ' wins '+str( clients[i].wins)) 569 | clients[i].clientsock.sendall('close'.encode('utf8')) 570 | except socket.error as e: 571 | logger.info(str('ERRORS ') + str(e)) 572 | rank = clients.copy() 573 | if currentnum == playernum: 574 | for i in range(playernum - 1): 575 | for j in range(playernum - i - 1): 576 | if (rank[j].wins < rank[j + 1].wins): 577 | rank[j], rank[j + 1] = rank[j + 1], rank[j] 578 | for i in range(playernum): 579 | logger.info('rank : ' + str(i+1) + ' ' + rank[i].ID + ' wins ' + str(rank[i].wins)) 580 | 581 | sock.close() 582 | 583 | 584 | def battle(client0, client1, detail): 585 | lastInfo = [] 586 | mapNeedRedraw = True # 是否需要重新绘制地图 587 | if detail: 588 | drawGameScreen(client0, client1) 589 | while True: 590 | 591 | moveTo = None # 棋子移动方向 592 | mapNeedRedraw = False 593 | n, ans = selectPawn(S) 594 | if detail: 595 | drawMovePawn(n, ans) 596 | for event in pygame.event.get(): 597 | if event.type == QUIT: 598 | terminate() 599 | try: 600 | sleep(SLEEPTIME) 601 | if COUNT % 2 == 0: 602 | p, moveTo = socketToMove(conn=client0.clientsock, n=n, ans=ans, S=S) 603 | if p == -1: 604 | logger.info(str('RESULT : '+client1.ID+' WIN')) 605 | return BLUEWIN 606 | except socket.error as e: 607 | logger.info(str('ERRORS ')+str(e) ) 608 | logger.info(str('RESULT : ' + client1.ID + ' WIN')) 609 | return BLUEWIN 610 | except ValueError as e1: 611 | logger.info(str('ERRORS ')+str(e1)) 612 | logger.info(str('RESULT : ' + client1.ID + ' WIN')) 613 | return BLUEWIN 614 | 615 | 616 | try: 617 | if COUNT % 2 == 1: 618 | p, moveTo = socketToMove(conn=client1.clientsock, n=n, ans=ans, S=S) 619 | if p == -1: 620 | str('RESULT : ' + client0.ID + ' WIN') 621 | return REDWIN 622 | except socket.error as e: 623 | logger.info(str('ERRORS ') + str(e)) 624 | logger.info(str('RESULT : ' + client0.ID + ' WIN')) 625 | return REDWIN 626 | except ValueError as e1: 627 | logger.info(str('ERRORS ') + str(e1)) 628 | logger.info(str('RESULT : ' + client0.ID + ' WIN')) 629 | return REDWIN 630 | 631 | 632 | if moveTo != None: 633 | moved = makeMove(p, moveTo) 634 | lastInfo = [n, p, moveTo] 635 | if moved: 636 | mapNeedRedraw = True 637 | if mapNeedRedraw and detail: # 如果需要重绘棋局界面,则: 638 | drawGameScreen(client0, client1) # 重绘棋局界面 639 | logger.info(str(S.map) + ' |id: ' + str(p) + ' |move : ' + moveTo) 640 | pass 641 | result = isEnd(S) # 检查游戏是否结束,返回游戏结果 642 | if result: 643 | lastInfo = [] 644 | logger.info(str('RESULT : '+client0.ID+' WIN') if result == 1 else str('RESULT : '+client1.ID+' WIN')) 645 | return result 646 | 647 | 648 | 649 | if __name__ == '__main__': 650 | # 测试局数 651 | cnt = 100 652 | result = startgame(port=50006, n=cnt) 653 | outputResult() 654 | input('enter any key to stop\n') 655 | sys.exit() 656 | -------------------------------------------------------------------------------- /EinsteinChessTestServer/einstein双人对战平台/双人对战平台使用说明.txt: -------------------------------------------------------------------------------- 1 | 1. 将py文件放到TestServer.py 相同目录即可运行 2 | 3 | 具体情况请参照压缩文件中视频 -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/1.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/2.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/3.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/4.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/5.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/6.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/AYST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/AYST.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/B1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/B1.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/B2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/B2.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/B3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/B3.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/B4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/B4.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/B5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/B5.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/B6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/B6.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/BLUEWIN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/BLUEWIN.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/R1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/R1.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/R2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/R2.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/R3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/R3.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/R4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/R4.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/R5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/R5.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/R6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/R6.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/REDWIN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/REDWIN.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/Y1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/Y1.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/Y2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/Y2.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/Y3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/Y3.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/Y4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/Y4.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/Y5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/Y5.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/Y6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/Y6.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/equation.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/equation.jpeg -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/black/shy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/black/shy.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/1.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/2.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/3.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/4.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/5.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/6.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/AYST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/AYST.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/B1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/B1.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/B2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/B2.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/B3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/B3.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/B4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/B4.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/B5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/B5.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/B6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/B6.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/BLUEWIN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/BLUEWIN.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/R1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/R1.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/R2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/R2.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/R3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/R3.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/R4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/R4.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/R5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/R5.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/R6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/R6.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/REDWIN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/REDWIN.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/Y1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/Y1.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/Y2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/Y2.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/Y3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/Y3.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/Y4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/Y4.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/Y5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/Y5.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/picture/white/Y6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/picture/white/Y6.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/示例图片/macos运行示例.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/示例图片/macos运行示例.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/示例图片/ubuntu运行示例.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/示例图片/ubuntu运行示例.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/示例图片/windows运行示例.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/示例图片/windows运行示例.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/示例图片/如何打开cmd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppbear/EinsteinChess_UCT/14bf652103e318c210ef4ff2faaa4125222086ce/EinsteinChessTestServer/示例图片/如何打开cmd.png -------------------------------------------------------------------------------- /EinsteinChessTestServer/配置环境.txt: -------------------------------------------------------------------------------- 1 | windows 平台下运行环境配置 2 | 1.https://www.cnblogs.com/weven/p/7252917.html 3 | 按照教程安装python3 和 pip 4 | 2. 以管理员权限打开windows cmd或powershell (见右键点击windows图标,见图片“如何打开cmd.png”) 5 | 3. 输入pip install pygame 命令 安装pygame包 6 | 4. 输入 python TestServer.py 运行测试服务器(此处可以不使用管理员权限) 7 | 8 | 9 | Ubuntu 平台运行环境配置 10 | 打开终端,依次输入以下命令 11 | 1. sudo apt-get install python3 12 | 2. sudo apt-get install python3-pip 13 | 3. pip3 install pygame 14 | 4. 输入 python3 TestServer.py 运行测试服务器 15 | 16 | 17 | MacOS 平台运行环境配置 18 | 打开终端,依次输入以下命令 19 | 1. 安装brew https://brew.sh/ 20 | 2. brew install python3 21 | 3. pip3 install pygame 22 | 4. 输入 python3 TestServer.py 运行测试服务器 23 | 24 | 具体运行情况可以查看目录下的运行示例图片 25 | 服务器运行结束后按回车键结束 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EinsteinChess_UCT 2 | 程设实验项目三 3 | 4 | 本项目采用的是基于蒙特卡洛树搜索的UCT算法 5 | 6 | 参考文档:https://www.cnblogs.com/KakagouLT/p/9201845.html 7 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "Einstein.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int play() 11 | { 12 | return 1; 13 | } 14 | 15 | int main() 16 | { 17 | Einstein e; 18 | int running = 1; 19 | while (running) 20 | { 21 | running = e.handle(); 22 | } 23 | 24 | e.logging("done!"); 25 | e.writelog(); 26 | 27 | //system("pause"); 28 | return 0; 29 | } 30 | --------------------------------------------------------------------------------