新年好啊,大过年的,自己的项目也差不多解决了,心情还比较愉悦。
本以为自己做不出这个项目的,然后还想着多方位去想各种办法去从侧面切入来解决这个麻烦的问题,所以给自己预留了很长的时间来完成,这个项目。
没想到功夫不负有心人,在我各种努力寻找解决方法的时候,最终给我找到了。
这里我就说一下,我在项目中遇到的小问题(但不是我上面千方百计想的麻烦的问题),并且如何解决的。
一、九宫格拼图bug的解决。
不知道大家有没有玩过win7自带的游戏(桌面右键选择‘小工具’选择‘图片拼图板’),这个游戏就像华容道一样,移动格子来拼成完整的图案。
这是我之前没网的时候常玩的游戏之一。我做这游戏的原因是看起来容易做(对,我就是那么懒)。但是当我完成之后就发现他有一个bug实在是十分棘手。
我先讲这游戏怎么做吧,好吧,网上都有这个做法,但是我还是要讲。
首先就是切割图片,我找了一下网上的,
QRectF target(0.0, 0.0, 140.0,140.0);//控件显示图片的坐标及宽高
QImage image(":/new/ xx.jpg");
QRectF source(0,0 , 140.0, 140.0); //截取其游戏图片的坐标及宽高
QPainter painter(label);
painter.drawImage(target, image, source);
后面这些用变量改变就行。
我用的是label做按钮,所以我注册了按键事件,并且为了方便,我将他们放入了一个Qlist中,这样好遍历操作。
但是当你想让控件显示这图片时,是不行的,因为只在界面初始化的时候绘图才行。
所以百度了一下,要注册控件事件过滤,然后重载其事件。
while(i<9)
{
QLabel_list[i]->installEventFilter(this);
i++;
}
-------------------------------------------------------------------------------------
bool XXX::eventFilter(QObject *watched,QEvent *event)
{
picnum=0;
if(loadok)
return QWidget::eventFilter(watched,event);
while(picnum<8)
{
if(watched==QLabel_list[picnum]&& event->type() == QEvent::Paint)
{
PaintInit(picnum);
picnum=0;
break;
}
picnum++;
}
return QWidget::eventFilter(watched,event);
}
这是基本的应该看的懂,重载eventFilter()这个事件,然后进入PaintInit(picnum);这个函数进行图片显示设置,我把上面的再写过吧,这个自己写很容易的。
QRectF target(0.0, 0.0, 140.0,140.0);//控件
QImageimage(":/new/prefix1/image/test/puzzle1.jpg");
QRectF source(position[sortnum[pn]-1][0],position[sortnum[pn]-1][1], 140.0, 140.0);//图片
QPainter painter(QLabel_list[pn]);
painter.drawImage(target, image, source);
这些我用了我自己的数组,这样方便一点。这里出来,图片是拼好的,不是打乱的。因为我用的是sortnum[]数组是没有乱序过的。
doubleposition[9][2]={{0.0,0.0},{140.0,0.0},{280.0,0.0},
{0.0,140.0},{140.0,140.0},{280.0,140.0},
{0.0,280.0},{140.0,280.0},{280.0,280.0}};
doublelabel_old_position[9][2]={{10.0,40.0},{152.0,40.0},{294.0,40.0},
{10.0,182.0},{152.0,182.0},{294.0,182.0},
{10.0,324.0},{152.0,324.0},{294.0,324.0}};
int sortnum[8]={1,2,3,4,5,6,7,8};
int luannum[8]={0,1,2,3,4,5,6,7};//将来用乱序函数使其乱序
这样就基本得了,然后想想怎么判断哪个图标可以移动的呢,答案是在空白格的上下左右的控件被点击到就可以移动(执行移动事件),笨办法,列出9个坐标一算,答案就是(该格子和空白格的坐标的的差)的绝对值为(格子的宽加上间距)就可以移动,代码里的null_x,null_y为空白格的坐标。
if((qAbs(QLabel_list[labelnum]->x()-null_x)+qAbs(QLabel_list[labelnum]->y()-null_y))==142)
{
canmove(labelnum);
}
Canmove()函数里面放着两个的坐标交换。最后一步怎么判断游戏赢了呢。
就是判断该控件的坐标是不是和我乱序之后的数组所对应的坐标数组相等
Label->x()==(label_old_position[sortnum[0]-1][0])&&Label->y()==(label_old_position[sortnum[0]-1][1])&&……
把8个图标的都列举出来&&就行了。
前面说了,运行之后图标是正常拼好的样子,你要把它打乱才行啊,
QRectF source(position[sortnum[pn]-1][0],position[sortnum[pn]-1][1], 140.0, 140.0);//图片
我之前是吧这个sortnum打乱,然后就完成了,但是这样,你自己可以玩玩看,有很大几率,最后有两个是交换不来的,这就是我所说的bug,这就是随机的bug,不能保证最终能拼成。
我想的解决办法想把它完整的拼好后,然后让他随机乱走,就成了随机的图,但是这样不科学,搞得我以为要涉及数学领域。。。。我要找到规律。最终在弟弟的帮助下,发现,只要偶数次随机打乱两个图,就能正确的拼出正确的图。So:
loadok=1;
int i=0;
while(i<16)
{
LuanXu(luannum,8);
int labelx1=QLabel_list[luannum[0]]->x();
intlabely1=QLabel_list[luannum[0]]->y();
int labelx2=QLabel_list[luannum[5]]->x();
int labely2=QLabel_list[luannum[5]]->y();
QLabel_list[luannum[0]]->move(labelx2,labely2);
QLabel_list[luannum[5]]->move(labelx1,labely1);
i++;
}
loadok=0;
最终解决了这个bug!!!!!
二、qt界面不刷新问题
我把一个界面hide之后再show出来时,他界面就不更新了,不知道是什么原因,可能是我上面控件多?可能是qt本身问题?可能是我代码问题?
无所知,我用了update()函数,repaint()函数,都不能解决这个问题,参考了百度说的,update可能也不能执行paintEvent()这个事件函数。然后我也不知道怎么写了。后面我发现,用其他窗口遮挡我的程序,也不能“刷新”,但是把窗口移到PC界面外,再移回来就刷新了,意思是我得不断的把窗口移出去才能刷新咯。那我就按照这个方法,show回来的时候,我用个计时器,每秒触发我‘移动到屏幕外的事件’,虽然可能偶尔会闪屏,但是这个方法是目前最好的解决方法了。后来我想到一个方法,我不再hide窗口,直接把窗口完全移到屏幕外面看不见,等到要show的时候,我再把它移回来。投机取巧也是办法。哈哈