实例介绍
【实例截图】
【核心代码】
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Imaging; using System.IO; using System.Media; namespace Chess { //棋子枚举类型 public enum Piece { 无子 = 0, 红车 = 1, 红马 = 2, 红相 = 3, 红士 = 4, 红帅 = 5, 红炮 = 6, 红卒 = 7, 蓝车 = 8, 蓝马 = 9, 蓝象 = 10, 蓝士 = 11, 蓝将 = 12, 蓝炮 = 13, 蓝兵 = 14 } //走棋方枚举类型 public enum Player { 无 = 0, 红 = 1, 蓝 = 2 } //主窗口类 public partial class FormMain : Form { //保存象棋棋盘的所有棋子值(棋盘共10行9列,但0行0列保留不用) private Piece[,] _chess = new Piece[11, 10]; //保存所有的走棋步骤(List对象) private List<Step> _stepList = new List<Step>(); //保存棋盘(细框)的左上角坐标 private Point _leftTop = new Point(60, 60); //保存棋盘格子的行高和列宽 private int _rowHeight = 60; private int _colWidth = 60; //保存棋子半径 private int _pieceR = 29; //保存拾起的棋子值(默认为"无子",即目前没有拾起棋子) private Piece _pickChess = Piece.无子; //保存拾起棋子的行号和列号 private int _pickRow = 0; private int _pickCol = 0; //保存落下棋子的行号和列号 private int _dropRow = 0; private int _dropCol = 0; //保存当前鼠标所在点坐标 private Point _curMousePoint = new Point(0, 0); //保存棋盘桌面位图 private Bitmap _deskBmp = new Bitmap("desktop.jpg"); //保存红蓝双方14中棋子位图(为了与Piece枚举类型值对应,_pieceBmp[0]舍弃不用) private Bitmap[] _pieceBmp = new Bitmap[15]; //保存红方头像位图 private Bitmap _redBmp = new Bitmap("红方头像.bmp"); //保存蓝方头像位图 private Bitmap _blueBmp = new Bitmap("蓝方头像.bmp"); //保存当前的走棋方 private Player _curPlayer = Player.无; //自定义类方法:绘制棋盘 public void DrawBoard(Graphics g) { //绘制棋盘桌面(注意:"desktop.jpg"文件由教师提供,然后拷贝到"bin\debug"目录下) g.DrawImage(_deskBmp, new Point(0, 0)); //创建粗画笔和细画笔 Pen thickPen = new Pen(Color.Black, 6); Pen thinPen = new Pen(Color.Black, 2); //绘制棋盘外围的粗框 int gap = (int)(_rowHeight * 0.15); g.DrawRectangle(thickPen, new Rectangle(_leftTop.X - gap, _leftTop.Y - gap, _colWidth * 8 2 * gap, _rowHeight * 9 2 * gap)); //绘制棋盘的10条横线(10行) for (int row = 1; row <= 10; row ) { g.DrawLine(thinPen, new Point(_leftTop.X, _leftTop.X _rowHeight * (row - 1)), new Point(_leftTop.X _colWidth * 8, _leftTop.Y _rowHeight * (row - 1))); } //绘制棋盘的9条竖线(9列) for (int col = 1; col <= 9; col ) { //绘制棋盘上半部分的竖线 g.DrawLine(thinPen, new Point(_leftTop.X _colWidth * (col - 1), _leftTop.Y), new Point(_leftTop.X _colWidth * (col - 1), _leftTop.Y _rowHeight * 4)); //绘制棋盘下半部分的竖线 g.DrawLine(thinPen, new Point(_leftTop.X _colWidth * (col - 1), _leftTop.Y _rowHeight * 5), new Point(_leftTop.X _colWidth * (col - 1), _leftTop.Y _rowHeight * 9)); } //绘制连接楚河汉界左右两端的两条短竖线 g.DrawLine(thinPen, new Point(_leftTop.X, _leftTop.Y _rowHeight * 4), new Point(_leftTop.X, _leftTop.Y _rowHeight * 5)); g.DrawLine(thinPen, new Point(_leftTop.X _colWidth * 8, _leftTop.Y _rowHeight * 4), new Point(_leftTop.X _colWidth * 8, _leftTop.Y _rowHeight * 5)); //绘制上方九宫格的交叉线 g.DrawLine(thinPen, new Point(_leftTop.X _colWidth * 3, _leftTop.Y), new Point(_leftTop.X _colWidth * 5, _leftTop.Y _rowHeight * 2)); g.DrawLine(thinPen, new Point(_leftTop.X _colWidth * 5, _leftTop.Y), new Point(_leftTop.X _colWidth * 3, _leftTop.Y _rowHeight * 2)); //绘制下方九宫格的交叉线 g.DrawLine(thinPen, new Point(_leftTop.X _colWidth * 3, _leftTop.Y _rowHeight * 7), new Point(_leftTop.X _colWidth * 5, _leftTop.Y _rowHeight * 9)); g.DrawLine(thinPen, new Point(_leftTop.X _colWidth * 5, _leftTop.Y _rowHeight * 7), new Point(_leftTop.X _colWidth * 3, _leftTop.Y _rowHeight * 9)); //书写"楚河"和"汉界" Font font1 = new Font("隶书", (float)(_rowHeight * 0.8), FontStyle.Regular, GraphicsUnit.Pixel); SolidBrush brush = new SolidBrush(Color.Black); g.DrawString("楚河", font1, brush, new Point(_leftTop.X _colWidth, (int)(_leftTop.Y _rowHeight * 4.1))); g.DrawString("汉界", font1, brush, new Point(_leftTop.X _colWidth * 5, (int)(_leftTop.Y _rowHeight * 4.1))); //书写行的数字编号 Font font2 = new Font("黑体", (float)(_rowHeight * 0.6), FontStyle.Regular, GraphicsUnit.Pixel); for (int row = 1; row <= 10; row ) g.DrawString(row.ToString(), font2, brush, new Point((int)(_leftTop.X _colWidth * 8.6), (int)(_leftTop.Y - _rowHeight * 0.4 _rowHeight * (row - 1)))); //书写列的数字编号 string[] colNumber = new string[9] { "一", "二", "三", "四", "五", "六", "七", "八", "九" }; Font font3 = new Font("黑体", (float)(_rowHeight * 0.5), FontStyle.Regular, GraphicsUnit.Pixel); for (int col = 1; col <= 9; col ) g.DrawString(colNumber[col - 1], font3, brush, new Point((int)(_leftTop.X - _colWidth * 0.3 _colWidth * (col - 1)), (int)(_leftTop.Y _rowHeight * 9.6))); //书写蓝方和红方 g.DrawString("蓝方", font3, brush, new Point(_leftTop.X _colWidth * 8 95, _leftTop.Y (int)(_rowHeight * 2.2))); g.DrawString("红方", font3, brush, new Point(_leftTop.X _colWidth * 8 95, _leftTop.Y (int)(_rowHeight * 6.4))); //绘制棋盘第3行的炮营营地标志 DrawCampMark(g, new Point(_leftTop.X _colWidth * 1, _leftTop.Y _rowHeight * 2), true, true); DrawCampMark(g, new Point(_leftTop.X _colWidth * 7, _leftTop.Y _rowHeight * 2), true, true); //绘制棋盘第4行的兵营营地标志 DrawCampMark(g, new Point(_leftTop.X _colWidth * 0, _leftTop.Y _rowHeight * 3), false, true); DrawCampMark(g, new Point(_leftTop.X _colWidth * 2, _leftTop.Y _rowHeight * 3), true, true); DrawCampMark(g, new Point(_leftTop.X _colWidth * 4, _leftTop.Y _rowHeight * 3), true, true); DrawCampMark(g, new Point(_leftTop.X _colWidth * 6, _leftTop.Y _rowHeight * 3), true, true); DrawCampMark(g, new Point(_leftTop.X _colWidth * 8, _leftTop.Y _rowHeight * 3), true, false); //绘制棋盘第7行的兵营营地标志 DrawCampMark(g, new Point(_leftTop.X _colWidth * 0, _leftTop.Y _rowHeight * 6), false, true); DrawCampMark(g, new Point(_leftTop.X _colWidth * 2, _leftTop.Y _rowHeight * 6), true, true); DrawCampMark(g, new Point(_leftTop.X _colWidth * 4, _leftTop.Y _rowHeight * 6), true, true); DrawCampMark(g, new Point(_leftTop.X _colWidth * 6, _leftTop.Y _rowHeight * 6), true, true); DrawCampMark(g, new Point(_leftTop.X _colWidth * 8, _leftTop.Y _rowHeight * 6), true, false); //绘制棋盘第8行的炮营营地标志 DrawCampMark(g, new Point(_leftTop.X _colWidth * 1, _leftTop.Y _rowHeight * 7), true, true); DrawCampMark(g, new Point(_leftTop.X _colWidth * 7, _leftTop.Y _rowHeight * 7), true, true); //绘制拾子位置的标记 DrawPickDropMark(g, _pickRow, _pickCol); //绘制落子位置的标记 DrawPickDropMark(g, _dropRow, _dropCol); //在相应的位置绘制走棋方的头像 if (_curPlayer == Player.蓝) g.DrawImage(_blueBmp, new Point(_leftTop.X _colWidth * 8 95, _leftTop.Y _rowHeight * 1 - 10)); else if(_curPlayer == Player.红) g.DrawImage(_redBmp, new Point(_leftTop.X _colWidth * 8 95, _leftTop.Y _rowHeight * 7 10)); } //自定义类方法:绘制(炮和兵)的营地标志 public void DrawCampMark(Graphics g, Point center, Boolean drawLeft, Boolean drawRight) { //偏移量和线段长度 int offset = (int)(_rowHeight * 0.08), length = (int)(_rowHeight * 0.16); //直角点坐标 Point corner = new Point(); //画笔对象 Pen thinPen = new Pen(Color.Black, 1); //是否需要绘制左边标志 if (drawLeft == true) { //绘制左上角的直角边 corner.X = center.X - offset; corner.Y = center.Y - offset; g.DrawLine(thinPen, new Point(corner.X, corner.Y), new Point(corner.X - length, corner.Y)); g.DrawLine(thinPen, new Point(corner.X, corner.Y), new Point(corner.X, corner.Y - length)); //绘制左下角的直角边 corner.X = center.X - offset; corner.Y = center.Y offset; g.DrawLine(thinPen, new Point(corner.X, corner.Y), new Point(corner.X - length, corner.Y)); g.DrawLine(thinPen, new Point(corner.X, corner.Y), new Point(corner.X, corner.Y length)); } //是否需要绘制右边标志 if (drawRight == true) { //绘制右上角的直角边 corner.X = center.X offset; corner.Y = center.Y - offset; g.DrawLine(thinPen, new Point(corner.X, corner.Y), new Point(corner.X length, corner.Y)); g.DrawLine(thinPen, new Point(corner.X, corner.Y), new Point(corner.X, corner.Y - length)); //绘制右下角的直角边 corner.X = center.X offset; corner.Y = center.Y offset; g.DrawLine(thinPen, new Point(corner.X, corner.Y), new Point(corner.X length, corner.Y)); g.DrawLine(thinPen, new Point(corner.X, corner.Y), new Point(corner.X, corner.Y length)); } } //自定义类方法:绘制棋子 public void DrawPiece(Graphics g) { //逐行逐列绘制象棋棋子 for (int row = 1; row <= 10; row ) { for (int col = 1; col <= 9; col ) { //如果该位置存在棋子 if (_chess[row, col] != Piece.无子) { //在棋盘交点位置绘制棋子 g.DrawImage(_pieceBmp[(int)_chess[row, col]], new Point(_leftTop.X _colWidth * (col - 1) - _pieceR, _leftTop.Y _rowHeight * (row - 1) - _pieceR)); } } } //在当前鼠标点位置绘制拾起的棋子,以显示出拾起的棋子随鼠标而动的效果 if (_pickChess != Piece.无子) { g.DrawImage(_pieceBmp[(int)_pickChess], new Point(_curMousePoint.X - _pieceR, _curMousePoint.Y - _pieceR)); } } //自定义类方法:把鼠标点击位置坐标转换为棋盘的行号和列号 public bool ConvertPointToRowCol(Point P, out int row, out int col) { //获取与鼠标点击位置距离最近的棋盘的交叉点的行号 row = (P.Y - _leftTop.Y) / _rowHeight 1; //如果鼠标点Y坐标超过棋盘行高的中线,则行号需要再加1 if ((P.Y - _leftTop.Y) % _rowHeight >= _rowHeight / 2) row = row 1; //获取与鼠标点击位置距离最近的棋盘的交叉点的列号 col = (P.X - _leftTop.X) / _colWidth 1; //如果鼠标点X坐标超过棋盘列宽的中线,则列号需要再加1 if ((P.X - _leftTop.X) % _colWidth >= _colWidth / 2) col = col 1; //获取与鼠标点击位置距离最近的棋盘的交叉点的坐标 Point chessP = new Point(); chessP.X = _leftTop.X _colWidth * (col - 1); chessP.Y = _leftTop.Y _rowHeight * (row - 1); //判断是否落在棋子半径之内,且在10行9列之内 double dist = Math.Sqrt(Math.Pow(P.X - chessP.X, 2) Math.Pow(P.Y - chessP.Y, 2)); if ((dist <= _pieceR) && (row <= 10) && (row >= 1) && (col <= 9) && (col >= 1)) { //返回true,表示该点击为有效点击 return true; } else { //把行号和列号设置为0,并返回false,表示该点击为无效点击 row = 0; col = 0; return false; } } //自定义类方法:绘制拾子或落子位置的标记 public void DrawPickDropMark(Graphics g, int row, int col) { //如果拾子或落子位置不存在 if (row != 0) { //画笔对象 Pen pen = new Pen(Color.Yellow, 4); //拾子或落子位置的点坐标 Point p = new Point(_leftTop.X _colWidth * (col - 1), _leftTop.Y _rowHeight * (row - 1)); //在拾子或落子位置的四个角绘制标记 g.DrawLine(pen, p.X - _pieceR, p.Y - _pieceR, p.X - _pieceR / 2, p.Y - _pieceR); g.DrawLine(pen, p.X - _pieceR, p.Y - _pieceR, p.X - _pieceR, p.Y - _pieceR / 2); g.DrawLine(pen, p.X _pieceR, p.Y - _pieceR, p.X _pieceR / 2, p.Y - _pieceR); g.DrawLine(pen, p.X _pieceR, p.Y - _pieceR, p.X _pieceR, p.Y - _pieceR / 2); g.DrawLine(pen, p.X - _pieceR, p.Y _pieceR, p.X - _pieceR / 2, p.Y _pieceR); g.DrawLine(pen, p.X - _pieceR, p.Y _pieceR, p.X - _pieceR, p.Y _pieceR / 2); g.DrawLine(pen, p.X _pieceR, p.Y _pieceR, p.X _pieceR / 2, p.Y _pieceR); g.DrawLine(pen, p.X _pieceR, p.Y _pieceR, p.X _pieceR, p.Y _pieceR / 2); } } //自定义类方法:播放声音文件 public void PlaySound(string waveFile) { //装载声音文件(需要添加System.Media命名空间) SoundPlayer soundPlay = new SoundPlayer(waveFile); //使用新线程播放声音 soundPlay.Play(); //注意:soundPlay.PlaySync()也可以播放声音,该方法使用用户界面(UI)线程播放,会导致用户界面的停顿 } //构造方法 public FormMain() { InitializeComponent(); //根据屏幕的分辨率设置棋盘格子的行高和列宽 _rowHeight = Screen.PrimaryScreen.Bounds.Size.Height / 14; _colWidth = _rowHeight; //设置象棋棋盘左上角坐标 _leftTop.Y = 2 * _rowHeight; _leftTop.X = _leftTop.Y; //把象棋棋盘的棋子数组初始化为"无子" for (int row = 1; row <= 10; row ) for (int col = 1; col <= 9; col ) _chess[row, col] = Piece.无子; //装载红蓝双方所有的棋子位图文件(_pieceBmp[0]舍弃不用) for (int i = 1; i <= 14; i ) { _pieceBmp[i] = new Bitmap(((Piece)i).ToString() ".bmp"); _pieceBmp[i].MakeTransparent(Color.White); } //保存红蓝方头像位图的透明色 _redBmp.MakeTransparent(Color.White); _blueBmp.MakeTransparent(Color.White); } //Paint(窗口绘制)事件响应方法 private void FormMain_Paint(object sender, PaintEventArgs e) { //绘制棋盘 DrawBoard(e.Graphics); //绘制棋子 DrawPiece(e.Graphics); } //"开局"菜单的Click事件响应方法 private void MenuItemBegin_Click(object sender, EventArgs e) { //显示提示确认框 if (MessageBox.Show("你是否需要开局?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { //清空_stepList中的所有走棋步骤 _stepList.Clear(); //设置走棋方(红方先走) _curPlayer = Player.红; //把象棋棋盘的棋子数组初始化为"无子" for (int row = 1; row <= 10; row ) for (int col = 1; col <= 9; col ) _chess[row, col] = Piece.无子; //初始化蓝方棋子(蓝方在上) _chess[1, 1] = Piece.蓝车; _chess[1, 2] = Piece.蓝马; _chess[1, 3] = Piece.蓝象; _chess[1, 4] = Piece.蓝士; _chess[1, 5] = Piece.蓝将; _chess[1, 6] = Piece.蓝士; _chess[1, 7] = Piece.蓝象; _chess[1, 8] = Piece.蓝马; _chess[1, 9] = Piece.蓝车; _chess[3, 2] = Piece.蓝炮; _chess[3, 8] = Piece.蓝炮; _chess[4, 1] = Piece.蓝兵; _chess[4, 3] = Piece.蓝兵; _chess[4, 5] = Piece.蓝兵; _chess[4, 7] = Piece.蓝兵; _chess[4, 9] = Piece.蓝兵; //初始化红方棋子(红方在下) _chess[10, 1] = Piece.红车; _chess[10, 2] = Piece.红马; _chess[10, 3] = Piece.红相; _chess[10, 4] = Piece.红士; _chess[10, 5] = Piece.红帅; _chess[10, 6] = Piece.红士; _chess[10, 7] = Piece.红相; _chess[10, 8] = Piece.红马; _chess[10, 9] = Piece.红车; _chess[8, 2] = Piece.红炮; _chess[8, 8] = Piece.红炮; _chess[7, 1] = Piece.红卒; _chess[7, 3] = Piece.红卒; _chess[7, 5] = Piece.红卒; _chess[7, 7] = Piece.红卒; _chess[7, 9] = Piece.红卒; //初始化拾起的棋子值为"无子" _pickChess = Piece.无子; //初始化拾起棋子的行号和列号为0 _pickRow = 0; _pickCol = 0; //初始化落下棋子的行号和列号为0 _dropRow = 0; _dropCol = 0; //使窗口失效,并发送Paint消息,从而触发Paint事件响应方法重绘棋盘和棋子 Invalidate(); //播放声音文件 PlaySound("Sounds\\begin.wav"); } } //MouseDown(鼠标下压)事件响应方法 private void FormMain_MouseDown(object sender, MouseEventArgs e) { //如果是鼠标左键下压,则拾起棋子或落下棋子 if (e.Button == MouseButtons.Left) { //把鼠标点击位置坐标转换为棋盘的行号和列号 int row, col; bool valid = ConvertPointToRowCol(new Point(e.X, e.Y), out row, out col); //判断鼠标点击是否有效 if (valid == true) { //处理拾子动作(判断拾起的棋子值是否为"无子","无子"表示目前没有拾起棋子) if (_pickChess == Piece.无子) { //判断该位置是否有棋子,且棋子属于当前的走棋方 if (_chess[row, col] != Piece.无子 && _chess[row, col].ToString().IndexOf(_curPlayer.ToString()) == 0) { //保存拾起的棋子值、行号、列号 _pickChess = _chess[row, col]; //保存拾子位置的行号和列号 _pickRow = row; _pickCol = col; //清空拾子位置的棋子值 _chess[_pickRow, _pickCol] = Piece.无子; //强制刷新窗口(注意:Invalidate()会触发窗口的Paint事件) Invalidate(); } } //处理落子动作 else { //判断落子位置是否无子或者为对方棋子 if (_chess[row, col] == Piece.无子 || _chess[row, col].ToString().IndexOf(_curPlayer.ToString()) == -1) { //定义落子标志,默认为false,表示不能落子 bool canDrop = false; //根据拾起的棋子值,进行相应的走棋规则判定,如果通过规则判定,则canDrop为true,可以落子 //象的走棋规则判定 if (_pickChess == Piece.蓝象) { //如果走田字,不绊象且不过河,则可以落子 if (Math.Abs(_pickRow - row) == 2 && Math.Abs(_pickCol - col) == 2 && _chess[(_pickRow row) / 2, (_pickCol col) / 2] == Piece.无子 && row <= 5) canDrop = true; } if (_pickChess == Piece.红相) { //如果走田字,中央无子且不越界时 if (Math.Abs(_pickRow - row) == 2 && Math.Abs(_pickCol - col) == 2 && _chess[(_pickRow row) / 2, (_pickCol col) / 2] == Piece.无子 && row >= 6) canDrop = true; } //马的走棋规则判定 if (_pickChess == Piece.红马 || _pickChess == Piece.蓝马) { //如果横着走日字,且不绊马脚 if (Math.Abs(_pickRow - row) == 1 && Math.Abs(_pickCol - col) == 2 && _chess[_pickRow, (_pickCol col) / 2] == Piece.无子) canDrop = true; //如果竖着走日字,且不绊马脚 if (Math.Abs(_pickRow - row) == 2 && Math.Abs(_pickCol - col) == 1 && _chess[(_pickRow row) / 2, _pickCol] == Piece.无子) canDrop = true; } //车的走棋规则 if (_pickChess == Piece.红车 || _pickChess == Piece.蓝车) { //如果车横着走 if (_pickRow == row) { //比较起点列和落点列的大小 int max = col > _pickCol ? col : _pickCol; int min = col > _pickCol ? _pickCol : col; //统计移动路径上(即起点列和落点列之间)棋子数量 int chessNum = 0; for (int i = min 1; i <= max - 1; i ) if (_chess[row, i] != Piece.无子) chessNum ; //只有当移动路径上(即起点列和落点列之间)棋子数量为0时,才允许落子 if (chessNum == 0) canDrop = true; } //如果车竖着走 if (_pickCol == col) { //比较起点行和落点行的大小 int max = row > _pickRow ? row : _pickRow; int min = row > _pickRow ? _pickRow : row; //统计移动路径上(即起点行和落点行之间)棋子数量 int chessNum = 0; for (int i = min 1; i <= max - 1; i ) if (_chess[i, col] != Piece.无子) chessNum ; //只有当移动路径上(即起点行和落点行之间)棋子数量为0时,才允许落子 if (chessNum == 0) canDrop = true; } } //士的走棋规则 if (_pickChess == Piece.蓝士) { if (col >= 4 && col <= 6 && row >= 1 && row <= 3 && Math.Abs(row - _pickRow) == 1 && Math.Abs(col - _pickCol) == 1) canDrop = true; } if (_pickChess == Piece.红士) { if (col >= 4 && col <= 6 && row >= 8 && row <= 10 && Math.Abs(row - _pickRow) == 1 && Math.Abs(col - _pickCol) == 1) canDrop = true; } //将的走棋规则 if (_pickChess == Piece.蓝将) { if (col >= 4 && col <= 6 && row >= 1 && row <= 3 && (Math.Abs(row - _pickRow) Math.Abs(col - _pickCol)) == 1) canDrop = true; } if (_pickChess == Piece.红帅) { if (col >= 4 && col <= 6 && row >= 8 && row <= 10 && (Math.Abs(row - _pickRow) Math.Abs(col - _pickCol)) == 1) canDrop = true; } //炮的走棋规则 if (_pickChess == Piece.红炮 || _pickChess == Piece.蓝炮) { //如果炮横着走 if (_pickRow == row) { //比较起点列和落点列的大小 int max = col > _pickCol ? col : _pickCol; int min = col > _pickCol ? _pickCol : col; //统计移动路径上(即起点列和落点列之间)棋子数量 int chessNum = 0; for (int i = min 1; i <= max - 1; i ) if (_chess[row, i] != Piece.无子) chessNum ; //只有当移动路径上(即起点列和落点列之间)棋子数量为小于等于1时,才允许落子 if ((chessNum == 1 && _chess[row, col] != Piece.无子) || (chessNum == 0 && _chess[row, col] == Piece.无子)) canDrop = true; } //如果炮竖着走 if (_pickCol == col) { //比较起点行和落点行的大小 int max = row > _pickRow ? row : _pickRow; int min = row > _pickRow ? _pickRow : row; //统计移动路径上(即起点行和落点行之间)棋子数量 int chessNum = 0; for (int i = min 1; i <= max - 1; i ) if (_chess[i, col] != Piece.无子) chessNum ; //只有当移动路径上(即起点行和落点行之间)棋子数量小于等于1时,才允许落子 if ((chessNum == 1 && _chess[row, col] != Piece.无子) || (chessNum == 0 && _chess[row, col] == Piece.无子)) canDrop = true; } } //兵的走棋规则 if (_pickChess == Piece.红卒) { if (_pickRow - row == 1 && col == _pickCol) canDrop = true; } if (_pickChess == Piece.蓝兵) { if (row - _pickRow == 1 && col == _pickCol) canDrop = true; } //如果通过走棋规则判定,则可以落子 if (canDrop == true) { //保存走棋步骤到_stepList中 Step tempStep = new Step(); tempStep._Player = _curPlayer; tempStep._PickChess = _pickChess; tempStep._PickRow = _pickRow; tempStep._PickCol = _pickCol; tempStep._DropChess = _chess[row, col]; tempStep._DropRow = row; tempStep._DropCol = col; _stepList.Add(tempStep); //判断被吃的棋子是否为"红帅"或者"蓝将" if (_chess[row, col] == Piece.红帅 || _chess[row, col] == Piece.蓝将) { //播放相应的声音文件 PlaySound("Sounds\\over.wav"); //显示获胜方信息 MessageBox.Show(_curPlayer.ToString() "方获胜!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); //禁止继续走棋 _curPlayer = Player.无; } else { //播放相应的声音文件 if (tempStep._DropChess == Piece.无子) PlaySound("Sounds\\drop.wav"); else PlaySound("Sounds\\eat.wav"); //交换走棋方 if (_curPlayer == Player.红) _curPlayer = Player.蓝; else _curPlayer = Player.红; } //设置落子位置的棋子值为拾起的棋子值 _chess[row, col] = _pickChess; //清空_pickChess的值 _pickChess = Piece.无子; //保存落子位置的行号和列号 _dropRow = row; _dropCol = col; //强制刷新窗口(注意:Invalidate()会触发窗口的Paint事件) Invalidate(); } } } } } //如果是鼠标右键下压,则取消拾起棋子 else if (e.Button == MouseButtons.Right) { //判断是否已经拾起了棋子 if (_pickChess != Piece.无子) { //把拾子位置设置为拾起的棋子值 _chess[_pickRow, _pickCol] = _pickChess; //清空_pickChess的值 _pickChess = Piece.无子; //强制刷新窗口(注意:Invalidate()会触发窗口的Paint事件) Invalidate(); } } } //MouseMove(鼠标移动)事件响应方法 private void FormMain_MouseMove(object sender, MouseEventArgs e) { //保存当前鼠标所在点的坐标 _curMousePoint = e.Location; //判断是否已经拾起棋子,已决定是否需要强制刷新窗口 if (_pickChess != Piece.无子) { //强制刷新窗口,以绘制出拾起的棋子随鼠标移动而动的效果 Invalidate(); } } //"悔棋"菜单的Click事件响应方法 private void MenuItemUndo_Click(object sender, EventArgs e) { //如果_stepList有走棋步骤,则可以悔棋 if (_stepList.Count >= 1) { //显示提示确认框 if (MessageBox.Show("你是否需要悔棋?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { //取出_stepList的最后一步走棋步骤到lastStep中 Step lastStep = _stepList[_stepList.Count - 1]; //还原最后一步走棋步骤 _curPlayer = lastStep._Player; _chess[lastStep._PickRow, lastStep._PickCol] = lastStep._PickChess; _chess[lastStep._DropRow, lastStep._DropCol] = lastStep._DropChess; //删除_stepList的最后一步走棋步骤 _stepList.RemoveAt(_stepList.Count - 1); //清空拾起的棋子值、拾子行号、拾子列号、落子行号、落子列号 _pickChess = Piece.无子; _pickRow = 0; _pickCol = 0; _dropRow = 0; _dropCol = 0; //如果_stepList还有走棋步骤,则需要显示上一步的拾子位置标记和落子位置标记 if (_stepList.Count >= 1) { //取出_stepList的最后一步走棋步骤到lastStep中 lastStep = _stepList[_stepList.Count - 1]; _pickRow = lastStep._PickRow; _pickCol = lastStep._PickCol; _dropRow = lastStep._DropRow; _dropCol = lastStep._DropCol; } //强制刷新窗口(注意:Invalidate()会触发窗口的Paint事件) Invalidate(); } } } //"保存残局"菜单的Click事件响应方法 private void MenuItemSave_Click(object sender, EventArgs e) { //显示保存残局对话框 if (saveFileDialog1.ShowDialog() == DialogResult.OK) { //创建一个文件流对象,用于写文件(需要添加System.IO命名空间) FileStream fs = new FileStream(saveFileDialog1.FileName, FileMode.Create); //创建一个与文件流对象相对应的二进制写入流对象 BinaryWriter bw = new BinaryWriter(fs); //写入当前的走棋方 bw.Write((int)_curPlayer); //逐一写入棋子值 for (int row = 1; row <= 10; row ) for (int col = 1; col <= 9; col ) bw.Write((int)_chess[row, col]); //写入走棋步骤数 bw.Write(_stepList.Count); //逐一写入走棋步骤 for (int i = 0; i <= _stepList.Count - 1; i ) { bw.Write((int)_stepList[i]._Player); bw.Write((int)_stepList[i]._PickChess); bw.Write(_stepList[i]._PickRow); bw.Write(_stepList[i]._PickCol); bw.Write((int)_stepList[i]._DropChess); bw.Write(_stepList[i]._DropRow); bw.Write(_stepList[i]._DropCol); } //关闭有关文件流对象 bw.Close(); fs.Close(); } } //"打开残局"菜单的Click事件响应方法 private void MenuItemOpen_Click(object sender, EventArgs e) { //显示打开残局对话框 if (openFileDialog1.ShowDialog() == DialogResult.OK) { //创建一个文件流对象,用于读文件 FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read); //创建一个与文件流对象相对应的二进制读入流对象 BinaryReader br = new BinaryReader(fs); //读取当前的走棋方 _curPlayer = (Player)br.ReadInt32(); //逐一读取棋子值 for (int row = 1; row <= 10; row ) for (int col = 1; col <= 9; col ) _chess[row, col] = (Piece)br.ReadInt32(); //读取走棋步骤数 int count = br.ReadInt32(); //清空原有的走棋步骤 _stepList.Clear(); //逐一写入走棋步骤 for (int i = 0; i <= count - 1; i ) { //读取走棋步骤到List中 Step step = new Step(); step._Player = (Player)br.ReadInt32(); step._PickChess = (Piece)br.ReadInt32(); step._PickRow = br.ReadInt32(); step._PickCol = br.ReadInt32(); step._DropChess = (Piece)br.ReadInt32(); step._DropRow = br.ReadInt32(); step._DropCol = br.ReadInt32(); _stepList.Add(step); } //初始化拾起的棋子值为"无子" _pickChess = Piece.无子; //取出_stepList的最后一步走棋步骤到lastStep中 Step lastStep = _stepList[_stepList.Count - 1]; _pickRow = lastStep._PickRow; _pickCol = lastStep._PickCol; _dropRow = lastStep._DropRow; _dropCol = lastStep._DropCol; //关闭有关文件流对象 br.Close(); fs.Close(); //强制刷新窗口(注意:Invalidate()会触发窗口的Paint事件) Invalidate(); } } } }
标签: 中国象棋单机版
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论