前言:“搶三十”是中國民間的一個游戲。游戲規則是:兩人從1開始輪流報數,每人每次可加1或加2,誰先報到30,誰就為勝方。一個簡單的游戲,要想獲勝也只有掌握了其中的奧妙才行。但要想用程序去實現該如何做呢?本文就為你做一個詳細的講解。
必勝的原理
如何才能輕易獲勝呢?這就要去尋找其中的規律。我制作了一個小程序,讓你可以和計算機單挑。程序界面如圖。
若你先報數,不是我誇口,你是一定斗不過計算機的;若計算機先報數,那麼就看你的了,如果你犯任何一次錯誤,計算機都會抓住機會反敗為勝。聽起來這個程序好像很智能,其實它的道理很簡單:
獲勝的必要條件是:牢牢抓住3的倍數。具體來講就是把對方報的數字與3求模,若值為1,則報的數字為對方的數字加2;若值為2,則報的數字為對方的數字加1;否則的話就隨意報1或者2。這樣在游戲中就能緊緊抓住3的倍數,堅持到最後就是勝利者。
把這個算法用程序實現後,電腦在與人對局的時候就智能化了。試問不知道此算法的人會是電腦的對手嗎?
關鍵代碼
在有了程序的算法和界面之後,要編寫完整的程序就不是很困難了。
最關鍵的顯示實報的數字的Edit控件的Onchange代碼:
procedure TForm1.Edit1Change(Sender: TObject);
begin
if flag=false then //得到控制權,計算機開始自動報數
begin
temp1:=s+1;
temp2:=s+2;
if (temp1 mod 3)=0 then //你報的最後的數字與3取模,若為1,則計算機加2
begin
s:=temp1;
j:=1;
end
else if (temp2 mod 3)=0 then //你報的最後的數字與3取模,若為2,則計算機加1
begin
s:=temp2;
j:=2;
end
else //否則計算機隨機報一個數字或兩個數字
begin
randomize();
j:=random(2)+1;
s:=s+j;
end;
Button2.Enabled :=true; //計算機報數完畢後把報數按鈕設為可用
Button3.Enabled :=true;
Button2.Caption :=IntToStr(s+1); //並把報數按鈕的Caption設為將要選擇的數字
Button3.Caption :=IntToStr(s+2);
Edit2.Text :=IntToStr(j); //顯示計算機報的個數
ListBox1.Items.Add('計算機報的個數: '+IntToStr(j));//寫入到歷史記錄
flag:=true; //交出控制權
Edit1.Text :=IntToStr(s); //顯示計算機實際報的數字
if s>=30 then //判斷游戲是否結束
begin
Button2.Enabled :=false;
Button3.Enabled :=false;
ShowMessage('嘿嘿,想贏我?動動腦筋再來吧!');
end;
end;
end;
難點講解
用一個BOOL變量來交接控制權,也就是什麼時候該由你報數,什麼時候該由計算機報數。
Form1.Edit1Change處理時要注意,Edit1顯示的是計算機實際報的數字。當控制權移交到計算機時,計算機處理完報數程序後要做兩件事:1交出控制權,2刷新Edit1的顯示。這裡要相當小心,看起來這兩件事的先後順序不重要,可實際上要特別注意:如果先刷新Edit1的顯示再交出控制權的話,數據就會溢出!
道理是這樣的,當程序執行到Edit1的顯示刷新時,程序不再向下執行而是回到本段程序的第一行開始依次執行,當執行到這裡時再次返回到第一行……死循環就產生了!所以一旦遇到刷新Edit1的顯示時,請仔細考慮所做的事情是否存在先後順序,因為執行Edit1的顯示代碼後程序將不再向下繼續執行,而是跳到TForm1.Edit1Change事件中,請仔細體會這段程序。