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