第四十四章 算法之美
「哎呀,別賣關(guān)子了,趕緊說吧!」
看著老爹一幅悠然閑適的樣子我牙根兒都癢癢,如果不是害怕遭雷劈可能早就用鞋底招呼過去了。
「好吧好吧,那我就說吧。其實要通過鍵值來避過switch目前我能夠想到的有兩種方法,其中一種比較取巧,另一種就是正兒八經(jīng)的通過計算得出來。
剛剛你們也說了,如果是對灰太狼進行上下移動,實質(zhì)上是在對行數(shù)x進行加減,左右移動,是對列數(shù)y做加減,那我們定義一個二維數(shù)組,把要加減的量放在數(shù)組里面,然后通過鍵值把數(shù)組取出來就好了。
向上移動,x-1,也就是x+(-1),y+0;
向下移動,x+1,y+0;
向左移動,x+0,y-1,也就是y+(-1);
向右移動,x+0,y+1;
鍵值的排列是左37,上38,右39,下40,如果我們對它們進行減運算,得到的結(jié)果是左0,上1,右2,下3,正好可以作為數(shù)組的下標。
于是就可以聲明一個偏移量數(shù)組:
int offset[4][2]={{0,-1},{-1,0},{0,1},{1,0}};
我們知道了灰太狼當前的位置,也可以通過鍵值獲取位置的改變量,那么下一個位置、下下個位置自然就能夠確定了。假設(shè)我們把移動這部分的邏輯定義成一個move函數(shù),那么實現(xiàn)邏輯大概如下:
int move(int keyCode)
{
int index = keyCode - 37;
int x1 =灰太狼當前位置x+ offset[index][0];
int y1 =灰太狼當前位置y+ offset[index][1];
int x2 =灰太狼當前位置x+ offset[index][0]* 2;
int y2 =灰太狼當前位置y+ offset[index][1]* 2;
/*移動判斷邏輯*/
}
x1,y1和x2,y2就是當前移動方向的下個位置,下下個位置的坐標,有了它們,實現(xiàn)功能應(yīng)該就不是什么難事兒了吧?」
「這樣……都行?」
我和小弦子都被老爹這波操作秀到了,真的特別讓人無語。就好像你想盡一切辦法,使盡渾身解數(shù)都沒有將一塊大石頭給搬起來,然而在這個時候某個人拿了幾個滑輪和繩子,不費吹灰之力就大石頭給搬起來了。
不僅是我和小弦子有這種感覺,就連之前陷入沉思的六叔叔也是好一陣無語,如果一定要用一個詞語來形容我們此時此刻的心情,大概還是只有「臥槽」這兩個字了。
但不得不是說的是,老爹的這種做法讓人挑不出來任何的毛病來,而且簡單易懂,實現(xiàn)起來也極為容易。
很顯然,這并不是我,小弦子和六叔叔想要看到的結(jié)果,因為這和我們想象中的算法相差太大了!
算法難道不應(yīng)該是經(jīng)過一系列精密的計算后,最終得到想要的結(jié)果么?
「哈哈,你們別這樣看著我,我之前聲明過的,這種方法比較取巧。而且作為一個合格的程序員,就是要用最簡潔的代碼實現(xiàn)最復(fù)雜的功能,因為簡潔同時也意味著效率高。」
老爹似乎是看穿了我們?nèi)齻€人的心思。好吧,我承認他說得很有道理的樣子,但是依然沒有辦法讓我平靜的接受,畢竟之前我為了考慮鍵值和位置移動偏移量的關(guān)系扣了那么久的頭皮,讓我如何能夠接受這種毫無技術(shù)含量的答案?
小弦子和六叔叔沒有說話,不過我猜他們和我想的應(yīng)該是差不多。
「行了行了,那我就說說第二種方法吧,如果這種方法依然不能讓你們滿意,我就沒有辦法了!」
老爹被我們?nèi)丝吹糜行╊^皮發(fā)麻,最終還是屈服了。
「首先,在上下方向上,上下的鍵值分別是38和40,這個時候通過計算得到的結(jié)果是:x的偏移量是±1,y的偏移量為0。x的偏移比較容易,用鍵值減去39就好了。
同理,在左右方向上,左右的鍵值分別是37和39,這個時候通過計算得到的結(jié)果是:x的偏移量為0,y的偏移量是±1。y的偏移比較容易,用鍵值減去38就好了。
換句話說,鍵值為38和40時,x的偏移量是±1,為37和39,x的偏移量是0。同樣,鍵值為38和40時,y的偏移量是0,為37和39,y的偏移量是±1。
那么,你們能不能告訴我,38、40和37、39這兩組數(shù)有什么區(qū)別么?」
老爹在一陣分析后,然后拋出了這個問題,如果沒有什么意外的話,這個問題的答案就是破解一切問題的關(guān)鍵所在。
「嗯~,都是數(shù)字,能有什么區(qū)別?數(shù)值不同?」
我想了半天,也沒能想出這其中有什么區(qū)別。
「難道是奇偶?」
就在這時,從上課開始到現(xiàn)在都沒有說話的六叔叔居然發(fā)聲的!
「對啊,就是奇偶!」
同時六叔叔的這句話也點醒了我和小弦子。
「沒錯,它們最大的不同就是奇偶性不同!我們的算法也正是要借助這一點,使用奇偶來完成一個統(tǒng)一的計算過程?!?p> 老爹坦言道。
有了老爹提供的思路,我腦袋飛速運轉(zhuǎn)了起來,開始挖掘移動偏移量和奇偶性的關(guān)系??墒羌幢闳绱?,我依然沒有能夠想出這其中的聯(lián)系所在,只能敗下陣來,等待老爹的最終答案。
「好吧,我還是直接公布答案吧,不然你們兩個小家伙怕是要被逼瘋了。
首先,我們依然對所有的鍵值進行減37處理,然后得到的結(jié)果就是:上1,下3,左0,右2。
注意,這個時候奇偶性已經(jīng)發(fā)生了改變。而且問題也已經(jīng)變成了通過1、3得到x偏移±1,y偏移量0;0、2得到x偏移0,y偏移±1。
1和3要得到±1,只需要減去2,但是0和2減去2變成了-2和0,怎么辦?如果這個時候我們再對減去2的結(jié)果對2取余呢?
也就是說,x的偏移量=(鍵值-37-2)%2,即x的偏移量=(鍵值-39)%2?!?p> 「對了!可以等到正確的結(jié)果!」
我和小弦子驚呼道。
「好了,按照相同的分析辦法,你們自己看看y的偏移量應(yīng)該如何計算?!?p> y的偏移量正好與x的相反,通過1、3得到y(tǒng)偏移量0;0、2得到 y偏移±1。
0和2要得到±1,只需要減去1就可以了,1和3減去1后是0和2,依然對2取余就可以得到0,因此y的偏移量=(鍵值-37-1)%2,即y的偏移量=(鍵值-38)%2!