Advertisement

c# - 中国象棋

阅读量:

c# - 作业4:中国象棋

    • 全局概览 & 无意义内容汇总区
        • 资源获取入口
      • 完整代码集合

        • 主界面代码.cs
        • 程序入口.cs
        • 国际象棋逻辑.cs
      • 当前存在的缺陷问题

总体视图 & 废话集结区

1

在记忆中,中国象棋的编写速度算是比较快的了,(毕竟会下象棋/挺有意思的哈哈哈哈

抢先一步,步步领先

我这是在说什么哈哈哈哈,确实挺有趣的

此外!!!重点强调!!!这次上传的版本是已经封装好的中国象棋//最初张老师教授的应该是未封装的中国象棋///不过之后应该有一节课专门讲解封装的内容,记得应该是和“我们一起来抓虫”那节课处于同一周

记错时间也是情有可原(因为当时我们班要上这节课的时候,张老师刚好出差了///之后也没有安排补课的打算///所以///记错时间也可以说是正常的?吧- - -

资源下载

c# - 作业4:中国象棋,点击下载

资源下载

代码(全)

FormMain.cs

复制代码
    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.IO;
    using System.Media;
    namespace MyChess
    {
    public partial class FormMain : Form
    {
    
        Chess chess = new Chess();
    
        //保存棋盘(细框)的左上角坐标
        private Point _leftTop = new Point(60, 60);
    
        //保存棋子半径
        private int _pieceR = 29;
    
        private int _dropRow = 0;
        private int _dropCol = 0;
    
    
        //保存当前所在点坐标
        private Point _curMousePoint = new Point(0, 0);
    
        private Color _markColor = Color.Yellow;
    
        //保存棋盘格子的行高和列数
        private int _rowHeight = 60;
        private int _colWidth = 60;
    
        private Bitmap _deskBmp = new Bitmap("desktop.jpg");//只装载一次,减少运行时间
    
        //保存红蓝双方14种棋子
        private Bitmap[] _pieceBmp = new Bitmap[15];
    
        //保存红方头像位图
        private Bitmap _redBmp = new Bitmap("红方头像.bmp");
    
        //保存蓝方头像位图
        private Bitmap _blueBmp = new Bitmap("蓝方头像.bmp");
    
    
        private void DrawBoard(Graphics g)
        {
            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));
    
            for (int row = 1; row <= 10; row++)
            {
                g.DrawLine(thinPen,new Point(_leftTop.X,_leftTop.Y+_rowHeight*(row-1)),
                                   new Point(_leftTop.X+8*_colWidth,_leftTop.Y+_rowHeight*(row-1)));
            }
    
            for (int col = 1; col <= 9; col++)
            {
                g.DrawLine(thinPen, new Point(_leftTop.X + (col - 1) * _colWidth, _leftTop.Y),
                                    new Point(_leftTop.X + (col - 1) * _colWidth, _leftTop.Y + _rowHeight * 4));
                g.DrawLine(thinPen, new Point(_leftTop.X + (col - 1) * _colWidth, _leftTop.Y + _rowHeight * 5),
                                    new Point(_leftTop.X + (col - 1) * _colWidth, _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 + 8 * _colWidth, _leftTop.Y + _rowHeight * 4),
                                new Point(_leftTop.X + 8 * _colWidth, _leftTop.Y + _rowHeight * 5));
            
            //上方九宫格交叉线
            g.DrawLine(thinPen,new Point(_leftTop.X + 3 * _colWidth,_leftTop.Y),
                               new Point(_leftTop.X + 5 * _colWidth,_leftTop.Y + 2 * _rowHeight));
            g.DrawLine(thinPen,new Point(_leftTop.X + 5 * _colWidth, _leftTop.Y),
                               new Point(_leftTop.X + 3 * _colWidth, _leftTop.Y + 2 * _rowHeight));
    
            g.DrawLine(thinPen,new Point(_leftTop.X + 3 * _colWidth, _leftTop.Y + 7 * _rowHeight),
                               new Point(_leftTop.X + 5 * _colWidth, _leftTop.Y + 9 * _rowHeight));
            g.DrawLine(thinPen,new Point(_leftTop.X + 5 * _colWidth, _leftTop.Y + 7 * _rowHeight),
                               new Point(_leftTop.X + 3 * _colWidth, _leftTop.Y + 9 * _rowHeight));
    
            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+8*_colWidth+95,_leftTop.Y+(int)(2.2*_rowHeight)));
            g.DrawString("红方",font3,brush,new Point(_leftTop.X+8*_colWidth+95,_leftTop.Y+(int)(6.4*_rowHeight)));
    
            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);
    
            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);
    
            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);
    
            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, chess._pickRow, chess._pickCol);
            //绘制落子位置的标记
            DrawPickDropMark(g, _dropRow, _dropCol);
    
            //在相应的位置绘制走棋方的头像
            if (chess._curPlayer == Player.蓝)
                g.DrawImage(_blueBmp, new Point(_leftTop.X + 8 * _colWidth + 95, _leftTop.Y + 1 * _rowHeight - 10));
            else if (chess._curPlayer == Player.红)
                g.DrawImage(_redBmp, new Point(_leftTop.X + 8 * _colWidth + 95, _leftTop.Y + 7 * _rowHeight + 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._chess[row, col] != Piece.无子)
                    {
                        //在棋盘交点绘制棋子
                        g.DrawImage(_pieceBmp[(int)chess._chess[row, col]], new Point(_leftTop.X + (col - 1) * _colWidth - _pieceR, _leftTop.Y + (row - 1) * _rowHeight - _pieceR));
                    }
                }
            }
    
            //在当前鼠标点位置绘制的棋子,以显示出拾起的棋子随鼠标而动的效果
            if (chess._pickChess != Piece.无子)
            {
                g.DrawImage(_pieceBmp[(int)chess._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 PlaySound(string wavFile)
        {
            //装载声音文件(需要添加System.Media命名空间)
            SoundPlayer soundPlay = new SoundPlayer(wavFile);
            //使用新线程播放声音
            soundPlay.Play();
            //注意:soundPlay.PlaySync()也可以播放声音,该方法使用用户界面(UI)线程播放,会导致用户界面的停顿
        }
    
        public FormMain()
        {
            InitializeComponent();
    
            //根据屏幕的分辨率设置棋盘格子的行高和列宽
            _rowHeight = Screen.PrimaryScreen.Bounds.Size.Height / 13;
            _colWidth = _rowHeight;
    
            //设置棋盘上左上角坐标
            _leftTop.X = _leftTop.Y;
            _leftTop.Y = _rowHeight * 2;
            
            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);
        }
    
        //自定义类方法:绘制拾子或落子位置的标记
        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);
            }
        }
    
        private void FormMain_Load(object sender, EventArgs e)
        {
    
        }
    
        private void FormMain_Paint(object sender, PaintEventArgs e)
        {
            DrawBoard(e.Graphics);
    
            DrawPiece(e.Graphics);
        }
    
        private void MenuItemBegin_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("你是否需要开局?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                //红方先走
                chess.Begin(Player.红);
    
                _dropRow = 0;
                _dropCol = 0;
    
                //使窗口失效,并发送paint消息,从而触发paint事件相应方法重绘棋盘和棋子
                Invalidate();
    
                PlaySound("Sounds\ begin.wav");
            }
        }
    
        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 (chess._curOperation == Operation.拾子)
                    {
                        if (chess.PickChess(row, col) == true)
                            chess._chess[row, col] = Piece.无子;
                    }
                    else if (chess._curOperation == Operation.落子)
                    {
    
                        if (chess.DropChess(row, col) == true )
                        {
                            if (chess.IsOver() != Player.无)
                            {
                                MessageBox.Show(chess.IsOver() + "赢了", "提示");
                            }
    
                            _dropRow = row;
                            _dropCol = col;
                        }
                    }
                    Invalidate();
                }
            }
            else if (e.Button == MouseButtons.Right)
            { 
                if (chess.UndoPickChess() == true)
                {
                    chess._chess[chess._pickRow, chess._pickCol] = chess._pickChess;
                    chess._pickRow = 0;
                    chess._pickCol = 0;
                    chess._pickChess = Piece.无子;
                }
                //强制刷新窗口
                Invalidate();
                
            }
        }
    
        private void FormMain_MouseMove(object sender, MouseEventArgs e)
        {
            //保存当前鼠标所在点的坐标
            _curMousePoint = e.Location;
            
            //判断是否已经拾起棋子,以决定是否需要强制刷新窗口
            if (chess._pickChess != Piece.无子)
            {
                Invalidate();
            }
        }
    
        private void MenuItemUndo_Click(object sender, EventArgs e)
        {
            chess.UndoLastStep();
        }
    
        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);
    
                chess.WriteTo(bw);
    
                //关闭有关文件流对象
                bw.Close();
                fs.Close();
            }
        }
    
        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);
    
                chess.ReadFrom(br);
    
                //关闭有关文件流对象
                br.Close();
                fs.Close();
    
                //强制刷新窗口(触发Paint事件)
                Invalidate();
            }
        }
    }
    }

Program.cs

复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace MyChess
    {
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new FormMain());
        }
    }
    }

Chess.cs代码实现

复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    
    namespace MyChess
    {
    //棋子枚举类型
    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 enum Operation
    {
        拾子, 落子
    }
    
    public class Step
    {
        public Player _player;
        public Piece _pickChess;
        public int _pickRow;
        public int _pickCol;
        public Piece _dropChess;
        public int _dropRow;
        public int _dropCol;
    
    }
    
    class Chess
    {
        //保存象棋棋盘所有棋子值
        public Piece[,] _chess = new Piece[11, 10];
    
        //保存当前的走棋方
        public Player _curPlayer = Player.无;
    
        //保存当前走棋操作
        public Operation _curOperation = Operation.拾子;
    
        //保存拾起的棋子
        public Piece _pickChess = Piece.无子;
        //保存拾起棋子的行号和列号
        public int _pickRow = 0;
        public int _pickCol = 0;
    
    
    
        //保存所有的走棋步骤
        public List<Step> _stepList = new List<Step>();
    
        public Step _lastStep
        {
            get
            {
                int stepCount = _stepList.Count;
                if (stepCount > 0)
                    return _stepList[stepCount - 1];
                else
                    return null;
            }
        }
    
        //构造方法
        public Chess()
        {
            //调用象棋初始化方法
            Initialize();
        }
    
        //初始化方法
        public void Initialize()
        {
            //初始化当前的走棋方
            _curPlayer = Player.无;
            //初始化当前的走棋操作
            _curOperation = Operation.拾子;
    
            //保存拾起的棋子
            _pickChess = Piece.无子;
            //保存拾起棋子的行号和列号
            _pickRow = 0;
            _pickCol = 0;
    
            //清空list表中的走棋步骤
            _stepList.Clear();
    
            //把棋盘上棋子值都设为无子
            for (int i = 1; i <= 10; i++)
                for (int j = 1; j <= 9; j++)
                {
                    _chess[i, j] = Piece.无子;
                }
        }
    
        //类方法,象棋开局
        public void Begin(Player firstPlayer)
        {
            //象棋初始化
            Initialize();
    
            //初始化当前走棋方
            _curPlayer = firstPlayer;
    
            //初始化蓝方棋子
            _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.红卒;
        }
    
        //类方法,拾起棋子
        public bool PickChess(int pickRow, int pickCol)
        {
            //如果当前走棋方不为无且走棋操作为拾子且拾起的是走棋方的棋子
            if (_curPlayer != Player.无 && _curOperation == Operation.拾子 &&
                _chess[pickRow, pickCol].ToString().IndexOf(_curPlayer.ToString()) == 0)
            {
                //保存拾起的棋子值,行号和列号
                _pickChess = _chess[pickRow, pickCol];
                //保存拾子位置的行号和列号
                _pickRow = pickRow;
                _pickCol = pickCol;
    
                //切换走棋操作为落子
                _curOperation = Operation.落子;
                return true;
            }
            else
                return false;
    
        }
    
        //类方法,落下棋子(true代表落子成功,false代表落子失败)
        public bool DropChess(int dropRow, int dropCol)
        {
            //如果当前走棋方不为无且走棋操作为落子且规则验证成功
            if (_curPlayer != Player.无 && _curOperation == Operation.落子 &&
                MatchRules(_curPlayer, _pickRow, _pickCol, dropRow, dropCol) == true)
            {
    
                //保存走棋步骤到_stepList中
                Step tempStep = new Step();
                tempStep._player = _curPlayer;
                tempStep._pickChess = _pickChess;
                tempStep._pickRow = _pickRow;
                tempStep._pickCol = _pickCol;
                tempStep._dropChess = _chess[dropRow, dropCol];
                tempStep._dropRow = dropRow;
                tempStep._dropCol = dropCol;
                _stepList.Add(tempStep);
    
                //落子位置设置为拾起位置的值
                _chess[dropRow, dropCol] = _pickChess;
    
                //清空拾子位置的棋子值
                _chess[_pickRow, _pickCol] = Piece.无子;
    
                //初始化拾起的棋子
                _pickChess = Piece.无子;
                //初始化拾起棋子的行号和列号
                _pickRow = 0;
                _pickCol = 0;
    
    
                //切换走棋步骤为拾子
                _curOperation = Operation.拾子;
    
                //切换走棋方
                if (_curPlayer == Player.红)
                    _curPlayer = Player.蓝;
                else if (_curPlayer == Player.蓝)
                    _curPlayer = Player.红;
                return true;
    
            }
            else
                return false;
        }
    
        public bool UndoPickChess()
        {
            //如果当前走棋方不为无且已经拾起了棋子(即当前为落子)
            if (_curPlayer != Player.无 && _curOperation == Operation.落子)
            {
                _curOperation = Operation.拾子;
                return true;
            }
            else
                return false;
        }
    
        //悔棋(true代表成功,false代表失败)
        public bool UndoLastStep()
        {
            //获取走棋步骤数
            int stepCount = _stepList.Count;
            //判断是否存在走棋步骤
            if (stepCount > 0)
            {
                //取出最后一部走棋信息
                Player player = _stepList[_stepList.Count - 1]._player;
                Piece pickChess = _stepList[_stepList.Count - 1]._pickChess;
                int pickRow = _stepList[_stepList.Count - 1]._pickRow;
                int pickCol = _stepList[_stepList.Count - 1]._pickCol;
                Piece dropChess = _stepList[_stepList.Count - 1]._dropChess;
                int dropRow = _stepList[_stepList.Count - 1]._dropRow;
                int dropCol = _stepList[_stepList.Count - 1]._dropCol;
    
                //删除最后一部走棋步骤
                _stepList.RemoveAt(_stepList.Count - 1);
    
                //还原走棋步骤
                _chess[pickRow, pickCol] = pickChess;
                _chess[dropRow, dropCol] = dropChess;
    
                //初始化走棋操作为拾子
                _curOperation = Operation.拾子;
                //初始化拾起的棋子
                _pickChess = Piece.无子;
                //初始化拾起棋子的行号和列号
                _pickRow = 0;
                _pickCol = 0;
    
                //设置当前的走棋方
                _curPlayer = player;
    
                return true;
            }
            else
                return false;
        }
    
        //类方法判断象棋是否结束并返回获胜方
        public Player IsOver()
        {
            //获取走棋步骤数
            int stepCount = _stepList.Count;
            //判断是否存在走棋步骤
            if (stepCount > 0)
            {
                //获取最后一步走棋步骤中落下或被吃的棋子
                Piece dropChess = _stepList[stepCount - 1]._dropChess;
                //判断落下棋子(被吃)棋子是否为帅
                if (dropChess == Piece.蓝将)
                {
                    //禁止继续下棋
                    _curPlayer = Player.无;
                    //返回获胜方
                    return Player.红;
                }
                else if (dropChess == Piece.红帅)
                {
                    //禁止继续下棋
                    _curPlayer = Player.无;
                    //返回获胜方
                    return Player.蓝;
                }
                else
                    return Player.无;
            }
            else
                return Player.无;
        }
    
        //类方法:匹配走棋规则(true代表成功,false代表失败)
        public bool MatchRules(Player player, int pickRow, int pickCol, int dropRow, int dropCol)
        {
            //定义一个匹配标志
            bool matchFlag = false;
    
            //如果走棋方不为无且拾起的是走棋方棋子且落子位置为无子或走棋方棋子
            if ( player != Player.无 
                && !(pickCol == dropCol && pickRow == dropRow)
                && _pickChess.ToString().Substring(0, 1) == player.ToString()
                && (_chess[dropRow, dropCol] == Piece.无子 
                    || _chess[dropRow, dropCol].ToString().Substring(0, 1) != player.ToString()))
            {
                //匹配车的走棋规则
                if (_pickChess == Piece.蓝车 || _pickChess == Piece.红车)
                {
                    //需要用到的局部变量申明
                    bool blankFlag = false;
                    int max, min;
                    //如果横冲
                    if (pickRow == dropRow)
                    {
                        //比较起点列和落点列的大小
                        max = dropCol > pickCol ? dropCol : pickCol;
                        min = dropCol > pickCol ? pickCol : dropCol;
    
                        //判断移动路径上棋子的是否全为无子
                        blankFlag = true;
                        for (int i = min + 1; i <= max - 1; i++)
                        {
                            if (_chess[dropRow, i] != Piece.无子)
                                blankFlag = false;
                        }
                        if (blankFlag == true)
                            matchFlag = true;
                    }
                    //如果直撞
                    if (pickCol == dropCol)
                    {
                        //比较起点列和落点列的大小
                        max = dropRow > pickRow ? dropRow : pickRow;
                        min = dropRow > pickRow ? pickRow : dropRow;
    
                        //判断移动路径上棋子的是否全为无子
                        blankFlag = true;
                        for (int i = min + 1; i <= max - 1; i++)
                        {
                            if (_chess[i, dropCol] != Piece.无子)
                                blankFlag = false;
                        }
                        if (blankFlag == true)
                            matchFlag = true;
                    }
                }
    
                //匹配马的走棋规则
                if (_pickChess == Piece.蓝马 || _pickChess == Piece.红马)
                {
                    //如果横着走日字且不拌马脚
                    if (Math.Abs(pickRow - dropRow) == 1 && Math.Abs(pickCol - dropCol) == 2 &&
                        _chess[pickRow, (pickCol + dropCol) / 2] == Piece.无子)
                        matchFlag = true;
    
                    //如果竖着走日字且不拌马脚
                    if (Math.Abs(pickRow - dropRow) == 2 && Math.Abs(pickCol - dropCol) == 1 &&
                        _chess[(pickRow + dropRow) / 2, pickCol] == Piece.无子)
                        matchFlag = true;
                }
    
                //匹配象的走棋规则
                if (_pickChess == Piece.蓝象)
                {
                    //走田字,不拌象脚
                    if (Math.Abs(pickRow - dropRow) == 2 && Math.Abs(pickCol - dropCol) == 2
                        && _chess[(pickRow + dropRow) / 2, (pickCol + dropCol) / 2] == Piece.无子 && dropRow <= 5)
                        matchFlag = true;
                }
                if (_pickChess == Piece.红相)
                {
                    //走田字,不拌象脚
                    if (Math.Abs(pickRow - dropRow) == 2 && Math.Abs(pickCol - dropCol) == 2
                        && _chess[(pickRow + dropRow) / 2, (pickCol + dropCol) / 2] == Piece.无子 && dropRow >= 6)
                        matchFlag = true;
                }
    
                //匹配士的走棋规则
                if (_pickChess == Piece.蓝士)
                {
                    if (Math.Abs(pickRow - dropRow) == 1 && Math.Abs(pickCol - dropCol) == 1 && dropRow <= 3 && dropRow >= 1 && dropCol <= 6 && dropCol >= 4)
                        matchFlag = true;
                }
                if (_pickChess == Piece.红士)
                {
                    if (Math.Abs(pickRow - dropRow) == 1 && Math.Abs(pickCol - dropCol) == 1 && dropRow <= 10 && dropRow >= 8 && dropCol <= 6 && dropCol >= 4)
                        matchFlag = true;
                }
    
                //匹配红帅的走棋规则
                if (_pickChess == Piece.红帅)
                {
                    //如果在九宫格内移动
                    if (((Math.Abs(pickRow - dropRow) == 1 && pickCol == dropCol) || (Math.Abs(pickCol - dropCol) == 1 && pickRow == dropRow)) && dropRow >= 8 && dropRow <= 10 && dropCol >= 4 && dropCol <= 6)
                    {
                        matchFlag = true;
                    }
                    //如果两帅想面对面火拼
                    if (_chess[dropRow, dropCol] == Piece.蓝将)
                    {
                        //判断两帅是否在同一列上
                        if (pickCol == dropCol)
                        {
                            bool blankFlag = true;
                            //检查两帅之间是否存在棋子
                            for (int i = dropRow + 1; i <= pickRow - 1; i++)
                            {
                                if (_chess[i, pickCol] != Piece.无子)
                                {
                                    blankFlag = false;
                                    break;
                                }
                            }
                            if (blankFlag == true)
                                matchFlag = true;
                        }
                    }
                }
                //匹配蓝将的走棋规则
                if (_pickChess == Piece.蓝将)
                {
                    //如果在九宫格内移动
                    if (((Math.Abs(pickRow - dropRow) == 1 && pickCol == dropCol) || (Math.Abs(pickCol - dropCol) == 1 && pickRow == dropRow)) && dropRow >= 1 && dropRow <= 3 && dropCol >= 4 && dropCol <= 6)
                    {
                        matchFlag = true;
                    }
                    //如果两帅想面对面火拼
                    if (_chess[dropRow, dropCol] == Piece.红帅)
                    {
                        //判断两帅是否在同一列上
                        if (pickCol == dropCol)
                        {
                            bool blankFlag = true;
                            //检查两帅之间是否存在棋子
                            for (int i = pickRow + 1; i <= dropRow - 1; i++)
                            {
                                if (_chess[i, pickCol] != Piece.无子)
                                {
                                    blankFlag = false;
                                    break;
                                }
                            }
                            if (blankFlag == true)
                                matchFlag = true;
                        }
                    }
                }
    
                //匹配炮的走棋规则
                if (_pickChess == Piece.红炮 || _pickChess == Piece.蓝炮)
                {
                    //需要用到的局部变量申明
                    bool blankFlag = false;
                    int max, min;
                    //如果落点存在棋子时
                    if (_chess[dropRow, dropCol] != Piece.无子)
                    {
                        //如果横着走
                        if (pickRow == dropRow)
                        {
                            //比较起点列和落点列的大小
                            max = dropCol > pickCol ? dropCol : pickCol;
                            min = dropCol < pickCol ? dropCol : pickCol;
    
                            //统计移动路径上棋子的数量
                            int chessNum = 0;
                            for (int i = min + 1; i <= max - 1; i++)
                            {
                                if (_chess[dropRow, i] != Piece.无子)
                                    chessNum++;
                            }
                            if (chessNum == 1)
                                matchFlag = true;
                        }
                        //如果竖着走
                        if (pickCol == dropCol)
                        {
                            //比较起点列和落点列的大小
                            max = dropRow > pickRow ? dropRow : pickRow;
                            min = dropRow < pickRow ? dropRow : pickRow;
    
                            //统计移动路径上棋子的数量
                            int chessNum = 0;
                            for (int i = min + 1; i <= max - 1; i++)
                            {
                                if (_chess[i, dropCol] != Piece.无子)
                                    chessNum++;
                            }
                            if (chessNum == 1)
                                matchFlag = true;
                        }
                    }
                    //如果落点不存在棋子时
                    if (_chess[dropRow, dropCol] == Piece.无子)
                    {
                        //如果横着走
                        if (pickRow == dropRow)
                        {
                            //比较起点列和落点列的大小
                            max = dropCol > pickCol ? dropCol : pickCol;
                            min = dropCol < pickCol ? dropCol : pickCol;
    
                            blankFlag = true;
                            //检查两帅之间是否存在棋子
                            for (int i = min + 1; i <= max - 1; i++)
                            {
                                if (_chess[dropRow, i] != Piece.无子)
                                {
                                    blankFlag = false;
                                }
                            }
                            if (blankFlag == true)
                                matchFlag = true;
                        }
                        //如果竖着走
                        if (pickCol == dropCol)
                        {
                            //比较起点列和落点列的大小
                            max = dropRow > pickRow ? dropRow : pickRow;
                            min = dropRow < pickRow ? dropRow : pickRow;
    
                            blankFlag = true;
                            //检查两帅之间是否存在棋子
                            for (int i = min + 1; i <= max - 1; i++)
                            {
                                if (_chess[i, dropCol] != Piece.无子)
                                {
                                    blankFlag = false;
                                }
                            }
                            if (blankFlag == true)
                                matchFlag = true;
                        }
                    }
                }
    
                //匹配兵的走棋规则
                if (_pickChess == Piece.蓝兵)
                {
                    //不过河
                    if (pickRow <= 5)
                    {
                        if ((dropRow - pickRow) == 1 && (dropCol == pickCol))
                            matchFlag = true;
                    }
                    //过河
                    if (pickRow >= 6)
                    {
                        //如果横着走
                        if (dropRow == pickRow && Math.Abs(dropCol - pickCol) == 1)
                            matchFlag = true;
                        //如果竖着走
                        if (dropCol == pickCol && (dropRow - pickRow) == 1)
                            matchFlag = true;
                    }
                }
                if (_pickChess == Piece.红卒)
                {
                    //不过河
                    if (pickRow >= 6)
                    {
                        if ((dropRow - pickRow) == -1 && (dropCol == pickCol))
                            matchFlag = true;
                    }
                    //过河
                    if (pickRow <= 5)
                    {
                        //如果横着走
                        if (dropRow == pickRow && Math.Abs(dropCol - pickCol) == 1)
                            matchFlag = true;
                        //如果竖着走
                        if (dropCol == pickCol && (dropRow - pickRow) == -1)
                            matchFlag = true;
                    }
                }
            }
            return matchFlag;
        }
    
    
        //保存残局
        public void WriteTo(BinaryWriter binaryWriter)
        {
            //保存当前的走棋方
            binaryWriter.Write(_curPlayer.ToString());
    
            //逐一保存棋盘上的棋子值
            for (int row = 1; row <= 10; row++)
            {
                for (int col = 1; col <= 9; col++)
                    binaryWriter.Write(_chess[row, col].ToString());
            }
    
            //保存走棋步骤的数量
            binaryWriter.Write(_stepList.Count);
            //逐一保存走棋步骤详细信息
            for (int i = 0; i <= _stepList.Count - 1; i++)
            {
                binaryWriter.Write(_stepList[i]._player.ToString());
                binaryWriter.Write(_stepList[i]._pickChess.ToString());
                binaryWriter.Write(_stepList[i]._pickRow);
                binaryWriter.Write(_stepList[i]._pickCol);
                binaryWriter.Write(_stepList[i]._dropChess.ToString());
                binaryWriter.Write(_stepList[i]._dropRow);
                binaryWriter.Write(_stepList[i]._dropCol);
            }
        }
        //读取残局
        public void ReadFrom(BinaryReader binaryReader)
        {
            //象棋初始化
            Initialize();
    
            //读取当前走棋方
            _curPlayer = (Player)Enum.Parse(typeof(Player), binaryReader.ReadString());
    
            //逐一读取棋盘上棋子
            for (int row = 1; row <= 10; row++)
                for (int col = 1; col <= 9; col++)
                    _chess[row, col] = (Piece)Enum.Parse(typeof(Piece), binaryReader.ReadString());
    
            //读取走棋步骤数
            int stepCount = binaryReader.ReadInt32();
            //逐一读取走棋步骤详细信息
            for (int i = 0; i <= stepCount - 1; i++)
            {
                Step step = new Step();
                step._player = (Player)Enum.Parse(typeof(Player), binaryReader.ReadString());
                step._pickChess = (Piece)Enum.Parse(typeof(Piece), binaryReader.ReadString());
                step._pickRow = binaryReader.ReadInt32();
                step._pickCol = binaryReader.ReadInt32();
                step._dropChess = (Piece)Enum.Parse(typeof(Piece), binaryReader.ReadString());
                step._dropRow = binaryReader.ReadInt32();
                step._dropCol = binaryReader.ReadInt32();
    
                //添加走棋步骤到列表
                _stepList.Add(step);
            }
            //设置当前走棋操作
            _curOperation = Operation.拾子;
    
            //初始化
            _pickChess = Piece.无子;
            _pickRow = _pickCol = 0;
        }
    
    }
    }

现存bug

是否存在尚未修复的漏洞尚不确定,尽管此前已进行过修改,但仍有遗漏的可能性。至少在提交作业之前,本人并未察觉到相关问题。

全部评论 (0)

还没有任何评论哟~