棋局建议
本文关键字:棋局 | 更新日期: 2023-09-27 18:07:33
我对编程比较陌生,我正在开始一个制作国际象棋游戏的项目。现在我只上了2节课-棋子(嵌套的职业:骑士,主教,兵,王后,国王)- board(嵌套类:Position)
并最终引导主窗体屏幕中的所有内容。
目前我不想添加块运动或任何东西…我的目标是建立一个良好的根,使胸部游戏更容易编程。所以我想问一下是否有人能给我一些建议,告诉我如何才能更好地做到这一点。
我主要关注面向对象设计和多态性
中Form1:
public partial class Form1 : Form
{
Board board = new Board(new Point(25, 25));
Peices peice = new Peices();
public Form1()
{
AllowTransparency = true;
this.Controls.Add(board);
//board.Controls.Add(p1);
peice.putOnBoard(board);
InitializeComponent();
}
}
Peice Class:
class Peices
{
private List<PictureBox> peiceList = new List<PictureBox>();
private static readonly Size PEICESSIZE = new Size(100,100);
private static readonly Color PEICESBACKBROUDCOLOR = Color.Transparent;
private static Image _blackImage;
public static Image blackImage
{
get { return _blackImage; }
set { _blackImage = value; }
}
static Image _whiteImage;
public static Image whiteImage
{
get { return _whiteImage; }
set { _whiteImage = value; }
}
public Peices()
{
peiceList.Add( new Pawn(Color.White) { Location = Board.Position.A2 });
peiceList.Add( new Pawn(Color.White) { Location = Board.Position.B2 });
peiceList.Add( new Pawn(Color.White) { Location = Board.Position.C2 });
peiceList.Add( new Pawn(Color.White) { Location = Board.Position.D2 });
peiceList.Add( new Pawn(Color.White) { Location = Board.Position.E2 });
peiceList.Add( new Pawn(Color.White) { Location = Board.Position.F2 });
peiceList.Add( new Pawn(Color.White) { Location = Board.Position.G2 });
peiceList.Add( new Pawn(Color.White) { Location = Board.Position.H2 });
peiceList.Add(new Knight(Color.White) { Location = Board.Position.B1 });
peiceList.Add(new Knight(Color.White) { Location = Board.Position.G1 });
peiceList.Add(new Bishop(Color.White) { Location = Board.Position.C1 });
peiceList.Add(new Bishop(Color.White) { Location = Board.Position.F1 });
peiceList.Add(new Rook(Color.White) { Location = Board.Position.A1 });
peiceList.Add(new Rook(Color.White) { Location = Board.Position.H1 });
peiceList.Add(new Queen(Color.White) { Location = Board.Position.D1 });
peiceList.Add(new King(Color.White) { Location = Board.Position.E1 });
peiceList.Add(new Pawn(Color.Black) { Location = Board.Position.A7 });
peiceList.Add(new Pawn(Color.Black) { Location = Board.Position.B7 });
peiceList.Add(new Pawn(Color.Black) { Location = Board.Position.C7 });
peiceList.Add(new Pawn(Color.Black) { Location = Board.Position.D7 });
peiceList.Add(new Pawn(Color.Black) { Location = Board.Position.E7 });
peiceList.Add(new Pawn(Color.Black) { Location = Board.Position.F7 });
peiceList.Add(new Pawn(Color.Black) { Location = Board.Position.G7 });
peiceList.Add(new Pawn(Color.Black) { Location = Board.Position.H7 });
peiceList.Add(new Knight(Color.Black) { Location = Board.Position.B8 });
peiceList.Add(new Knight(Color.Black) { Location = Board.Position.G8 });
peiceList.Add(new Bishop(Color.Black) { Location = Board.Position.C8 });
peiceList.Add(new Bishop(Color.Black) { Location = Board.Position.F8 });
peiceList.Add(new Rook(Color.Black) { Location = Board.Position.A8 });
peiceList.Add(new Rook(Color.Black) { Location = Board.Position.H8 });
peiceList.Add(new Queen(Color.Black) { Location = Board.Position.D8 });
peiceList.Add(new King(Color.Black) { Location = Board.Position.E8 });
}
public void putOnBoard(Board board)
{
for (int i = 0; i < peiceList.Count; i++)
{
board.Controls.Add(peiceList[i]);
}
}
static Image makeImageBackgroundInvis(Image pb)
{
Bitmap imgBitmap = (Bitmap)pb;
imgBitmap.MakeTransparent(imgBitmap.GetPixel(0, 0));
pb = imgBitmap;
return pb;
}
public class Pawn : PictureBox
{
public Pawn( Color pawnColor)
{
blackImage = makeImageBackgroundInvis(Image.FromFile("BlackPawn.bmp"));
whiteImage = makeImageBackgroundInvis(Image.FromFile("WhitePawn.bmp"));
BackColor = PEICESBACKBROUDCOLOR;
Size = PEICESSIZE;
if (pawnColor == Color.Black) { Image = blackImage; }
if (pawnColor == Color.White) { Image = whiteImage; }
}
}
public class Knight : PictureBox
{
public Knight(Color pawnColor)
{
blackImage = makeImageBackgroundInvis(Image.FromFile("BlackKnight.bmp"));
whiteImage = makeImageBackgroundInvis(Image.FromFile("WhiteKnight.bmp"));
BackColor = PEICESBACKBROUDCOLOR;
Size = PEICESSIZE;
if (pawnColor == Color.Black) { Image = blackImage; }
if (pawnColor == Color.White) { Image = whiteImage; }
}
}
public class Bishop : PictureBox
{
public Bishop(Color pawnColor)
{
blackImage = makeImageBackgroundInvis(Image.FromFile("BlackBishop.bmp"));
whiteImage = makeImageBackgroundInvis(Image.FromFile("WhiteBishop.bmp"));
BackColor = PEICESBACKBROUDCOLOR;
Size = PEICESSIZE;
if (pawnColor == Color.Black) { Image = blackImage; }
if (pawnColor == Color.White) { Image = whiteImage; }
}
}
public class Rook : PictureBox
{
public Rook(Color pawnColor)
{
blackImage = makeImageBackgroundInvis(Image.FromFile("BlackRook.bmp"));
whiteImage = makeImageBackgroundInvis(Image.FromFile("WhiteRook.bmp"));
BackColor = PEICESBACKBROUDCOLOR;
Size = PEICESSIZE;
if (pawnColor == Color.Black) { Image = blackImage; }
if (pawnColor == Color.White) { Image = whiteImage; }
}
}
public class Queen : PictureBox
{
public Queen(Color pawnColor)
{
blackImage = makeImageBackgroundInvis(Image.FromFile("BlackQueen.bmp"));
whiteImage = makeImageBackgroundInvis(Image.FromFile("WhiteQueen.bmp"));
BackColor = PEICESBACKBROUDCOLOR;
Size = PEICESSIZE;
if (pawnColor == Color.Black) { Image = blackImage; }
if (pawnColor == Color.White) { Image = whiteImage; }
}
}
public class King : PictureBox
{
public King(Color pawnColor)
{
blackImage = makeImageBackgroundInvis(Image.FromFile("BlackKing.bmp"));
whiteImage = makeImageBackgroundInvis(Image.FromFile("WhiteKing.bmp"));
BackColor = PEICESBACKBROUDCOLOR;
Size = PEICESSIZE;
if (pawnColor == Color.Black) { Image = blackImage; }
if (pawnColor == Color.White) { Image = whiteImage; }
}
}
}
Board Class:
class Board : Panel
{
public static readonly Size BOARD_SIZE = new Size(800,800);
public static readonly int BOARD_ROW = 8;
public static readonly int BOARD_COLUMN = 8;
public static readonly Size BOARD_TILE_LENGTH = new Size((BOARD_SIZE.Height / BOARD_COLUMN), (BOARD_SIZE.Width / BOARD_ROW));
private static readonly int BORD_PEICE_NUMBER = 64;
public Board(Point locationPoint )
{
new Position();
Size = BOARD_SIZE;
Location = locationPoint;
BackgroundImage = Image.FromFile("ChestBord.png");
}
public class Position
{
static public Point A1;
static public Point A2;
static public Point A3;
static public Point A4;
static public Point A5;
static public Point A6;
static public Point A7;
static public Point A8;
static public Point B1;
static public Point B2;
static public Point B3;
static public Point B4;
static public Point B5;
static public Point B6;
static public Point B7;
static public Point B8;
static public Point C1;
static public Point C2;
static public Point C3;
static public Point C4;
static public Point C5;
static public Point C6;
static public Point C7;
static public Point C8;
static public Point D1;
static public Point D2;
static public Point D3;
static public Point D4;
static public Point D5;
static public Point D6;
static public Point D7;
static public Point D8;
static public Point E1;
static public Point E2;
static public Point E3;
static public Point E4;
static public Point E5;
static public Point E6;
static public Point E7;
static public Point E8;
static public Point F1;
static public Point F2;
static public Point F3;
static public Point F4;
static public Point F5;
static public Point F6;
static public Point F7;
static public Point F8;
static public Point G1;
static public Point G2;
static public Point G3;
static public Point G4;
static public Point G5;
static public Point G6;
static public Point G7;
static public Point G8;
static public Point H1;
static public Point H2;
static public Point H3;
static public Point H4;
static public Point H5;
static public Point H6;
static public Point H7;
static public Point H8;
public Position()
{
A1 = new Point(BOARD_TILE_LENGTH.Width*0, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*1);
A2 = new Point(BOARD_TILE_LENGTH.Width*0, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*2);
A3 = new Point(BOARD_TILE_LENGTH.Width*0, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*3);
A4 = new Point(BOARD_TILE_LENGTH.Width*0, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*4);
A5 = new Point(BOARD_TILE_LENGTH.Width*0, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*5);
A6 = new Point(BOARD_TILE_LENGTH.Width*0, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*6);
A7 = new Point(BOARD_TILE_LENGTH.Width*0, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*7);
A8 = new Point(BOARD_TILE_LENGTH.Width*0, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*8);
B1 = new Point(BOARD_TILE_LENGTH.Width*1, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*1);
B2 = new Point(BOARD_TILE_LENGTH.Width*1, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*2);
B3 = new Point(BOARD_TILE_LENGTH.Width*1, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*3);
B4 = new Point(BOARD_TILE_LENGTH.Width*1, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*4);
B5 = new Point(BOARD_TILE_LENGTH.Width*1, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*5);
B6 = new Point(BOARD_TILE_LENGTH.Width*1, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*6);
B7 = new Point(BOARD_TILE_LENGTH.Width*1, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*7);
B8 = new Point(BOARD_TILE_LENGTH.Width*1, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*8);
C1 = new Point(BOARD_TILE_LENGTH.Width*2, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*1);
C2 = new Point(BOARD_TILE_LENGTH.Width*2, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*2);
C3 = new Point(BOARD_TILE_LENGTH.Width*2, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*3);
C4 = new Point(BOARD_TILE_LENGTH.Width*2, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*4);
C5 = new Point(BOARD_TILE_LENGTH.Width*2, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*5);
C6 = new Point(BOARD_TILE_LENGTH.Width*2, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*6);
C7 = new Point(BOARD_TILE_LENGTH.Width*2, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*7);
C8 = new Point(BOARD_TILE_LENGTH.Width*2, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*8);
D1 = new Point(BOARD_TILE_LENGTH.Width*3, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*1);
D2 = new Point(BOARD_TILE_LENGTH.Width*3, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*2);
D3 = new Point(BOARD_TILE_LENGTH.Width*3, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*3);
D4 = new Point(BOARD_TILE_LENGTH.Width*3, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*4);
D5 = new Point(BOARD_TILE_LENGTH.Width*3, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*5);
D6 = new Point(BOARD_TILE_LENGTH.Width*3, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*6);
D7 = new Point(BOARD_TILE_LENGTH.Width*3, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*7);
D8 = new Point(BOARD_TILE_LENGTH.Width*3, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*8);
E1 = new Point(BOARD_TILE_LENGTH.Width*4, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*1);
E2 = new Point(BOARD_TILE_LENGTH.Width*4, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*2);
E3 = new Point(BOARD_TILE_LENGTH.Width*4, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*3);
E4 = new Point(BOARD_TILE_LENGTH.Width*4, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*4);
E5 = new Point(BOARD_TILE_LENGTH.Width*4, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*5);
E6 = new Point(BOARD_TILE_LENGTH.Width*4, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*6);
E7 = new Point(BOARD_TILE_LENGTH.Width*4, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*7);
E8 = new Point(BOARD_TILE_LENGTH.Width*4, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*8);
F1 = new Point(BOARD_TILE_LENGTH.Width*5, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*1);
F2 = new Point(BOARD_TILE_LENGTH.Width*5, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*2);
F3 = new Point(BOARD_TILE_LENGTH.Width*5, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*3);
F4 = new Point(BOARD_TILE_LENGTH.Width*5, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*4);
F5 = new Point(BOARD_TILE_LENGTH.Width*5, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*5);
F6 = new Point(BOARD_TILE_LENGTH.Width*5, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*6);
F7 = new Point(BOARD_TILE_LENGTH.Width*5, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*7);
F8 = new Point(BOARD_TILE_LENGTH.Width*5, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*8);
G1 = new Point(BOARD_TILE_LENGTH.Width*6, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*1);
G2 = new Point(BOARD_TILE_LENGTH.Width*6, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*2);
G3 = new Point(BOARD_TILE_LENGTH.Width*6, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*3);
G4 = new Point(BOARD_TILE_LENGTH.Width*6, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*4);
G5 = new Point(BOARD_TILE_LENGTH.Width*6, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*5);
G6 = new Point(BOARD_TILE_LENGTH.Width*6, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*6);
G7 = new Point(BOARD_TILE_LENGTH.Width*6, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*7);
G8 = new Point(BOARD_TILE_LENGTH.Width*6, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*8);
H1 = new Point(BOARD_TILE_LENGTH.Width*7, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*1);
H2 = new Point(BOARD_TILE_LENGTH.Width*7, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*2);
H3 = new Point(BOARD_TILE_LENGTH.Width*7, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*3);
H4 = new Point(BOARD_TILE_LENGTH.Width*7, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*4);
H5 = new Point(BOARD_TILE_LENGTH.Width*7, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*5);
H6 = new Point(BOARD_TILE_LENGTH.Width*7, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*6);
H7 = new Point(BOARD_TILE_LENGTH.Width*7, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*7);
H8 = new Point(BOARD_TILE_LENGTH.Width*7, BOARD_SIZE.Width - (BOARD_TILE_LENGTH.Width)*8);
}
}
}
就我个人而言,我会创建一个BoardCoordinate
类,它将处理所有的板定位逻辑,并允许您以多种方式(数字和id)访问坐标。
public class BoardCoordinate
{
private const string[] xCoordId = new string[]{"A","B","C","D","E","F","G","H"};
private const string[] yCoordId = new string[]{"1","2","3","4","5","6","7","8"};
private Dictionary<string, Point> idToPoint;
public BoardCoordinate()
{
idToPoint = new Dictionary<string,Point>();
for(int i = 0; i < xCoordId.length; i++)
{
for(int j = 0; j < yCoordId.length; j++)
{
idToPoint.Add(xCoordId[i] + yCoordId[j], new Point(i,j));
}
}
}
public string getId(Point point)
{
return xCoordId[point.x] + yCoordId[point.y];
}
public Point getPoint(string id)
{
if(idToPoint.ContainsKey(id))
{
return idToPoint[id];
}
return null;
}
}
正如icemanind在评论中提到的,您希望将逻辑与显示分离,因此为什么BoardCoordinate
只处理游戏逻辑所需的实际整数坐标。你可以很容易地拥有另一个类(例如你的Board
类),它将转换/乘以适当的坐标来生成一个视觉坐标。例如,如果你想同时拥有游戏的2d和3d可视化,这将非常有用。在这种情况下,Board2D
将以不同于Board3D
的方式变换坐标,但BoardCoordinate
不需要任何更改。
如果你愿意,你可以在类中为所有点的完整id(例如A1, A2, B1等)创建getter。
例如:public Point A1 {
get { return getPoint("A1"); }
}
因为它只是一个helper类,所以您也可以选择将其设置为静态。
至于部件,我会将其分解为两种类型的类,一种用于视觉,一种用于逻辑,每种都有一个接口(例如IPieceDisplay
和IPieceLogic
)。
IPieceLogic
接口可能有一些必要的方法,将用于游戏的逻辑,如:
public interface IPieceLogic
{
PieceType pieceType { get; }
boolean isAlive { get; }
List<Point> getAvailableMoves();
boolean canMoveTo(Point position);
void moveTo(Point newPosition);
Point getPosition();
void die();
}
然后为每种类型的Piece
实现一个类。理论上,您可以使用单个PieceLogic
类。要做到这一点,你需要抽象出每个棋子的移动逻辑,例如,创建一个MovementBehavior
接口/类来定义棋子如何移动,PieceLogic
将有一个MovementBehavior
的实例用于所有的计算(例如KnightMoveBehavoir
, QueenMoveBehavior
等)。
IPieceDisplay
可能看起来像这样:
public interface IPieceDisplay
{
void animateTo(Point newPosition);
void die();
void select();
void unselect();
void draw();
void setBitmap(Bitmap b);
}
同样,您将为每种类型的片段实现PieceDisplay
类。对于一个非常简单的游戏,如果没有任何部分需要任何独特的视觉/动画/绘图逻辑,你可以求助于使用单个PieceDisplay
实现。
最后,您将有一个Piece
类,它将具有IPieceDisplay
和IPieceLogic
的实例,并将处理对片段的视觉和逻辑更新。你的Board
(或者可能是一个单独的BoardController
或GameController
类)可以保存所有的Piece
实例,并负责游戏流程、棋子交互和用户交互。
我能给你的第一条建议是枚举将成为你的朋友。
大多数棋盘是8x8的大小。总共64个平方。首先你要做的是创建一个类和枚举,像这样:
public enum PieceColors {
Black,
White
}
public enum PieceTypes {
Rook,
Pawn,
Knight,
Queen,
King,
Bishop
}
public class Piece {
public PieceTypes PieceType { get; set; };
public PieceColors PieceColor { get; set; };
public Bitmap GetPieceBitmap()
{
// Return a Bitmap representing the piece based on PieceType and PieceColor
}
}
然后是board class:
public class Board {
public Piece[] Pieces { get; set; }
public Board() {
Pieces = new Piece[64];
// Setup initial white pawns
for (int x = 8; x < 16; x++)
{
Pieces[x].PieceColor = PieceColors.White;
Pieces[x].PieceType = PieceTypes.Pawn;
}
}
}
这样的事情应该让你去!