跳转到内容

从 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. 鸟

Game of Animal in Gambas

代码使用以下名称引用这些对象。以下是它们。顶部的彩色文本是TextLabel1。“你想到一种动物了吗?”那一行有标签LabPrompt,按钮bYesbNo。“你想到的动物是…”那一行有标签LabPromptForAnimal,文本框tbNewAnimal。“请键入一个问题…”那一行有标签LabQuestionPrompt。后面跟着一个长的文本框tbQuestion。它下面是另一个标签LabQuestion。最后一行“对于 1111,答案是…”有标签LabPrompt2,按钮bYes2bNo2。最底部的按钮从左到右分别命名为bShowDatabResetbSavebOpenbQuit

下一个是另一个表单,允许你查看数据。它通过点击数据…按钮显示出来。

Gambas form for showing data in the game of Animal

这个表单叫做FData。它会在你通过拖动它的角手柄调整它的大小时自动调整它上面对象的排列。要做到这一点,将它的 Arrangement 属性设置为 Vertical。这使得它的对象从上到下堆叠。文本区域taData的 expand 属性被设置为 True,因此它的尺寸会扩展以填充可用的空间。

三个按钮bSavebCopybClose都在一个红色的矩形中,这是一个 HBox。HBox 会水平地扩展其内容。这个叫做HBox1。有两个面板叫做Panel1Panel2。一个在 hbox 上面,一个在CopyClose按钮之间,用于将它们隔开。有一个很小的弹簧叫做Spring1,它将Save按钮推到左边,并将Copy按钮、小隔板和Close按钮推到右边。

Playing the game of Animal in Gambas, frame 1

当游戏开始时,这些是唯一可见的对象。所有其他对象的可见属性都设置为 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到达一行包含动物名称并且该名称被拒绝的行,程序会用你提供的新问题替换该行,并且新动物和错误动物会被添加到列表的末尾。

在开始时声明为PublicPrivate的变量是为了让多个子程序能够访问它们。它们不仅仅在子程序持续的时间内存在。它们属于表单而不是任何特定的子程序。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.Visible 为真,则标签可见。如果为假,则不可见。

LabPrompt 的可见性取决于你提供的数字是否为 1。

if InStr(z[L], "/") > 0 Then 如果字符串z[L]中包含斜杠,则执行某些操作。InStr(LookInThis, ForThis) 给出第二个字符串在第一个字符串中的位置。
从 Zip 编程 Gambas
 ← 数组 文本文件 表单排列 → 
华夏公益教科书