跳转至

第一阶报告

一、完成情况

1.实现基本的棋盘运行,单个棋子移动、分为一次一格的连续跳跃,不会出现吃掉其他棋子,移动至不合理位置的情况

2.在进入游戏后出现选择双人、四人、六人的游戏形式

3.在棋盘右上角显示当前进行操作的玩家棋子颜色

4.直接进行相邻移动自动结束玩家下棋回合,进行跳跃后需要再点击一次棋子结束下棋回合

二、实现思路

1.棋盘显示实现思路

(1)基础界面

选用了Qwight组件作为基础的界面,用代码+ui的方式设计界面

(2)棋盘

直接用棋子摆放作为棋盘本体,因为采用2*2的数组作为棋盘,因此将棋盘建立在斜坐标系的第一象限,通过改变基向量,扩大棋子之间的距离比例来自动生成所有的棋子

坐标变换

2.棋子实现思路

棋子采用父类为QPushbutton的组件来实现,通过继承创建了新的MyButton类,拥有原组件的功能的同时还可以记录自己的直角坐标,是否放置棋子和棋子所属的玩家等信息

#define MYBUTTON_H
#include <QWidget>
#include<QPushButton>
#include<QEvent>
#include<QMouseEvent>

class Mybutton : public QPushButton
{
    Q_OBJECT
    public:
    //后续接入各种功能代码
}

3.可控功能按钮与状态显示

在ui界面创建QPushButton并设置槽函数,在槽函数内实现相关功能,利用Qlabel组件来显示玩家状态

二、行棋逻辑

基本思路:通过直角坐标系判断棋子关系,通过点击事件获取棋子坐标与棋子状态并记录,再通过第二次点击事件判断是否能行棋,通过改变棋子的颜色来实现棋子位置的转移

1.判断函数

通过直角坐标系的特性可以写判断各个区域位置,棋子之间是否接壤等函数,将这些函数全部写在一个名为"judgement"的类中

2.棋子改变方式

改变单个棋子中的状态以及棋子自己的背景颜色来改变棋子状态

三、实现结果

图片1

图片2

四、重要代码部分

1.主界面代码

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    //int judge_out(int x,int y); //判断棋格btn[x][y]是否在有效棋盘之内
    void set_position();   //给btn设置位置
    void set_player(int x);     //设置Player x 的棋子
    //最重要的一个函数,点击按钮之后的槽函数
    void mycao(int,int);
    void myconnect(int x,int y);       //给每一个按钮设置连接函数
    int judgeround(int p,int x1,int y1,int x2,int y2);  //判断轮次的函数
    void setui();   //修改ui界面的函数集合
    void Change_Rouond();    //修改当前需要下棋的人的状态的函数
private slots:
    void on_Big_but1_clicked(); //生成双人对决的棋子
    void on_Big_but2_clicked();
    void on_Big_but3_clicked();
    void on_Leave_clicked();
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();
    void on_pbStart_clicked();
private:
    QTimer * timer;
    QTime * TimeRecord;
public:
    void initTime();
    void updateTime();
    void pbStart_clicked();
    void walk(int x,int y,int score);
    int jud_move(int x,int y);
private:
    void change_direction();    //转动棋盘的函数
    void exchange_position(int x1,int y1,int x2,int y2);   //交换单个棋子的位置的函数
private:
    Ui::Widget *ui;
    Mybutton *btn[17][17];      //代表整个直角坐标系下所有按钮的可能性
    Judgement jd;               //一个存储所有判断函数的类
    int ju_x,ju_y;              //临时存储
    int P;
    int flag;
    int X,Y;//记录上次所走的棋子位置;
    int Player_Round;
    int tur=1;
};

2.判断函数部分

class Judgement
{
public:
    Judgement();
    int judge_out(int x,int y); //判断棋格btn[x][y]是否在有效棋盘之内
    int judge_P1(int x,int y);  //判断是否在P1的区域内,后以此类推
    int judge_P4(int x,int y);
    int judge_P2(int x,int y);
    int judge_P3(int x,int y);
    int judge_P5(int x,int y);
    int judge_P6(int x,int y);
    int judgemove_01(int x1,int y1,int x2,int y2);
    int judgemove_02(int x1,int y1,int x2,int y2);
};

3.逻辑函数具体实现

void Widget::mycao(int a1, int a2)      //最重要的逻辑函数,可以完成点击按钮之后的各种操作
{
    timer->start(1000);
    //getsate获得状态,0没有棋子,123456为玩家123456的棋子(走棋第一步)
    if(btn[a1][a2]->getsate()!=0&&flag==0)
    {
        ju_x=a1;
        ju_y=a2;
    }
    //(走棋第二步)
    else
    {
        //双击棋子,导致前面的状态被清除,进入下一个人的回合
        if(ju_x==a1&&ju_y==a2)
        {
            ju_x=0;
            ju_y=0;
            flag=0;
            Change_Rouond();
        }
        //如果之前没有选中棋子,则不做操作
        if(ju_x==0&&ju_y==0){}
        //如果之前有选中棋子,则进入判断阶段
        else                                //ju_x,ju_y是原来棋子的位置,a1,a2是要走的位置
        {

            //判断是否进行单次跳跃
            if(jd.judgemove_01(ju_x, ju_y, a1, a2)&&judgeround(P,X,Y,ju_x,ju_y)&&flag==0)   //进行单次跳跃之后的函数
                        {
                        int sate=btn[ju_x][ju_y]->getsate();//获得之前棋格的状态
                        btn[ju_x][ju_y]->clearsate();//clearsate清空棋子
                        btn[a1][a2]->putsate(sate);//putsate设置棋子
                        X=a1;
                        Y=a2;
                        ju_x=0;
                        ju_y=0;
                        Change_Rouond();
                        }

            //进行隔跳之后的操作函数
            else if(jd.judgemove_02(ju_x, ju_y, a1, a2)&&btn[(ju_x+a1)/2][(ju_y+a2)/2]->getsate()!=0&&(judgeround(P,X,Y,ju_x,ju_y)||flag==1))
            {
                int sate=btn[ju_x][ju_y]->getsate();//获得之前棋格的状态
                btn[ju_x][ju_y]->clearsate();//clearsate清空棋子
                btn[a1][a2]->putsate(sate);//putsate设置棋子
                X=a1;
                Y=a2;
                //如果是第一次隔跳,则不结束当前回合而进入连跳的状态
                if(jd.judgemove_02(a1, a2,a1-2,a2+2)&&ju_x!=(a1-2)&&ju_y!=(a2+2)||jd.judgemove_02(a1, a2,a1+2,a2-2)&&ju_x!=(a1+2)&&ju_y!=(a2-2)||jd.judgemove_02(a1, a2,a1,a2+2)&&ju_x!=a1&&ju_y!=(a2+2)||jd.judgemove_02(a1, a2,a1,a2-2)&&ju_x!=a1&&ju_y!=(a2-2)||jd.judgemove_02(a1, a2,a1+2,a2)&&ju_x!=(a1+2)&&ju_y!=a2||jd.judgemove_02(a1, a2,a1-2,a2)&&ju_x!=(a1-2)&&ju_y!=a2){
                    ju_x=a1;
                    ju_y=a2;
                    flag=1;
                }
                else {
                    flag=0;
                    ju_x=0;
                    ju_y=0;
                }

            }
            //如果既不是单跳也不是隔跳
            else {}
        }
    }
}