扫雷程序实现之 part 1
先贴一点上来。随后我会抽时间做一些设计模式的分析:)
////////////////////////////////////////////////////////////////////
//
// Project: 扫雷
// Author: Chen Rong
// History:
// v1.0 2004,3,7 基本实现扫雷逻辑
// v1.1 2005,7,7 重构
//
////////////////////////////////////////////////////////////////////
using System;
namespace ChenRong.WinMine {
/// <summary>
/// 扫雷游戏对象
/// </summary>
public class MineGame {
public MineCell[,] Board {
get { return _board; }
}
MineCell[,] _board;
int _rows, _cols, _mines;
GameResult _gameResult = GameResult.None;
public int Rows {
get { return _rows; }
}
public int Cols {
get { return _cols; }
}
public int Mines {
get { return _mines; }
}
public GameResult Result {
get { return _gameResult; }
}
/// <summary>
/// 初始化雷区, 随机摆放地雷
/// </summary>
/// <param name="rows"></param>
/// <param name="cols"></param>
/// <param name="mines"></param>
public void Reset(int rows, int cols, int mines) {
if (rows <= 0 || cols <= 0)
throw new Exception("雷区的长,宽必须为正整数。");
if (mines >= rows * cols)
throw new Exception("您设定的雷数目太多!");
_gameResult = GameResult.None;
_mines = mines;
_rows = rows;
_cols = cols;
_board = new MineCell[rows, cols];
InitializeCells();
PlaceRandomMines();
UpdateNearbyMinesCount();
}
/// <summary>
/// 更新每个位置周围地雷的统计数字
/// </summary>
private void UpdateNearbyMinesCount() {
for (int i = 0; i < _rows; i++) {
for (int j = 0; j < _cols; j++) {
_board[i, j].NearbyMines = GetNearbyMines(i, j);
}
}
}
/// <summary>
/// 摆放随机地雷
/// </summary>
private void PlaceRandomMines() {
int count = 0;
Random r = new Random((int)DateTime.Now.Ticks);
while (count < _mines) {
int row = r.Next(0, _rows);
int col = r.Next(0, _cols);
if (!_board[row, col].IsMine) {
_board[row, col].IsMine = true;
count++;
}
}
}
/// <summary>
/// 判断一个点是否为有效位置
/// </summary>
/// <param name="row"></param>
/// <param name="col"></param>
/// <returns></returns>
private bool IsValidCell(int row, int col) {
return (row >= 0 && col >= 0 && row < _rows && col < _cols);
}
/// <summary>
/// 从一个格子出发向四周的可能的位移
/// </summary>
private int[,] moves = new int[8, 2] {{-1, -1}, {-1, 0},{-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};
/// <summary>
/// 得到某个位置周围的地雷数
/// </summary>
/// <param name="row"></param>
/// <param name="col"></param>
/// <returns></returns>
private int GetNearbyMines(int row, int col) {
int minesFound = 0;
for (int i = 0; i < moves.GetLength(0); i++) {
int r = row + moves[i, 0];
int c = col + moves[i, 1];
if (IsValidCell(r, c) && _board[r, c].IsMine)
minesFound++;
}
return minesFound;
}
/// <summary>
/// 揭开某个点, 相当于鼠标左键单击触发的行为
/// </summary>
/// <param name="row"></param>
/// <param name="col"></param>
public void Uncover(int row, int col) {
if (! IsValidCell(row, col))
return;
MineCell cell = _board[row, col];
if (cell.Uncovered)
return;
cell.Uncovered = true;
// 如果周围雷数是 0, 那么顺便把周围的 8 个位置都翻开
if (!cell.IsMine && cell.NearbyMines == 0) {
for (int i = 0; i < moves.GetLength(0); i++)
Uncover(row + moves[i, 0], col + moves[i, 1]);
}
}
/// <summary>
/// 设定或取消标志, 相当于鼠标右键单击的行为
/// </summary>
/// <param name="row"></param>
/// <param name="col"></param>
public void ChangeMark(int row, int col) {
MineCell cell = _board[row, col];
if (cell.Uncovered)
return;
// 轮换几种标志
if (cell.Mark == Mark.None)
cell.Mark = Mark.Mine;
else if (cell.Mark == Mark.Mine)
cell.Mark = Mark.Question;
else if (cell.Mark == Mark.Question)
cell.Mark = Mark.None;
}
/// <summary>
/// 检验游戏结果
/// </summary>
public void CheckGameResult() {
int iUncovered = 0;
int iMarkedAsMine = 0;
// 先检测是否已经标出全部地雷
for (int i = 0; i < _rows; i++) {
for (int j = 0; j < _cols; j++) {
MineCell cell = _board[i, j];
if (cell.Uncovered) {
iUncovered++;
continue;
}
if (cell.Mark == Mark.Mine) {
iMarkedAsMine++;
if (!cell.IsMine) {
_gameResult = GameResult.Lose;
return;
}
}
}
}
// 所有的点都已经探测到,而且标注没有失误, 就是赢了
if ((iUncovered + iMarkedAsMine) == _rows * _cols)
_gameResult = GameResult.Win;
}
/// <summary>
/// 初始化每个单元格对象
/// </summary>
private void InitializeCells() {
for (int i = 0; i < _rows; i++) {
for (int j = 0; j < _cols; j++) {
_board[i, j] = new MineCell();
}
}
}
}
}
//
// Project: 扫雷
// Author: Chen Rong
// History:
// v1.0 2004,3,7 基本实现扫雷逻辑
// v1.1 2005,7,7 重构
//
////////////////////////////////////////////////////////////////////
using System;
namespace ChenRong.WinMine {
/// <summary>
/// 扫雷游戏对象
/// </summary>
public class MineGame {
public MineCell[,] Board {
get { return _board; }
}
MineCell[,] _board;
int _rows, _cols, _mines;
GameResult _gameResult = GameResult.None;
public int Rows {
get { return _rows; }
}
public int Cols {
get { return _cols; }
}
public int Mines {
get { return _mines; }
}
public GameResult Result {
get { return _gameResult; }
}
/// <summary>
/// 初始化雷区, 随机摆放地雷
/// </summary>
/// <param name="rows"></param>
/// <param name="cols"></param>
/// <param name="mines"></param>
public void Reset(int rows, int cols, int mines) {
if (rows <= 0 || cols <= 0)
throw new Exception("雷区的长,宽必须为正整数。");
if (mines >= rows * cols)
throw new Exception("您设定的雷数目太多!");
_gameResult = GameResult.None;
_mines = mines;
_rows = rows;
_cols = cols;
_board = new MineCell[rows, cols];
InitializeCells();
PlaceRandomMines();
UpdateNearbyMinesCount();
}
/// <summary>
/// 更新每个位置周围地雷的统计数字
/// </summary>
private void UpdateNearbyMinesCount() {
for (int i = 0; i < _rows; i++) {
for (int j = 0; j < _cols; j++) {
_board[i, j].NearbyMines = GetNearbyMines(i, j);
}
}
}
/// <summary>
/// 摆放随机地雷
/// </summary>
private void PlaceRandomMines() {
int count = 0;
Random r = new Random((int)DateTime.Now.Ticks);
while (count < _mines) {
int row = r.Next(0, _rows);
int col = r.Next(0, _cols);
if (!_board[row, col].IsMine) {
_board[row, col].IsMine = true;
count++;
}
}
}
/// <summary>
/// 判断一个点是否为有效位置
/// </summary>
/// <param name="row"></param>
/// <param name="col"></param>
/// <returns></returns>
private bool IsValidCell(int row, int col) {
return (row >= 0 && col >= 0 && row < _rows && col < _cols);
}
/// <summary>
/// 从一个格子出发向四周的可能的位移
/// </summary>
private int[,] moves = new int[8, 2] {{-1, -1}, {-1, 0},{-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};
/// <summary>
/// 得到某个位置周围的地雷数
/// </summary>
/// <param name="row"></param>
/// <param name="col"></param>
/// <returns></returns>
private int GetNearbyMines(int row, int col) {
int minesFound = 0;
for (int i = 0; i < moves.GetLength(0); i++) {
int r = row + moves[i, 0];
int c = col + moves[i, 1];
if (IsValidCell(r, c) && _board[r, c].IsMine)
minesFound++;
}
return minesFound;
}
/// <summary>
/// 揭开某个点, 相当于鼠标左键单击触发的行为
/// </summary>
/// <param name="row"></param>
/// <param name="col"></param>
public void Uncover(int row, int col) {
if (! IsValidCell(row, col))
return;
MineCell cell = _board[row, col];
if (cell.Uncovered)
return;
cell.Uncovered = true;
// 如果周围雷数是 0, 那么顺便把周围的 8 个位置都翻开
if (!cell.IsMine && cell.NearbyMines == 0) {
for (int i = 0; i < moves.GetLength(0); i++)
Uncover(row + moves[i, 0], col + moves[i, 1]);
}
}
/// <summary>
/// 设定或取消标志, 相当于鼠标右键单击的行为
/// </summary>
/// <param name="row"></param>
/// <param name="col"></param>
public void ChangeMark(int row, int col) {
MineCell cell = _board[row, col];
if (cell.Uncovered)
return;
// 轮换几种标志
if (cell.Mark == Mark.None)
cell.Mark = Mark.Mine;
else if (cell.Mark == Mark.Mine)
cell.Mark = Mark.Question;
else if (cell.Mark == Mark.Question)
cell.Mark = Mark.None;
}
/// <summary>
/// 检验游戏结果
/// </summary>
public void CheckGameResult() {
int iUncovered = 0;
int iMarkedAsMine = 0;
// 先检测是否已经标出全部地雷
for (int i = 0; i < _rows; i++) {
for (int j = 0; j < _cols; j++) {
MineCell cell = _board[i, j];
if (cell.Uncovered) {
iUncovered++;
continue;
}
if (cell.Mark == Mark.Mine) {
iMarkedAsMine++;
if (!cell.IsMine) {
_gameResult = GameResult.Lose;
return;
}
}
}
}
// 所有的点都已经探测到,而且标注没有失误, 就是赢了
if ((iUncovered + iMarkedAsMine) == _rows * _cols)
_gameResult = GameResult.Win;
}
/// <summary>
/// 初始化每个单元格对象
/// </summary>
private void InitializeCells() {
for (int i = 0; i < _rows; i++) {
for (int j = 0; j < _cols; j++) {
_board[i, j] = new MineCell();
}
}
}
}
}
posted on 2005-07-07 20:31 NeilChen 阅读(3062) 评论(15) 编辑 收藏 举报