跳转到内容

从 Zip/ASCII 开始学习 Gambas 编程

来自维基教科书,开放世界中的开放书籍

记忆游戏

[编辑 | 编辑源代码]

你一定知道这个游戏:卡片正面朝下排列,你翻开一张卡片,然后你尝试记住你见过它的匹配在哪里。它就在某个地方......想想......是的,就在这里!你把它翻过来,却发现......没有匹配!它在其他地方。你把卡片翻过来,你的朋友开始轮流。如果你翻开了匹配的卡片,你就可以拿走这些卡片。最后谁的卡片最多谁就赢了。

用卡片玩记忆游戏,也称为“记忆游戏”

在这个版本中,只有一个玩家,你正在与时间赛跑,争取匹配所有卡片。

表单宽 508,高 408,但我使用 Cooper Black 字体和 +12 的字体大小增量时需要这些尺寸。Cooper Black 有漂亮的大黑体字。

文件 菜单有三个项目:放弃、新游戏和退出。

表单的排列 设置为填充,以便单独的网格视图gv1 填充整个窗口。但是,它不应该调整大小,因此将可调整大小 设置为

我们将创建一个 6x6 的网格。所有方格将是浅黄色。在内存中,有一个类似于网格的数组,名为z,它就像网格的镜像。我们之前使用过的数组都是列表。列表是一系列排列成行的项目。行是一维的。它们的一维是它们的长度。网格是二维的,它们的两个维度是长度和宽度。对于网格视图,有行和列。在我们的例子中,z 有行和列,就像网格视图gv1 一样。Public z As New String[6, 6] 将创建z,它是一个内存中的网格。网格视图的左上角单元格是gv1[0,0]z 的左上角是z[0,0]。网格视图的右下角单元格是gv1[5,5]z 的右下角是z[5,5]。网格视图中的 36 个单元格,就像z 中的 36 个记忆一样,按行和列排列。

网格视图显示了我们翻转的“卡片”。数组z 存储着“卡片的背面”。你的最亲近人的照片会很不错,但现在它们将会有大大的 Cooper Black 字母,每个卡片上都有一个。

你点击一个网格单元格。卡片翻转:我们显示隐藏在z 中的字母。如果我们每次点击一个网格单元格时都这样做,就根本没有游戏了。我们会逐渐揭示所有字母。因此,当您显示一个字母时,我们会设置一个标志,表示“一个字母正在显示”。如果该标志已设置,那么下次您点击单元格时,我们会知道已经翻开了第二张卡片,现在该检查是否匹配了。不匹配?隐藏字母并取消设置标志——没有字母正在显示。如果我们匹配了,也许这是最后一张卡片,你已经完成了游戏。或者也许这不是最后一张卡片,你可以让卡片翻转(显示字母)并继续游戏,记住取消设置该标志,因为下一次点击将再次点击一对卡片中的第一张。该标志是一个布尔(真/假,有帽子/没帽子)变量,名为OneShowing

我们怎么知道游戏是否结束了?每次我们匹配时,都会将已出局的卡片数量的运行总计加 2。当该总数达到 36 时,所有卡片都已匹配。用于计数的变量名为TurnedOver,它是一个整数。它是一个公共(或私有,如“表单私有”——这并不重要)变量,在开头与其他需要在表单存在期间存在且不会在子程序完成时消失的变量一起声明。

包含一个计时器。内置函数Timer() 表示应用程序启动以来的秒数。当你第一次点击时,时间将存储在StartTime 中。你玩游戏花了多长时间将被放入变量secs 中。

Dim secs As Integer = Timer() - StartTime

游戏板在Initialise 子程序中设置。它将需要清零的项清零。它调用GetRandomLetters 来创建一个名为s[] 的列表,该列表包含将被分配到z 单元格中的字母,z 有 6 行 6 列。s 需要包含 18 个随机字母,每个字母重复一次,因此会有匹配对。它共有 36 个项目。以下是屏幕截图和代码。

Game of Concentration running in Gambas
寻找匹配项...
Where the letters were hidden in a game of Concentration played in Gambas
“放弃”显示了所有卡片的位置。
Gambas form for the game of Concentration
508 x 458 的表单。排列 属性 = 填充gv1扩展 设置为
Const nRows As Integer = 6
Const nCols As Integer = 6
Const PaleYellow As Integer = &hFFFFAA
Public TurnedOver As Integer
Public z As New String[nRows, nCols]
Public s As New String[]
Public OneShowing As Boolean
Public FirstRow As Integer
Public FirstColumn As Integer
Public StartTime As Float

Public Sub Form_Open()

  Dim i, j As Integer
  gv1.Columns.count = nCols
  gv1.Rows.Count = nRows
  gv1.Background = Color.DarkBlue
  For i = 0 To gv1.Columns.max
    gv1.Columns[i].Alignment = Align.Center
    gv1.Columns[i].Width = 84
    For j = 0 To gv1.Rows.max
      gv1[i, j].Padding = 16
    Next
  Next
  Initialise

End

Public Sub Initialise()

  Dim i, j, n, nCol, nRow As Integer
  Dim c As String

  nCol = gv1.Columns.max
  nRow = gv1.Rows.Max
  GetRandomLetters(18) 'each letter twice
  For i = 0 To nRow
    For j = 0 To nCol
      c = s[n]
      z[i, j] = c
      gv1[i, j].ForeGround = Color.Black
      gv1[i, j].Text = ""
      gv1[i, j].Background = Color.DarkBlue
      n = n + 1
    Next
  Next
  TurnedOver = 0

End

Public Sub GetRandomLetters(Count As Integer)

  Dim i, p, r1, r2 As Integer
  Randomize 'different random numbers every time
  s.clear
  p = Rand(Asc("A"), Asc("Z")) 'start with any letter
  Do Until s.count >= 2 * Count
    s.Add(Chr(p))
    s.Add(Chr(p)) 'other one in the pair
    p += 1
    If p > Asc("Z") Then p = Asc("A") 'back to the start
  Loop
  For i = 0 To s.Count 'c.shuffle() 'When I update to 3.13 I can use this!
    r1 = Rand(0, s.max)
    r2 = Rand(0, s.max)
    Swap s[r1], s[r2]
  Next

End

Public Sub MenuNew_Click()
  Initialise
End

Public Sub MenuQuit_Click()
  Quit
End

Public Sub gv1_Click()

  If TurnedOver = 0 Then StartTime = Timer 'begin timing from the first click
  If OneShowing Then
    gv1[gv1.row, gv1.Column].Background = Color.DarkBlue
    gv1[gv1.row, gv1.Column].Foreground = Color.White
    gv1[gv1.row, gv1.Column].Text = z[gv1.row, gv1.Column]
    gv1.Refresh
    Wait 'finish pending operations and do the refresh
    Evaluate(gv1.row, gv1.Column)
  Else
    FirstRow = gv1.row
    FirstColumn = gv1.Column
    gv1[FirstRow, Firstcolumn].Background = Color.DarkBlue
    gv1[FirstRow, Firstcolumn].Foreground = Color.White
    gv1[FirstRow, Firstcolumn].Text = z[FirstRow, FirstColumn]
    OneShowing = True
  Endif

End

Public Sub Evaluate(row As Integer, column As Integer)

  If z[FirstRow, FirstColumn] = gv1[row, column].Text Then 'a match
    TurnedOver += 2
    If TurnedOver = nRows * nCols Then
      Dim t As String
      t = TheTime()
      Message("Well done!<br>You took " & t)
      Initialise
    Else
      Wait 0.5
      gv1[FirstRow, FirstColumn].Text = ""
      gv1[row, column].Text = ""
      gv1[FirstRow, FirstColumn].Background = PaleYellow
      gv1[row, column].Background = PaleYellow
    Endif

  Else 'no match
    Wait 1 'second
    gv1[FirstRow, FirstColumn].Text = ""
    gv1[row, column].Text = ""
    gv1[FirstRow, FirstColumn].Background = Color.DarkBlue
    gv1[row, column].Background = Color.DarkBlue

  Endif
  OneShowing = False

End

Public Sub TheTime() As String

  Dim secs As Integer = Timer() - StartTime
  Dim h As Integer = secs / 60 / 60

  Secs -= h * 60 * 60
  Dim m As Integer = secs / 60
  Secs -= m * 60
  Return If(h > 0, Str(h) & "h ", "") & If(m > 0, Str(m) & "m ", "") & Str(secs) & "s"

End

Public Sub MenuGiveUp_Click()

  For i As Integer = 0 To nRows - 1
    For j As Integer = 0 To nCols - 1
      If gv1[i, j].Text = "" Then
        gv1[i, j].ForeGround = Color.Red
        gv1[i, j].Text = z[i, j]
        gv1[i, j].Background = Color.DarkRed
      End If
    Next
  Next

End

如果你喜欢点击图片,你需要在你的图片文件夹中创建一个名为 Pix 的文件夹。你需要在其中放 18 张图片(jpg 或 png)。

Gambas Concentration game played with pictures
现在,另一只史努比在哪里呢?
Gambas Concentration Game showing where all the pictures were
放弃”显示了所有卡片的位置。

在接下来的代码中,图片文件被读入一个图片数组中。Gambas 中的图片和图像在内存中的存储位置不同。与图片不同,图像可以拉伸以适应任何宽度和高度的区域。因此,数组中的 18 个图像中的一个,当需要时,会被放入一个名为 Img 的单个图像中,拉伸以适应一个网格单元格。然后将生成的图像(现在大小正确)使用图像具有的 Picture 方法转换为图片。

要显示一个图像,请将单元格的 Picture 属性设置为已转换的图像。要隐藏它,请将图片属性设置为 Null。当您点击单元格时,就会发生这种情况。

有一个相应的二维(行/列)图片名称数组。要查看是否匹配,请比较两个点击的单元格中的图片名称。

当 18 个单元格正确匹配(一次两个)时,该是祝贺获胜者的时候了。

Const nRows As Integer = 6
Const nCols As Integer = 6
Const PaleYellow As Integer = &hFFFFAA
Public TurnedOver As Integer
Public z As New String[nRows, nCols] 'names of the pictures
Public Images As New Image[nRows, nCols] 'the images themselves
Public Img As Image
Public s As New String[]
Public OneShowing As Boolean
Public FirstRow As Integer
Public FirstColumn As Integer
Public StartTime As Float

Public Sub Form_Open()

  Dim i, j As Integer

  gv1.Columns.count = nCols
  gv1.Rows.Count = nRows
  gv1.Background = PaleYellow
  For i = 0 To gv1.Columns.max
    gv1.Columns[i].Alignment = Align.Center
    gv1.Columns[i].Width = 84
  Next
  Initialise

End

Public Sub Initialise()

  Dim i, j, n, nCol, nRow As Integer
  Dim c As String

  nCol = gv1.Columns.max
  nRow = gv1.Rows.Max
  GetRandomLetters 'each picture twice
  For i = 0 To nRow
    gv1.Rows[i].Height = 70
    For j = 0 To nCol
      c = s[n]
      z[i, j] = c
      gv1[i, j].Picture = Null
      gv1[i, j].Background = Color.DarkCyan
      n = n + 1
    Next
  Next
  TurnedOver = 0

End

Public Sub GetRandomLetters()

  Dim i, j, n As Integer
  Dim path As String = User.Home &/ "Pictures/Pix/" 'must be 18 pictures in here
  Dim cellW As Float = gv1[0, 0].Width
  Dim cellH As Float = gv1[0, 0].Height
  Dim scale As Float = Min(CellW, CellH)

  If Not Exist(Path) Then
    Message("Please create a folder called Pix in your Pictures folder.<br>Put 18 pictures in it.")
    Quit
  Endif
  s = Dir(path, "*.png")
  s.Insert(Dir(path, "*.jpg"))
  If s.Count < 18 Then
    Message("Please put 18 pictures in the Pix folder inside your Pictures folder.<br>There were only " & s.Count)
    Quit
  Endif
  s.Insert(s) 'second copy
  s.Shuffle
  For i = 0 To gv1.Rows.Max
    For j = 0 To gv1.Columns.Max
      Images[i, j] = Image.Load(path & s[n])
      n += 1
    Next
  Next

End

Public Sub MenuNew_Click()

  Initialise

End

Public Sub MenuQuit_Click()

  Quit

End

Public Sub gv1_Click()

  If TurnedOver = 0 Then StartTime = Timer 'begin timing from the first click
  If OneShowing Then
    gv1[gv1.row, gv1.Column].Background = Color.White
    Img = Images[gv1.row, gv1.Column].stretch(70, 70)
    gv1[gv1.row, gv1.Column].Picture = Img.Picture
    gv1.Refresh
    Wait 'finish pending operations and do the refresh
    Evaluate(gv1.row, gv1.Column)
  Else
    FirstRow = gv1.row
    FirstColumn = gv1.Column
    gv1[FirstRow, Firstcolumn].Background = Color.White
    Img = Images[FirstRow, FirstColumn].stretch(70, 70)
    gv1[FirstRow, Firstcolumn].Picture = Img.Picture
    OneShowing = True
  Endif

End

Public Sub Evaluate(row As Integer, column As Integer)

  If z[FirstRow, FirstColumn] = z[row, column] Then 'a match
    TurnedOver += 2
    If TurnedOver = nRows * nCols Then
      Dim t As String
      t = TheTime()
      Message("Well done!<br>You took " & t)
      Initialise
    Else
      Wait 0.5 'half second
      gv1[FirstRow, FirstColumn].Picture = Null
      gv1[row, column].Picture = Null
      gv1[FirstRow, FirstColumn].Background = PaleYellow
      gv1[row, column].Background = PaleYellow
    Endif

  Else 'no match
    Wait 1 'second
    gv1[FirstRow, FirstColumn].Picture = Null
    gv1[row, column].Picture = Null
    gv1[FirstRow, FirstColumn].Background = Color.DarkCyan
    gv1[row, column].Background = Color.DarkCyan

  Endif
  OneShowing = False

End

Public Sub TheTime() As String

  Dim secs As Integer = Timer() - StartTime
  Dim h As Integer = secs / 60 / 60

  Secs -= h * 60 * 60
  Dim m As Integer = secs / 60
  Secs -= m * 60
  Return If(h > 0, Str(h) & "h ", "") & If(m > 0, Str(m) & "m ", "") & Str(secs) & "s"

End

Public Sub MenuGiveUp_Click()

  For i As Integer = 0 To nRows - 1
    For j As Integer = 0 To nCols - 1
      If gv1[i, j].Picture = Null Then
        Img = Images[i, j].Stretch(70, 70)
        gv1[i, j].Picture = Img.Picture
        gv1[i, j].Background = Color.White
      End If
    Next
  Next

End

ASCII 码

[编辑 | 编辑源代码]

字符(字母、数字、标点符号)在计算机的内存中以数字的形式存储。使用最广泛的系统是 ASCII,即美国信息交换标准代码。它是在美国开发的,维基百科告诉我,管理机构更喜欢称它为 US-ASCII,因为它使用的是美元符号 ($) 和拉丁字母。每当你按下键盘上的一个键,这些代码数字中的一个就会进入计算机。即使是非打印字符也有 ASCII 码。空格键 是 32。按下删除 键,127 会进入。退格 键发送数字 8。为了让你困惑,数字“1” 的 ASCII 码是 49。计算机如何处理这些代码数字取决于应用程序。而正在编写应用程序。在上面的程序中,输入任何你喜欢的字符,什么都不会发生(除了 CTRL-G,我把它用于“放弃”,CTRL-N 是“新游戏”,CTRL-Q 是退出快捷键)。

打字机

在老式的手动打字机上,一行结束时,你需要弹动一个杠杆,带纸张滚动的滚轴会回弹到行首(回车),并将纸张向上拉一行(换行),准备开始输入下一行。回车 是 13。ASCII 13 也是 Control-M(写成^M),在编程语言中有时写成\r。换行是 10,也是 Control-J (^J)。有一个换页 控制符,Control-L,它用于转到新的一页(ASCII 12)。你不会记得手动打字机,除非你常去博物馆,但对我来说,那就像昨天一样(叹息)。如今,ASCII 在很大程度上被 Unicode 取代了。ASCII 被限制为 128 个字符。维基百科说,Unicode 可以显示 137,993 个字符——足以显示各种非英语字符和你能想到的所有表情符号。

即使是最初的 ASCII 也给使用非英语语言的人带来了一些问题。维基百科有一个有趣的例子:‘一个瑞典程序员给另一个程序员发邮件,询问他们是否应该一起去吃午餐,可能会收到 "N{ jag har sm|rg}sar" 作为回复,这应该是 "Nä jag har smörgåsar",意思是 "不,我有三明治"’,而他或她只能忍受这种错误。’[1]

从 Zip 开始学习 Gambas 编程
 ← 上下文菜单 ASCII 单选按钮 → 
  1. https://en.wikipedia.org/wiki/ASCII
华夏公益教科书