魔方教学系统(基于QT)
之前沒(méi)能及時(shí)復(fù)盤(pán)寫(xiě)下來(lái) 現(xiàn)在很多想不起來(lái),慢慢回憶著寫(xiě)吧
背景
之前指導(dǎo)本科生做的伺服電機(jī)的機(jī)械臂解魔方機(jī)器人,老師提出能不能低成本化,就嘗試了舵機(jī)和低價(jià)相機(jī),外邊做成黑色殼子阻絕光線(xiàn)的方法。最終把伺服電機(jī)機(jī)械臂替換成了兩個(gè)舵機(jī)和轉(zhuǎn)動(dòng)平臺(tái)組成的執(zhí)行機(jī)構(gòu),四個(gè)相機(jī)減到一個(gè)相機(jī),實(shí)現(xiàn)的效果很成功。然后因?yàn)橛?jì)算機(jī)解魔方有個(gè)特點(diǎn),可以從一種狀態(tài)解算的任何另一種狀態(tài),所以又衍生出了用魔方機(jī)器人教學(xué)的想法。通過(guò)把打亂的魔方交給魔方機(jī)器人,造出指定的場(chǎng)景,從而達(dá)到反復(fù)訓(xùn)練的目的。
系統(tǒng)組成
下位機(jī)是一塊STM32的板卡,用來(lái)控制舵機(jī),操作相機(jī)抓圖,把魔方的角塊和顏色編碼后通過(guò)串口傳給上位機(jī)。上位機(jī)直接就是筆記本電腦,用QT寫(xiě)的完整GUI界面,包括解魔方教學(xué)步驟的圖片和視頻,對(duì)應(yīng)的要機(jī)器人還原的指定狀態(tài)的選擇。確定后再傳回下位機(jī)控制舵機(jī)完成還原操作。
由于這套系統(tǒng)還在跟公司合作,以后可能會(huì)商業(yè)化,所以不能在這里放內(nèi)部結(jié)構(gòu)圖和完整代碼,有之前伺服電機(jī)解魔方機(jī)器人的圖,放一些示意一下。
學(xué)習(xí)到的技術(shù)
-
顏色識(shí)別
顏色識(shí)別采用OpenCV實(shí)現(xiàn)。因?yàn)槟Х轿恢煤拖鄼C(jī)位置基本固定,先采用OpenCV的圖像標(biāo)定函數(shù),標(biāo)定出各個(gè)角塊的坐標(biāo)點(diǎn),然后采用HSV顏色模型來(lái)識(shí)別顏色。之所以不用RGB顏色模型也是考慮到外界環(huán)境可能出現(xiàn)的光照等原因?qū)︻伾R(shí)別造成的誤差。
在魔方拍攝與識(shí)別這一問(wèn)題中只需要考慮其中的H 值與S 值即可,顯然明度的問(wèn)題并不會(huì)影響到本文的顏色識(shí)別,而且它最大的優(yōu)點(diǎn)在于可以一定程度上削弱光照條件對(duì)識(shí)別結(jié)果的影響,這樣可以大大地提高本文的識(shí)別效果。當(dāng)然,忽略V 值的影響雖然不會(huì)在程序中影響到最終的識(shí)別情況,但是需要指出光照條件的變化H 值與S 值是會(huì)產(chǎn)生較大變化的,并不存在使用了HSV 模型就可以忽略光照條件的影響。
先把魔方還原,對(duì)每一個(gè)攝像頭進(jìn)行標(biāo)定。單獨(dú)啟動(dòng)每一個(gè)攝像頭拍攝基準(zhǔn)照片,根據(jù)拍攝的照片在其上用鼠標(biāo)選擇取色基準(zhǔn)點(diǎn)。完成每一個(gè)攝像頭的標(biāo)定后開(kāi)始編寫(xiě)程序,將每一個(gè)攝像頭的每一個(gè)取色基準(zhǔn)點(diǎn)的橫縱坐標(biāo)值輸入,并同時(shí)取該點(diǎn)周?chē)?個(gè)其他像素點(diǎn),讀入9個(gè)點(diǎn)的數(shù)據(jù)計(jì)算平均值,將得到的平均值作為最終的輸出結(jié)果。
因?yàn)楸疚牡哪Х接幸环N顏色是白色的,那本文大可以單獨(dú)考慮S 值來(lái)區(qū)分這一顏色。通過(guò)對(duì)白色的面進(jìn)行大量地拍攝和識(shí)別發(fā)現(xiàn),白色的小塊幾乎不會(huì)出現(xiàn)S 值超過(guò)70的情況,所以將S 上的閾值設(shè)置在70,只要是S 值低于70時(shí),則將其認(rèn)為是白色。雖然看起來(lái)這樣的判定方法是有些單純的,但它的實(shí)際效果并不差,白色的識(shí)別準(zhǔn)確率在作者的實(shí)驗(yàn)中是最高的,在36次的實(shí)驗(yàn)中白色小塊沒(méi)有一次被識(shí)別錯(cuò)誤的。
對(duì)于其他的五種顏色作者則都在H 值上進(jìn)行劃分。通過(guò)大量的拍攝圖像識(shí)別的情況來(lái)看,在白天的實(shí)驗(yàn)室內(nèi),保持一個(gè)相對(duì)恒定的光照條件時(shí),以下的閾值設(shè)置效果較好,如果出現(xiàn)因?yàn)殚撝挡划?dāng)而導(dǎo)致的識(shí)別出錯(cuò)問(wèn)題則應(yīng)該根據(jù)實(shí)際情況對(duì)閾值進(jìn)行調(diào)整(實(shí)際情況來(lái)看這種操作也是比較有必要的,在上午、正午、傍晚時(shí)的閾值都需要進(jìn)行一定的微調(diào),尤其是紅色的上限值和橙色的下限值,在夜晚沒(méi)有外界自然光只有室內(nèi)日光燈和機(jī)器補(bǔ)光燈的條件下往往需要對(duì)閾值進(jìn)行較大的調(diào)整)。將紅色的閾值設(shè)置為H 值大于等于0且小于7,而橙色的閾值為大于等于7且小于33,將黃色的閾值設(shè)置為大于等于33且小于51,將綠色的閾值設(shè)置為大于等于51且小于80,將藍(lán)色的閾值設(shè)置為大于等于80且小于130,將大于等于130且小于180的部分判定為紅色(這種情況是極少出現(xiàn)的)。
-
解法實(shí)現(xiàn)
人為地解魔方的方法有很多種,例如較為常見(jiàn)的有層先法和CFOP 法,這兩種方法具有一個(gè)極大的優(yōu)勢(shì)就是它們更容易形成讓人很快就能記住的解魔方的公式,即使是一個(gè)完全沒(méi)有接觸過(guò)三階魔方的普通人,也能很快地學(xué)會(huì)層先法解魔方的公式。
而計(jì)算機(jī)的解魔方算法就有很多種了,因?yàn)橛?jì)算機(jī)是不需要考慮公式和可記憶性問(wèn)題的,也不需要考慮是否會(huì)花費(fèi)大量的時(shí)間去計(jì)算復(fù)雜的數(shù)學(xué)問(wèn)題,只要算法在數(shù)學(xué)原理上沒(méi)有錯(cuò)誤,編寫(xiě)成對(duì)應(yīng)的程序就能完成解魔方的任務(wù)。目前已經(jīng)被開(kāi)發(fā)的較為完善的有二階段算法、Thistlethwaite 算法、Jaap Scherphuis 算法等等。其中有的算法可能會(huì)檢索出最小還原路徑但犧牲的是求解的時(shí)間,有的可能求解極為迅速但可能其求解出的步驟會(huì)較多。單純?nèi)绻麨榇舜蔚闹悄軝C(jī)器人創(chuàng)意大賽中的解魔方項(xiàng)目取得好成績(jī)考慮的話(huà),采用二階段算法或Thistlethwaite 算法是較為合適的,因?yàn)樗鼈兡芮蠼猥@得一個(gè)步驟不那么多的還原路徑,并且求解的速度相對(duì)較快,是兩種在速度和步驟數(shù)量上比較均衡的算法。
本文解魔方算法使用Thistlethwaite 算法。
魔方解算步驟的編碼
三階魔方具有6個(gè)顏色完全不同的面,每個(gè)面都有9個(gè)小色塊。本文將這9個(gè)色塊都按照第一行為1,2,3號(hào),第二行為4,5,6號(hào),第三行為7,8,9號(hào)進(jìn)行編號(hào),在旋轉(zhuǎn)魔方時(shí)魔方本身的一個(gè)特點(diǎn)就是:每一個(gè)面最中間的那個(gè)5號(hào)色塊是并不會(huì)轉(zhuǎn)動(dòng)的。因此只要保持魔方本身的姿態(tài)不變化,讓某一個(gè)顏色的色塊一直朝向某一個(gè)方向,就可以用一組字母來(lái)描述每個(gè)面。本文定義了U(up)、D(down)、L(left)、R(right)、F(front)、B(behind) 這幾個(gè)字母來(lái)描述6個(gè)面,同時(shí)本文規(guī)定,對(duì)于一個(gè)標(biāo)準(zhǔn)三階魔方其U 面為黃色,D 面為白色,L 面為橙色,R 面為紅色,F 面為藍(lán)色,B 面為綠色。至此,本文已經(jīng)完成了對(duì)魔方每個(gè)面的定義,每一個(gè)魔方只要通過(guò)這種擺放姿勢(shì)擺放,給出的一個(gè)還原路徑的執(zhí)行方式就唯一。
在規(guī)定了面的名稱(chēng)后再對(duì)面的旋轉(zhuǎn)進(jìn)行規(guī)定。顯然每個(gè)面都只能順、逆時(shí)針旋轉(zhuǎn)90度和旋轉(zhuǎn)180度,本文將其定義為“1”,“3”,“2”三個(gè)數(shù)字。需要注意的是,這里的“順時(shí)針”和“逆時(shí)針”是指當(dāng)你面向這個(gè)面時(shí)的順時(shí)針和逆時(shí)針。舉個(gè)例子,將一個(gè)魔方的F 面朝向你的臉,此時(shí)的F 面順時(shí)針旋轉(zhuǎn)90度就是將1號(hào)色塊轉(zhuǎn)到3號(hào)色塊的位置這樣旋轉(zhuǎn),而此時(shí)的B 面順時(shí)針旋轉(zhuǎn)則需要你將魔方的B 面朝向你的臉,然后將1號(hào)色塊轉(zhuǎn)到3號(hào)色塊位置這樣旋轉(zhuǎn)。
通過(guò)對(duì)面的名稱(chēng)和旋轉(zhuǎn)的規(guī)定,本文得到了U、D、L、R、F、B 六個(gè)字母和1、3、2這三個(gè)數(shù)字,將其組合就得到了F1、U2、D3等等這樣的組合,這種組合形成的一系列旋轉(zhuǎn)動(dòng)作就是本文的還原路徑了。例如F1 U2 D3 R3 U2 L1 U1這個(gè)還原路徑,很顯然,如果你將F 面面朝自己,這個(gè)還原路徑將變成一個(gè)唯一的動(dòng)作。
Thistlethwaite 算法是由Morwen B. Thistlethwaite 這位數(shù)學(xué)家設(shè)計(jì)并以他的名字進(jìn)行命名的一種計(jì)算機(jī)解魔方算法[11],整個(gè)解魔方的算法分為4個(gè)階段,每個(gè)階段完成一些工作來(lái)限制小塊的位置,當(dāng)魔方的每一個(gè)小塊都只剩下一個(gè)可能的位置時(shí)就完成了魔方的還原了[6]。
使用這種算法可以得到一種步驟極少的還原魔方的路徑,但是由于其四個(gè)還原步驟都相當(dāng)?shù)膹?fù)雜,并且需要大量的參考表(公式),作為一個(gè)普通的人類(lèi)是完全無(wú)法使用這種方法來(lái)解魔方的,因?yàn)樗膮⒖急?#xff08;公式)多到根本無(wú)法記憶(僅僅第一個(gè)還原階段的位置數(shù)量就多達(dá)4.33*10 19種)。
對(duì)于這個(gè)算法的四個(gè)步驟做以下的簡(jiǎn)單描述:
第一步,先進(jìn)行幾步旋轉(zhuǎn)來(lái)使得魔方的狀態(tài)變成不使用U1、U3、D1和D3這四種動(dòng)作就可以完成復(fù)原的狀態(tài)。這個(gè)過(guò)程通常需要不超過(guò)十步來(lái)完成。
第二步,再將魔方的狀態(tài)調(diào)整到不需要F1、F3、B1和B3這四種動(dòng)作就可以完成復(fù)原的狀態(tài)。這個(gè)過(guò)程的步驟數(shù)量或多或少,最多可能會(huì)出現(xiàn)十幾步。
第三步,將魔方調(diào)整到只需要F2、B2、L2、R2、U2和D2動(dòng)作就能完成復(fù)原的狀態(tài)。這個(gè)過(guò)程所需要的步驟數(shù)量也是不確定的,要根據(jù)魔方的實(shí)際狀態(tài)來(lái)看。通常情況下也是需要十幾步的。
第四步,只使用F2、B2、L2、R2、U2和D2動(dòng)作完成最后的調(diào)整,讓所有小塊可能出現(xiàn)的位置都變成唯一位置,完成魔方的復(fù)原。
整個(gè)過(guò)程看起來(lái)似乎并不是很難,簡(jiǎn)單來(lái)說(shuō)就是在逐次地限制小塊的位置可能性,讓小塊可能存在的位置數(shù)量越來(lái)越少,先限制U 面和D 面的小塊,再限制F 面和B 面的小塊,最后限制L 面和R 面的小塊,當(dāng)完成全部限制后,在U 面和D 面都只會(huì)存在有兩種顏色的小塊,F 面和B 面以及L 面和R 面也是如此,然后就可以通過(guò)F2、B2、L2、R2、U2 和D2 動(dòng)作就能完成還原了。但是實(shí)際上執(zhí)行這四個(gè)步驟時(shí)所需要花費(fèi)的計(jì)算量是極為龐大的,下面的這張表格中顯示的就是執(zhí)行四個(gè)步驟時(shí)需要的一些數(shù)據(jù)量。
從數(shù)學(xué)的角度上來(lái)看,它實(shí)際上是一個(gè)嵌套組的序列,算法的每一個(gè)階段都是一張查找表,用來(lái)尋找到商陪集空間中每一個(gè)元素的解。而最后一列中顯示的就是這個(gè)陪集空間的順序,也就是每一個(gè)階段的查找表的大小。至于這個(gè)因子數(shù)量的計(jì)算公式,這和這種算法在限制不同面的小塊時(shí)是如何限制的有關(guān)。[6]具體的一些數(shù)學(xué)原理就非常深?yuàn)W了,涉及到太多作者并沒(méi)有接觸過(guò)的更為高深和專(zhuān)業(yè)數(shù)學(xué)知識(shí),在此就不多做分析和討論了。
在第一階段時(shí),目標(biāo)是限制U 面與D 面都只能采用U2和D2的動(dòng)作來(lái)進(jìn)行后續(xù)的調(diào)整,其實(shí)它所做的工作在魔方層面來(lái)看就是修正魔方的棱塊的方向,因?yàn)橐骍 面與D 面都只能轉(zhuǎn)半圈而不能轉(zhuǎn)四分之一圈,所以就決定了是不可能再調(diào)整四邊棱塊的了,通過(guò)這種限制就可以完成將四邊棱塊限制在一個(gè)完全正確的位置上。
在第二階段時(shí),目標(biāo)是在第一階段的基礎(chǔ)上開(kāi)始限制F 面與B 面的小塊。如果要求在F、B、U 和D 面都只能使用半圈的旋轉(zhuǎn)方式而不能使用四分之一圈的旋轉(zhuǎn)方式,那么這階段就可以完成對(duì)于八個(gè)角塊的位置確定,并對(duì)這八個(gè)角塊的方向進(jìn)行確定,讓角塊和第一階段確定的棱塊完成正確的拼接。在完成第二階段后,八個(gè)角塊和四個(gè)棱塊都會(huì)進(jìn)入位置確定,角塊方向不定的一種狀態(tài),但即使是方向不定但因?yàn)槟Х奖旧淼慕Y(jié)果和角塊的顏色,它們依然會(huì)受到移動(dòng)限制。
在第三階段,開(kāi)始限制剩下的L 面與R 面的小塊,目的是完成對(duì)所有面上小塊的限制,讓每一個(gè)面都只有“相對(duì)顏色”(例如F 面為藍(lán)色,B 面為綠色,則在完成第三階段后,F 面和B 面都只會(huì)存在藍(lán)色與綠色兩種顏色,絕不會(huì)出現(xiàn)其他的4種顏色在這兩個(gè)面中)。在此種狀態(tài)下,所有的角塊和棱塊都已經(jīng)進(jìn)入了正確的位置,只需要在進(jìn)行U2、D2、F2、B2、L2和R2這六種動(dòng)作就能將魔方徹底地復(fù)原。
第四個(gè)階段就是只使用旋轉(zhuǎn)半圈的六種動(dòng)作將魔方徹底地復(fù)原。
很顯然這個(gè)算法的搜索方法看起來(lái)很美好,但它使用的查找表實(shí)在是太大了,及時(shí)是計(jì)算機(jī)直接去運(yùn)行也會(huì)有不小的計(jì)算壓力,所以就需要想辦法來(lái)縮小這個(gè)檢查表。為了減小這個(gè)檢查表,Tistlethwaite 嘗試簡(jiǎn)化了初始的這種搜索方法,這也是為什么有時(shí)他需要的實(shí)際還原步驟是比這個(gè)商空間的“直徑”(搜索出的最佳的還原路徑)要多一些的原因。在之后他的一些學(xué)生針對(duì)這個(gè)問(wèn)題進(jìn)行了更深層次的研究,他們對(duì)這些嵌套組進(jìn)行了完整的分析,然后改進(jìn)了算法,讓搜索出的最佳還原路徑降低到五十步。再隨后,他們繼續(xù)研究了每一個(gè)階段的搜索算法,對(duì)每一個(gè)階段的搜索算法又進(jìn)行了全面而深入的分析,將最佳還原路徑降低到了45步。再之后又有一名叫做Hans Kloosterman 的人繼續(xù)改進(jìn)了第三階段和第四節(jié)段的算法,成功將最佳還原路徑的步驟降低到了42步,這個(gè)42步被實(shí)現(xiàn)的時(shí)間是在1991年[6]。再之后計(jì)算機(jī)的運(yùn)算能力開(kāi)始大幅度提高,借助運(yùn)算性能更強(qiáng)的計(jì)算機(jī),數(shù)學(xué)家Mike Reid 通過(guò)更復(fù)雜的數(shù)學(xué)分析得出的結(jié)論是從第一階段到第二階段理論上需要12步即可完成,第三階段和第四階段理論上需要18步即可完成,將其組合起來(lái)后理論上30步之內(nèi)就可以完成用這種算法來(lái)求解任何一個(gè)打亂的三階魔方。
-
全局變量的使用
當(dāng)時(shí)對(duì)面向?qū)ο罄斫獠簧羁?#xff0c;魔方的狀態(tài),因?yàn)樵谀Х浇馑憷镆灿玫?#xff0c;在串口通訊時(shí)也要用到,就定義成了全局變量。也順便記錄一下用全局變量的方法:
extern char color_sides[6][9];在頭文件通過(guò)extern 聲明全局變量,其他地方需要使用時(shí),只需include進(jìn)相應(yīng)的頭文件即可
但C++不提倡使用全局變量
因?yàn)槿肿兞縝ai容易導(dǎo)致代碼的可復(fù)用性下降,以及對(duì)象管理的困難。
試想,如果某個(gè)類(lèi)使用了全局變量,則移植該類(lèi)的時(shí)候,必須將全局變量也一起移植。更可怕的是,如果這個(gè)全局變量還是一個(gè)對(duì)象,并且初始化也在不同的類(lèi)中實(shí)現(xiàn),那么所有這些代碼將被永久捆綁在一起,無(wú)法分離了。任何一個(gè)與此全局變量相關(guān)聯(lián)的代碼一旦有改動(dòng),即可對(duì)其他使用該變量的代碼產(chǎn)生不可預(yù)知的影響。
影響函數(shù)的封裝性能:我們肯定是希望我們寫(xiě)的函數(shù)具有重入性,就如一個(gè)黑盒子一般,只 通過(guò)函數(shù)參數(shù)就能得到返回,內(nèi)部 實(shí)現(xiàn)要獨(dú)立,但是如果函數(shù)中使用了全局變量,這勢(shì)必就破壞了函數(shù)的封裝性,會(huì)造成對(duì)全局變量的依賴(lài)。
1 全局變量是很好。
2 但是有缺點(diǎn):容易被修改錯(cuò),尤其在工程很大的時(shí)候。
3 使用時(shí)一定要控制好全局變量的修改。
4 不過(guò)小工程小項(xiàng)目使用全局變量是很方便的!
1.全局變量在程序執(zhí)行過(guò)程中一直占用存儲(chǔ)單元,耗費(fèi)空間。
2.使函數(shù)的通用性、移植性降低了,耦合性變強(qiáng)了。
3.使程序的可讀性降低,難以判斷全局變量在一定時(shí)刻的具體值。
重新構(gòu)建你的數(shù)據(jù)結(jié)構(gòu),把公有數(shù)據(jù)成員抽離出來(lái),單獨(dú)做成模塊,提供一個(gè)接口對(duì)其操作。
如果確實(shí)有大量數(shù)據(jù)需要共享的話(huà),建議還是用單獨(dú)的類(lèi)封裝一下。其實(shí)類(lèi)的使用,個(gè)人認(rèn)為主要還是邏輯上清晰為第一原則
-
播放器
因?yàn)橐菔窘饽Х浇虒W(xué)視頻,所以用QT寫(xiě)了一個(gè)播放器。實(shí)現(xiàn)的功能主要有播放本地視頻,暫停,進(jìn)度條拖動(dòng)。
用到的QT庫(kù):
QMediaplayer:用于解析音頻文件和視頻文件。
使用QMediaplayer,除了需要添加必要的頭文件之外,還需要在.pro(Qt的工程配置文件)添加QT += multimedia。下面解析有關(guān)QMediaplayer的相關(guān)知識(shí)。
QMediaPlayer播放視頻要在界面上顯示出來(lái),還需要其他類(lèi)進(jìn)行輔助,比如QVideoWidget。
QVideoWidget:QVideoWidget繼承自QWidget,所有它可以作為一個(gè)普通窗口部件進(jìn)行顯示,也可以嵌入到其他窗口。將QVideoWidget指定為QMediaPlayer的視頻輸出窗口后,就可以顯示播放的視頻畫(huà)面。
如果播放無(wú)圖像,并報(bào)錯(cuò):
DirectShowPlayerService::doRender: Unresolved error code 80040266原因:
Qt 中的多媒體播放,底層是使用DirectShowPlayerService,所以安裝一個(gè)DirectShow解碼器,例如LAV Filters,就可以解決運(yùn)行出錯(cuò)問(wèn)題
另外為了實(shí)現(xiàn)進(jìn)度條拖動(dòng)跳轉(zhuǎn)功能,又用QSlider和事件過(guò)濾器單獨(dú)寫(xiě)了個(gè)進(jìn)度條組件加到下面。通過(guò)信號(hào)槽與播放器連接,一旦拖動(dòng)進(jìn)度條釋放鼠標(biāo)后就發(fā)出信號(hào)量,播放器里接收,通過(guò)player->setpostion設(shè)定進(jìn)度。
串口通訊
也用了QT庫(kù)。網(wǎng)上很多相關(guān)寫(xiě)法,就不再贅述了。
#include
#include
記得配置文件.pro里要加QT += serialport
有個(gè)需要注意的地方,因?yàn)閭骰貋?lái)的魔方數(shù)據(jù)較長(zhǎng),在觸發(fā)串口接收函數(shù)后,要先加上:
while (m_serialPort->waitForReadyRead(500));延時(shí)等待一會(huì)兒,不然會(huì)出現(xiàn)數(shù)據(jù)不全的情況。
-
線(xiàn)程
因?yàn)榻饽Х剿惴ㄐ枰欢〞r(shí)間,所以給它專(zhuān)門(mén)開(kāi)個(gè)線(xiàn)程處理。
注意幾個(gè)點(diǎn):
線(xiàn)程處理函數(shù)里不能操作圖形界面,需要操作,要發(fā)信號(hào)量出來(lái),在主線(xiàn)程里操作。
線(xiàn)程不能指定父對(duì)象,關(guān)窗口時(shí)記得delete
QT的線(xiàn)程真的很簡(jiǎn)便:
t = new QThread(this); solve = new Solution; solve->moveToThread(t); t->start();這就完成了,只要Solution類(lèi)也繼承自QObject即可。
記得析構(gòu)的時(shí)候,把線(xiàn)程退出,并且delete掉。
-
互斥鎖
因?yàn)橛袝r(shí)候識(shí)別有錯(cuò)誤,會(huì)出現(xiàn)解不出來(lái)的情況,所以需要定時(shí)檢測(cè)算法有沒(méi)有結(jié)果。本來(lái)想直接寫(xiě)個(gè)標(biāo)志位解決,但有個(gè)問(wèn)題,可能查查看的時(shí)候,剛好那邊在寫(xiě),而且也分處兩個(gè)不同的線(xiàn)程,所以想到加個(gè)互斥鎖解決。
在Qt的多線(xiàn)程控制中,互斥量的訪(fǎng)問(wèn)最簡(jiǎn)單的控制是添加一個(gè)mutex鎖,對(duì)一個(gè)函數(shù)或者變量鎖定。
如果QMutex::lock()得不到這個(gè)鎖,那么它將會(huì)一直等直到得到該鎖為止,而另一個(gè)方法QMutex::tryLock()可以檢測(cè)當(dāng)前是否可以得到這個(gè)鎖,如果可以得到則返回1,否則返回0(不會(huì)一直等,但如果可以得到鎖,那就拿到鎖,不會(huì)光判斷而不獲取鎖),該函數(shù)只執(zhí)行一次,不會(huì)一直等到得到鎖為止。
最后就是設(shè)計(jì)模式的探討,不然情景選擇按鍵下全是switch,這個(gè)之后再補(bǔ)充。
相關(guān)代碼因?yàn)轫?xiàng)目還在進(jìn)行中,而且將來(lái)要商業(yè)化,所以不能放上來(lái)了。
總結(jié)
通過(guò)這次又對(duì)QT熟悉一點(diǎn),開(kāi)發(fā)更加迅速,而且也算把師弟領(lǐng)進(jìn)門(mén)了。這個(gè)項(xiàng)目本身也很有趣,開(kāi)發(fā)的過(guò)程中能夠樂(lè)在其中,并且也很有挑戰(zhàn)性,最后慢慢解出魔方,速度越來(lái)越快,真是感覺(jué)一切都值了。
參考文獻(xiàn):
http://bbs.mf8-china.com/forum.php?mod=viewthread&tid=38810
https://www.cnblogs.com/sixbeauty/p/3790693.html
https://www.cnblogs.com/dupengcheng/p/7205527.html
https://blog.csdn.net/qq_36969386/article/details/85072605
總結(jié)
以上是生活随笔為你收集整理的魔方教学系统(基于QT)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 尚不成熟的单个摄像头触屏方案
- 下一篇: 计算机里的文案怎么设置背景,PPT怎么设