把别人的Tcl/Tk代码加入到Go语言里15 游戏8 翻牌游戏

名字不能长 · · 2060 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

这次文章主要引用了网上的这篇教学http://www.cwflynt.com/TclForTeens/

步骤a 下载第17课里提到的扑克图像包

http://www.cwflynt.com/TclForTeens/cards.zip

解压缩cards.zip内所有文件到c:\cards\目录下

【你可以放在桌面的cards目录里,随意】


步骤b 跳到第20课http://www.cwflynt.com/TclForTeens/lsn20.html

找到最后一段框起来的源代码,它的上一句是“And that's all the changes.  Here's the complete game.”

把这段框起来的代码复制到如下go代码的字符串常量里

package main
import "github.com/nsf/gothic"

const init_script = `
#init_script字符串常量,tcl/tk代码从下一行开始

`

func main() {
    ir := gothic.NewInterpreter(init_script)

    <-ir.Done
}

步骤c 保存go文件到c:\cards\目录下

【总之和图像文件在一起、同一目录就行】

步骤d  运行和编译

liteide下编译如下图

运行效果如下图:


步骤e 发行

从ActiveTcl 开发环境的安装目录(一般都是c:\tcl\)下找到

bin文件夹,把里面的tcl86.dll tk86.dll和zlib1.dll这3个文件复制到

c:\cards\目录下

再从c:\tcl\lib下找到tcl8.6和tk8.6文件夹,把这俩也复制到

c:\cards\lib\下

【如果必要可以删除一些用不上的包以减少发布文件的大小】


【完】

【附上全部go源代码,只有400多行,其中含tcl/tk代码的#注释都快有100行了】

package main
import "github.com/nsf/gothic"

const init_script = `
################################################################
# proc loadImages {}--
#    Load the card images 
# Arguments
#   NONE
# 
# Results
#   The global array "concentration" is modified to include a 
#   list of card image names
# 
proc loadImages {} {
  global concentration
  
  # The card image fileNames are named as S_V.gif where 
  #  S is a single letter for suit (Hearts, Diamonds, Spades, Clubs)
  #  V is a 1 or 2 character descriptor of the suit - one of:
  #     a k q j 10 9 8 7 6 5 4 3 2
  #
  # glob returns a list of fileNames that match the pattern - *_*.gif 
  #  means all fileNames that have a underbar in the name, and a .gif extension.
  
  
  foreach fileName [glob *_*.gif] {
    # We discard the aces to leave 48 cards because that makes a 
    # 6x8 card display.

    if {($fileName ne "c_a.gif") &&
        ($fileName ne "h_a.gif") &&
    ($fileName ne "d_a.gif") &&
    ($fileName ne "s_a.gif")} {
    
      # split the card name (c_8) from the suffix (.gif)
      set card [lindex [split $fileName .] 0]
    
      # Create an image with the card name, using the file
      # and save it in a list of card images: concentration(cards)

      image create photo $card -file $fileName
      lappend concentration(cards) $card
    }
  }
  
  # Load the images to use for the card back and 
  #   for blank cards

  foreach fileName {blank.gif back.gif} {
      # split the card name from the suffix (.gif)
      set card [lindex [split $fileName .] 0]
    
      # Create the image
      image create photo $card -file $fileName
  }
}

################################################################
# proc randomizeList {}--
#    Change the order of the cards in the list
# Arguments
#   originalList    The list to be shuffled
# 
# Results
#   The concentration(cards) list is changed - no cards will be lost
#   of added, but the order will be random.
# 
proc randomizeList {originalList} {

  # How many cards are we playing with.
  set listLength [llength $originalList]
  
  # Initialize a new (random) list to be empty
  set newList {}
  
  # Loop for as many cards as are in the card list at the
  #   start.  We remove one card on each pass through the loop.
  for {set i $listLength} {$i > 0} {incr i -1} {

    # Select a random card from the remaining cards.
    set p1 [expr int(rand() * $i)]

    # Put that card onto the new list of cards
    lappend newList [lindex $originalList $p1]

    # Remove that card from the card list.
    set originalList [lreplace $originalList $p1 $p1]
  }
  
  # Replace the empty list of cards with the new list that's got all
  # the cards in it.
  return $newList
}

################################################################
# proc makeGameBoard {}--
#    Create the game board widgets - canvas and labels.
# Arguments
#   NONE
# 
# Results
#   New GUI widgets are created.
# 
proc makeGameBoard {} {
  # Create and grid the canvas that will hold the card images
  canvas .game -width 800 -height 724 -bg gray
  grid .game -row 1 -column 1 -columnspan 6
  
  # Create and grid the labels for turns and score
  label .lmyScoreLabel -text "My Score"
  label .lmyScore -textvariable concentration(player,score)
  label .lturnLabel -text "Turn"
  label .lturn -textvariable concentration(turn)

  grid .lmyScoreLabel -row 0 -column 1 -sticky e
  grid .lmyScore -row 0 -column 2  -sticky w
  grid .lturnLabel -row 0 -column 5  -sticky e
  grid .lturn -row 0 -column 6  -sticky w
}

################################################################
# proc startGame {}--
#    Actually start a game running
# Arguments
#   NONE
# 
# Results
#   initializes per-game indices in the global array "concentration"
#   The card list is randomized
#   The GUI is modified.
# 
proc startGame {} {
  global concentration
  set concentration(player,score) 0
  set concentration(turn) 0
  set concentration(selected,rank) {}

  set concentration(player,x) 0
  set concentration(player,y) 2

  set concentration(cards) [randomizeList $concentration(cards)]
  
  # Save the height and width of the cards to make the code easier
  #  to read.
  set height [image height [lindex $concentration(cards) 0]]
  set width [image width  [lindex $concentration(cards) 0]]

  # Leave spaces between cards.

  incr width
  incr height
  
  # Remove any existing items on the canvas
  .game delete all
  
  # Start in the upper left hand corner
  set x 90
  set y 2
  
  # Step through the list of cards
  
  for {set pos 0} {$pos < [llength $concentration(cards)]} {incr pos} {
    # Place the back-of-a-card image on the board
    # to simulate a card that is face-down.

    .game create image $x $y -image back  -anchor nw -tag card_$pos
    
    # Add a binding on the card back to react 
    #  to a player left-clicking the back.

    .game bind card_$pos <ButtonRelease-1> "playerTurn $pos"
    
    # Step to the next column (the width of a card)
    incr x $width

    # If we've put up 8 columns of cards, reset X to the
    #   far left, and step down one row.
    if {$x >= [expr 90 + ($width * 8)] } {
      set x 90
      incr y $height
    }
  }
}

################################################################
# proc flipImageX {canvas canvasID start end background}--
#    Makes it appear that an image object on a canvas is being flipped
# Arguments
#   canvas    The canvas holding the image
#   canvasID    The identifier for this canvas item
#   start    The initial image being displayed
#   end        The final  image to display
#   background  The color to show behind the image being flipped.
#               This is probably the canvas background color
# 
# Results
#   configuration for the canvas item is modified.
# 
proc flipImageX {canvas canvasID start end background} {
  global concentration
  
  # Get the height/width of the image we'll be using
  set height [image height $start]
  set width  [image width  $start]
  
  # The image will rotate around the X axis
  # Calculate and save the center, since we'll be using it a lot
  set centerX [expr $width  / 2]
  
  # Create a new temp image that we'll be modifying.
  image create photo temp -height $height -width $width
  
  # Copy the initial image into our temp image, and configure the
  # canvas to show our temp image, instead of the original image
  # in this location.
  temp copy $start
  $canvas itemconfigure $canvasID -image temp
  update idle
  after 25

  # copy the start image into the temp with greater
  #   subsampling (making it appear like more and more of an
  #   edge view of the image).  
  # Move the start of the image to the center on each pass
  #  through the loop
  for {set i 2} {$i < 8} {incr i} {
    set left [expr $centerX - $width / (2 * $i)]
    set right [expr $centerX + $width / (2 * $i)]
    temp put $background -to 0 0 $width $height
    temp copy -to $left 0 $right $height -subsample $i 1 $start
    update idle
    after 10
  }

  # copy the end image into the temp with less and less
  #   subsampling (making it appear like less and less of an
  #   edge view of the image).  
  # Move the start of the image away from thecenter on each pass
  #  through the loop
  for {set i 8} {$i > 1} {incr i -1} {
    set left [expr $centerX - $width / (2 * $i)]
    set right [expr $centerX + $width / (2 * $i)]
    temp put $background -to 0 0 $width $height
    temp copy -to $left 0 $right $height -subsample $i 1 $end
    update idle
    after 10
  }
  # configure the canvas to show the final image, and
  # delete our temporary image
  $canvas itemconfigure $canvasID -image $end
  image delete temp
}

################################################################
# proc playerTurn {position}--
#    Selects a card for comparison, or checks the current
#    card against a previous selection.
# Arguments
# position     The position of this card in the deck.
#
# Results
#     The selection fields of the global array "concentration"
#     are modified.
#     The GUI is modified.
# 
proc playerTurn {position} {
  global concentration
  
  set card [lindex $concentration(cards) $position]
  flipImageX .game card_$position back $card gray
  
  set rank [lindex [split $card _] 1]

  # If concentration(selected,rank) is empty, this is the first
  #   part of a turn.  Mark this card as selected and we're done.
  if {{} eq $concentration(selected,rank)} {
      # Increment the turn counter
    incr concentration(turn)

    set concentration(selected,rank) $rank
    set concentration(selected,position) $position
    set concentration(selected,card) $card
  } else {
    # If we're here, then this is the second part of a turn.
    # Compare the rank of this card to the previously saved rank.
    
    if {$position == $concentration(selected,position)} {
      return
    }

    # Update the screen *NOW* (to show the card), and pause for one second.
    update idle
    after 1000
  
    # If the ranks are identical, handle the match condition
    if {$rank eq $concentration(selected,rank)} {

      # Increase the score by one
      incr concentration(player,score)

      # Remove the two cards and their backs from the board
      .game bind card_$position <ButtonRelease-1> ""
      .game bind card_$concentration(selected,position) <ButtonRelease-1> ""
      
      moveCards card_$position \
          card_$concentration(selected,position) player
      
      # Check to see if we've won yet.
      if {[checkForFinished]} {
        endGame
      }
    } else {
      # If we're here, the cards were not a match.
      # flip the cards to back up (turn the cards face down)

       flipImageX .game card_$position $card back gray
       flipImageX .game card_$concentration(selected,position) \
         $concentration(selected,card) back gray
    }
    
    # Whether or not we had a match, reset the concentration(selected,rank)
    # to an empty string so that the next click will be a select.
    set concentration(selected,rank) {}
  }
}

################################################################
# proc moveCards {cvs id1 id2 prefix}--
#    moves Cards from their current location to the
#  score pile for 
# Arguments
#   id1        An identifier for a canvas item
#   id2        An identifier for a canvas item
#   prefix    Identifier for which location should get the card
# 
# Results
#   
# 
proc moveCards {id1 id2 prefix} {
  global concentration

  .game raise $id1 
  .game raise $id2
  
  .game coords $id1 $concentration($prefix,x) $concentration($prefix,y)
  .game coords $id2 $concentration($prefix,x) $concentration($prefix,y)
  incr concentration($prefix,y) 30
}

################################################################
# proc checkForFinished {}--
#    checks to see if the game is won.  Returns true/false
# Arguments
#   
# 
# Results
#   
# 
proc checkForFinished {} {
  global concentration

  global concentration
  if {$concentration(player,score) == 24} {
    return TRUE
  } else {
    return FALSE
  }
}

################################################################
# proc endGame {}--
#    Provide end of game display and ask about a new game
# Arguments
#   NONE
# 
# Results
#   GUI is modified
# 
proc endGame {} {
  global concentration
    
  set position 0
  foreach card $concentration(cards) {
    .game itemconfigure card_$position -image $card
    incr position
  }
    
  # Update the screen *NOW*, and pause for 2 seconds
  update idle;
  after 2000
    
  .game create rectangle 250 250 450 400 -fill blue \
      -stipple gray50 -width 3 -outline gray  

  button .again -text "Play Again" -command { 
      destroy .again
      destroy .quit
      startGame
  }

  button .quit -text "Quit" -command "exit"

  .game create window 350 300 -window .again
  .game create window 350 350 -window .quit
}
loadImages
makeGameBoard
startGame

`

func main() {
    ir := gothic.NewInterpreter(init_script)

    <-ir.Done
}






有疑问加站长微信联系(非本文作者)

本文来自:开源中国博客

感谢作者:名字不能长

查看原文:把别人的Tcl/Tk代码加入到Go语言里15 游戏8 翻牌游戏

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2060 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传