这次文章主要引用了网上的这篇教学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 }
有疑问加站长微信联系(非本文作者)