必败时自动认输

This commit is contained in:
CalciteM 2019-09-08 09:28:49 +08:00
parent d2df0c1c13
commit 8fd1303cc3
7 changed files with 79 additions and 9 deletions

View File

@ -291,6 +291,7 @@
<addaction name="actionSound_S"/>
<addaction name="actionAnimation_A"/>
<addaction name="separator"/>
<addaction name="actionGiveUpIfMostLose_G"/>
<addaction name="actionAutoRestart_A"/>
<addaction name="actionRandomMove_R"/>
</widget>
@ -1113,6 +1114,17 @@
<string>电脑着法随机(&amp;R)</string>
</property>
</action>
<action name="actionGiveUpIfMostLose_G">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>必败时认输(&amp;G)</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

View File

@ -831,6 +831,7 @@ const char* MillGameAi_ab::bestMove()
{
vector<Node*> bestMoves;
size_t bestMovesSize = 0;
bool isMostLose = true; // 是否必败
if ((rootNode->children).empty()) {
return "error!";
@ -867,6 +868,30 @@ const char* MillGameAi_ab::bestMove()
i++;
}
// 检查是否必败
MillGame::Player whosTurn = chess_.whosTurn();
for (auto child : rootNode->children) {
// TODO: 使用常量代替
if (whosTurn == MillGame::PLAYER1 && child->value > -10000 ||
whosTurn == MillGame::PLAYER2 && child->value < 10000) {
isMostLose = false;
break;
}
}
// 自动认输
if (isMostLose) {
if (whosTurn == MillGame::PLAYER1) {
sprintf(cmdline, "Player1 give up!");
} else if (whosTurn == MillGame::PLAYER2) {
sprintf(cmdline, "Player2 give up!");
}
return cmdline;
}
for (auto child : rootNode->children) {
if (child->value == rootNode->value) {
bestMoves.push_back(child);

View File

@ -168,6 +168,7 @@ MillGame &MillGame::operator = (const MillGame &chess)
currentStep = chess.currentStep;
moveStep = chess.moveStep;
randomMove_ = chess.randomMove_;
giveUpIfMostLose_ = chess.giveUpIfMostLose_;
board_ = context.board;
currentPos = chess.currentPos;
winner = chess.winner;
@ -663,8 +664,11 @@ void MillGame::createMillTable()
}
// 设置配置
bool MillGame::configure(bool randomMove)
bool MillGame::configure(bool giveUpIfMostLose, bool randomMove)
{
// 设置是否必败时认输
this->giveUpIfMostLose_ = giveUpIfMostLose;
// 设置是否随机走子
this->randomMove_ = randomMove;
@ -1398,10 +1402,12 @@ bool MillGame::giveup(Player loser)
winner = PLAYER2;
tips = "玩家1投子认负。";
sprintf(cmdline, "Player1 give up!");
score_2++;
} else if (loser == PLAYER2) {
winner = PLAYER1;
tips = "玩家2投子认负。";
sprintf(cmdline, "Player2 give up!");
score_1++;
}
cmdlist.emplace_back(string(cmdline));
@ -1465,7 +1471,7 @@ bool MillGame::command(const char *cmd)
}
// 认输
args = sscanf(cmd, "Players%1u give up!", &t);
args = sscanf(cmd, "Player%1u give up!", &t);
if (args == 1) {
if (t == 1) {

View File

@ -304,7 +304,7 @@ public:
MillGame &operator=(const MillGame &);
// 设置配置
bool configure(bool randomMove);
bool configure(bool giveUpIfMostLose, bool randomMove);
// 设置棋局状态和棋盘上下文,用于初始化
bool setContext(const struct Rule *rule,
@ -362,6 +362,12 @@ public:
int getMoveStep() const
{
return moveStep;
}
// 获取是否必败时认输
bool getGiveUpIfMostLose() const
{
return giveUpIfMostLose_;
}
// 获取 AI 是否随机走子
@ -575,6 +581,9 @@ private:
// 从走子阶段开始或上次吃子起的步数
int moveStep {};
// 是否必败时认输
bool giveUpIfMostLose_ {true};
// AI 是否随机走子
bool randomMove_ {true};

View File

@ -54,6 +54,7 @@ GameController::GameController(GameScene & scene, QObject * parent) :
ruleNo_(-1),
timeLimit(0),
stepsLimit(50),
giveUpIfMostLose_(true),
randomMove_(true)
{
// 已在view的样式表中添加背景scene中不用添加背景
@ -116,7 +117,7 @@ const QMap<int, QStringList> GameController::getActions()
void GameController::gameStart()
{
chess_.configure(randomMove_);
chess_.configure(giveUpIfMostLose_, randomMove_);
chess_.start();
chessTemp = chess_;
@ -142,7 +143,7 @@ void GameController::gameReset()
}
// 重置游戏
chess_.configure(randomMove_);
chess_.configure(giveUpIfMostLose_, randomMove_);
chess_.reset();
chessTemp = chess_;
@ -283,7 +284,7 @@ void GameController::setRule(int ruleNo, MillGame::step_t stepLimited /*= -1*/,
void GameController::setEngine1(bool arg)
{
chess_.configure(randomMove_);
chess_.configure(giveUpIfMostLose_, randomMove_);
isAiPlayer1 = arg;
if (arg) {
@ -299,7 +300,7 @@ void GameController::setEngine1(bool arg)
void GameController::setEngine2(bool arg)
{
chess_.configure(randomMove_);
chess_.configure(giveUpIfMostLose_, randomMove_);
isAiPlayer2 = arg;
if (arg) {
@ -370,6 +371,11 @@ void GameController::playSound(const QString &soundPath)
#endif /* ! DONOT_PLAY_SOUND */
}
void GameController::setGiveUpIfMostLose(bool arg)
{
giveUpIfMostLose_ = arg;
}
void GameController::setAutoRestart(bool arg)
{
isAutoRestart = arg;
@ -778,11 +784,9 @@ bool GameController::giveUp()
if (chess_.whosTurn() == MillGame::PLAYER1) {
result = chess_.giveup(MillGame::PLAYER1);
chess_.score_2++;
}
else if (chess_.whosTurn() == MillGame::PLAYER2) {
result = chess_.giveup(MillGame::PLAYER2);
chess_.score_1++;
}
if (result) {

View File

@ -70,6 +70,11 @@ public:
return stepsLimit;
}
bool getGiveUpIfMostLose()
{
return giveUpIfMostLose_;
}
bool getRandomMove()
{
return randomMove_;
@ -150,6 +155,9 @@ public slots:
// 播放声音
void playSound(const QString &soundPath);
// 是否必败时认输
void setGiveUpIfMostLose(bool arg);
// 是否自动开局
void setAutoRestart(bool arg = false);
@ -240,6 +248,9 @@ private:
// 是否有落子音效
bool hasSound;
// 是否必败时认输
bool giveUpIfMostLose_;
// 是否棋局结束后自动重新开局
bool isAutoRestart;

View File

@ -204,6 +204,9 @@ void MillGameWindow::initialize()
connect(ui.actionAnimation_A, SIGNAL(toggled(bool)),
game, SLOT(setAnimation(bool)));
connect(ui.actionGiveUpIfMostLose_G, SIGNAL(toggled(bool)),
game, SLOT(setGiveUpIfMostLose(bool)));
connect(ui.actionAutoRestart_A, SIGNAL(toggled(bool)),
game, SLOT(setAutoRestart(bool)));