Qt简易的井字棋

        之前写了棋盘绘制之类的,打算做五子棋象棋之类的,但是想起了一个更加简单的棋类游戏,井字棋,大家小时候应该都玩过把。

        百度的游戏规则:

        两个玩家,一个打圈(O),一个打叉(X),轮流在3乘3的格上打自己的符号,最先以横、直、斜连成一线则为胜。如果双方都下得正确无误,将得和局。这种游戏实际上是由第一位玩家所控制,第一位玩家是攻,第二位玩家是守。

        需求分析

        首先肯定是绘制棋盘,然后就是点击下棋功能,下一个判断是否胜利,判断是否平局。我这里写的是人人对战,人机对战的算法研究一下之后应该会做。

        结果展示

        

        具体实现步骤

      1.画棋盘:  棋盘这些格子之类的绘画,就不用UI设计了,for循环的代码肯定更香啊,我这里除了画棋盘,还设置了一个开始游戏的按钮,点击按钮棋盘才可用。

void Widget:: Print(){
    //设置窗体背景为白色
    QPalette palette(this->palette());
    palette.setColor(QPalette::Background, Qt::white);
    this->setPalette(palette);

    //设置九个网格图片
    int x = 0, y = 0, w = 180, h = 180;
    for(int i = 0; i < 3; ++ i){
        for(int j = 0; j < 3; ++ j){
            QPushButton *button = new QPushButton(this);
             gridButton.push_back(button);
            //坐标
            x = j * 180 + 30, y = i * 180 + 30;

            button->setGeometry(x, y, w, h);    //设置按钮位置和大小

           button->setStyleSheet("border-image:url(:/img/grid.png);"); //设置按钮图片
            connect(button, SIGNAL(clicked(bool)), this, SLOT(ButtonClick()));//为每个按钮添加响应函数
        }
    }
    qDebug()<<gridButton.size();
    for(int k=0;k<gridButton.size();k++){
        gridButton[k]->setEnabled(false);
    }
    QPushButton *play = new QPushButton(this);
    play->setGeometry(640, 225, 200, 100);    //设置按钮位置和大小
    play->setText("开始游戏");
    connect(play, SIGNAL(clicked(bool)), this, SLOT(gameAction()));

}

        2.人下棋函数的设计,就是点击该处按钮,读取后进行图片的替换,然后设置为不可用,用一个flag判断玩家是谁,我这里1是玩家1,下了之后就变成玩家2.

int Widget::HumanChess1(QPushButton *button)
{
    int i = button->pos().x() / 180;
    int j = (button->pos().y() - 30) / 180;
    chess[j][i] = 1;    //人类在点(i, j)下了一个子
    button->setStyleSheet("border-image: url(:/img/circle.png);");
    button->setEnabled(false);  //只能下一次
    cur_player = 2;
    return 2;   //下棋成功
}
int Widget::HumanChess2(QPushButton *button)
{
    int i = button->pos().x() / 180;
    int j = (button->pos().y() - 30) / 180;
    chess[j][i] = -1;    //人类在点(i, j)下了一个子
    button->setStyleSheet("border-image: url(:/img/fork.png);");
    button->setEnabled(false);  //只能下一次
    cur_player = 1;
    return 1;   //下棋成功
}

        3. 判断游戏的输赢和是否和棋,你每下一布棋就进行判断,输赢  是根据和进行判断的,玩家1下的点每个赋值为1,判断水平,列和斜的和,为3即1胜利,2下的是-1,和棋是判断是否每个地方都已经下了棋(可以优化)。 

int Widget::GetWinPeople()  //判断输赢
{
    int sum = 0;
    for(int i = 0; i < 3; ++ i){//水平方向
        sum = chess[i][0] +chess[i][1] + chess[i][2];
        if( sum == 3) return 1;
        else if(sum == -3) return -1;
    }

    for(int i = 0; i < 3; ++ i){//垂直方向
        sum = chess[0][i] + chess[1][i] + chess[2][i];
        if(sum == 3) return 1;
        else if(sum == -3) return -1;
    }
    int psum = chess[0][0] + chess[1][1] + chess[2][2];//正对角线
    int csum = chess[2][0] + chess[1][1] + chess[0][2];//副对角线
    if(psum == 3 || csum == 3) return 1;
    else if(psum == -3 || csum == -3) return -1;

    return 0;   //未决胜负
}

  

bool Widget::Tie()  //平局
{
    int cnt = 0;    //有多少个格子走过
    for(int i = 0; i < 3; ++ i){
        for(int j = 0; j < 3; ++ j){
            if(chess[i][j] != 0){
                ++cnt;
            }
        }
    }
    if(cnt == 9){   //9个格子都走过
        QMessageBox::information(this, tr("井字棋"), tr("平局"), QMessageBox::Ok);
        GameOver(); //游戏结束
        return true;
    }
    return false;
}

        游戏结束,棋盘重制

void Widget::GameOver() //游戏结束
{
    for(int i = 0; i < 9; ++ i){
        gridButton[i]->setStyleSheet("border-image: url(:/img/grid.png);");
        gridButton[i]->setEnabled(true);
    }

    //棋盘重置
    for(int i = 0; i < 3; ++ i){
        for(int j = 0; j < 3; ++ j){
            chess[i][j] = 0;
        }
    }
    for(int k=0;k<gridButton.size();k++){
        gridButton[k]->setEnabled(false);
    }
}

        很简单的井字棋游戏,希望对大家有所帮助,后续研究一下算法,会出人机对战,然后就是五子棋,象棋,之后会通过TCP或者其他方式进行联机。

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值