小时候经常玩的游戏,和小伙伴在地上画个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;
}
}
目前只完成了基本的功能,悔棋、AI选手都还没有写完,会继续完善这个小游戏!!!