算法源自网络(网络源码连接:http://www.mycodes.net/161/6659.htm)
整体思路:用二维数组构建棋盘每一个数组元素封装为一个picturebox附带若干属性(例如:棋子归属方、棋子的类型),用一个抽象基类规定基本的棋子移动规则(例如:不能选中空白picturebox、该红方走棋时不能选中蓝方棋子),具体的棋子单独从基类棋子类派生 重写派生类的方法规定其走棋规则,和相应填充picturebox的图片(例如: 炮不能斜着走不能直线吃子,翻山炮必须吃子且移动路径上只能有一个棋子)
窗体所用控件:lable、timer、picturebox
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing; namespace 象棋_封_
{
enum chess_type
{
blank,
jiang,
che,
ma,
pao,
xiang,
zu,
shi
};//棋类的枚举类型
enum player_type
{
blank,
red,
blue,
};//玩家类别的枚举类型
abstract class Chess
{
private static Chess[] cover_blue =new Chess[];//被吃区
private static int r=;
private static Chess[] cover_red = new Chess[];//被吃区
private static int f=;
protected static int chosenX;
protected static int chosenY;
public static bool chosen;
static int n = ;
public static player_type control_side;
public PictureBox PB;
public chess_type type;
public player_type side;
public Chess()
{
side = player_type.blank;
type = chess_type.blank;
}
public abstract bool Move_judge(object sender, int X, int Y, Chess[][] checkerboard);
public abstract void Put_picture();
//public void Assignment(chess_type ct, player_type pt, Image pic)
//{
// side = pt;
// type = ct;
// PB.Image = pic;
//}//给棋子赋值
public void Bg_Tored()
{
this.PB.BackColor = Color.Red;
}//背景变为红色
public void Bg_Toblank()
{
this.PB.BackColor = Color.Transparent;
}//背景变为白色
private void Chess_Toblank(ref Chess a, PictureBox PB)
{
this.Bg_Toblank();
this.PB.Image = null;
a = new Chess_blank(PB);
}//棋子属性清空
public static void Clearground(Main f, ref Chess[][] checkerboard)//布置战场
{
int i, j;
Control[] col_blue=null;
Control[] col_red=null;
Chess.control_side = player_type.red;
Chess.chosen = false;
//*********************初始化被吃区**************//
for (i = ; i < ; i++)
{
cover_blue[i] = new Chess_blank();
cover_red[i] = new Chess_blank();
}
for (i = ; i <= ; i++)
{
col_blue = f.Controls.Find("Cover_PBox_blue" + i, false);//检索控件
col_red = f.Controls.Find("Cover_PBox_red" + i, false);//检索控件
cover_blue[i - ].PB = col_blue[] as PictureBox;
cover_red[i - ].PB = col_red[] as PictureBox;
}
//*********************初始话被吃区**************// //*****************构建棋盘********************//
checkerboard = new Chess[][];
for (i = ; i < ; i++)
{
checkerboard[i] = new Chess[];//10行9列
}
for (i = ; i < ; i++)
for (j = ; j < ; j++)
{
checkerboard[i][j] = new Chess_blank();
}
checkerboard[][] = new Chess_che(player_type.blue);
checkerboard[][] = new Chess_ma(player_type.blue);
checkerboard[][] = new Chess_xiang(player_type.blue);
checkerboard[][] = new Chess_shi(player_type.blue);
checkerboard[][] = new Chess_jiang(player_type.blue);
checkerboard[][] = new Chess_shi(player_type.blue);
checkerboard[][] = new Chess_xiang(player_type.blue);
checkerboard[][] = new Chess_ma(player_type.blue);
checkerboard[][] = new Chess_che(player_type.blue);
checkerboard[][] = new Chess_pao(player_type.blue);
checkerboard[][] = new Chess_pao(player_type.blue);
checkerboard[][] = new Chess_zu(player_type.blue);
checkerboard[][] = new Chess_zu(player_type.blue);
checkerboard[][] = new Chess_zu(player_type.blue);
checkerboard[][] = new Chess_zu(player_type.blue);
checkerboard[][] = new Chess_zu(player_type.blue); checkerboard[][] = new Chess_zu(player_type.red);
checkerboard[][] = new Chess_zu(player_type.red);
checkerboard[][] = new Chess_zu(player_type.red);
checkerboard[][] = new Chess_zu(player_type.red);
checkerboard[][] = new Chess_zu(player_type.red);
checkerboard[][] = new Chess_pao(player_type.red);
checkerboard[][] = new Chess_pao(player_type.red);
checkerboard[][] = new Chess_che(player_type.red);
checkerboard[][] = new Chess_ma(player_type.red);
checkerboard[][] = new Chess_xiang(player_type.red);
checkerboard[][] = new Chess_shi(player_type.red);
checkerboard[][] = new Chess_jiang(player_type.red);
checkerboard[][] = new Chess_shi(player_type.red);
checkerboard[][] = new Chess_xiang(player_type.red);
checkerboard[][] = new Chess_ma(player_type.red);
checkerboard[][] = new Chess_che(player_type.red);
for (i = ; i < ; i++)
for (j = ; j < ; j++)//control 是一个存放控件类的容器
{
Control[] col = f.Controls.Find("pictureBox" + (i * + j + ), false);//检索控件
checkerboard[i][j].PB = col[] as PictureBox;//类型转换
checkerboard[i][j].PB.Location = new Point( + * j, * i);
}
for (i = ; i < ; i++)
for (j = ; j < ; j++)
{
checkerboard[i][j].Put_picture();
}
//*****************构建棋盘********************//
}
protected static int Getx(object sender)
{
int x;
string name = (sender as PictureBox).Name;
string number = name.Substring();//在字符串中从指定位开始检索(这里是在x后也就是picturebox控件ID不同的尾号)
int index = Convert.ToInt32(number);
x = (index - ) / ;//列
return x;
}
protected static int Gety(object sender)
{
int y;
string name = (sender as PictureBox).Name;
string number = name.Substring();//在字符串中从指定位开始检索(这里是在x后也就是picturebox控件ID不同的尾号)
int index = Convert.ToInt32(number);
y = (index - ) % ;//行
return y;
}
public static void Nochozen_dispose(object sender, Chess[][] checkerboard)
{
Chess.chosen = true;
chosenX = Chess.Getx(sender);
chosenY = Chess.Gety(sender);
if (checkerboard[chosenX][chosenY].side != control_side)//选择的不是当前应该走棋的一方
{
chosen = false;
return;
}
if (checkerboard[chosenX][chosenY].side != player_type.blank)//选择的不是空白
checkerboard[chosenX][chosenY].Bg_Tored();
return;
}
public static bool Chozen_dispose(object sender, Chess[][] checkerboard)
{
Chess.chosen = false;
int x= Getx(sender);
int y= Gety(sender);
if (checkerboard[chosenX][chosenY].side == checkerboard[x][y].side)//移动位置与选择位是同一阵营
{
checkerboard[chosenX][chosenY].Bg_Toblank();
return false;
}
if (checkerboard[chosenX][chosenY].side == player_type.blank)//选中的是空白
return false;
if (checkerboard[chosenX][chosenY].type == chess_type.ma || checkerboard[chosenX][chosenY].type == chess_type.xiang || checkerboard[chosenX][chosenY].type == chess_type.shi)//马象士的移动不能同y或同x
{
if (chosenX == x || chosenY == y)
{
checkerboard[chosenX][chosenY].Bg_Toblank();
return false;
}
}
else
{
if (chosenX != x && chosenY != y)//其他棋类都必须同x或同y移动
{
checkerboard[chosenX][chosenY].Bg_Toblank();
return false;
}
} if (!checkerboard[chosenX][chosenY].Move_judge(sender, x, y, checkerboard))
{
checkerboard[chosenX][chosenY].Bg_Toblank();
return false;
}
if (Chess.Setmove(checkerboard, x, y))
return true;
else
return false;
}
static bool Setmove(Chess[][] checkerboard,int X,int Y)
{
n++;
bool over = false;
player_type z=player_type.blank;
if (checkerboard[X][Y].type == chess_type.jiang)
{
over = true;
z = checkerboard[X][Y].side;
}
if (checkerboard[X][Y].PB.Image!=null)
Cover(checkerboard[X][Y]);
Chess.Change(ref checkerboard[Chess.chosenX][Chess.chosenY],ref checkerboard[X][Y]);
Chess.chosen = false;
if (over)
{
if (z == player_type.blue)
MessageBox.Show("红方胜利");
else
MessageBox.Show("蓝方胜利");
End f = new End(Time.fen + "分" + Time.miao + "秒");
f.Show();
return true;
}
if (n % == )
Chess.control_side = player_type.blue;
else
Chess.control_side = player_type.red;
return false;
}
private static void Change(ref Chess a,ref Chess b)//a子位移到b子
{
Chess c = new Chess_blank();
c.PB = b.PB;
switch (a.type)
{
case chess_type.zu:
b = new Chess_zu(a.side);break;
case chess_type.pao:
b = new Chess_pao(a.side);break;
case chess_type.che:
b = new Chess_che(a.side); break;
case chess_type.ma:
b = new Chess_ma(a.side); break;
case chess_type.xiang:
b = new Chess_xiang(a.side); break;
case chess_type.shi:
b = new Chess_shi(a.side); break;
case chess_type.jiang:
b = new Chess_jiang(a.side); break;
}
b.type = a.type;
b.side = a.side;
b.PB = c.PB;
b.PB.Image = a.PB.Image;
a.Chess_Toblank(ref a,a.PB);
}
private static void Cover(Chess a)
{
if (a.side == player_type.blue)
{
Change(ref a, ref cover_red[r]);
r++;
}
else
{
Change(ref a, ref cover_blue[f]);
f++;
} }//棋子被吃后移动到被吃区 }
}
棋子抽象基类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms; namespace 象棋_封_
{
class Chess_blank : Chess
{
public Chess_blank()
{
base.type = chess_type.blank;
base.side = player_type.blank;
}
public Chess_blank(PictureBox PB)
{
base.type = chess_type.blank;
base.side = player_type.blank;
this.PB = PB;
}
public override bool Move_judge(object sender, int X, int Y, Chess[][] checkerboard)
{
return false;
}
public override void Put_picture()
{
this.PB.Image = null;
}
}
}
空白属性棋子类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 象棋_封_
{
class Chess_che:Chess
{
public Chess_che(player_type b)
{
base.type = chess_type.che;
base.side = b;
}
public override bool Move_judge(object sender, int X, int Y, Chess[][] checkerboard)
{
int i, j, k;
if (Chess.chosenX == X)
{
i = Chess.chosenY < Y ? Chess.chosenY : Y;
j = Chess.chosenY > Y ? Chess.chosenY : Y;
for (k = i + ; k < j; k++)
{
if (checkerboard[X][k].side != player_type.blank)//在移动路径上有棋子情况
{
return false;
}
}
}
if (Chess.chosenY == Y)
{
i = Chess.chosenX < X ? Chess.chosenX : X;
j = Chess.chosenX > X ? Chess.chosenX : X;
for (k = i + ; k < j; k++)
{
if (checkerboard[k][Y].side != player_type.blank)
{
return false;
}
}
}
return true;
}
public override void Put_picture()
{
if (base.side == player_type.red)
this.PB.Image = global::象棋_封_.Properties.Resources.红車;
else
this.PB.Image = global::象棋_封_.Properties.Resources.蓝車;
}
}
}
车类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 象棋_封_
{
class Chess_jiang:Chess
{
public Chess_jiang(player_type b)
{
base.type = chess_type.jiang;
base.side = b;
}
public override bool Move_judge(object sender, int X, int Y, Chess[][] checkerboard)
{
int i, j, k;
if (checkerboard[X][Y].type == chess_type.jiang && Chess.chosenY == Y)//王吃王情况
{
i = Chess.chosenX < X ? Chess.chosenX : X;//棋子移动的起点行
j = Chess.chosenX > X ? Chess.chosenX : X;//棋子移动的结束行
for (k = i + ; k < j; k++)
{
if (checkerboard[k][Y].side != player_type.blank)//中间有棋子情况
{
return false;
}
}
return true;
}
if (this.side == player_type.blue)
{ if (Y < || Y > || X > )//当控制者是蓝色方 限制将的移动范围
{
return false;
}
}
else
{
if (Y < || Y > || X < )//当控制者是红色方 限制将的移动范围
{
return false;
}
}
if ((Chess.chosenX - X) * (Chess.chosenX - X) + (Chess.chosenY - Y) * (Chess.chosenY - Y) != )//点到点距离x平方加y平方
{
return false;
}
return true;
}
public override void Put_picture()
{
if (base.side == player_type.red)
this.PB.Image = global::象棋_封_.Properties.Resources.红帥;
else
this.PB.Image = global::象棋_封_.Properties.Resources.蓝将;
}
}
}
将类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 象棋_封_
{
class Chess_ma:Chess
{
public Chess_ma(player_type b)
{
base.type = chess_type.ma;
base.side = b;
}
public override bool Move_judge(object sender, int X, int Y, Chess[][] checkerboard)
{
if (Math.Abs(Chess.chosenX - X) == && Math.Abs(Chess.chosenY - Y) == )//移动X方向绝对值为1y方向为2
{
if (checkerboard[Chess.chosenX][Chess.chosenY + (Y - Chess.chosenY) / Math.Abs(Y - Chess.chosenY)].side != player_type.blank)//不是撇脚马
{
return false;
}
}
else if (Math.Abs(Chess.chosenX - X) == && Math.Abs(Chess.chosenY - Y) == )//移动y方向绝对值为2x方向为1
{
if (checkerboard[Chess.chosenX + (X - Chess.chosenX) / Math.Abs(X - Chess.chosenX)][Chess.chosenY].side != player_type.blank)//不是撇脚马
{
return false;
}
}
else
{
return false;
}
return true;
}
public override void Put_picture()
{
if (base.side == player_type.red)
this.PB.Image = global::象棋_封_.Properties.Resources.红马;
else
this.PB.Image = global::象棋_封_.Properties.Resources.蓝马;
}
}
}
马类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 象棋_封_
{
class Chess_pao:Chess
{
public Chess_pao(player_type b)
{
base.type = chess_type.pao;
base.side = b;
}
public override bool Move_judge(object sender, int X, int Y, Chess[][] checkerboard)
{
int p = ;//用于记录路径上的棋子数
int i, j, k;
if (Chess.chosenX == X)//同列移动情况
{
i = Chess.chosenY < Y ? Chess.chosenY : Y;//定起始点
j = Chess.chosenY > Y ? Chess.chosenY : Y;//定起始点
p = ;
for (k = i + ; k < j; k++)
{
if (checkerboard[X][k].side != player_type.blank)
{
p++;//移动路径上有棋子的个数
}
}
if (p > )
{
return false;
}
} else if (Chess.chosenY == Y)//同行移动情况
{
i = Chess.chosenX < X ? Chess.chosenX : X;
j = Chess.chosenX > X ? Chess.chosenX : X;
p = ;
for (k = i + ; k < j; k++)
{
if (checkerboard[k][Y].side != player_type.blank)
{
p++;
}
}
if (p > )
{
return false;
}
}
else
{
return false;
}
if (p == && checkerboard[X][Y].side != player_type.blank)//中间没有棋子炮不能吃子
{
return false;
}
if (p == && checkerboard[X][Y].side == player_type.blank)//中间有棋子但是不能打空炮
{
return false;
}
return true;
}
public override void Put_picture()
{
if (base.side == player_type.red)
this.PB.Image = global::象棋_封_.Properties.Resources.红炮;
else
this.PB.Image = global::象棋_封_.Properties.Resources.蓝炮;
}
}
}
炮类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 象棋_封_
{
class Chess_shi:Chess
{
public Chess_shi(player_type b)
{
base.type = chess_type.shi;
base.side = b;
}
public override bool Move_judge(object sender, int X, int Y, Chess[][] checkerboard)
{
if (this.side == player_type.blue)
{
if (Y < || Y > || X > )//限制将的移动范围
{
return false;
}
}
else
{
if (Y < || Y > || X < )//限制将的移动范围
{
return false;
}
}
if (Math.Abs(X - Chess.chosenX) != || Math.Abs(Chess.chosenY - Y) != )//只能跨一个方格
{
return false;
}
return true;
}
public override void Put_picture()
{
if (base.side == player_type.red)
this.PB.Image = global::象棋_封_.Properties.Resources.红士;
else
this.PB.Image = global::象棋_封_.Properties.Resources.蓝士;
}
}
}
士类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 象棋_封_
{
class Chess_xiang:Chess
{
public Chess_xiang(player_type b)
{
base.type = chess_type.xiang;
base.side = b;
}
public override bool Move_judge(object sender, int X, int Y, Chess[][] checkerboard)
{
if (this.side == player_type.blue)
{
if (X > )
{
return false;
}
}
else
{
if (X < )
{
return false;
}
}
if ((X - Chess.chosenX) * (X - Chess.chosenX) + (Chess.chosenY - Y) * (Chess.chosenY - Y) != )
{
return false;
}
if (checkerboard[(X + Chess.chosenX) / ][(Y + Chess.chosenY) / ].side != player_type.blank)
{
return false;
}
return true;
}
public override void Put_picture()
{
if (base.side == player_type.red)
this.PB.Image = global::象棋_封_.Properties.Resources.红象;
else
this.PB.Image = global::象棋_封_.Properties.Resources.蓝象;
}
}
}
象类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 象棋_封_
{
class Chess_zu:Chess
{
public Chess_zu(player_type b)
{
base.type = chess_type.zu;
base.side = b;
}
public override bool Move_judge(object sender, int X, int Y, Chess[][] checkerboard)
{
if (this.side == player_type.blue)//蓝方卒
{
if (Chess.chosenX < && X - Chess.chosenX != )//在5行后选中的卒
{
return false;
}
if (Chess.chosenX > )//移动布数不能大于1
{
if (X == Chess.chosenX && Math.Abs(Y - Chess.chosenY) != )
{
return false;
}
if (Y == Chess.chosenY && X - Chess.chosenX != )
{
return false;
}
}
}
else//红方卒
{
if (Chess.chosenX > && Chess.chosenX - X != )
{
return false;
}
if (Chess.chosenX < )
{
if (X == Chess.chosenX && Math.Abs(Y - Chess.chosenY) != )
{
return false;
}
if (Y == Chess.chosenY && Chess.chosenX - X != )
{
return false;
}
}
}
return true;
}
public override void Put_picture()
{
if (base.side == player_type.red)
this.PB.Image = global::象棋_封_.Properties.Resources.红兵;
else
this.PB.Image = global::象棋_封_.Properties.Resources.蓝卒;
}
}
}
卒类
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; namespace 象棋_封_
{
public partial class Start : Form
{
public Start()
{
InitializeComponent();
} private void LB_Begin_Click(object sender, EventArgs e)
{
Main f = new Main();
f.Show();
this.Hide();
} private void label2_Click(object sender, EventArgs e)
{
About f = new About();
f.Show();
this.Hide();
} private void LB_exit_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
主窗体代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms; namespace 象棋_封_
{
class Time
{
public Timer t;
private Label l;
private double s ;
private double m ;
public double sum=;
public static string fen="";
public static string miao ="";
public Time(Timer t,Label L)
{
s = ;
m = ;
this.t = t;
this.l = L;
}
public string outtime()
{
string second;
string minute;
s++;
if (s >= )
{
m = s / ;
s = s % ;
}
second = Convert.ToString(s);
minute = Convert.ToString(m);
string sum = minute + ":" + second;
return sum;
}
public void clear()
{
fen = (Convert.ToInt32(fen) + m).ToString();
miao = (Convert.ToInt32(miao) + s).ToString();
l.Text = "";
m = ;
s = ;
}
}
}
timer类