Golden Thumb

1-on-1 tutor of chosen kids
個人資料
正文

Lucas 的洗牌經曆

(2022-01-15 05:39:46) 下一個

二年級開始玩編程,如今已經五年級了。從具象到抽象,最近用 C 語言多些。

要交換兩個變量的內容,用個臨時變量幫忙很容易:

int a, b;
a = 3;
b = 5;
int tmp = a;
a = b;
b = tmp;

Lucas 卻很享受不使用第三個臨時變量的小花招。比如:

int a, b;
a = 3;
b = 5;
printf("%d %dn", a, b); // 3 5

a = a + b;
b = a - b;
a = a - b;

printf("%d %dn", a, b); // 5 3

所以,隻要碰到需要交換兩個變量的時候,他總是掏出這個小花招。我心裏忍俊不住,真不嫌腦累。他後來告訴我:“這個小花招從未失手過。”

這一天終於來了。

在實現洗牌算法的時候,需要交換數組中的兩個元素的位置,相當於交換兩張牌的位置。Lucas 一如既往地再次拿出小“妙”招。
結果出狀況了,52 張牌用 1~52代表,洗過之後有時(很容易重現)出現了 0 ,甚至還不止一個。


如果將小妙招換成平淡無奇的辦法,即圖中注釋掉的用一個臨時變量幫忙的普通招數,問題就消失了。經過一番研究,咱們知道 0 的出現,是由於某張牌自己跟自己換位置。但牌“3”和自己“換”位置,還應該是牌“3”啊,怎麽就變成“0”了呢?

Lucas 很鬱悶,自己心愛多年的小妙招難道靠不住了?即使是兩個數一樣,小妙招也照樣靈驗啊。比如:

int a, b;
a = 3;
b = 3;
printf("%d %dn", a, b); // 3 3

a = a + b;
b = a - b;
a = a - b;

printf("%d %dn", a, b); // 3 3

當我讓他試試把所有的 b 換成 a 時,他就徹底明白了。:D
int a;
a = 3;
printf("%d %dn", a, a); // 3 3

a = a + a;
a = a - a;
a = a - a;

這是導致小妙招“失靈”的原因。

解決方案特簡單,如果洗牌過程中,一張牌需要跟自己換位置時,啥也別幹就得了唄。有趣的是,Lucas 第一次寫

if(c == d) continue;

時,把第一個 n 上下翻了個個,寫成 coutinue 了。

後來,我把這個可遇不可求的精彩案例,分享給 Lucas 的雙胞胎弟弟 Marius 時,也就是在同樣這個環節,Marius 也“完整無誤”寫出了同樣的 coutinue 。

我服了,雙胞胎。

[ 打印 ]
閱讀 ()評論 (0)
評論
目前還沒有任何評論
登錄後才可評論.