Sjakkbrett
FormMain | ChessBoard | Square | Pawns
FormMain
Klassen er laget slik at den ikke vet noe særlig om sjakkbrettet. Det eneste den gjør er å tegne opp bokstavene og siffrene som angir navn på sjakkrutene. Ansvaret for dette burde nok vært flyttet til klassen ChessBoard.
Det er FormMain som husker om vi holder på å trekke på en brikke, hvor den var sist osv. Denne logikken er imidlertid hel uavhengig av vilken brikke eller sjakkbrettets geometri.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace test1 { public partial class FormMain : Form { ChessBoard Board = null; // variables to control the moving piece Boolean b_pieceIsMoving = false; int LastX = -1; int LastY = -1; int StartX = -1; int StartY = -1; public FormMain() { InitializeComponent(); // panelBoard is squares only Board = new ChessBoard(panelBoard.Size); } private void paintPanel(object sender, PaintEventArgs e) { // work on the panel with the chessboard Graphics g=panelBoard.CreateGraphics(); Board.drawBoard(g); g.Dispose(); // work on the frame(this) itself g = this.CreateGraphics(); // produce name om rows and columns Size s = panelBoard.Size; int top = panelBoard.Top; int left = panelBoard.Left; int dx = s.Width/8; int dy = s.Height/8; // need a font with a color, bold and gray is ok Font f = new Font(this.Font, FontStyle.Bold); Brush graybrush=new SolidBrush(Color.Gray); //north and south for (int x = 0; x <8; x++) { Char ch=(char)(int)('a'+x); String str=new String(ch,1); g.DrawString(str, Font, graybrush, left+dx/3+x*dx,top-15); g.DrawString(str, Font, graybrush, left+dx/3+x*dx, top+s.Height +5); } // east and west for (int y = 8; y >0; y--) { String str=y.ToString(); int vpos = top + s.Height+dy/2 - y * dy; g.DrawString(str, Font, graybrush, left - 10, vpos); g.DrawString(str, Font, graybrush, left + s.Width + 5, vpos); } } private void PanelMouseDown(object sender, MouseEventArgs e) { // left button to pick a pawn if (e.Button == MouseButtons.Left) { b_pieceIsMoving = Board.PickUpPawn(e.X, e.Y); if (b_pieceIsMoving) { // Capture events: all coming events routed to panel, panelBoard.Capture = true; LastX = e.X; LastY = e.Y; StartX = e.X; StartY = e.Y; // set move cursor panelBoard.Cursor = new Cursor("resources/mover.cur"); } } } private void PanelMouseMove(object sender, MouseEventArgs e) { if (b_pieceIsMoving) { Graphics g = panelBoard.CreateGraphics(); Board.MovePawn(e.X, e.Y,g); // remove/show a rubberband line to indicate move in progress ControlPaint.DrawReversibleLine( panelBoard.PointToScreen(new Point(StartX, StartY)), panelBoard.PointToScreen(new Point(LastX, LastY)), SystemColors.Control); ControlPaint.DrawReversibleLine( panelBoard.PointToScreen(new Point(StartX, StartY)), panelBoard.PointToScreen(new Point(e.X, e.Y)), SystemColors.Control); LastX = e.X; LastY = e.Y; } } private void PanelMouseUp(object sender, MouseEventArgs e) { panelBoard.Capture=false; if (b_pieceIsMoving) { // remove the rubberband line to indicate move in progress ControlPaint.DrawReversibleLine( panelBoard.PointToScreen(new Point(StartX, StartY)), panelBoard.PointToScreen(new Point(LastX, LastY)), SystemColors.Control); Board.DropPawn(e.X, e.Y); Graphics g = panelBoard.CreateGraphics(); Board.drawBoard(g); LastX = -1; LastY = -1; } b_pieceIsMoving = false; // set back cursor to hand panelBoard.Cursor = System.Windows.Forms.Cursors.Hand; } private void buttonQuit_MouseClick(object sender, MouseEventArgs e) { this.Dispose(); } } }
ChessBoard
Alt som har med selve sjakkbrettet er pakket inn her.
public class ChessBoard { Square[,] S = new Square[8, 8]; Square fromS = null; Square toS = null; public ChessBoard(Size limits) { // set up squares Size s = limits; int dx = s.Width / 8; int dy = s.Height / 8; Color dark = Color.FromArgb(181, 148, 115); Color lite = Color.FromArgb(214, 206, 181); Color c = Color.Black; for (int x = 0; x < 8; x++) { if (c == dark) c = lite; else c = dark; for (int y = 0; y < 8; y++) { Rectangle R = new Rectangle(x * dx, y * dy, dx, dy); if (c == dark) c = lite; else c = dark; S[x, y] = new Square(R, c,x,y); } } // init board initBoard(); } public void initBoard() { // set up as seen from white // white S[0, 7].SetPiece(piece.w_rook); S[7, 7].SetPiece(piece.w_rook); S[6, 7].SetPiece(piece.w_knight); S[1, 7].SetPiece(piece.w_knight); S[5, 7].SetPiece(piece.w_bishop); S[2, 7].SetPiece(piece.w_bishop); S[3, 7].SetPiece(piece.w_queen); S[4, 7].SetPiece(piece.w_king); for (int ix = 0; ix < 8; ix++) S[ix, 6].SetPiece(piece.w_pawn); // black S[0, 0].SetPiece(piece.b_rook); S[7, 0].SetPiece(piece.b_rook); S[6, 0].SetPiece(piece.b_knight); S[1, 0].SetPiece(piece.b_knight); S[5, 0].SetPiece(piece.b_bishop); S[2, 0].SetPiece(piece.b_bishop); S[3, 0].SetPiece(piece.b_queen); S[4, 0].SetPiece(piece.b_king); for (int ix = 0; ix < 8; ix++) S[ix, 1].SetPiece(piece.b_pawn); } public void drawBoard(Graphics g) { for (int x = 0; x < 8; x++) for (int y = 0; y < 8; y++) S[x, y].DrawMe(g); } public Boolean PickUpPawn(int x, int y) { fromS = FindSquare(x, y); if ((fromS != null)&&(fromS.GetPiece()!=piece.no_piece)) return true; return false; } public void MovePawn(int x, int y, Graphics g) { // .. if we want to do something here Square currentS = FindSquare(x, y); } public Boolean DropPawn(int x, int y) { toS = FindSquare(x, y); if (toS == null) return false; // do drop action, is it a legal move if (LegalMove(fromS, toS)) { if (fromS != toS) { toS.SetPiece(fromS.GetPiece()); fromS.SetPiece(piece.no_piece); } return true; } return false; } private Square FindSquare(int x, int y) { for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) if (S[i, j].contains(x, y)) return S[i, j]; return null; } private Boolean LegalMove(Square fromS, Square toS) { // basis version, make sure that the squares are ok if ((fromS == null)||(toS == null)) return false; // we accept the move if target square is empty if (toS.GetPiece() == piece.no_piece) return true; // we also accept if target square contains an opponent if (( (fromS.GetPiece() < piece.b_king) && (toS.GetPiece() >= piece.b_king)) || ((fromS.GetPiece() > piece.b_king) && (toS.GetPiece() <= piece.b_king))) return true; return false; } }
piece er definert slik:
public enum piece { no_piece, w_king, w_queen, w_bishop, w_knight, w_rook, w_pawn, b_king, b_queen, b_bishop, b_knight, b_rook, b_pawn};
Square
public class Square : Object { Rectangle R = new Rectangle(); Color C = Color.Azure; int row = 0; int col = 0; int P = 0; Char verticalName = '0'; Char horizontalName = '0'; public Square(Rectangle r, Color c,int x,int y) { R = r; C = c; row = x; col = y; verticalName = (char)(int)('1' + row); horizontalName = (char)(int)('a' + col); } public void SetPiece(piece p) { P = (int)p; } public piece GetPiece() { return (piece)P; } public Point getPos(){ return new Point(row,col); } public void DrawMe(Graphics g) { g.FillRectangle(new SolidBrush(C), R); g.DrawRectangle(new Pen(Color.Black), R); g.DrawImage(Pawns.GetImage(P), new Point(R.Left, R.Top)); } public Boolean contains(int x,int y) { return R.Contains(x, y); } public Point GetCenter(){ return new Point((int)(R.Left + R.Width / 2), (int)(R.Top + R.Height / 2)); } }
Pawns
public static class Pawns : Object { public static Image GetImage(int p) { switch (p) { case (int)piece.w_king: return test1.Properties.Resources.wKonge; case (int)piece.w_queen: return test1.Properties.Resources.wDronning; case (int)piece.w_bishop: return test1.Properties.Resources.wLoper; case (int)piece.w_knight: return test1.Properties.Resources.wSpringer; case (int)piece.w_rook: return test1.Properties.Resources.wTarn; case (int)piece.w_pawn: return test1.Properties.Resources.wBonde; case (int)piece.b_king: return test1.Properties.Resources.bKonge; case (int)piece.b_queen: return test1.Properties.Resources.bDronning; case (int)piece.b_bishop: return test1.Properties.Resources.bLoper; case (int)piece.b_knight: return test1.Properties.Resources.bSpringer; case (int)piece.b_rook: return test1.Properties.Resources.bTarn; case (int)piece.b_pawn: return test1.Properties.Resources.bBonde; default: return test1.Properties.Resources.no_piece; } } }