接着前一篇文章,
Minesweeper: GDI+ 初步实现,本文在代码结构上做一些改进,不涉及新的功能。
首先我们来看MineBoard类的Init方法:
public
void
Init(
int
rows,
int
columns,
int
mines)
{
if
(rows
<=
0
||
columns
<=
0
||
mines
>=
columns
*
rows)
{
throw
new
ArgumentException();
}
cells
=
new
MineCell[rows, columns];
totalMines
=
mines;
makedMines
=
0
;
status
=
GameStatus.NotStarted;
PlaceRandomMines();
UpdateNearbyMinesCount();
}
实际的游戏开发中,随机布局整个游戏区域的情况并不多,更为常见的还是从地图中读取。同时,为了实现游戏过程中保存当前的游戏进展,然后读取后继续,或者支持从网络上下载布局,以及同其他人分享等,需要将布局的功能移到MineBoard在之外。
调整后的代码如下:
public
interface
IMineBoardBuilder
{
int
TotalMines {
get
; }
int
MarkedMines {
get
; }
MineCell[,] BuildMineCells();
}
public
class
RandomBoardBuilder : IMineBoardBuilder
{
private
int
rows;
private
int
columns;
private
int
totalMines;
public
RandomBoardBuilder(
int
rows,
int
columns,
int
mines)
{
if
(rows
<=
0
||
columns
<=
0
||
mines
>=
columns
*
rows)
{
throw
new
ArgumentException();
}
this
.rows
=
rows;
this
.columns
=
columns;
this
.totalMines
=
mines;
}
public
int
TotalMines {
get
{
return
totalMines; } }
public
int
MarkedMines {
get
{
return
0
; } }
public
MineCell[,] BuildMineCells()
{
MineCell[,] cells
=
new
MineCell[rows, columns];
PlaceRandomMines(cells);
UpdateNearbyMinesCount(cells);
return
cells;
}
}
PlaceRandomMines和UpdateNearbyMinesCount实现跟上一篇文章中一样,就不给出了。
MineBoard的Init方法则重构为:
public
void
Init(IMineBoardBuilder builder)
{
cells
=
builder.BuildMineCells();
totalMines
=
builder.TotalMines;
makedMines
=
builder.MarkedMines;
status
=
GameStatus.NotStarted;
}
下面的这个类可以很容易的实现二进制地图文件的读取。文本/XML格式的地图读取,也可以很容易的实现。
[Serializable]
public
class
BoardFileLoader : IMineBoardBuilder
{
private
MineCell[,] cells;
private
int
totalMines;
private
int
markedMines;
public
int
TotalMines {
get
{
return
totalMines; } }
public
int
MarkedMines {
get
{
return
markedMines; } }
public
MineCell[,] BuildMineCells()
{
return
cells;
}
}
相应的,可以为MineBoard类添加保存游戏进展的功能。
在交互方面,也可作如下改进:
public
void
WalkNearByCells(
int
row,
int
col, MineWalkCallback callback, Predicate
<
MineCell
>
match)
{
if
(IsValidCell(row, col))
{
callback(
ref
cells[row, col]);
if
(match(cells[row, col]))
{
for
(
int
i
=
-
1
; i
<
2
; i
++
)
{
for
(
int
j
=
-
1
; j
<
2
; j
++
)
{
if
(i
!=
0
||
j
!=
0
)
{
WalkNearByCells(row
+
i, j
+
i, callback, match);
}
}
}
}
}
}
public
void
DoAction(IMineBoardAction action)
{
action.Run(
this
);
}
这两个新增的方法可以将连续揭开一片区域、计算相邻雷数等操作实现移到MineBoard类外实现,这样就可以进一步引入脚本引擎,将一些逻辑实现在脚本中。
项目文件下载:20080319.zip
系列索引:Minesweeper: 索引