從 Zip/文字檔案程式設計 Gambas
動物遊戲,電腦試圖透過向你提問來猜出你正在想的動物,這個遊戲在人們擁有自己的電腦之前就已經存在了。它至少可以追溯到 20 世紀 70 年代初期。網站 http://www.animalgame.com/ 的作者說,他/她第一次看到它是在“101 BASIC 計算機遊戲”(由 David H. Ahl 編輯 - Maynard, Mass., Digital Equipment, 1973。)我還記得那本書。這個遊戲最初是由達特茅斯學院的 Arthur Luehrmann 開發的。http://www.smalltime.com/Dictator 有一個線上版本,你猜的是獨裁者而不是動物。
電腦一開始只知道兩種動物,鳥和魚,以及一個能區分這兩種動物的問題,“它會游泳嗎?”。問題可以回答“是”或“否”。如果你的動物不是這兩種中的任何一種,就會要求你提出一個可以識別你動物的問題。逐漸地,動物和問題的列表就會建立起來,電腦也會變得越來越聰明。這是一種簡單的形式的人工智慧(AI)。有人曾經說過,“自然愚蠢總是勝過人工智慧”。
對於剛開始學習電腦的人來說,這可能太複雜了。但是,這裡可能有一些有用的東西,比如從文字檔案儲存和載入文字,或者透過將大型程式分解成小的、有意義的子程式來管理大型程式等等。讓它洗刷你的思想,並對事情有一個大致的瞭解。在你打錯字導致程式無法執行時,練習除錯。我在 70 年代就對它很感興趣,它太棒了,不能不包括它。
這是一個典型的對話
- 你想到一種動物了嗎?是(否將結束程式。)
- 它是一種魚。否。
- 你想到的動物是…?狗
- 請鍵入一個可以區分狗和魚的問題。它有腿嗎?
- 對於狗來說,答案是…?是
- 你想到一種動物了嗎?是
- 它會游泳嗎?是
- 它有腿嗎?是
- 它是一種狗。是
這是一個數據檔案。它只是文字。每個問題結尾都有一個表示是或否的下一行。
- 0. 它會游泳嗎?/1/2
- 1. 它有腿嗎?/3/4
- 2. 它有兩個大耳朵嗎?/5/6
- 3. 狗
- 4. 它會吹氣嗎?/9/10
- 5. 兔子
- 6. 它很小,會咬你嗎?/7/8
- 7. 蚊子
- 8. 它很小嗎?/11/12
- 9. 鯨魚
- 10. 魚
- 11. 蒼蠅
- 12. 鳥
程式碼使用以下名稱引用這些物件。以下是它們。頂部的彩色文字是TextLabel1。“你想到一種動物了嗎?”那一行有標籤LabPrompt,按鈕bYes和bNo。“你想到的動物是…”那一行有標籤LabPromptForAnimal,文字框tbNewAnimal。“請鍵入一個問題…”那一行有標籤LabQuestionPrompt。後面跟著一個長的文字框tbQuestion。它下面是另一個標籤LabQuestion。最後一行“對於 1111,答案是…”有標籤LabPrompt2,按鈕bYes2和bNo2。最底部的按鈕從左到右分別命名為bShowData、bReset、bSave、bOpen和bQuit。
下一個是另一個表單,允許你檢視資料。它透過點選資料…按鈕顯示出來。
這個表單叫做FData。它會在你透過拖動它的角手柄調整它的大小時自動調整它上面物件的排列。要做到這一點,將它的 Arrangement 屬性設定為 Vertical。這使得它的物件從上到下堆疊。文字區域taData的 expand 屬性被設定為 True,因此它的尺寸會擴充套件以填充可用的空間。
三個按鈕bSave、bCopy和bClose都在一個紅色的矩形中,這是一個 HBox。HBox 會水平地擴充套件其內容。這個叫做HBox1。有兩個面板叫做Panel1和Panel2。一個在 hbox 上面,一個在Copy和Close按鈕之間,用於將它們隔開。有一個很小的彈簧叫做Spring1,它將Save按鈕推到左邊,並將Copy按鈕、小隔板和Close按鈕推到右邊。
當遊戲開始時,這些是唯一可見的物件。所有其他物件的可見屬性都設定為 False。程式稍後會將它們的可見性設定為 true。有四個區域。根據你所處的遊戲階段,它們會一個一個地顯示出來,而其他區域會被隱藏。
再看看示例資料檔案
- 0. 它會游泳嗎?/1/2
- 1. 它有腿嗎?/3/4
- 2. 它有兩個大耳朵嗎?/5/6
- 3. 狗
- 4. 它會吹氣嗎?/9/10
- 5. 兔子
- 6. 它很小,會咬你嗎?/7/8
- 7. 蚊子
- 8. 它很小嗎?/11/12
- 9. 鯨魚
- 10. 魚
- 11. 蒼蠅
- 12. 鳥
如果行計數器L到達一行包含動物名稱並且該名稱被拒絕的行,程式會用你提供的新問題替換該行,並且新動物和錯誤動物會被新增到列表的末尾。
在開始時宣告為Public和Private的變數是為了讓多個子程式能夠訪問它們。它們不僅僅在子程式持續的時間記憶體在。它們屬於表單而不是任何特定的子程式。Z[ ]需要被另一個表單訪問,所以它是Public。
Public z As New String[] 'database
Private Right As Integer 'line to go to if Yes is clicked
Private Wrong As Integer 'line to go to if No is clicked
Private QuestionPrompt As String
Private AnimalPrompt As String
Private NewAnimal As String
Private AskedAQuestion As Boolean 'true if we've just said, "Is it a...?"
Private NewQuestion As String
Private L As Integer 'which line in database?
Private FromYesLink As Boolean
Public Sub bQuit_Click()
Quit
End
Public Sub bShowData_Click()
FData.ShowModal
FMain.SetFocus
End
Public Sub Form_Open()
'Make sure the NoTabFocus property is set to true for all buttons, otherwise one will be highlighted when you start.
QuestionPrompt = "Please type in a question that would distinguish a<br><b>1111</b> from a <b>2222.</b> <br><br>(e.g. Does it have...? Can it...? Is it...? ):"
AnimalPrompt = "For a <b>1111</b> the answer would be..."
StartGame(True) 'clears data too
End
Public Sub bSave_Click()
SaveData
End
Public Sub SaveData()
Dialog.Filter = ["*.txt", "Text Files"]
If Dialog.SaveFile() Then Return
File.Name = File.BaseName & ".txt"
File.Save(Dialog.Path, z.Join(Chr(13)))
FMain.SetFocus
Catch
Message.Info(Error.Text)
End
Public Sub bOpen_Click()
Dialog.Filter = ["*.txt", "Text Files"]
If Dialog.OpenFile() Then Return
Dim s As String = File.Load(Dialog.Path)
z = Split(s, Chr(13))
FMain.SetFocus
Catch
Message.Info(Error.Text)
End
Public Sub ShowStep(Stage As Integer) '1, 2, 3 or 4
labPrompt.Visible = (Stage = 1)
bYes.Visible = (Stage = 1)
bNo.Visible = (Stage = 1)
labPromptForAnimal.Visible = (Stage = 2)
tbNewAnimal.Visible = (Stage = 2)
labQuestionPrompt.visible = (Stage = 3)
tbQuestion.Visible = (Stage = 3)
labQuestion.Visible = (Stage = 4)
labPrompt2.Visible = (Stage = 4)
bYes2.Visible = (Stage = 4)
bNo2.Visible = (Stage = 4)
Select Case Stage
Case 2
tbNewAnimal.SetFocus
Case 3
tbQuestion.SetFocus
Case Else
FMain.SetFocus 'a futile attempt to stop buttons being highlighted
End Select
End
Public Sub bReset_Click()
StartGame(True) 'clear all data too
FMain.SetFocus
End
Public Sub StartGame(ClearDataToo As Boolean)
If ClearDataToo Then
z.Clear
z.add("Can it swim?/1/2")
z.add("fish")
z.Add("bird")
Endif
L = 0
Right = 0
Wrong = 0
AskedAQuestion = True
labPrompt.text = "Are you thinking of an animal?"
tbQuestion.Text = ""
tbNewAnimal.Text = ""
ShowStep(1)
End
Public Sub tbNewAnimal_KeyPress() 'Enter should cause the LostFocus event
If Key.Code = Key.Enter Or Key.Code = Key.Return Then FMain.SetFocus
End
Public Sub tbNewAnimal_LostFocus() 'by pressing Enter or clicking elsewhere
NewAnimal = LCase(tbNewAnimal.text)
If IsNull(NewAnimal) Then Return 'user pressed enter without typing anything; don't proceed.
Dim s As String = Replace(QuestionPrompt, "1111", NewAnimal) 'Please type in a question...
s = Replace(s, "2222", z[L])
labQuestionPrompt.text = s
ShowStep(3)
End
Public Sub tbQuestion_KeyPress()
If Key.Code = Key.Enter Or Key.Code = Key.Return Then FMain.SetFocus
End
Public Sub tbQuestion_LostFocus()
NewQuestion = tbQuestion.Text
If IsNull(NewQuestion) Then Return 'user pressed enter without typing anything; don't proceed.
NewQuestion = UCase(NewQuestion[0]) & Right(NewQuestion, -1) 'capitalise first letter
If Right(NewQuestion, 1) <> "?" Then NewQuestion &= "?"
labQuestion.Text = NewQuestion
labPrompt2.Text = Replace(AnimalPrompt, "1111", NewAnimal) 'For a gorilla the answer would be...
ShowStep(4)
End
Public Sub AskQuestion()
Dim k As New String[]
k = Split(z[L], "/")
labPrompt.text = k[0]
Right = Val(k[1])
Wrong = Val(k[2])
AskedAQuestion = True
tbNewAnimal.SetFocus
End
Public Sub MakeGuess()
labPrompt.Text = "It is " & If(InStr(Left(z[L], 1), "aeiou") > 0, "an ", "a ") & z[L] & "."
AskedAQuestion = False
End
Public Sub bYes_Click() 'Yes has been clicked
If AskedAQuestion Then
L = Right 'take the right fork
If InStr(z[L], "/") > 0 Then AskQuestion Else MakeGuess
Else 'made a guess...
StartGame(False)
Endif
FMain.SetFocus
End
Public Sub bNo_Click() 'No has been clicked
If labPrompt.text = "Are you thinking of an animal?" Then Quit 'If you won't play, I quit!
If AskedAQuestion Then
L = Wrong 'take the left fork
If InStr(z[L], "/") > 0 Then AskQuestion Else MakeGuess
Else 'made a wrong guess, so add an animal
ShowStep(2)
Endif
End
Public Sub bYes2_Click()
Dim s As String = NewQuestion & "/" & Str(z.max + 1) & "/" & Str(z.max + 2)
z.Add(NewAnimal) 'the right animal
z.Add(z[L]) 'the wrong animal
z[L] = s 'replace the earlier wrong animal with the new question
StartGame(False)
End
Public Sub bNo2_Click()
Dim s As String = NewQuestion & "/" & Str(z.max + 1) & "/" & Str(z.max + 2)
z.Add(z[Wrong]) 'the wrong animal
z.Add(NewAnimal) 'the right animal
z[Wrong] = s 'replace the earlier wrong animal with the new question
StartGame(False)
End
FData表單的程式碼如下
Public Sub Form_Open()
taData.Text = FMain.z.Join(Chr(13)) 'Chr(13) is Return
End
Public Sub bClose_Click()
Me.close
End
Public Sub bCopy_Click()
Clipboard.Copy(taData.text)
End
Public Sub bSave_Click()
FMain.SaveData
End
筆記
| Fmain.SetFocus | 當你點選一個按鈕時,它會高亮顯示。為了讓高亮顯示在完成操作後消失,請將焦點設定為表單。這似乎是必要的。 |
| Dim z as new string[] z = split( "a/b/c" , "/" ) |
z 將獲得三行。z[0] = “a”,z[1] = “b”,z[2] = “c” 你可以指定分隔符,它可以超過一個字元長。 |
| Dim s as string s= z.join(" ") |
將陣列 z 連線成一個字串,中間用空格分隔 |
| IsNull(s) | 如果字串 s 為空(其中沒有字元),則為真 |
| Chr(13) | 每個字元都有一個程式碼編號。13 是 Return 的編號。如果你感興趣,A 是 chr(65),a 是 char(97)。該程式碼稱為 ASCII。 |
| Public Sub ShowStep(Stage As Integer) labPrompt.Visible = (Stage = 1)
ShowStep(1) 或 ShowStep(2)。
LabPrompt 的可見性取決於你提供的數字是否為 1。 | |
| if InStr(z[L], "/") > 0 Then | 如果字串z[L]中包含斜槓,則執行某些操作。InStr(LookInThis, ForThis) 給出第二個字串在第一個字串中的位置。 |