中国象棋控件 2.0.14
载入中...
搜索中...
未找到
ChineseChess.cpp
1// 作者:康林 <kl222@126.com>
2
3#include "ChineseChess.h"
4#include <algorithm>
5
6CChineseChess::CChineseChess()
7{
8 m_bPromptSound = true;
9 m_bPromptMessage = true;
10 SetBoardLayout(TopBlackAndBottomRed);
11}
12
13CChineseChess::~CChineseChess()
14{}
15
16int CChineseChess::Initial()
17{
18 m_WalkState = RedReadly;
19 m_PreviouPositionX = m_PreviouPositionX = -1;
20 m_CurrentPositionX = m_CurrentPositionY = -1;
21
22 return 0;
23}
24
25CChineseChess::ENUM_BoardLayout CChineseChess::GetBoardLayout()
26{
27 return m_BoardLayout;
28}
29
30int CChineseChess::SetBoardLayout(ENUM_BoardLayout layout)
31{
32 Initial();
33 m_BoardLayout = layout;
34
35 CPiece::ENUM_QiZi board[9][10];
36 //初始化空棋局
37 int i, j;
38 for (i = 0; i < 9; i++)
39 for (j = 0; j < 10; j++)
40 {
41 m_ChessBoard[i][j] = CPiece::NoQiZi;
42 board[i][j] = CPiece::NoQiZi;
43 }
44
45 if(m_Game.m_StartGame.size())
46 {
47 std::vector<CChessGame::strStartGame>::iterator it;
48 for(it = m_Game.m_StartGame.begin(); it != m_Game.m_StartGame.end(); it++)
49 {
50 if((CPiece::IsRedQiZi(it->qz) && (m_BoardLayout & OnlyBottomRed))
51 || (CPiece::IsBlackQiZi(it->qz) && (m_BoardLayout & OnlyTopBlack)))
52 board[it->i][it->j] = it->qz;
53 }
54 int nRet = m_Game.CheckGame(board);
55 if(nRet) return nRet;
56
57 for(i = 0; i < 9; i++)
58 for(j = 0; j < 10; j++)
59 {
60 if(CPiece::IsExistQiZi(board[i][j]))
61 {
62 int x, y;
63 ConvertQiPang(i, j, x, y);
64 m_ChessBoard[x][y] = board[i][j];
65 }
66 }
67 }
68 else
69 {
70 if (m_BoardLayout & OnlyTopBlack)
71 {
72 if (m_BoardLayout & SwapRedBetweenBlack)
73 {
74 m_ChessBoard[0][0] = m_ChessBoard[8][0] = CPiece::RChe;
75 m_ChessBoard[1][0] = m_ChessBoard[7][0] = CPiece::RMa;
76 m_ChessBoard[2][0] = m_ChessBoard[6][0] = CPiece::RXiang;
77 m_ChessBoard[3][0] = m_ChessBoard[5][0] = CPiece::RShi;
78 m_ChessBoard[4][0] = CPiece::RShuai;
79 m_ChessBoard[1][2] = m_ChessBoard[7][2] = CPiece::RPao;
80 m_ChessBoard[0][3] = m_ChessBoard[2][3] = m_ChessBoard[4][3] = m_ChessBoard[6][3] = m_ChessBoard[8][3] = CPiece::RBing;
81 }
82 else {
83 m_ChessBoard[0][0] = m_ChessBoard[8][0] = CPiece::BChe;
84 m_ChessBoard[1][0] = m_ChessBoard[7][0] = CPiece::BMa;
85 m_ChessBoard[2][0] = m_ChessBoard[6][0] = CPiece::BXiang;
86 m_ChessBoard[3][0] = m_ChessBoard[5][0] = CPiece::BShi;
87 m_ChessBoard[4][0] = CPiece::BShuai;
88 m_ChessBoard[1][2] = m_ChessBoard[7][2] = CPiece::BPao;
89 m_ChessBoard[0][3] = m_ChessBoard[2][3] = m_ChessBoard[4][3] = m_ChessBoard[6][3] = m_ChessBoard[8][3] = CPiece::BBing;
90 }
91 }
92
93 if (m_BoardLayout & OnlyBottomRed)
94 {
95 if (m_BoardLayout & SwapRedBetweenBlack)
96 {
97 m_ChessBoard[0][9] = m_ChessBoard[8][9] = CPiece::BChe;
98 m_ChessBoard[1][9] = m_ChessBoard[7][9] = CPiece::BMa;
99 m_ChessBoard[2][9] = m_ChessBoard[6][9] = CPiece::BXiang;
100 m_ChessBoard[3][9] = m_ChessBoard[5][9] = CPiece::BShi;
101 m_ChessBoard[4][9] = CPiece::BShuai;
102 m_ChessBoard[1][7] = m_ChessBoard[7][7] = CPiece::BPao;
103 m_ChessBoard[0][6] = m_ChessBoard[2][6] = m_ChessBoard[4][6] = m_ChessBoard[6][6] = m_ChessBoard[8][6] = CPiece::BBing;
104 }
105 else {
106 m_ChessBoard[0][9] = m_ChessBoard[8][9] = CPiece::RChe;
107 m_ChessBoard[1][9] = m_ChessBoard[7][9] = CPiece::RMa;
108 m_ChessBoard[2][9] = m_ChessBoard[6][9] = CPiece::RXiang;
109 m_ChessBoard[3][9] = m_ChessBoard[5][9] = CPiece::RShi;
110 m_ChessBoard[4][9] = CPiece::RShuai;
111 m_ChessBoard[1][7] = m_ChessBoard[7][7] = CPiece::RPao;
112 m_ChessBoard[0][6] = m_ChessBoard[2][6] = m_ChessBoard[4][6] = m_ChessBoard[6][6] = m_ChessBoard[8][6] = CPiece::RBing;
113 }
114 }
115 }
116
117 return 0;
118}
119
120bool CChineseChess::IsValidPosition(int i, int j)
121{
122 if (i < 0 || i > (9 - 1) || j < 0 || j > (10 - 1))
123 { //出界
124 return false;
125 }
126 return true;
127}
128
129int CChineseChess::EnablePromptSound(bool sound)
130{
131 m_bPromptSound = sound;
132 return 0;
133}
134
135bool CChineseChess::getEnablePromptSound()
136{
137 return m_bPromptSound;
138}
139
140int CChineseChess::EnablePromptMessage(bool bMsg)
141{
142 m_bPromptMessage = bMsg;
143 return 0;
144}
145
146bool CChineseChess::getEnablePromptMessage()
147{
148 return m_bPromptMessage;
149}
150
162int CChineseChess::CleanPrompt(int &i, int &j)
163{
164 if (-1 == i || -1 == j)
165 return 0;
166 int oI = i, oJ = j;
167 i = -1;
168 j = -1;
169 onCleanPrompt(oI, oJ);
170 return 0;
171}
172
173
188bool CChineseChess::GoChess(int i, int j, bool bNext)
189{
190 if (IsGoChess(i, j))
191 { //走棋
192
193 if (!bNext)
194 {
195 onGoChess(i, j, m_ChessBoard[i][j]); //事件
196 int x, y;
197 ConvertQiPang(i, j, x, y);
198 m_Game.SaveStep(x, y, m_ChessBoard[i][j]); //保存到棋局中
199 }
200
201 // 显示提示框
202 switch (m_WalkState)
203 {
204 case RedReadly:
205 if (m_bPromptSound) onPromptSound(Select);
206
207 CleanPrompt(m_PreviouPositionX, m_PreviouPositionY);
208 CleanPrompt(m_CurrentPositionX, m_CurrentPositionY);
209
210 m_PreviouPositionX = i;
211 m_PreviouPositionY = j;
212
213 onDrawPrompt(i, j);
214
215 m_WalkState = RedWalked;
216 break;
217 case RedWalked:
218 m_CurrentPositionX = i;
219 m_CurrentPositionY = j;
220
221 m_ChessBoard[i][j] = m_ChessBoard[m_PreviouPositionX][m_PreviouPositionY];
222 m_ChessBoard[m_PreviouPositionX][m_PreviouPositionY] = CPiece::NoQiZi;
223
224 onDrawPrompt(m_CurrentPositionX, m_CurrentPositionY);
225 onDrawPrompt(m_PreviouPositionX, m_PreviouPositionY);
226
227 m_WalkState = BlackReadly;
228 break;
229 case BlackReadly:
230 if (m_bPromptSound) onPromptSound(Select);
231
232 CleanPrompt(m_PreviouPositionX, m_PreviouPositionY);
233 CleanPrompt(m_CurrentPositionX, m_CurrentPositionY);
234
235 m_PreviouPositionX = i;
236 m_PreviouPositionY = j;
237 onDrawPrompt(i, j);
238
239 m_WalkState = BlackWalked;
240 break;
241 case BlackWalked:
242 m_CurrentPositionX = i;
243 m_CurrentPositionY = j;
244
245 m_ChessBoard[i][j] = m_ChessBoard[m_PreviouPositionX][m_PreviouPositionY];
246 m_ChessBoard[m_PreviouPositionX][m_PreviouPositionY] = CPiece::NoQiZi;
247
248 onDrawPrompt(m_CurrentPositionX, m_CurrentPositionY);
249 onDrawPrompt(m_PreviouPositionX, m_PreviouPositionY);
250
251 m_WalkState = RedReadly;
252 break;
253 }
254 return true;
255 }
256 else //不能走
257 {
258 if (m_bPromptSound) onPromptSound();
259 return false;
260 }
261}
262
263
276bool CChineseChess::IsGoChess(int i, int j)
277{
278 if(!IsValidPosition(i, j))
279 { //出界
280 return false;
281 }
282
283 switch (m_WalkState)
284 {
285 case RedReadly:
286 return CPiece::IsRedQiZi(m_ChessBoard[i][j]) ? true : false;
287 case RedWalked:
288 //本方的棋,重新选取
290 {
291 m_Game.RevokeStep();
292 m_WalkState = RedReadly;
293 return true;
294 }
295 //判断能否走棋
296 switch (m_GoRule.GoChess(i, j, m_PreviouPositionX, m_PreviouPositionY, m_ChessBoard))
297 {
298 case CGoRule::JIANGJUN://将军
299 if(m_bPromptSound) onPromptSound(JiangJun);
300 return true;
301 case CGoRule::RETURNTRUE://可以走棋
302 if (m_bPromptSound)
303 {
304 m_ChessBoard[i][j] ? onPromptSound(Eat) : onPromptSound(Go);
305 }
306 return true;
307 case CGoRule::BEIJIANGJUN://被将
308 if(m_bPromptMessage) onPromptMessage(CGoRule::BEIJIANGJUN);
309 return false;
310 case CGoRule::JIANGDUIMIAN://将对面
311 if (m_bPromptMessage) onPromptMessage(CGoRule::JIANGDUIMIAN);
312 return false;
313 case CGoRule::RETURNFALSE://非法走棋
314 default:
315 return false;
316 }
317
318 case BlackReadly:
319 return CPiece::IsBlackQiZi(m_ChessBoard[i][j]) ? true : false;
320 case BlackWalked:
321 //本方的棋,重新选取
322 if (CPiece::IsBlackQiZi(m_ChessBoard[i][j]))
323 {
324 m_Game.RevokeStep();
325 m_WalkState = BlackReadly;
326 return true;
327 }
328 //判断能否走棋
329 switch (m_GoRule.GoChess(i, j, m_PreviouPositionX, m_PreviouPositionY, m_ChessBoard))
330 {
331 case CGoRule::JIANGJUN://将军
332 if (m_bPromptSound) onPromptSound(JiangJun);
333 return true;
334 case CGoRule::RETURNTRUE://可以走棋
335 if (m_bPromptSound)
336 {
337 m_ChessBoard[i][j] ? onPromptSound(Eat) : onPromptSound(Go);
338 }
339 return true;
340 case CGoRule::BEIJIANGJUN://被将
341 if (m_bPromptMessage) onPromptMessage(CGoRule::BEIJIANGJUN);
342 return false;
343 case CGoRule::JIANGDUIMIAN://将对面
344 if (m_bPromptMessage) onPromptMessage(CGoRule::JIANGDUIMIAN);
345 return false;
346 case CGoRule::RETURNFALSE://非法走棋
347 default:
348 return false;
349 }
350
351 }
352
353 return false;
354}
355
356
367{
368 int i, j;
370 if (m_Game.GetNextStep(i, j, qz))
371 {
372 if (m_bPromptSound) onPromptSound();
373 return -1;
374 }
375 int x, y;
376 ConvertQiPang(i, j, x, y);
377 if (GoChess(x, y, true))
378 return 0;
379
380 return -2;
381}
382
383
394{
395 int i, j;
397
398 switch (m_WalkState)
399 {
400 case RedWalked:
401 case BlackWalked:
402 CleanPrompt(m_PreviouPositionX, m_PreviouPositionY);
403 CleanPrompt(m_CurrentPositionX, m_CurrentPositionY);
404 if (m_Game.GetPreviouStep(i, j, qz))
405 {
406 if (m_bPromptSound) onPromptSound();
407 }
408 case RedReadly:
409 case BlackReadly:
410 CleanPrompt(m_PreviouPositionX, m_PreviouPositionY);
411 CleanPrompt(m_CurrentPositionX, m_CurrentPositionY);
412
413 if (m_Game.GetPreviouStep(i, j, qz))
414 {
415 if (m_bPromptSound) onPromptSound();
416 return -1;
417 }
418
419 int x, y;
420 ConvertQiPang(i, j, x, y);
421 m_ChessBoard[x][y] = qz;
422 m_CurrentPositionX = x;
423 m_CurrentPositionY = y;
424 CleanPrompt(m_CurrentPositionX, m_CurrentPositionY);
425
426 if (m_Game.GetPreviouStep(i, j, qz))
427 {
428 if (m_bPromptSound) onPromptSound();
429 return -1;
430 }
431 ConvertQiPang(i, j, x, y);
432 m_ChessBoard[x][y] = qz;
433 m_PreviouPositionX = x;
434 m_PreviouPositionY = y;
435
436 if (IsValidPosition(m_PreviouPositionX, m_PreviouPositionY))
437 onDrawPrompt(m_PreviouPositionX, m_PreviouPositionY);
438
439 switch (m_WalkState)
440 {
441 case RedReadly:
442 case RedWalked:
443 m_WalkState = BlackReadly;
444 break;
445 case BlackReadly:
446 case BlackWalked:
447 m_WalkState = RedReadly;
448 }
449 break;
450 }
451
452 return 0;
453}
454
455int CChineseChess::SaveChessGame(const char* pszFile)
456{
457 std::string szFile(pszFile);
458 size_t pos = szFile.rfind('.');
459 if(szFile.npos != pos)
460 {
461 std::string szExt = szFile.substr(pos + 1);
462 std::transform(szExt.begin(), szExt.end(), szExt.begin(), ::tolower);
463 if("pgn" == szExt)
464 return m_Game.SaveChessGamePgn(pszFile);
465 }
466 return m_Game.SaveChessGame(pszFile);
467}
468
469int CChineseChess::LoadChessGame(const char* pszFile)
470{
471 int nRet = 0;
472
473 std::string szFile(pszFile);
474 size_t pos = szFile.rfind('.');
475 if(szFile.npos != pos)
476 {
477 std::string szExt = szFile.substr(pos + 1);
478 std::transform(szExt.begin(), szExt.end(), szExt.begin(), ::tolower);
479 if("pgn" == szExt)
480 return m_Game.LoadChessGamePgn(pszFile);
481 else
482 {
483 nRet = m_Game.LoadChessGame(pszFile);
484 if (nRet) return nRet;
485 }
486 }
487 else
488 {
489 nRet = m_Game.LoadChessGame(pszFile);
490 if (nRet) return nRet;
491 }
492
493 SetBoardLayout(m_BoardLayout);
494 return nRet;
495}
496
497int CChineseChess::SetRedName(const char* pszName)
498{
499 return m_Game.SetRedName(pszName);
500}
501
502std::string CChineseChess::GetRedName()
503{
504 return m_Game.GetRedName();
505}
506
507int CChineseChess::SetBlackName(const char* pszName)
508{
509 return m_Game.SetBlackName(pszName);
510}
511
512std::string CChineseChess::GetBlackName()
513{
514 return m_Game.GetBlackName();
515}
516
517int CChineseChess::SetStartTime(const time_t& tm)
518{
519 return m_Game.SetStartTime(tm);
520}
521
522time_t CChineseChess::GetStartTime()
523{
524 return m_Game.GetStartTime();
525}
526
527int CChineseChess::SetEndTime(const time_t& tm)
528{
529 return m_Game.SetEndTime(tm);
530}
531
532time_t CChineseChess::GetEndTime()
533{
534 return m_Game.GetEndTime();
535}
536
537std::string CChineseChess::GetGameTag(const std::string &tag)
538{
539 return m_Game.GetTag(tag);
540}
541
542int CChineseChess::AddGameTag(const std::string &tag, const std::string &val)
543{
544 return m_Game.AddTag(tag, val);
545}
546
547int CChineseChess::ConvertQiPang(const int &i, const int &j, int &x, int &y)
548{
549 if(m_BoardLayout & SwapRedBetweenBlack)
550 {
551 x = 8 - i; //9 - i - 1;
552 y = 9 - j; //10 - j - 1;
553 return 0;
554 }
555 x = i;
556 y = j;
557 return 0;
558}
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 SaveStep(int i, int j, CPiece::ENUM_QiZi qz, const char *pDescript=nullptr, time_t tm=time(nullptr))
保存一步
int GetNextStep(int &i, int &j, CPiece::ENUM_QiZi &qz)
Gets the next step
static int CheckGame(const CPiece::ENUM_QiZi board[][10])
棋盘开局 检测布局是否合法, 使用标准棋盘布局,红下黑上
int CleanPrompt(int &i, int &j)
清理提示,并把提示框位置设置成无效值
CPiece::ENUM_QiZi m_ChessBoard[9][10]
棋盘描述
virtual int onPromptMessage(CGoRule::ENUM_ReturnValue val)=0
提示错误消息
virtual int onGoChess(int i, int j, CPiece::ENUM_QiZi chess)=0
走棋事件
enum CChineseChess::_ENUM_BoardLayout ENUM_BoardLayout
标准棋盘布局:详见《象棋竞赛规则(2011)》第一章 第1条。红棋在下,黑棋在上。 界面可以支持非标准棋盘布局(红在上,黑在下)
int PreviouStep()
函数名:PreviouStep 功 能:上步棋 参 数:无 返回值:走棋步数 作 者:康 林 版 本:1.0.0.1 日 期:2004-10-5 时 间:10:19:51
virtual int onDrawPrompt(int i, int j)=0
画提示框
virtual int LoadChessGame(const char *pszFile)
加载棋局。 根据文件扩展名来解析文件的格式。 当前支持自定义格式、PGN格式
virtual int onCleanPrompt(int i, int j)=0
清除提示框
int NextStep()
函数名:NextStep 功 能:下步棋 参 数:无 返回值:走棋步数 作 者:康 林 版 本:1.0.0.1 日 期:2004-10-5 时 间:10:19:33
bool GoChess(int i, int j, bool bNext=false)
走棋
virtual int SaveChessGame(const char *pszFile)
保存棋局。 根据文件扩展名来保存为相应的格式。 当前支持自定义格式、PGN格式
@ BEIJIANGJUN
错误,不能走
Definition GoRule.h:31
@ JIANGDUIMIAN
被将军
Definition GoRule.h:32
@ RETURNTRUE
将已被吃
Definition GoRule.h:35
@ JIANGJUN
将对面
Definition GoRule.h:33
ENUM_ReturnValue GoChess(int ito, int jto, int ifrom, int jfrom, CPiece::ENUM_QiZi ChessBoard[][10])
函数名:GoChess 功 能:判断能否从点(ifrom, jfrom)到点(ito, jto)走棋 参 数: int ito:目标点横坐标[0-8] int jto:目标点纵坐标[0-9] int i...
Definition GoRule.cpp:41
static bool IsRedQiZi(ENUM_QiZi qz)
函数名:GetQiZiSide 功 能:得到棋子是红棋,还是黑棋 参 数: ENUM_QiZi qz:要专断的棋子 返回值:返回红棋还是黑棋或无棋 作 者:康 林 版 本:1....
Definition Piece.cpp:31
enum CPiece::_ENUM_QiZi ENUM_QiZi
棋子枚举值 四个位表示棋子,最左1位表示颜色