1.关于本文
“天马行空”这个游戏是我十几年前在一个游戏网站(cchild,现在已经不存在了)上看到的,时隔多年我才发现我仍然没有找到这个游戏的解法(从图论上理解应该是一个寻找汉密尔顿路径的问题)。现在我把它用实现出来,一来期待哪天顿悟,或是哪位高人帮我答疑解惑;二来锻炼一下我已经快一年没有用过的VB.NET编程能力。
本程序的下载地址位于:http://pan.baidu.com/s/1ntkGIEl
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 If
RESULT:
'如果行棋合法,则行棋,否则不行棋
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
''' <summary>
''' 初始化棋盘界面
''' </summary>
''' <remarks>将所有按钮都置为Red</remarks>
Private Sub Restart()
'游戏回复到未开始状态
isGameStarted = False
'背景颜色全部置红
For Each btn As Button In pnlBoard.Controls
btn.BackColor = Color.Red
Next
End Sub
''' <summary>
''' 判断本局游戏是否胜利
''' </summary>
''' <returns> true:游戏胜利 false:游戏尚未胜利</returns>
''' <remarks></remarks>
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 Sub
End Class