1.关于本文
“天马行空”这个游戏是我十几年前在一个游戏网站(cchild,现在已经不存在了)上看到的,时隔多年我才发现我仍然没有找到这个游戏的解法(从图论上理解应该是一个寻找汉密尔顿路径的问题)。现在我把它用实现出来,一来期待哪天顿悟,或是哪位高人帮我答疑解惑;二来锻炼一下我已经快一年没有用过的VB.NET编程能力。
本程序的下载地址位于:
2.游戏规则
1)指定一个m*n大小的棋盘,每次进入游戏时程序都会通过InputBox来向玩家询问
2)在棋盘上任意选择一点,按照国际象棋中棋子“马”的行棋方法在棋盘上移动,不允许第二次移动到已经路过的位置
3)如果棋盘上所有的点都被走过一次,则认为游戏胜利;如果无法再移动,则认为游戏失败
下图为游戏示例
3.程序控件
手工放置到程序中的控件很少。程序中就一个Form,名为FormMain
其中,FormMain的Size属性为(688, 664),StartPosition属性被设置为CenterScreen。Panel控件pnlControl的BorderStyle属性被设置为FixedSingle,Dock属性被设置为Top;pnlBoard的Dock属性被设置为Fill
4.程序源码
Public Class FormMain 'w:矩阵列数-1 h:矩阵行数-1 Dim w As Integer = 7 Dim h As Integer = 7 '初始化窗体 Private Sub FormMain_Load(sender As Object, e As EventArgs) _ Handles MyBase.Load '输入矩阵行数 Do Try h = InputBox("设定矩阵行数", "欢迎", 8) - 1 If h < 3 Then Throw New Exception("矩阵行数应大于或等于4") End If Exit Do Catch ex As Exception MessageBox.Show(ex.Message) Continue Do End Try Loop '输入矩阵列数 Do Try w = InputBox("设定矩阵列数", "欢迎", 8) - 1 If w < 3 Then Throw New Exception("矩阵列数应大于或等于4") End If Exit Do Catch ex As Exception MessageBox.Show(ex.Message) Continue Do End Try Loop '部署控件 For i As Integer = 0 To h For j As Integer = 0 To w Dim btn As Button = New Button '设置按钮属性 With btn .Location = New System.Drawing.Point _ (j * pnlBoard.Width / (w + 1), i * pnlBoard.Height / (h + 1)) .Size = New System.Drawing.Size _ (pnlBoard.Width / (w + 1), pnlBoard.Height / (h + 1)) .Tag = {i, j} '按钮对应的行列,存储在Tag中 End With '设置按钮事件 AddHandler btn.Click, AddressOf btnPosition_Click '在棋盘上添加该按钮 pnlBoard.Controls.Add(btn) Next Next '初始化棋盘 Restart() End Sub Dim isGameStarted As Boolean = False '单击棋盘上的一个按钮 Private Sub btnPosition_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim btnTemp As Button = DirectCast(sender, Button) '如果行棋位置之前已经走过,不合法 If btnTemp.BackColor <> Color.Red Then Return End If '读取该按钮所对应的行列 Dim array() As Integer = DirectCast(btnTemp.Tag, Integer()) Dim row As Integer = array(0) Dim col As Integer = array(1) '判断本次行棋是否合法 Dim isLegal As Boolean = False '若尚未开始游戏则开始游戏 If isGameStarted = False Then isGameStarted = True isLegal = True GoTo RESULT End If '向右下偏左行棋 If row >= 2 And col >= 1 Then If pnlBoard.Controls((row - 2) * (w + 1) + col - 1).BackColor = Color.Green Then isLegal = True GoTo RESULT End If End If '向右下偏右行棋 If row >= 1 And col >= 2 Then If pnlBoard.Controls((row - 1) * (w + 1) + col - 2).BackColor = Color.Green Then isLegal = True GoTo RESULT End If End If '向右上偏左行棋 If row <= w - 2 And col >= 1 Then If pnlBoard.Controls((row + 2) * (w + 1) + col - 1).BackColor = Color.Green Then isLegal = True GoTo RESULT End If End If '向右上偏右行棋 If row <= w - 1 And col >= 2 Then If pnlBoard.Controls((row + 1) * (w + 1) + col - 2).BackColor = Color.Green Then isLegal = True GoTo RESULT End If End If '向左下偏右行棋 If row >= 2 And col <= h - 1 Then If pnlBoard.Controls((row - 2) * (w + 1) + col + 1).BackColor = Color.Green Then isLegal = True GoTo RESULT End If End If '向左下偏左行棋 If row >= 1 And col <= h - 2 Then If pnlBoard.Controls((row - 1) * (w + 1) + col + 2).BackColor = Color.Green Then isLegal = True GoTo RESULT End If End If '向左上偏左行棋 If row <= w - 1 And col <= h - 2 Then If pnlBoard.Controls((row + 1) * (w + 1) + col + 2).BackColor = Color.Green Then isLegal = True GoTo RESULT End If End If '向左上偏右行棋 If row <= w - 2 And col <= h - 1 Then If pnlBoard.Controls((row + 2) * (w + 1) + col + 1).BackColor = Color.Green Then isLegal = True GoTo RESULT End If End IfRESULT: '如果行棋合法,则行棋,否则不行棋 If isLegal Then '将之前点下的按钮都置为草绿 For Each btn As Button In pnlBoard.Controls If btn.BackColor <> Color.Red Then btn.BackColor = Color.LawnGreen End If Next '将当前点下的按钮置为绿色 btnTemp.BackColor = Color.Green If IsWin() Then MessageBox.Show("You made a good job!") End If End If End Sub '''''' 初始化棋盘界面 ''' '''将所有按钮都置为Red Private Sub Restart() '游戏回复到未开始状态 isGameStarted = False '背景颜色全部置红 For Each btn As Button In pnlBoard.Controls btn.BackColor = Color.Red Next End Sub '''''' 判断本局游戏是否胜利 ''' '''true:游戏胜利 false:游戏尚未胜利 '''Public Function IsWin() As Boolean '有没有变绿的按钮,则认为游戏没有取胜 For Each btn As Button In pnlBoard.Controls If btn.BackColor = Color.Red Then Return False End If Next '所有按钮都变绿,游戏胜利 Return True End Function '重新开始游戏 Private Sub btnRestart_Click(sender As Object, e As EventArgs) _ Handles btnRestart.Click Restart() End Sub '关闭程序 Private Sub btnClose_Click(sender As Object, e As EventArgs) _ Handles btnClose.Click Application.Exit() End SubEnd Class