添加棋局的镜像、翻转、旋转算法,未完成,临时上传。

This commit is contained in:
liuweilhy 2018-12-11 23:28:25 +08:00
parent d762f55d70
commit 82b39b02ac
6 changed files with 335 additions and 22 deletions

View File

@ -273,6 +273,42 @@ void GameController::playSound(const QString &soundPath)
}
}
// 上下翻转
void GameController::flip()
{
chess.mirror();
chess.rotate(180);
chessTemp = chess;
updateScence();
}
// 左右镜像
void GameController::mirror()
{
chess.mirror();
chessTemp = chess;
updateScence();
}
// 视图须时针旋转90°
void GameController::turnRight()
{
chess.rotate(90);
chessTemp = chess;
updateScence();
}
// 视图逆时针旋转90°
void GameController::turnLeft()
{
chess.rotate(270);
chessTemp = chess;
updateScence();
}
//bool GameController::eventFilter(QObject * watched, QEvent * event)
//{
// return QObject::eventFilter(watched, event);

View File

@ -67,6 +67,15 @@ public slots:
void setSound(bool arg = true);
// 播放声音
void playSound(const QString &soundPath);
// 上下翻转
void flip();
// 左右镜像
void mirror();
// 视图须时针旋转90°
void turnRight();
// 视图逆时针旋转90°
void turnLeft();
// 根据QGraphicsScene的信号和状态来执行选子、落子或去子
bool actionPiece(QPointF p);
// 认输

View File

@ -1588,3 +1588,263 @@ void NineChess::getPlayer_TimeMS(int &p1_ms, int &p2_ms)
p1_ms = player1_MS;
p2_ms = player2_MS;
}
void NineChess::mirror(bool cmdChange /*= true*/)
{
char ch;
int i, j;
for (i = 1; i <= RING; i++) {
for (j = 1; j < SEAT / 2; j++) {
ch = board[i*SEAT + j];
board[i*SEAT + j] = board[(i + 1)*SEAT - j];
board[(i + 1)*SEAT - j] = ch;
}
}
int16_t p1, p2, p3;
if (move_ < 0) {
i = (-move_) / SEAT;
j = (-move_) % SEAT;
j = (SEAT - j) % SEAT;
move_ = -(i * SEAT + j);
}
else {
p1 = move_ >> 8;
p2 = move_ & 0x00ff;
i = p1 / SEAT;
j = p1 % SEAT;
j = (SEAT - j) % SEAT;
p1 = i * SEAT + j;
i = p2 / SEAT;
j = p2 % SEAT;
j = (SEAT - j) % SEAT;
p2 = i * SEAT + j;
move_ = (p1 << 8) | p2;
}
i = currentPos / SEAT;
j = currentPos % SEAT;
j = (SEAT - j) % SEAT;
currentPos = i * SEAT + j;
if (rule.canRepeated) {
for (auto mill = data.millList.begin(); mill != data.millList.end(); mill++) {
p1 = (*mill & 0x000000ff00000000) >> 32;
p2 = (*mill & 0x0000000000ff0000) >> 16;
p2 = (*mill & 0x00000000000000ff);
i = p1 / SEAT;
j = p1 % SEAT;
j = (SEAT - j) % SEAT;
p1 = i * SEAT + j;
i = p2 / SEAT;
j = p2 % SEAT;
j = (SEAT - j) % SEAT;
p2 = i * SEAT + j;
i = p3 / SEAT;
j = p3 % SEAT;
j = (SEAT - j) % SEAT;
p3 = i * SEAT + j;
*mill &= 0xffffff00ff00ff00;
*mill |= (p1 << 32) | (p2 << 16) | p3;
}
}
// 命令行解析
if (cmdChange) {
;
}
}
void NineChess::turn(bool cmdChange /*= true*/)
{
char ch;
int i, j;
for (i = 0; i < SEAT; i++) {
ch = board[SEAT + i];
board[SEAT + i] = board[SEAT*RING + i];
board[SEAT*RING + i] = ch;
}
int16_t p1, p2, p3;
if (move_ < 0) {
i = (-move_) / SEAT;
j = (-move_) % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
move_ = -(i * SEAT + j);
}
else {
p1 = move_ >> 8;
p2 = move_ & 0x00ff;
i = p1 / SEAT;
j = p1 % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
p1 = i * SEAT + j;
i = p2 / SEAT;
j = p2 % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
p2 = i * SEAT + j;
move_ = (p1 << 8) | p2;
}
i = currentPos / SEAT;
j = currentPos % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
currentPos = i * SEAT + j;
if (rule.canRepeated) {
for (auto mill = data.millList.begin(); mill != data.millList.end(); mill++) {
p1 = (*mill & 0x000000ff00000000) >> 32;
p2 = (*mill & 0x0000000000ff0000) >> 16;
p2 = (*mill & 0x00000000000000ff);
i = p1 / SEAT;
j = p1 % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
p1 = i * SEAT + j;
i = p2 / SEAT;
j = p2 % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
p2 = i * SEAT + j;
i = p3 / SEAT;
j = p3 % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
p3 = i * SEAT + j;
*mill &= 0xffffff00ff00ff00;
*mill |= (p1 << 32) | (p2 << 16) | p3;
}
}
// 命令行解析
if (cmdChange) {
;
}
}
void NineChess::rotate(int degrees, bool cmdChange /*= true*/)
{
// 将degrees转化为0~359之间的数
degrees = degrees % 360;
if (degrees < 0)
degrees += 360;
if (degrees != 90 || degrees != 180 || degrees != 270)
return;
else
degrees /= 45;
char ch;
int i, j;
for (i = 0; i < SEAT; i++) {
ch = board[SEAT + i];
board[SEAT + i] = board[SEAT*RING + i];
board[SEAT*RING + i] = ch;
}
int16_t p1, p2, p3;
if (move_ < 0) {
i = (-move_) / SEAT;
j = (-move_) % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
move_ = -(i * SEAT + j);
}
else {
p1 = move_ >> 8;
p2 = move_ & 0x00ff;
i = p1 / SEAT;
j = p1 % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
p1 = i * SEAT + j;
i = p2 / SEAT;
j = p2 % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
p2 = i * SEAT + j;
move_ = (p1 << 8) | p2;
}
i = currentPos / SEAT;
j = currentPos % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
currentPos = i * SEAT + j;
if (rule.canRepeated) {
for (auto mill = data.millList.begin(); mill != data.millList.end(); mill++) {
p1 = (*mill & 0x000000ff00000000) >> 32;
p2 = (*mill & 0x0000000000ff0000) >> 16;
p2 = (*mill & 0x00000000000000ff);
i = p1 / SEAT;
j = p1 % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
p1 = i * SEAT + j;
i = p2 / SEAT;
j = p2 % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
p2 = i * SEAT + j;
i = p3 / SEAT;
j = p3 % SEAT;
if (i == 1)
i = RING;
else if (i == RING)
i = 1;
p3 = i * SEAT + j;
*mill &= 0xffffff00ff00ff00;
*mill |= (p1 << 32) | (p2 << 16) | p3;
}
}
// 命令行解析
if (cmdChange) {
;
}
}

View File

@ -89,7 +89,7 @@ public:
ACTION_CAPTURE = 0x0400 // 提子
};
// 棋局结构体,包含当前棋盘数据
// 棋局结构体,算法相关,包含当前棋盘数据
// 单独分离出来供AI判断局面用生成置换表时使用
struct ChessData {
// 棋局抽象为一个5×8的char数组上下两行留空
@ -222,21 +222,23 @@ public:
bool reset();
// 游戏开始
bool start();
// 选子在第c圈第p个位置为迎合日常c和p下标都从1开始
bool choose(int c, int p);
// 落子在第c圈第p个位置为迎合日常c和p下标都从1开始
bool place(int c, int p, long time_p = -1);
// 去子在第c圈第p个位置为迎合日常c和p下标都从1开始
bool capture(int c, int p, long time_p = -1);
// 下面3个函数没有算法无关判断和无关操作
bool choose(int pos);
bool place(int pos);
bool capture(int pos);
// 认输
bool giveup(Players loser);
// 命令行解析函数
bool command(int16_t move);
bool command(const char *cmd);
// 局面左右镜像
void mirror(bool cmdChange = true);
// 局面内外翻转
void turn(bool cmdChange = true);
// 局面顺时针旋转
void rotate(int degrees, bool cmdChange = true);
protected:
// 判断棋盘pos处的棋子处于几个“三连”中
@ -266,6 +268,12 @@ protected:
// 设置提示
void setTip();
// 下面几个函数没有算法无关判断和无关操作,节约算法时间
bool command(int16_t move);
bool choose(int pos);
bool place(int pos);
bool capture(int pos);
private:
// 当前使用的规则
struct Rule rule;

View File

@ -120,9 +120,10 @@ void NineChessAi_ab::buildChildren(Node *node)
void NineChessAi_ab::sortChildren(Node *node)
{
// 这个函数对效率的影响很大,排序好的话,剪枝较早,节省时间,但不能在此函数耗费太多时间
// 先赋初值初始值不会影响alpha-beta剪枝
// 这里我用一个随机排序使AI不至于每次走招相同
srand((unsigned)time(0));
for (auto i : node->children) {
i->value = evaluate(node);
i->value = rand();
}
// 排序
if(chessTemp.whosTurn() == NineChess::PLAYER1)

View File

@ -57,20 +57,6 @@ NineChessWindow::NineChessWindow(QWidget *parent)
ui.actionInternet_I->setDisabled(true);
ui.actionSetting_O->setDisabled(true);
// 关联既有动作信号和主窗口槽
// 视图上下翻转
connect(ui.actionFlip_F, &QAction::triggered,
ui.gameView, &GameView::flip);
// 视图左右镜像
connect(ui.actionMirror_M, &QAction::triggered,
ui.gameView, &GameView::mirror);
// 视图须时针旋转90°
connect(ui.actionTurnRight_R, &QAction::triggered,
ui.gameView, &GameView::turnRight);
// 视图逆时针旋转90°
connect(ui.actionTurnLeftt_L, &QAction::triggered,
ui.gameView, &GameView::turnLeft);
// 初始化游戏规则菜单
ui.menu_R->installEventFilter(this);
@ -167,6 +153,19 @@ void NineChessWindow::initialize()
connect(ui.actionAnimation_A, SIGNAL(toggled(bool)),
game, SLOT(setAnimation(bool)));
// 视图上下翻转
connect(ui.actionFlip_F, &QAction::triggered,
game, &GameController::flip);
// 视图左右镜像
connect(ui.actionMirror_M, &QAction::triggered,
game, &GameController::mirror);
// 视图须时针旋转90°
connect(ui.actionTurnRight_R, &QAction::triggered,
game, &GameController::turnRight);
// 视图逆时针旋转90°
connect(ui.actionTurnLeftt_L, &QAction::triggered,
game, &GameController::turnLeft);
// 关联控制器的信号和主窗口控件的槽
// 更新LCD1显示玩家1用时
connect(game, SIGNAL(time1Changed(QString)),