中国象棋控件 v2.0.13
载入中...
搜索中...
未找到
FrmChineseChess.cpp
1#include "FrmChineseChess.h"
2#include "ui_FrmChineseChess.h"
3#include "DlgAbout/DlgAbout.h"
4#include "RabbitCommonDir.h"
5#include "RabbitCommonTools.h"
6
7#include <QResizeEvent>
8#include <QMouseEvent>
9#include <QPoint>
10#include <QMessageBox>
11#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
12 #include <QSoundEffect>
13#else
14 #include <QSound>
15#endif
16#include <QBitmap>
17
18CFrmChineseChess::CFrmChineseChess(QWidget *parent) :
19 QWidget(parent),
21 ui(new Ui::CFrmChineseChess),
22 m_QiPangColor(0, 0, 0),
23 m_TiShiBoxColor(0, 255, 0)
24{
25 ui->setupUi(this);
26
27 m_QiPangStartX = m_QiPangStartY = 0;
28 m_QiPangDistance = 0;
29
30 m_QiPangPicture.load(":/image/QIPANG");
31 SetTransparentImage(m_QiPangPicture);
32 m_RedShuai.load(":/image/RSHUAI");
33 //SetTransparentImage(m_RedShuai);
34 m_RedShi.load(":/image/RSHI");
35 //SetTransparentImage(m_RedShi);
36 m_RedXiang.load(":/image/RXIANG");
37 //SetTransparentImage(m_RedXiang);
38 m_RedMa.load(":/image/RMA");
39 //SetTransparentImage(m_RedMa);
40 m_RedChe.load(":/image/RCHE");
41 //SetTransparentImage(m_RedChe);
42 m_RedBing.load(":/image/RBING");
43 //SetTransparentImage(m_RedBing);
44 m_RedPao.load(":/image/RPAO");
45 //SetTransparentImage(m_RedPao);
46 m_BlackShuai.load(":/image/BSHUAI");
47 //SetTransparentImage(m_BlackShuai);
48 m_BlackShi.load(":/image/BSHI");
49 //SetTransparentImage(m_BlackShi);
50 m_BlackXiang.load(":/image/BXIANG");
51 //SetTransparentImage(m_BlackXiang);
52 m_BlackMa.load(":/image/BMA");
53 //SetTransparentImage(m_BlackMa);
54 m_BlackChe.load(":/image/BCHE");
55 //SetTransparentImage(m_BlackChe);
56 m_BlackBing.load(":/image/BZU");
57 //SetTransparentImage(m_BlackBing);
58 m_BlackPao.load(":/image/BPAO");
59 //SetTransparentImage(m_BlackPao);
60
61 m_Chu.load(":/image/CHU");
62 SetTransparentImage(m_Chu);
63 m_He.load(":/image/HE");
64 SetTransparentImage(m_He);
65 m_Han.load(":/image/HAN");
66 SetTransparentImage(m_Han);
67 m_Jie.load(":/image/JIE");
68 SetTransparentImage(m_Jie);
69 m_KL.load(":/image/KL");
70}
71
72CFrmChineseChess::~CFrmChineseChess()
73{
74 delete ui;
75}
76
77static QSharedPointer<QTranslator> g_Translator;
78int CFrmChineseChess::InitResource(const QString szLanguage)
79{
80 Q_INIT_RESOURCE(ResourceChineseChess);
81#if (defined(DEBUG) || defined(_DEBUG)) && !defined (BUILD_SHARED_LIBS)
82 Q_INIT_RESOURCE(translations_ChineseChessQt);
83#endif
84 g_Translator = RabbitCommon::CTools::Instance()->InstallTranslator(
85 "ChineseChessQt",
86 RabbitCommon::CTools::TranslationType::Library,
87 "",
88 szLanguage);
89 if(g_Translator)
90 return 0;
91 return -1;
92}
93
95{
96 RabbitCommon::CTools::Instance()->RemoveTranslator(g_Translator);
97
98#if (defined(DEBUG) || defined(_DEBUG)) && !defined (BUILD_SHARED_LIBS)
99 Q_CLEANUP_RESOURCE(translations_ChineseChessQt);
100#endif
101 Q_CLEANUP_RESOURCE(ResourceChineseChess);
102 return 0;
103}
104
105void CFrmChineseChess::mouseReleaseEvent(QMouseEvent *event)
106{
107 int i = 0, j = 0;
108 long x = 0, y = 0;
109 QPoint p = event->pos();
110 x = p.x();
111 y = p.y();
112 ConvertCoordinate(&x, &y, &i, &j);
113 if (GoChess(i, j))
114 {
115
116 }
117}
118
119void CFrmChineseChess::paintEvent(QPaintEvent *event)
120{
121 QPainter painter(this);
122
123 // 设置平滑模式
124 painter.setRenderHint(QPainter::SmoothPixmapTransform);
125
126 DrawQiPang(&painter, rect());
127}
128
129void CFrmChineseChess::resizeEvent(QResizeEvent *event)
130{
131 QSize s = event->size();
132 SetQiPang(s.width(), s.height());
133}
134
135int CFrmChineseChess::onPromptSound(PROMPT_SOUND sound)
136{
137 QString szFile;
138 switch (sound)
139 {
140 case JiangJun:
141 szFile = ":/sound/CHECK";
142 break;
143 case Eat:
144 szFile = ":/sound/EAT";
145 break;
146 case Go:
147 szFile = ":/sound/GO";
148 break;
149 case NoGo:
150 szFile = ":/sound/DEAD";
151 break;
152 case Select:
153 szFile = ":/sound/SELECT";
154 break;
155 default:
156 return 0;
157 }
158#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
159 QSoundEffect effect;
160 effect.setSource(QUrl::fromLocalFile(szFile));
161// effect.setLoopCount(1);
162// effect.setVolume(1);
163 effect.play();
164#else
165 QSound::play(szFile);
166#endif
167 return 0;
168}
169
170int CFrmChineseChess::onPromptMessage(CGoRule::ENUM_ReturnValue val)
171{
172 QMessageBox msg(this);
173 switch (val)
174 {
175 case CGoRule::BEIJIANGJUN:
176 msg.setText(tr("This step cannot be taken, otherwise you will lose"));
177 msg.setWindowTitle(tr("checked"));
178 break;
179 case CGoRule::JIANGDUIMIAN:
180 msg.setText(tr("This step cannot be taken, otherwise you will lose"));
181 msg.setWindowTitle(tr("Opposite"));
182 break;
183 default:
184 return 0;
185 }
186 msg.exec();
187 return 0;
188}
189
191{
192 Q_UNUSED(i)
193 Q_UNUSED(j)
194 int nRet = 0;
195 this->update();
196 return nRet;
197}
198
200{
201 Q_UNUSED(i)
202 Q_UNUSED(j)
203 int nRet = 0;
204 this->update();
205 return nRet;
206}
207
208int CFrmChineseChess::onGoChess(int i, int j, CPiece::ENUM_QiZi chess)
209{
210 emit sigGoChess(i, j, chess);
211 return 0;
212}
213
214void CFrmChineseChess::AboutBox()
215{
216 CDlgAbout about(this);
217 about.m_szAppName = tr("Chinese chess control");
218 about.m_szHomePage = "https://github.com/KangLin/ChineseChessControl";
219 about.m_szCopyrightTime = "1994 - " + QString::number(QDate::currentDate().year());
220 about.exec();
221}
222
223QDateTime CFrmChineseChess::GetStartTime()
224{
225 time_t t = CChineseChess::GetStartTime();
226 QDateTime time;
227 time.setMSecsSinceEpoch(t);
228 return time;
229}
230
231int CFrmChineseChess::SetStartTime(const QDateTime &t)
232{
233 return CChineseChess::SetStartTime(t.toMSecsSinceEpoch());
234}
235
236QDateTime CFrmChineseChess::GetEndTime()
237{
238 QDateTime t;
239 t.setMSecsSinceEpoch(CChineseChess::GetEndTime());
240 return t;
241}
242
243int CFrmChineseChess::SetEndTime(const QDateTime &t)
244{
245 return CChineseChess::SetEndTime(t.toMSecsSinceEpoch());
246}
247
248QString CFrmChineseChess::GetRedName()
249{
250 return CChineseChess::GetRedName().c_str();
251}
252
253int CFrmChineseChess::SetRedName(const QString &name)
254{
255 return CChineseChess::SetRedName(name.toStdString().c_str());
256}
257
258QString CFrmChineseChess::GetBlackName()
259{
260 return CChineseChess::GetBlackName().c_str();
261}
262
263int CFrmChineseChess::SetBlackName(const QString &name)
264{
265 return CChineseChess::SetBlackName(name.toStdString().c_str());
266}
267
268
285bool CFrmChineseChess::ConvertCoordinate(long *x, long *y, int *i, int *j, ENUM_ConvertCoordinate eCC)
286{
287 switch (eCC)
288 {
289 case XYToIJ:
290 *i = (*x - m_QiPangStartX + m_QiPangDistance / 2) / m_QiPangDistance;
291 *j = (*y - m_QiPangStartY + m_QiPangDistance / 2) / m_QiPangDistance;
292 break;
293 case IJToXY:
294 *x = m_QiPangStartX + *i * m_QiPangDistance;
295 *y = m_QiPangStartY + *j * m_QiPangDistance;
296 break;
297 }
298 return true;
299}
300
301
313bool CFrmChineseChess::SetQiPang(int width, int height)
314{
315 if (width > height)
316 {
317 m_QiPangDistance = height / 11;
318 m_QiPangStartX = (width - m_QiPangDistance * 10) / 2 + m_QiPangDistance;
319 m_QiPangStartY = m_QiPangDistance;
320 }
321 else
322 {
323 m_QiPangDistance = width / 10;
324 m_QiPangStartX = m_QiPangDistance;
325 m_QiPangStartY = (height - m_QiPangDistance * 11) / 2 + m_QiPangDistance;
326 }
327 return true;
328}
329
330
342void CFrmChineseChess::DrawQiPang(QPainter *pPainter, QRect rect)
343{
344 if(nullptr == pPainter)
345 return;
346
347 pPainter->save();
348
349 DrawImage(pPainter, rect, m_QiPangPicture);
350
351 int i, j;
352 for (i = 0; i < 9; i++) //纵格
353 {
354 if (i == 0 || i == 8)
355 {
356 QPen pen;
357 pen.setColor(m_QiPangColor);
358 pen.setWidth(2);
359 pPainter->setPen(pen);
360 pPainter->drawLine(m_QiPangStartX + i * m_QiPangDistance,
361 m_QiPangStartY,
362 m_QiPangStartX + i * m_QiPangDistance,
363 m_QiPangStartY + 9 * m_QiPangDistance);
364 }
365 else
366 {
367 QPen pen(QBrush(m_QiPangColor), 1);
368 pPainter->setPen(pen);
369 pPainter->drawLine(m_QiPangStartX + i * m_QiPangDistance,
370 m_QiPangStartY,
371 m_QiPangStartX + i * m_QiPangDistance,
372 m_QiPangStartY + 4 * m_QiPangDistance);
373 pPainter->drawLine(m_QiPangStartX + i * m_QiPangDistance,
374 m_QiPangStartY + 5 * m_QiPangDistance,
375 m_QiPangStartX + i * m_QiPangDistance,
376 m_QiPangStartY + 9 * m_QiPangDistance);
377 }
378 }
379
380 for (i = 0; i < 10; i++) //横格
381 {
382 QPen pen;
383 pen.setColor(m_QiPangColor);
384 if (i == 0 || i == 9)
385 {
386 pen.setWidth(2);
387 }
388 else
389 {
390 pen.setWidth(1);
391 }
392
393 pPainter->setPen(pen);
394
395 pPainter->drawLine(m_QiPangStartX,
396 m_QiPangStartY + i * m_QiPangDistance,
397 m_QiPangStartX + 8 * m_QiPangDistance,
398 m_QiPangStartY + i * m_QiPangDistance);
399
400 }
401
402 //九宫
403 QPen pen;
404 pen.setColor(m_QiPangColor);
405 pen.setWidth(1);
406 pPainter->setPen(pen);
407 pPainter->drawLine(m_QiPangStartX + 3 * m_QiPangDistance,
408 m_QiPangStartY,
409 m_QiPangStartX + 5 * m_QiPangDistance,
410 m_QiPangStartY + 2 * m_QiPangDistance);
411
412 pPainter->drawLine(m_QiPangStartX + 5 * m_QiPangDistance,
413 m_QiPangStartY,
414 m_QiPangStartX + 3 * m_QiPangDistance,
415 m_QiPangStartY + 2 * m_QiPangDistance);
416
417 pPainter->drawLine(m_QiPangStartX + 3 * m_QiPangDistance,
418 m_QiPangStartY + 7 * m_QiPangDistance,
419 m_QiPangStartX + 5 * m_QiPangDistance,
420 m_QiPangStartY + 9 * m_QiPangDistance);
421
422 pPainter->drawLine(m_QiPangStartX + 5 * m_QiPangDistance,
423 m_QiPangStartY + 7 * m_QiPangDistance,
424 m_QiPangStartX + 3 * m_QiPangDistance,
425 m_QiPangStartY + 9 * m_QiPangDistance);
426
427
428 //星位
429 DrawXinWei(pPainter, 1, 2);
430 DrawXinWei(pPainter, 7, 2);
431 DrawXinWei(pPainter, 1, 7);
432 DrawXinWei(pPainter, 7, 7);
433 DrawXinWei(pPainter, 0, 3, Right_XinWei);
434 DrawXinWei(pPainter, 2, 3);
435 DrawXinWei(pPainter, 4, 3);
436 DrawXinWei(pPainter, 6, 3);
437 DrawXinWei(pPainter, 8, 3, Left_XinWei);
438 DrawXinWei(pPainter, 0, 6, Right_XinWei);
439 DrawXinWei(pPainter, 2, 6);
440 DrawXinWei(pPainter, 4, 6);
441 DrawXinWei(pPainter, 6, 6);
442 DrawXinWei(pPainter, 8, 6, Left_XinWei);
443
444 //楚河汉界
445 //楚
446 DrawPicture(pPainter, 7, 4, m_Chu, true);
447 //河
448 DrawPicture(pPainter, 6, 4, m_He, true);
449 //汉
450 DrawPicture(pPainter, 1, 4, m_Han, true);
451 //界
452 DrawPicture(pPainter, 2, 4, m_Jie, true);
453 //KL
454 DrawPicture(pPainter, 4, 4, m_KL, true);
455
456 //画棋子
457 for (i = 0; i < 9; i++)
458 for (j = 0; j < 10; j++)
459 {
460 DrawQiZi(pPainter, i, j, m_ChessBoard[i][j]);
461 }
462
463 //显示提示框
464 if (IsValidPosition(m_PreviouPositionX, m_PreviouPositionY))
465 DrawTiShiBox(pPainter, m_PreviouPositionX, m_PreviouPositionY);
466 if (IsValidPosition(m_CurrentPositionX, m_CurrentPositionY))
467 DrawTiShiBox(pPainter, m_CurrentPositionX, m_CurrentPositionY);
468
469 pPainter->restore();
470}
471
472
489void CFrmChineseChess::DrawXinWei(QPainter *pPainter, int i, int j, ENUM_XINWEI xinwei)
490{
491 int d, ds;
492 long x, y;
493
494 d = m_QiPangDistance * 4 / 10;
495 ds = m_QiPangDistance * 2 / 10;
496
497 ConvertCoordinate(&x, &y, &i, &j, IJToXY);
498
499 QPen pen;
500 pen.setColor(m_QiPangColor);
501 pen.setWidth(1);
502 pPainter->setPen(pen);
503
504 if (xinwei != Left_XinWei)
505 {
506 pPainter->drawLine(x + ds, y + ds, x + d, y + ds);
507 pPainter->drawLine(x + ds, y - ds, x + d, y - ds);
508
509 pPainter->drawLine(x + ds, y + ds, x + ds, y + d);
510
511 pPainter->drawLine(x + ds, y - ds, x + ds, y - d);
512 }
513
514 if (xinwei != Right_XinWei)
515 {
516 pPainter->drawLine(x - ds, y - ds, x - ds, y - d);
517
518 pPainter->drawLine(x - ds, y + ds, x - ds, y + d);
519
520 pPainter->drawLine(x - ds, y + ds, x - d, y + ds);
521
522 pPainter->drawLine(x - ds, y - ds, x - d, y - ds);
523 }
524}
525
526
538bool CFrmChineseChess::DrawTiShiBox(QPainter *pPainter, int i, int j)
539{
540 // CClientDC dc(this);
541
542 long m_X, m_Y, m_L = m_QiPangDistance / 2;
543
544 QPen pen;
545 pen.setColor(m_TiShiBoxColor);
546 pen.setWidth(1);
547 pPainter->setPen(pen);
548
549 ConvertCoordinate(&m_X, &m_Y, &i, &j, IJToXY);
550 pPainter->drawLine(m_X - m_L, m_Y - m_L, m_X - m_L, m_Y - m_L / 2);
551
552 pPainter->drawLine(m_X - m_L, m_Y - m_L, m_X - m_L / 2, m_Y - m_L);
553
554 pPainter->drawLine(m_X + m_L, m_Y + m_L, m_X + m_L, m_Y + m_L / 2);
555
556 pPainter->drawLine(m_X + m_L, m_Y + m_L, m_X + m_L / 2, m_Y + m_L);
557
558 pPainter->drawLine(m_X - m_L, m_Y + m_L, m_X - m_L, m_Y + m_L / 2);
559
560 pPainter->drawLine(m_X - m_L, m_Y + m_L, m_X - m_L / 2, m_Y + m_L);
561
562 pPainter->drawLine(m_X + m_L, m_Y - m_L, m_X + m_L, m_Y - m_L / 2);
563
564 pPainter->drawLine(m_X + m_L, m_Y - m_L, m_X + m_L / 2, m_Y - m_L);
565
566 return true;
567}
568
569
582int CFrmChineseChess::DrawQiZi(QPainter *pPainter, int i, int j, CPiece::ENUM_QiZi eQiZi)
583{
584
585 QImage qz;
586#pragma warning( disable : 4806 )
587
588 switch (eQiZi)
589 {
590 case CPiece::NoQiZi:
591 return false;
592 case CPiece::RShuai:
593 qz = m_RedShuai;
594 break;
595 case CPiece::RShi:
596 qz = m_RedShi;
597 break;
598 case CPiece::RXiang:
599 qz = m_RedXiang;
600 break;
601 case CPiece::RMa:
602 qz = m_RedMa;
603 break;
604 case CPiece::RChe:
605 qz = m_RedChe;
606 break;
607 case CPiece::RPao:
608 qz = m_RedPao;
609 break;
610 case CPiece::RBing:
611 qz = m_RedBing;
612 break;
613 case CPiece::BShuai:
614 qz = m_BlackShuai;
615 break;
616 case CPiece::BShi:
617 qz = m_BlackShi;
618 break;
619 case CPiece::BXiang:
620 qz = m_BlackXiang;
621 break;
622 case CPiece::BMa:
623 qz = m_BlackMa;
624 break;
625 case CPiece::BChe:
626 qz = m_BlackChe;
627 break;
628 case CPiece::BPao:
629 qz = m_BlackPao;
630 break;
631 case CPiece::BBing:
632 qz = m_BlackBing;
633 break;
634 }
635
636#pragma warning( default : 4806 )
637
638 if (!qz.isNull())
639 return DrawPicture(pPainter, i, j, qz);
640
641 return -1;
642}
643
644
645
660int CFrmChineseChess::DrawPicture(QPainter *pPainter, int i, int j, QImage image, bool CHHJKL)
661{
662 long m_X, m_Y;
663
664 ConvertCoordinate(&m_X, &m_Y, &i, &j, IJToXY);
665 if (CHHJKL) //画楚河汉界
666 {
667 m_X -= m_QiPangDistance / 2;
668 }
669 else
670 {
671 m_X -= m_QiPangDistance / 2;
672 m_Y -= m_QiPangDistance / 2;
673 }
674
675 QRect r(m_X, m_Y, m_QiPangDistance, m_QiPangDistance);
676 return DrawImage(pPainter, r, image);
677}
678
686int CFrmChineseChess::DrawImage(QPainter *pPainter, QRect rect, QImage image)
687{
688 pPainter->drawImage(rect, image);
689
691 //QImage bmp = image.scaled(rect.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
692 //pPainter->drawImage(rect, bmp, bmp.rect());
693
694 //QPixmap p = QPixmap::fromImage(image);
695 //p = p.scaled(r.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
696 //pPainter->drawPixmap(r, p, p.rect());
697 return 0;
698}
699
706int CFrmChineseChess::SetTransparentImage(QImage &image, const QColor &col)
707{
708 //设置位图透明
709 QImage mask = image.createMaskFromColor(col.rgb(), Qt::MaskOutColor);
710 image.setAlphaChannel(mask);
711 return 0;
712}
713
720int CFrmChineseChess::SetTransparentPixmap(QPixmap &pixmap, const QColor &col)
721{
722 QBitmap bmp = pixmap.createMaskFromColor(col, Qt::MaskOutColor);
723 pixmap.setMask(bmp);
724 return 0;
725}
中国象棋类
CPiece::ENUM_QiZi m_ChessBoard[9][10]
棋盘描述
bool GoChess(int i, int j, bool bNext=false)
走棋
中国象棋窗体,完成中国象棋的界面
virtual int onDrawPrompt(int i, int j) override
画提示框
virtual int onGoChess(int i, int j, CPiece::ENUM_QiZi chess) override
走棋事件
virtual int onPromptMessage(CGoRule::ENUM_ReturnValue val) override
提示错误消息
static int CleanResource()
清理资源,仅在程序结束时调用一次
virtual int onCleanPrompt(int i, int j) override
清除提示框
static int InitResource(const QString szLanguage)
初始化资源,仅在程序开始时调用一次