-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathboard.cpp
More file actions
431 lines (338 loc) · 12.6 KB
/
Copy pathboard.cpp
File metadata and controls
431 lines (338 loc) · 12.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
#include "board.h"
#include "ui_board.h"
#include "game.h"
Board::Board(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Board)
{
ui->setupUi(this);
this->setWindowTitle("五子棋");
Board::nextMove = {-1, -1, game::Chessquer::non};
/// START THE GAME
Game = new game;
/// 干掉不好看的上面导航栏
this->setWindowFlags(Qt::FramelessWindowHint);
BLACKCHESSQUER = QPixmap(":/black_chess.png");
WHITECHESSQUER = QPixmap(":/white_chess.png");
BACKGROUND = QPixmap(":/background.jpg");
//game->MakeMove(true, 0, 0);
//game->MakeMove(false, 0, 1);
}
Board::~Board()
{
delete ui;
}
/// 绘制棋盘
void Board::paintEvent(QPaintEvent *event){
painter = new QPainter;
painter->begin(this);
/// draw background
const int LEFT = MARGEIN / 2, WID = MARGEIN + WIDTH * LINE;
painter->drawPixmap(LEFT, LEFT, WID, WID, BACKGROUND);
/// draw lines
for (int i = 0; i <= LINE; ++i) {
painter->drawLine(x, y + WIDTH * i, x + WIDTH * LINE, y + WIDTH * i);
}
for (int i = 0; i <= LINE; ++i) {
painter->drawLine(x + WIDTH * i, y, x + WIDTH * i, y + WIDTH * LINE);
}
/// draw chequers
const std::vector<game::Move> s = Game->getGameData();
for (auto elem : s) {
int x1 = elem.x, y1 = elem.y;
//// TODO 把画棋子封装成小函数
if (elem.color == game::white) { /// BAO LOU JIE KOU LE
painter->drawPixmap(x + WIDTH * x1 - R, y + WIDTH * y1 - R, R * 2, R * 2, WHITECHESSQUER);
// painter->setBrush(QBrush(Qt::white, Qt::SolidPattern));
// painter->drawEllipse(x + WIDTH * x1 - R, y + WIDTH * y1 - R, R * 2, R * 2);
} else {
painter->drawPixmap(x + WIDTH * x1 - R, y + WIDTH * y1 - R, R * 2, R * 2, BLACKCHESSQUER);
// painter->setBrush(QBrush(Qt::black, Qt::SolidPattern));
// painter->drawEllipse(x + WIDTH * x1 - R, y + WIDTH * y1 - R, R * 2, R * 2);
}
}
/// TODO 画虚拟的棋子
if (Board::nextMove.x != -1) {
switch(Board::nextMove.type) {
case game::Chessquer::black:
painter->setBrush(QBrush(Qt::black, Qt::SolidPattern));
break;
case game::Chessquer::white:
painter->setBrush(QBrush(Qt::white, Qt::SolidPattern));
break;
case game::Chessquer::invalid:
painter->setBrush(QBrush(Qt::red, Qt::SolidPattern));
break;
}
painter->drawEllipse(x + WIDTH * Board::nextMove.x - R / 2, y + WIDTH * Board::nextMove.y - R / 2, R, R);
}
painter->end();
}
/// 判断鼠标移动,预先画
/// TODO
void Board::mouseMoveEvent(QMouseEvent *event) {
// if (Game->hasDecideWinner()) {
// Board::nextMove.x = -1;
// Board::nextMove.y = -1;
// return;
// }
// int mouseX = event->x(), mouseY = event->y();
// if (mouseX >= MARGEIN / 2 && mouseX <= MARGEIN + WIDTH * LINE + MARGEIN / 2
// && mouseY >= MARGEIN / 2 && mouseY <= MARGEIN + WIDTH * LINE + MARGEIN / 2) {
// qDebug() << mouseX << " " << mouseY;
// auto [absX, absY] = Board::getPointAbsLocation(mouseX, mouseY);
// bool canMove = Game->canMakeMove(absX, absY);
// /// TODO bug!!!
// if (canMove) {
// /// 能下棋,写成可行的
// /// 已经排除了棋局结束的情况,所有只有白瞎或黑瞎的情况
// Board::nextMove.type = (Game->getGameState() == game::gameState::whiteToD ? game::Chessquer::white : game::Chessquer::black);
// } else {
// /// 不能下棋,写成红色的叉号
// Board::nextMove.type = game::Chessquer::invalid;
// }
// Board::nextMove.x = absX;
// Board::nextMove.y = absY;
// update();
// }
}
/// 鼠标释放,画实心的
void Board::mouseReleaseEvent(QMouseEvent *event) {
if (Game->hasDecideWinner())
return;
/// 已经被弃用 怎么改 TODO
int mouseX = event->x(), mouseY = event->y();
/// around the board ,in play
if (mouseX >= MARGEIN / 2 && mouseX <= MARGEIN + WIDTH * LINE + MARGEIN / 2
&& mouseY >= MARGEIN / 2 && mouseY <= MARGEIN + WIDTH * LINE + MARGEIN / 2) {
qDebug() << mouseX << " " << mouseY;
auto [absX, absY] = Board::getPointAbsLocation(mouseX, mouseY);
bool canMove = Game->canMakeMove(absX, absY);
if (canMove) {
qDebug() << mouseX << " " << mouseY << "could make move";
Board::nextMove = {-1, -1, game::Chessquer::non};
Game->MakeMoveHelper(absX, absY);
Board::NotSave();
/// 文本修改,提示轮到谁下
Board::updateLabelText();
update();
if (Game->hasDecideWinner()) {
//// todo 有BUG
QString winnertr;
QString title = "CONGRATULATION!!!";
game::Chessquer winner = Game->Winner();
if (winner == game::Chessquer::white) {
if (Board::isPVE) {
/// TODO
winnertr = (Board::AIMode == Board::Mode::ComputerWhite ? "你赢了" : "你输了");
} else {
winnertr = "白子胜";
}
} else if (winner == game::Chessquer::black){
if (Board::isPVE) {
winnertr = (Board::AIMode == Board::Mode::ComputerBlack? "你赢了" : "你输了");
} else {
winnertr = "黑子胜";
}
} else if (winner == game::Chessquer::non) {
winnertr = "势均力敌";
}
QMessageBox::information(this, title, winnertr, QMessageBox::Ok, QMessageBox::NoButton);
} else {
/// 还可以继续挣扎
if (Board::isPVE) {
/// 装模作样暂停一秒 TODO
ChessAI::nextStep(absX, absY);
Point p = ChessAI::getLastPoint();
/// TODO 复制粘贴不好
Game->MakeMoveHelper(p.x, p.y);
if (Game->hasDecideWinner()) {
//// todo 有BUG
QString winnertr;
QString title = "CONGRATULATION!!!";
game::Chessquer winner = Game->Winner();
if (winner == game::Chessquer::white) {
if (Board::isPVE) {
/// TODO
} else {
winnertr = "白子胜";
}
} else if (winner == game::Chessquer::black){
if (Board::isPVE) {
/// TODO
} else {
winnertr = "黑子胜";
}
}
QMessageBox::information(this, title, winnertr, QMessageBox::Ok, QMessageBox::NoButton);
}
/// TODO
Board::updateLabelText();
}
}
update();
}
}
}
//// TODO 自定义内容
void Board::closeEvent(QCloseEvent *event) {
if (hasSaved()) {
} else {
/// 没有被保存,弹出提示框进行保存
QString dialtitle = "Warning";
QString strInfo = "你的对局还没有保存,是否确定保存并退出";
QMessageBox::StandardButton result=QMessageBox::question(this, dialtitle, strInfo,
QMessageBox::Yes|QMessageBox::No );
if (result == QMessageBox::Yes) {
/// TODO
/// SAVE IT!!!
Board::saveFile();
}
event->accept();
}
}
std::pair<size_t, size_t> Board::getPointAbsLocation(int mouseX, int mouseY) {
size_t x, y;
x = ( mouseX - MARGEIN + EDGE - 1) / WIDTH;
y = ( mouseY - MARGEIN + EDGE - 1) / WIDTH;
return std::make_pair(x, y);
}
/// 重新开始对局
void Board::on_restart_clicked()
{
/// 友好提示框
QString dialtitle = "Warning";
QString strInfo = "本操作不可撤销,确定重新开始吗";
QMessageBox::StandardButton result=QMessageBox::question(this, dialtitle, strInfo,
QMessageBox::Yes|QMessageBox::No );
if (result == QMessageBox::Yes) {
Game->restart();
update();
if (Board::isPVE) {
ChessAI::reset(Board::AIMode == Board::Mode::ComputerBlack ? 0 : 1);
}
}
}
void Board::on_huiqi_clicked()
{
/// TODO 怎么禁止人在AI下棋时候悔棋
if (Game->getGameData().size() < 2) {
QMessageBox::information(this, "title", "布什葛萌", QMessageBox::Ok, QMessageBox::NoButton);
return;
}
Game->huiqi();
Game->huiqi();
if (Board::isPVE) {
/// TODO
ChessAI::takeBack();
}
Board::updateLabelText();
update();
}
/// 按键保存
void Board::on_save_clicked()
{
Board::saveFile();
}
void Board::updateLabelText() {
switch (Game->getGameState()) {
case game::gameState::blackToD:
stateT = (Board::isPVE ? (Board::AIMode == Board::Mode::ComputerBlack ? "人机下" : "该你了") : "轮到黑子");
break;
case game::gameState::whiteToD:
stateT = (Board::isPVE ? (Board::AIMode == Board::Mode::ComputerWhite? "人机下" : "该你了") : "轮到白子");
break;
case game::gameState::whiteWin:
stateT = (Board::isPVE ? (Board::AIMode == Board::Mode::ComputerWhite ? "人机赢了" : "你赢了") :"白子胜利");
break;
case game::gameState::blackWin:
stateT = (Board::isPVE ? (Board::AIMode == Board::Mode::ComputerBlack ? "人机赢了" : "你赢了") :"黑子胜利");
break;
default:
stateT = "出BUG了!";
break;
}
Board::ui->label->setText(stateT);
qDebug() << "update label text to:" << stateT;
}
/// TODO : 怎么吧文件名传过来
void Board::openGameFile(const std::string filename) {
std::vector<game::Move> his;
if (fileutils::readFromFile(filename, his)) {
Game->loadDataToGame(his);
Board::updateLabelText();
update();
this->filename = filename;
} else {
qDebug() << "读取文件中数据失败";
}
}
void Board::on_end_clicked()
{
if (!hasSaved()) {
/// 没有被保存,弹出提示框进行保存
QString dialtitle = "Warning";
QString strInfo = "你的对局还没有保存,是否确定保存并退出";
QMessageBox::StandardButton result=QMessageBox::question(this, dialtitle, strInfo,
QMessageBox::Yes|QMessageBox::No);
if (result == QMessageBox::Yes) {
/// TODO
/// SAVE IT!!!
Board::saveFile();
}
}
emit goBackStart();
}
/// 保存文件
void Board::saveFile() {
//// TODO
/// 如果处于已保存状态不用理会
/// 更改是否保存过这一变量
if (isSaved)
return;
/// 代表没有文件名在加载中,还没有保存过
if (filename.size() == 0) {
std::stringstream oss;
/// TODO 怎么把这个.data设置成常量
oss << __DATE__ << " " << __TIME__ << ".data";
filename = oss.str();
/// 起名字好烦
std::replace(filename.begin(), filename.end(), ':', '-');
}
/// 有了文件名了,向里面保存就可以
if (fileutils::writeTo(Game->getGameData(), filename ) ) {
qDebug() << "succeed saving the game";
YesSaved();
/// TODO: GUI it!
}
}
bool Board::hasSaved() {
return isSaved;
}
void Board::NotSave() {
isSaved = false;
}
void Board::YesSaved() {
isSaved = true;
}
void Board::on_label_linkHovered(const QString &link)
{
///hahaha
}
void Board::useAIMode(const Board::Mode mode) {
Board::isPVE = true;
Board::AIMode = mode;
/// init AI
qDebug() << "初始化AI:" << (mode == Board::ComputerBlack ? "AI黑子" : "AI白子");
ChessAI::reset(mode);
ui->label->setText((mode == Board::ComputerBlack ? "电脑下" : "轮到你了"));
/// AI先手,下在天元
if (mode == Board::Mode::ComputerBlack) {
Game->MakeMoveHelper(7, 7);
Board::NotSave();
/// TODO 变成小函数
updateLabelText();
qDebug() << "AI 先手";
}
update();
}