第一阶报告¶
一、完成情况¶
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.主界面代码¶
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 {}
}
}
}