中国象棋控件 2.0.15
载入中...
搜索中...
未找到
ChessGame.cpp
1// 作者:康林 <kl222@126.com>
2
3#include "ChessGame.h"
4#include <fstream>
5#include <time.h>
6#include <string.h>
7#include <memory>
8#include "Pgn.h"
9#include "Fen.h"
10
11#ifdef WIN32
12#include <WinSock2.h>
13#else
14#include <arpa/inet.h>
15#endif
16
17#include "Pgn.h"
18
19CChessGame::CChessGame()
20{
21 m_nIndex = -1;
22 m_bFuPang = false;
23 /*
24 m_StartGame.push_back({0, 0, CPiece::BChe});
25 m_StartGame.push_back({1, 0, CPiece::BMa});
26 m_StartGame.push_back({2, 0, CPiece::BXiang});
27 m_StartGame.push_back({3, 0, CPiece::BShi});
28 m_StartGame.push_back({4, 0, CPiece::BShuai});
29 m_StartGame.push_back({5, 0, CPiece::BShi});
30 m_StartGame.push_back({6, 0, CPiece::BXiang});
31 m_StartGame.push_back({7, 0, CPiece::BMa});
32 m_StartGame.push_back({8, 0, CPiece::BChe});
33
34 m_StartGame.push_back({1, 2, CPiece::BPao});
35 m_StartGame.push_back({7, 2, CPiece::BPao});
36
37 m_StartGame.push_back({0, 3, CPiece::BBing});
38 m_StartGame.push_back({2, 3, CPiece::BBing});
39 m_StartGame.push_back({4, 3, CPiece::BBing});
40 m_StartGame.push_back({6, 3, CPiece::BBing});
41 m_StartGame.push_back({8, 3, CPiece::BBing});
42
43 m_StartGame.push_back({0, 9, CPiece::RChe});
44 m_StartGame.push_back({1, 9, CPiece::RMa});
45 m_StartGame.push_back({2, 9, CPiece::RXiang});
46 m_StartGame.push_back({3, 9, CPiece::RShi});
47 m_StartGame.push_back({4, 9, CPiece::RShuai});
48 m_StartGame.push_back({5, 9, CPiece::RShi});
49 m_StartGame.push_back({6, 9, CPiece::RXiang});
50 m_StartGame.push_back({7, 9, CPiece::RMa});
51 m_StartGame.push_back({8, 9, CPiece::RChe});
52
53 m_StartGame.push_back({1, 7, CPiece::RPao});
54 m_StartGame.push_back({7, 7, CPiece::RPao});
55
56 m_StartGame.push_back({0, 6, CPiece::RBing});
57 m_StartGame.push_back({2, 6, CPiece::RBing});
58 m_StartGame.push_back({4, 6, CPiece::RBing});
59 m_StartGame.push_back({6, 6, CPiece::RBing});
60 m_StartGame.push_back({8, 6, CPiece::RBing});
61 //*/
62
63}
64
65CChessGame::~CChessGame()
66{}
67
77int CChessGame::QiZiBianMa(int *i, int *j, CPiece::ENUM_QiZi *qz, strCODE *pCode, ENUM_BianMa bianma)
78{
79 switch (bianma)
80 {
81 case BianMa:
82 pCode->step[0] = *i;
83 pCode->step[1] = *j;
84 pCode->step[2] = *qz;
85 break;
86 case JieMa:
87 *i = pCode->step[0];
88 *j = pCode->step[1];
89 *qz = static_cast<CPiece::ENUM_QiZi>(pCode->step[2]);
90 break;
91 }
92
93 return 0;
94}
95
110 const char* pDescript, time_t tm)
111{
112 strStep step;
113 QiZiBianMa(&i, &j, &qz, &step.code);
114 if (pDescript)
115 step.szDescript = pDescript;
116
117 step.tm = tm;
118
119 // 调整容器大小
120 if (m_nIndex + 1 < m_ChessGame.size())
121 {
122 m_ChessGame.resize(m_nIndex + 1);
123 }
124
125 m_ChessGame.push_back(step);//保存到棋局中
126 m_nIndex++;
127
128 return 0;
129}
130
140{
141 if (m_nIndex < 0)
142 return -1;
143 m_nIndex--;
144 m_ChessGame.erase(--m_ChessGame.end());
145 return 0;
146}
147
148
159{
160 if (m_nIndex < 0)
161 return -1;
162
163 QiZiBianMa(&i, &j, &qz, &m_ChessGame[m_nIndex].code, JieMa);
164 m_nIndex--;
165 return 0;
166}
167
180{
181 if (m_ChessGame.size() <= m_nIndex + 1)
182 return -1;
183
184 QiZiBianMa(&i, &j, &qz, &m_ChessGame[++m_nIndex].code, JieMa);
185
186 return 0;
187}
188
189int CChessGame::SaveChessGame(const char* szFile)
190{
191 if (!szFile) return -1;
192 strFile head;
193#ifdef WIN32
194#ifdef MINGW
195 strncpy_s(head.head.szAppName, MAX_STRING_BUFFER, APPNAME, MAX_STRING_BUFFER);
196 strncpy_s(head.head.szAuthor, MAX_STRING_BUFFER, AUTHOR, MAX_STRING_BUFFER);
197#else
198 strncpy_s(head.head.szAppName, APPNAME, MAX_STRING_BUFFER);
199 strncpy_s(head.head.szAuthor, AUTHOR, MAX_STRING_BUFFER);
200#endif
201#else
202 strncpy(head.head.szAppName, APPNAME, MAX_STRING_BUFFER);
203 strncpy(head.head.szAuthor, AUTHOR, MAX_STRING_BUFFER);
204#endif
205
206 head.head.dwVersion = 2;
207 head.iBuShu = htons(m_ChessGame.size());
208
209 head.timeStart = htonl(m_tmStart);
210 head.timeEnd = htonl(m_tmEnd);
211#ifdef WIN32
212#ifdef MINGW
213 strncpy_s(head.szRedName, MAX_STRING_BUFFER, m_szRedName.c_str(), MAX_STRING_BUFFER);
214 strncpy_s(head.szBlackName, MAX_STRING_BUFFER, m_szBlackName.c_str(), MAX_STRING_BUFFER);
215#else
216 strncpy_s(head.szRedName, m_szRedName.c_str(), MAX_STRING_BUFFER);
217 strncpy_s(head.szBlackName, m_szBlackName.c_str(), MAX_STRING_BUFFER);
218#endif
219#else
220 strncpy(head.szRedName, m_szRedName.c_str(), MAX_STRING_BUFFER);
221 strncpy(head.szBlackName, m_szBlackName.c_str(), MAX_STRING_BUFFER);
222#endif
223
224 std::ofstream out(szFile);
225 if (!out.is_open())
226 return -2;
227 out.write((char*)&head, sizeof(strFile));
228
229 // 保存标签
230 short nTag = htons(m_Tags.size());
231 out.write((char*)&nTag, sizeof (short));
232 for(const auto& item: m_Tags)
233 {
234 std::string key = item.first;
235 std::string val = item.second;
236 WriteStringToFile(out, key);
237 WriteStringToFile(out, val);
238 }
239
240 //保存开局
241 char nLen = 0; //开局最多30子
242 nLen = m_StartGame.size();
243 out.write(&nLen, sizeof (char));
244 if(nLen > 0)
245 {
246 std::vector<strStartGame>::iterator it;
247 for(it = m_StartGame.begin(); it != m_StartGame.end(); it++)
248 {
249 strCODE code;
250 QiZiBianMa(&it->i, &it->j, &it->qz, &code);
251 out.write(code.step, sizeof(strCODE));
252 }
253 }
254
255 //保存着法
256 std::vector<strStep>::iterator it;
257 for (it = m_ChessGame.begin(); it != m_ChessGame.end(); it++)
258 {
259 out.write(it->code.step, sizeof(strCODE));
260 long t = htonl(it->tm);
261 out.write((char*)&t, sizeof(long));
262 WriteStringToFile(out, it->szDescript);
263 }
264 out.close();
265 return 0;
266}
267
268int CChessGame::LoadChessGame(const char* szFile)
269{
270 int nRet = 0;
271 if (!szFile) return -1;
272
273 strFile head;
274 memset(&head, 0, sizeof(strFile));
275
276 std::ifstream in(szFile);
277 if (!in.is_open())
278 return -2;
279
280 in.read((char*)&head, sizeof(strFile));
281 m_szRedName = head.szRedName;
282 m_szBlackName = head.szBlackName;
283 m_tmStart = ntohl(head.timeStart);
284 m_tmEnd = ntohl(head.timeEnd);
285
286 do {
287 if (strcmp(head.head.szAppName, APPNAME))
288 {
289 nRet = -3;
290 break;
291 }
292 if (strcmp(head.head.szAuthor, AUTHOR))
293 {
294 nRet = -4;
295 break;
296 }
297 if (head.head.dwVersion != 2)
298 {
299 nRet = -5;
300 break;
301 }
302
303 //加载标签
304 short nTags = 0;
305 in.read((char*)&nTags, sizeof (short));
306 nTags = ntohs(nTags);
307 if(nTags) m_Tags.clear();
308 while(nTags-- > 0)
309 {
310 std::string key, val;
311 ReadStringFromFile(in, key);
312 ReadStringFromFile(in, val);
313 m_Tags[key] = val;
314 }
315
316 //加载开局
317 m_StartGame.clear();
318 char nLen = 0;
319 in.read(&nLen, sizeof (char));
320 if(nLen > 0)
321 {
322 while (nLen--) {
323 strCODE code;
324 in.read(code.step, sizeof(strCODE));
325 strStartGame g;
326 QiZiBianMa(&g.i, &g.j, &g.qz, &code, JieMa);
327 m_StartGame.push_back(g);
328 }
329 }
330
331 //加载着法
332 m_ChessGame.clear();
333 m_nIndex = ntohs(head.iBuShu);
334 while (m_nIndex--)
335 {
336 strStep step;
337 in.read((char*)&step.code, sizeof(strCODE));
338 long tm;
339 in.read((char*)&tm, sizeof(long));
340 step.tm = ntohl(tm);
341 ReadStringFromFile(in, step.szDescript);
342 m_ChessGame.push_back(step);
343 }
344 m_nIndex = -1;
345 } while (0);
346
347 in.close();
348 return nRet;
349}
350
351int CChessGame::SaveChessGamePgn(const char *pFileName, _SavePgnFormat f)
352{
353 int nRet = 0;
354 if (!pFileName) return -1;
355
356 CPGN pgn;
357 std::shared_ptr<CChessSteps> Steps;
358
359 //设置 Tag
360 if(!m_szRedName.empty())
361 pgn.SetRed(m_szRedName.c_str());
362 if(!m_szBlackName.empty())
363 pgn.SetBlack(m_szBlackName.c_str());
364
365 CPiece::ENUM_QiZi board[9][10];
366 if(m_StartGame.empty())
367 {
368 GetStartGameBoard(board);
369 }
370
371 std::string szFen;
372 CFen fen;
373 nRet = fen.FenFromBoard(szFen, board);
374 if(0 == nRet)
375 pgn.SetFen(szFen.c_str());
376
377 for(const auto& item: m_Tags)
378 {
379 std::string key = item.first;
380 std::string val = item.second;
381 pgn.SetTag(key, val);
382 }
383
384 switch (f) {
385 case ICCS:
386 pgn.SetFormat("ICCS");
387 Steps = std::shared_ptr<CChessStepsIccs>(new CChessStepsIccs());
388 break;
389 case WXF:
390 pgn.SetFormat("WXF");
391 break;
392 case Chinese:
393 pgn.SetFormat("Chinese");
394 Steps = std::shared_ptr<CChessStepsChinese>(new CChessStepsChinese());
395 break;
396 }
397
398 GetStartGameBoard(Steps->m_Board);
399 for(auto& item: m_ChessGame)
400 {
401 int i = 0, j = 0;
402 CPiece::ENUM_QiZi qz = CPiece::NoQiZi;
403 QiZiBianMa(&i, &j, &qz, &item.code, JieMa);
404 Steps->AddStep(i, j, qz, item.szDescript);
405 }
406
407 std::ofstream out(pFileName);
408 if (!out.is_open())
409 return -2;
410 pgn.SetSteps(Steps);
411 out << pgn.toString();
412 out.close();
413
414 return nRet;
415}
416
417int CChessGame::LoadChessGamePgn(const char *pFileName, _SavePgnFormat f)
418{
419 int nRet = 0;
420 if (!pFileName) return -1;
421
422 //TODO:
423 std::ifstream in(pFileName);
424 if (!in.is_open())
425 return -2;
426
427
428 in.close();
429 return nRet;
430}
431
432int CChessGame::WriteStringToFile(std::ofstream &o, std::string &s)
433{
434 short nLen = s.size();
435 short n = htons(nLen);
436 o.write((char*)&n, sizeof(short));
437 if (nLen > 0)
438 {
439 o.write(s.c_str(), nLen);
440 }
441 return 0;
442}
443
444int CChessGame::ReadStringFromFile(std::ifstream &i, std::string &s)
445{
446 short nLen = 0;
447 i.read((char*)&nLen, sizeof(short));
448 nLen = ntohs(nLen);
449 if (nLen > 0)
450 {
451 char* pBuf = new char[nLen + 1];
452 memset(pBuf, 0, nLen + 1);
453 i.read(pBuf, nLen);
454 s = pBuf;
455 delete[]pBuf;
456 }
457 return 0;
458}
459
460time_t CChessGame::GetStartTime()
461{
462 return m_tmStart;
463}
464
465int CChessGame::SetStartTime(const time_t& t)
466{
467 m_tmStart = t;
468 return 0;
469}
470
471time_t CChessGame::GetEndTime()
472{
473 return m_tmEnd;
474}
475
476int CChessGame::SetEndTime(const time_t& t)
477{
478 m_tmEnd = t;
479 return 0;
480}
481
482std::string CChessGame::GetRedName()
483{
484 return m_szRedName;
485}
486
487int CChessGame::SetRedName(const char* pszName)
488{
489 m_szRedName = pszName;
490 return 0;
491}
492
493std::string CChessGame::GetBlackName()
494{
495 return m_szBlackName;
496}
497
498int CChessGame::SetBlackName(const char* pszName)
499{
500 m_szBlackName = pszName;
501 return 0;
502}
503
504std::string CChessGame::GetTag(const std::string &szpTag)
505{
506 std::map<std::string, std::string>::iterator it;
507 it = m_Tags.find(szpTag);
508 if(m_Tags.end() != it)
509 return it->second;
510 return std::string();
511}
512
513int CChessGame::AddTag(const std::string &szTag, const std::string &szVal)
514{
515 m_Tags[szTag] = szVal;
516 return 0;
517}
518
519//检测布局是否合法, 使用标准棋盘布局,红下黑上
521{
522 int nRet = 0;
523
524 int nRChe = 0;
525 int nRMa = 0;
526 int nRXiang = 0;
527 int nRShi = 0;
528 int nRShuai = 0;
529 int nRPao = 0;
530 int nRBing = 0;
531
532 int nBChe = 0;
533 int nBMa = 0;
534 int nBXiang = 0;
535 int nBShi = 0;
536 int nBShuai = 0;
537 int nBPao = 0;
538 int nBBing = 0;
539
540 //检查各种棋子个数
541 for(int i = 0; i < 9; i++) {
542 for(int j = 0; j < 10; j++) {
543 switch(board[i][j])
544 {
545 case CPiece::RChe:
546 nRChe++;
547 break;
548 case CPiece::RMa:
549 nRMa++;
550 break;
551 case CPiece::RXiang:
552 nRXiang++;
553 if(!((2 == i && 9 == j) || (6 == i && 9 == j)
554 || (0 == i && 7 == j) || (8 == i && 7 == j)
555 || (2 == i && 5 == j) || (6 == i && 5 == j)
556 ))
557 return -1;
558 break;
559 case CPiece::RShi:
560 nRShi++;
561 if((i < 3) || (i > 5) || (j < 7))
562 return -2;
563 if((i == 3 || 5 == i) && j == 8)
564 return -3;
565 if(i == 4 && (j == 9 || j == 7))
566 return -4;
567 break;
568 case CPiece::RShuai:
569 nRShuai++;
570 if((i < 3) || (i > 5) || (j < 7))
571 return -5;
572 break;
573 case CPiece::RPao:
574 nRPao++;
575 break;
576 case CPiece::RBing:
577 nRBing++;
578 if(j > 6) return -6;
579 break;
580 case CPiece::BBing:
581 nBBing++;
582 if(j < 3) return -7;
583 break;
584 case CPiece::BPao:
585 nBPao++;
586 break;
587 case CPiece::BChe:
588 nBChe++;
589 break;
590 case CPiece::BMa:
591 nBMa++;
592 break;
593 case CPiece::BXiang:
594 nBXiang++;
595 if(!((2 == i && 0 == j) || (6 == i && 0 == j)
596 || (0 == i && 2 == j) || (8 == i && 2 == j)
597 || (2 == i && 4 == j) || (6 == i && 4 == j)
598 ))
599 return -8;
600 break;
601 case CPiece::BShi:
602 nBShi++;
603 if((i < 3) || (i > 5) || (j > 2))
604 return -9;
605 if((i == 3 || 5 == i) && j == 1)
606 return -10;
607 if(i == 4 && (j == 0 || j == 2))
608 return -11;
609 break;
610 case CPiece::BShuai:
611 nBShuai++;
612 if((i < 3) || (i > 5) || (j > 2))
613 return -12;
614 break;
615 default:
616 break;
617 }
618 }
619 }
620
621 if(nBChe > 2 || nRChe > 2
622 || nBMa > 2 || nRMa > 2
623 || nBXiang > 2 || nRXiang > 2
624 || nBShi > 2 || nBShi > 2
625 || nBShuai > 1 || nRShuai > 1
626 || nBPao > 2 || nRPao > 2
627 || nBBing > 5 || nRBing > 5)
628 return -13;
629
630 return nRet;
631}
632
634{
635 //初始化空棋局
636 int i, j;
637 for (i = 0; i < 9; i++)
638 for (j = 0; j < 10; j++)
639 {
640 board[i][j] = CPiece::NoQiZi;
641 }
642
643 if(m_StartGame.size())
644 {
645 std::vector<CChessGame::strStartGame>::iterator it;
646 for(it = m_StartGame.begin(); it != m_StartGame.end(); it++)
647 {
648 board[it->i][it->j] = it->qz;
649 }
650 return CheckGame(board);
651 }
652 else
653 {
654 board[0][0] = board[8][0] = CPiece::BChe;
655 board[1][0] = board[7][0] = CPiece::BMa;
656 board[2][0] = board[6][0] = CPiece::BXiang;
657 board[3][0] = board[5][0] = CPiece::BShi;
658 board[4][0] = CPiece::BShuai;
659 board[1][2] = board[7][2] = CPiece::BPao;
660 board[0][3] = board[2][3] = board[4][3] = board[6][3] = board[8][3] = CPiece::BBing;
661
662 board[0][9] = board[8][9] = CPiece::RChe;
663 board[1][9] = board[7][9] = CPiece::RMa;
664 board[2][9] = board[6][9] = CPiece::RXiang;
665 board[3][9] = board[5][9] = CPiece::RShi;
666 board[4][9] = CPiece::RShuai;
667 board[1][7] = board[7][7] = CPiece::RPao;
668 board[0][6] = board[2][6] = board[4][6] = board[6][6] = board[8][6] = CPiece::RBing;
669 }
670 return 0;
671}
time_t m_tmStart
棋局
Definition ChessGame.h:153
std::string m_szBlackName
红方名
Definition ChessGame.h:156
std::map< std::string, std::string > m_Tags
黑方名
Definition ChessGame.h:157
std::string m_szRedName
结束时间
Definition ChessGame.h:155
int GetPreviouStep(int &i, int &j, CPiece::ENUM_QiZi &qz)
函数名:GetPreviouStep 功 能:上步棋 参 数:无 返回值:走棋步数 作 者:康 林 版 本:1.0.0.1 日 期:2004-10-5 时 间:10:19:51
int RevokeStep()
撤销一步
int SaveChessGame(const char *pFileName)
Saves the chess game
int QiZiBianMa(int *i, int *j, CPiece::ENUM_QiZi *qz, strCODE *pCode, ENUM_BianMa bianma=BianMa)
棋子编解码
Definition ChessGame.cpp:77
std::vector< strStep > m_ChessGame
复盘标志
Definition ChessGame.h:151
int SaveStep(int i, int j, CPiece::ENUM_QiZi qz, const char *pDescript=nullptr, time_t tm=time(nullptr))
保存一步
time_t m_tmEnd
开始时间
Definition ChessGame.h:154
int GetNextStep(int &i, int &j, CPiece::ENUM_QiZi &qz)
Gets the next step
bool m_bFuPang
走棋步数
Definition ChessGame.h:150
int GetStartGameBoard(CPiece::ENUM_QiZi board[][10])
得到开局棋盘布局
static int CheckGame(const CPiece::ENUM_QiZi board[][10])
棋盘开局 检测布局是否合法, 使用标准棋盘布局,红下黑上
The CChessStepsChinese class
ICCS是中国象棋互联网服务器(Internet Chinese Chess Server)的缩写。
Definition ChessSteps.h:58
福斯夫-爱德华兹记号法 (Forsyth-Edwards Notation)
Definition Fen.h:20
Class to hold all information for the Portable Game Notation (PGN) of a single game.
Definition Pgn.h:23
std::string toString() const
Gets the game as PGN string.
Definition Pgn.cpp:75
enum CPiece::_ENUM_QiZi ENUM_QiZi
棋子枚举值 四个位表示棋子,最左1位表示颜色
std::string szDescript
走棋时间
Definition ChessGame.h:138