跳轉到內容

從 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
華夏公益教科書