棋盘游戏 - 四路爬

小时候经常玩的游戏,和小伙伴在地上画个4X4的棋盘就可以开搞,不知道你们有没有听说过玩过。

工作闲暇之余,用C#写了一个四路爬小游戏,怀恋下当年的感觉。

游戏规则:在4X4的棋盘,每人共4颗棋子,沿横向或纵向每次走一格,当双方棋子在相邻格时,则一家棋子跳过该子落在另一格种, 当双方棋子在相邻格时,则一家棋子跳过该子落在另一格中,则对家该子被吃掉(就相当于从该棋子头上跳过去,则该子就被吃掉),直到吃掉全部棋子则胜利。

直接上代码

//Program.cs
class Program
    {
        static  void Main(string[] args)
        {
            Console.WriteLine("    *************************************************************");
            Console.WriteLine("    *                             四路爬                        *");
            Console.WriteLine("    *                      Copyright 2021 凌风游                *");
            Console.WriteLine("    *     https://gitee.com/lkj1420428992/four-way-climbing     *");
            Console.WriteLine("    *************************************************************");
            Console.WriteLine();
            Console.WriteLine("    在4X4的棋盘,每人共4颗棋子,沿横向或纵向每次走一格,");
            Console.WriteLine("    当双方棋子在相邻格时,则一家棋子跳过该子落在另一格种,");
            Console.WriteLine("    则对家该子被吃掉(就相当于从该棋子头上跳过去,则该子就背吃掉)。 ");
            Console.WriteLine("    直到吃掉全部棋子则胜利。");
            Console.WriteLine("    ");
            Console.WriteLine("    玩法:exit:退出,  光标处输入: 1,1(对应棋子的坐标),然后按上下左右键,分别对应相应的移动。");
            Console.WriteLine("   ");
            Console.WriteLine("   ");
            Console.WriteLine("   ");
            Console.WriteLine("   ");

            bool isExit = false;
            FwcPlay fwc = new FwcPlay();
            fwc.Init();
            fwc.ShowChessBorad();
            string msg = string.Empty;
            while (!isExit) {
                var key = Console.ReadKey();

                switch (key.Key) {
                    case ConsoleKey.Enter:
                        if (msg =="exit") {
                            isExit = true;
                        }
                        break;
                    case ConsoleKey.UpArrow:
                        fwc.PlayChess(msg,Chess.Dir.TOP);
                        msg = string.Empty;
                        break;
                    case ConsoleKey.DownArrow:
                        fwc.PlayChess(msg, Chess.Dir.BOTTOM);
                        msg = string.Empty;
                        break;
                    case ConsoleKey.LeftArrow:
                        fwc.PlayChess(msg, Chess.Dir.LEFT);
                        msg = string.Empty;
                        break;
                    case ConsoleKey.RightArrow:
                        fwc.PlayChess(msg, Chess.Dir.RIGHT);
                        msg = string.Empty;
                        break;
                    default:
                        msg += key.KeyChar;
                        break;
                }
            }
        }
    }
    //FwcPlay.cs
    /// <summary>
    /// 四路爬控制器
    /// </summary>
    public class FwcPlay
    {
        private ChessBoard _chessBoard = null;
        private Referee _referee = null;
        private const int bannerTop = 15;
        private const int boardTop = 12;

        public void ShowChessBorad(){
            Console.SetCursorPosition(0, 0+ bannerTop);
            Console.WriteLine(_chessBoard.Render());
            Console.WriteLine("                                                                                     ");
            Console.WriteLine("                                                                                     ");
            Console.WriteLine("                                                                                     ");
            Console.WriteLine("                                                                                     ");
            Console.WriteLine("                                                                                     ");
            Console.WriteLine("                                                                                     ");
            Console.WriteLine("                                                                                     ");
            Console.WriteLine("                                                                                     ");
            Console.WriteLine("                                                                                     ");
            Console.SetCursorPosition(0, boardTop + bannerTop);
            Console.Write($"执[{_referee.CurrentPlayer.Tag}]棋子,请{_referee.CurrentPlayer.Name}落子:");                    
        }

        public void Init() {
            var player1 = new RealPlayer("小明");
            player1.InitChessPieces("O", true);
            var player2 = new RealPlayer("小王");
            player2.InitChessPieces("X", false);

            _chessBoard = new ChessBoard();
            _chessBoard.Init(player1.GetChessPieces(), player2.GetChessPieces());
            _referee = new Referee(_chessBoard, player1, player2);

            ShowChessBorad();
        }

        public void PlayChess(string posStr,Dir dir) {
            string pattern = "^[1-4]{1},[1-4]{1}$";
            if (!System.Text.RegularExpressions.Regex.IsMatch(posStr, pattern)) {
                ErrorInfo("请输入正确的棋子坐标");
                return;
            }
            string[] posArr = posStr.Trim().Split(",");
            var res = _referee.MoveChessPiece(Int32.Parse(posArr[0])-1, Int32.Parse(posArr[1]) - 1, dir);
            if (!res) {
                ErrorInfo("此处无棋子,或棋子移动违规");
                return;
            }
            ShowChessBorad();

            var winPlayer = _referee.GetWinner();
            if (winPlayer != null) {
                ErrorInfo($"{winPlayer.Name}获得本局胜利");
            }
        }

        public void ErrorInfo(string msg) {
            Console.SetCursorPosition(0, boardTop -1 + bannerTop);
            Console.WriteLine("                                                                                     ");
            Console.SetCursorPosition(0, boardTop -1 + bannerTop);
            Console.WriteLine(msg);
            Console.SetCursorPosition(22, boardTop + bannerTop);
            Console.Write("                                            ");
            Console.SetCursorPosition(22, boardTop + bannerTop);
        }
    }
    //ChessPiece.cs
    /// <summary>
    /// 棋子
    /// </summary>
    public class ChessPiece
    {
        private int _row = -1;  //棋子在棋盘行坐标 0-3  其他值为无效棋子
        private int _col = -1;  //棋子在棋盘的列坐标 0-3  其他值为无效棋子
        private string _tag = ""; //棋子标记

        public ChessPiece(int row,int col,string tag) {
            this._row = row;
            this._col = col;
            this._tag = tag;
        }

        public string Tag
        {
            get { return _tag; }
            set { _tag = value; }  
        }

        /// <summary>
        /// 获取在棋盘的坐标位置
        /// </summary>
        public (int row, int col) GetPosition() {
            return (_row,_col);        
        }

        /// <summary>
        /// 判断该坐标位置是否是自己
        /// </summary>
        public Boolean IsMine(int row,int col) {
            return row == _row && col == _col;
        }

        /// <summary>
        /// 移动位置
        /// </summary>
        public void Move(int row,int col) {
            this._row = row;
            this._col = col;
        }

        /// <summary>
        /// 棋子被吃掉
        /// </summary>
        public void Dead() {
            this._row = -1;
            this._col = -1;
        }

        /// <summary>
        /// 判断棋子是否被吃掉
        /// </summary>
        public Boolean IsDead
        {
            get { return _row <0 || _col <0; }          
        }
    }
    //ChessBoard.cs
    /// <summary>
    /// 棋盘
    /// </summary>
    public class ChessBoard
    {
        private int[] _positions = new int[16];  //棋盘所有坐标位置
        private List<ChessPiece> _player1ChessPieces = null;  //选手1的棋子
        private List<ChessPiece> _player2ChessPieces = null;  //选手2的棋子

        public ChessBoard() { 
        
        }

        /// <summary>
        /// 初始化棋盘
        /// </summary>
        public void Init(List<ChessPiece> player1ChessPieces, List<ChessPiece> player2ChessPieces) 
        {
            this._player1ChessPieces = player1ChessPieces;
            this._player2ChessPieces = player2ChessPieces;
        }

        /// <summary>
        /// 将选手的棋子摆到棋盘中
        /// </summary>
        private void SetBoard() 
        {
            for (int i=0;i<_positions.Length;i++) {
                _positions[i] = 0;
            }

            _player1ChessPieces.ForEach(item=> {
                if (!item.IsDead) {
                    var pos = item.GetPosition();
                    _positions[PositionsIndex(pos.row, pos.col)] = 1;
                }
            });

            _player2ChessPieces.ForEach(item=> {
                if (!item.IsDead)
                {
                    var pos = item.GetPosition();
                    _positions[PositionsIndex(pos.row, pos.col)] = -1;
                }
            });
        }

        /// <summary>
        /// 棋盘坐标和真是数据位置的转换
        /// </summary>
        private int PositionsIndex(int row,int col) {
            return (row * 4) + col;
        }

        /// <summary>
        /// 获取棋盘棋子的标记,没有棋子就是默认棋盘标记
        /// </summary>
        private string GetChessPieceTag(int row, int col)
        {
            int chessPieces = _positions[PositionsIndex(row,col)];
            string res = string.Empty;
            switch (chessPieces)
            {
                case 0:
                    res = "+";
                    break;
                case 1:
                    res = _player1ChessPieces[0].Tag;
                    break;
                case -1:
                    res = _player2ChessPieces[0].Tag;
                    break;
            }
            return res;
        }

        /// <summary>
        /// 获取棋盘数据
        /// </summary>
        public int[] GetBoard() {
            SetBoard();
            return _positions;
        }

        /// <summary>
        /// 渲染棋盘
        /// </summary>
        public string Render() {
            SetBoard();
            StringBuilder sb = new StringBuilder();
            sb.Append("       1    2    3    4    \n");
            sb.Append($"     1 { GetChessPieceTag(0, 0)}----{GetChessPieceTag(0, 1)}----{GetChessPieceTag(0, 2)}----{GetChessPieceTag(0, 3)} 1");
            sb.Append("\n");
            sb.Append("       |    |    |    |  ");
            sb.Append("\n");
            sb.Append($"     2 { GetChessPieceTag(1, 0)}----{GetChessPieceTag(1, 1)}----{GetChessPieceTag(1, 2)}----{GetChessPieceTag(1, 3)} 2");
            sb.Append("\n");
            sb.Append("       |    |    |    |  ");
            sb.Append("\n");
            sb.Append($"     3 { GetChessPieceTag(2, 0)}----{GetChessPieceTag(2, 1)}----{GetChessPieceTag(2, 2)}----{GetChessPieceTag(2, 3)} 3");
            sb.Append("\n");
            sb.Append("       |    |    |    |  ");
            sb.Append("\n");
            sb.Append($"     4 { GetChessPieceTag(3, 0)}----{GetChessPieceTag(3, 1)}----{GetChessPieceTag(3, 2)}----{GetChessPieceTag(3, 3)} 4");
            sb.Append("\n");
            sb.Append("       1    2    3    4    \n");            
            return sb.ToString();
        }

        /// <summary>
        /// 判断棋位是否合法
        /// </summary>
        public Boolean CheckPositionVaild(int row,int col) {
            return (0 <= row && row <= 3) && (0 <= col && col <= 3);
        }

        /// <summary>
        /// 判断棋位是否是空的 没有棋子
        /// </summary>
        public Boolean IsEmpty(int row,int col) {
            return _positions[PositionsIndex(row, col)] == 0;
        }

        /// <summary>
        /// 从棋盘移除棋子
        /// </summary>
        public void RemoveChessPiece(int row,int col) {
            var cp = _player1ChessPieces.FirstOrDefault(x => x.IsMine(row, col));
            if (cp == null) cp = _player2ChessPieces.FirstOrDefault(x => x.IsMine(row, col));
            if (cp != null) cp.Dead();
        }
    }
    //Player.cs
    /// <summary>
    /// 选手
    /// </summary>
    public abstract class Player
    {
        protected string _name;
        protected string _tag;

        protected List<ChessPiece> _chessPieces;  //选手的棋子

        public ChessPiece GetChessPiece(int row,int col) {
            return _chessPieces?.FirstOrDefault(x => x.IsMine(row, col));
        }

        public List<ChessPiece> GetChessPieces() {
            return _chessPieces;
        }

        /// <summary>
        /// 选手名称
        /// </summary>
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        /// <summary>
        /// 棋子标记
        /// </summary>
        public string Tag
        {
            get { return _tag; }          
        }

        /// <summary>
        /// 初始化自己的棋子
        /// </summary>
        public void InitChessPieces(string tag,Boolean isFirstPalyer) {
            this._tag = tag;
            _chessPieces = new List<ChessPiece>();

            if (isFirstPalyer)
            {
                _chessPieces.Add(new ChessPiece(3, 0, tag));
                _chessPieces.Add(new ChessPiece(3, 1, tag));
                _chessPieces.Add(new ChessPiece(3, 2, tag));
                _chessPieces.Add(new ChessPiece(3, 3, tag));
            }
            else {
                _chessPieces.Add(new ChessPiece(0, 0, tag));
                _chessPieces.Add(new ChessPiece(0, 1, tag));
                _chessPieces.Add(new ChessPiece(0, 2, tag));
                _chessPieces.Add(new ChessPiece(0, 3, tag));
            }
        }

        /// <summary>
        /// 是否输掉
        /// </summary>
        public Boolean IsLost
        {
            get { return !_chessPieces.Exists(x => !x.IsDead); }
        }
    }
    //RealPlayer.cs
    /// <summary>
    /// 真人选手
    /// </summary>
    public class RealPlayer:Player
    {
        public RealPlayer(string name)
        {
            this._name = name;
        }


        
    }


    //AIPlayer.cs
    /// <summary>
    /// AI选手
    /// </summary>
    public class AIPlayer:Player
    {
        public AIPlayer(string name) {
            this._name = name;
        }
    }
    //Referee.cs
    /// <summary>
    /// 裁判
    /// </summary>
    public class Referee
    {
        private ChessBoard _chessBoard;
        private Player _player1;
        private Player _player2;
        private Player _currentPlayer;

        public Referee(ChessBoard chessBoard, Player player1, Player player2) {
            this._chessBoard = chessBoard;
            this._player1 = player1;
            this._player2 = player2;
            this._currentPlayer = player1;
        }

        /// <summary>
        /// 轮到对方选手执棋
        /// </summary>
        private void NextPlayer() {
            if (ReferenceEquals(_currentPlayer, _player1))
            {
                _currentPlayer = _player2;
            }
            else {
                _currentPlayer = _player1;
            }   
        }

        /// <summary>
        /// 当前执棋选手
        /// </summary>
        public Player CurrentPlayer
        {
            get { return _currentPlayer; }
        }

        /// <summary>
        /// 移动棋子
        /// </summary>
        public Boolean MoveChessPiece(int row,int col,Dir dir) {
            var chessPiece = _currentPlayer.GetChessPiece(row,col);
            if (chessPiece == null) return false;
            return MoveChessPiece(chessPiece,dir);
        }

        /// <summary>
        /// 移动棋子
        /// </summary>
        public Boolean MoveChessPiece(ChessPiece chessPiece, Dir dir)
        {
            var rule = new MoveChessPieceRule(_chessBoard, _currentPlayer, chessPiece, dir);
            if (rule.Execute()) {
                NextPlayer();
                return true;
            }
            return false;
        }

        /// <summary>
        /// 判断选手输赢
        /// </summary>
        public Player GetWinner() {
            var rule1 = new LostRule(_player1);
            if (rule1.Execute()) return _player2;
            var rule2 = new LostRule(_player2);
            if (rule2.Execute()) return _player1;
            return null;
        }
    }

    /// <summary>
    /// 方向枚举
    /// </summary>
    public enum Dir
    {
        LEFT = 1,
        RIGHT = 2,
        TOP = 3,
        BOTTOM = 4,
    }
    //IRule.cs
    /// <summary>
    /// 规则
    /// </summary>
    public interface IRule
    {
        /// <summary>
        /// 规则执行体
        /// </summary>
        bool Execute();
    }


    //MoveChessPieceRule.cs
    /// <summary>
    /// 移动棋子规则
    /// </summary>
    public class MoveChessPieceRule : IRule
    {
        private ChessBoard _chessBoard;
        private Player _player;
        private ChessPiece _chessPiece;
        private Dir _dir;

        public MoveChessPieceRule(ChessBoard chessBoard, Player player, ChessPiece chessPiece, Dir dir) {
            this._chessBoard = chessBoard;
            this._player = player;
            this._chessPiece = chessPiece;
            this._dir = dir;
        }

        public bool Execute()
        {
            var pos = _chessPiece.GetPosition();
            int row = pos.row;
            int col = pos.col;

            switch (_dir)
            {
                case Dir.LEFT:
                    col--;
                    break;
                case Dir.RIGHT:
                    col++;
                    break;
                case Dir.TOP:
                    row--;
                    break;
                case Dir.BOTTOM:
                    row++;
                    break;
            }
            //检查位置是否合法
            if (!_chessBoard.CheckPositionVaild(row, col)) return false;

            //检查此处是否有棋子
            if (_chessBoard.IsEmpty(row, col)) {
                //移动棋子
                _chessPiece.Move(row,col);
                return true;
            }

            //检查是否是自己的棋子
            if (_player.GetChessPiece(row, col) != null) return false;

            //是对方的棋子,检查是否能吃掉
            //检查跳过去的位置
            int row1 = row;
            int col1 = col;
            switch (_dir)
            {
                case Dir.LEFT:
                    col1--;
                    break;
                case Dir.RIGHT:
                    col1++;
                    break;
                case Dir.TOP:
                    row1--;
                    break;
                case Dir.BOTTOM:
                    row1++;
                    break;
            }

            //检查位置是否合法
            if (!_chessBoard.CheckPositionVaild(row1, col1)) return false;

            //检查此处是否有棋子
            if (_chessBoard.IsEmpty(row1, col1)) {
                //移动并吃掉对方棋子
                _chessPiece.Move(row1,col1);
                _chessBoard.RemoveChessPiece(row,col);
                return true;
            }
            return false;
        }
    }


    //LostRule.cs
    /// <summary>
    /// 失败规则
    /// </summary>
    public class LostRule : IRule
    {
        private Player _player;

        public LostRule(Player player) {
            this._player = player;        
        }

        public bool Execute()
        {
            return _player.IsLost;
        }
     }

ceshi

 


目前只完成了基本的功能,悔棋、AI选手都还没有写完,会继续完善这个小游戏!!!

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌风游

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值