从 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) 给出第二个字符串在第一个字符串中的位置。 |