实例介绍
【实例截图】
【核心代码】
public partial class Form1 : Form
{
//数据区××××××××××××××××××××数据区×××××××××××××××××××××××××××××
public class StepPoint//下棋点,用于回溯
{
public int x;
public int y;
public int color;
};
public FormSet formSet;//设置对话框
public FormAbout formAbout;//关于对话框
public Bitmap blackBmp;//黑子
public Bitmap whiteBmp;//白子
public Bitmap boardBmp;//棋盘
bool end = false;
public int[,] chessBoard;//1:黑子,-1:白子,0:无子
Bitmap backGroundImage;//直接设为前景,从而不用重绘控件
Graphics pbGraph;//把缓冲图画到前景上
public int computerColor;
public int manColor;
public Stack<Point> tryStepStack = new Stack<Point>();//用来试探步子回溯的栈
public Stack<StepPoint> backStack = new Stack<StepPoint>();//悔棋用的。
int totalChessCount = 0;//棋盘上的棋子数
//数据区×××××××××××××××××××××××数据区××××××××××××××××××××××××××
public Form1()//初始化
{
InitializeComponent();
formSet = new FormSet();
formAbout = new FormAbout();
blackBmp = new Bitmap("black.bmp");
blackBmp.MakeTransparent(Color.Red);
whiteBmp = new Bitmap("white.bmp");
whiteBmp.MakeTransparent(Color.Red);
boardBmp = new Bitmap("board.bmp");
chessBoard = new int[15, 15];
backGroundImage = new Bitmap(pbBoard.Width, pbBoard.Height);
pbGraph = Graphics.FromImage(backGroundImage);
pbBoard.BackgroundImage = boardBmp;
pbGraph.DrawImage(boardBmp, 0, 0);
pbBoard.Image = backGroundImage;//哈哈,Lisa的聪明之计,不用刷新窗体。
pbBoard.Refresh();
totalChessCount = 0;
if (formSet.isComputerFirst)
{
computerColor = 1;
manColor = -1;
}
else
{
computerColor = -1;
manColor = 1;
}
if (formSet.isComputerFirst)
{
putChess(1, 7, 7);//在棋盘中心画下一个黑棋
}
end = false;
}
private void btnNewGame_Click(object sender, EventArgs e)
{
for (int i = 0; i < 15; i )//初始化棋盘
for (int j = 0; j < 15; j )
{
chessBoard[i, j] = 0;
}
if (formSet.isComputerFirst)
{
computerColor = 1;
manColor = -1;
}
else
{
computerColor = -1;
manColor = 1;
}
totalChessCount = 0;
pbGraph.DrawImage(boardBmp, 0, 0);
pbBoard.Refresh();
if (formSet.isComputerFirst)
{
putChess(1, 7, 7);//在棋盘中心画下一个黑棋
}
end = false;
backStack.Clear();
}
private void btnSet_Click(object sender, EventArgs e)
{
if (formSet.ShowDialog() == DialogResult.OK)
{
for (int i = 0; i < 15; i )//初始化棋盘
for (int j = 0; j < 15; j )
{
chessBoard[i, j] = 0;
}
if (formSet.isComputerFirst)
{
computerColor = 1;
manColor = -1;
}
else
{
computerColor = -1;
manColor = 1;
}
totalChessCount = 0;
pbGraph.DrawImage(boardBmp, 0, 0);
pbBoard.Refresh();
if (formSet.isComputerFirst)
{
putChess(1, 7, 7);//在棋盘中心画下一个黑棋
}
end = false;
backStack.Clear();
}
}
//放一个棋子到棋盘上////////////////////////////////////
private void putChess(int color, int x, int y)
{
StepPoint point = new StepPoint();
point.x = x;
point.y = y;
point.color = color;
backStack.Push(point);
if (color == 1)
{
chessBoard[x, y] = 1;
pbGraph.DrawImage(blackBmp, x * 23 2, y * 23 2);//画棋子
}
else
{
chessBoard[x, y] = -1;
pbGraph.DrawImage(whiteBmp, x * 23 2, y * 23 2);//画棋子
}
totalChessCount ;
pbBoard.Refresh();
}//放一下棋子到棋盘上
//悔棋////////////////////////////////////
private void btnBack_Click(object sender, EventArgs e)
{
if (backStack.Count > 0)
{
StepPoint point = backStack.Pop();
if (point.color == computerColor)
{
if (backStack.Count == 0)
{
backStack.Push(point);
return;
}
chessBoard[point.x, point.y] = 0;
totalChessCount--;
point = backStack.Pop();
}
chessBoard[point.x, point.y] = 0;
totalChessCount--;
pbGraph.DrawImage(boardBmp, 0, 0);
for (int i = 0; i < 15; i )
{
for (int j = 0; j < 15; j )
{
if (chessBoard[i, j] == 1) pbGraph.DrawImage(blackBmp, i * 23 2, j * 23 2);
if (chessBoard[i, j] == -1) pbGraph.DrawImage(whiteBmp, i * 23 2, j * 23 2);
}
}
pbBoard.Refresh();
end = false;
}
}//悔棋
private void btnAbout_Click(object sender, EventArgs e)
{
formAbout.ShowDialog();
}
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
private void pbBoard_MouseClick(object sender, MouseEventArgs e)
{
int x = (e.X 2) / 23;
int y = (e.Y 2) / 23;
if ( x < 15 && y < 15 && chessBoard[x, y] == 0)
{
if (!end)
{
int weightTmp = pointWeight(manColor, x, y);//先称一称该点的权重
if (weightTmp == -2)//长连禁手
{
MessageBox.Show("抱歉!本点为长连禁手点,你不能下!", "警告", MessageBoxButtons.OK);
return;
}
else if (weightTmp >= 150000)//赢了
{
putChess(manColor, x, y);
MessageBox.Show("恭喜,你赢了!", "本局结果", MessageBoxButtons.OK);
end = true;
return;
}
else if (weightTmp == -1)
{
MessageBox.Show("抱歉!本点为禁手点,你不能下!", "警告", MessageBoxButtons.OK);
return;
}
else if (totalChessCount >= 224)
{
putChess(manColor, x, y);
MessageBox.Show("棋盘已满,本局平棋!", "本局结果", MessageBoxButtons.OK);
end = true;
return;
}
else
{
putChess(manColor, x, y);
int bx = 0, by = 0;
if (searchBestPoint(computerColor, ref bx, ref by))
{
weightTmp = pointWeight(computerColor, bx, by);
putChess(computerColor, bx, by);
if (weightTmp >= 150000)
{
MessageBox.Show("抱歉,你输了!要加油哦!", "本局结果", MessageBoxButtons.OK);
end = true;
return;
}
else if (totalChessCount == 225)
{
MessageBox.Show("棋盘已满,本局平棋!", "本局结果", MessageBoxButtons.OK);
end = true;
return;
}
}
else
{
MessageBox.Show("恭喜你,你赢了!棋盘上所有的点都是电脑的禁手点!", "本局结果", MessageBoxButtons.OK);
end = true;
return;
}
}
}
}
}
//判断点(x,y)放入黑棋后是否形成长连////////////////////////////////////
private bool hasLongLink(int x, int y)
{
int count = 1;
for (int i = 5; i >= 0; i--)
{
int c = x, d = y, cmin = 0, cmax = 9, dmin = 0, dmax = 9, xp = 1, yp = 0;
for (int t = 0; t < 2; t )
{
if (c - i >= cmin && c - i <= cmax)
{
for (int j = 0; j < 6; j )// -水平|垂直
{
count = chessBoard[x - (i - j) * xp, y - (i - j) * yp];
}
if (count == 6) return true;
count = 1;
if (yp < 1) yp = 1; else xp = -1;
if (d - i * xp >= dmin && d - i * xp <= dmax)// \/方向
{
for (int j = 0; j < 6; j )
{
count = chessBoard[x - (i - j) * xp, y - (i - j) * yp];
}
if (count == 6) return true;
count = 1;
}
}
xp = 0; yp = 1; c = y; d = x; dmin = 5; dmax = 14;
}
}
return false;
}//判断点(x,y)放入黑棋后是否形成长连
//判断两点(x1,y1),(x2,y2)间是否存在活的count////////////////////////////////////
private bool liveCount(int color, int count, int x1, int y1, int x2, int y2)
{
int x, y, i, j, length, xPlus = 0, yPlus = 0, sum;
int temp1, temp2;
temp1 = Math.Min(Math.Min(Math.Min(5 - count, x1), y1), 14 - y1);
temp2 = Math.Min(Math.Min(Math.Min(5 - count, 14 - x2), 14 - y2), y2);
length = Math.Max(Math.Abs(x1 - x2), Math.Abs(y1 - y2)) 1 temp1 temp2;
if (x1 != x2) xPlus = 1;
if (y1 != y2) yPlus = (y2 - y1) / Math.Abs(y2 - y1);
for (i = 0; i < length - 4; i )
{
x = x1 - temp1 * xPlus i * xPlus;
y = y1 - temp1 * yPlus i * yPlus;
if (x 4 * xPlus > 14 || y 4 * yPlus > 14)
break;
sum = 0;
for (j = 0; j < 4; j )
{
if (chessBoard[x j * xPlus, y j * yPlus] == color)
sum ;
else if (chessBoard[x j * xPlus, y j * yPlus] == -color)
{
sum = 0;
break;
}
}
if (0 < x && 0 <= y - yPlus && y - yPlus <= 14)
{
if (sum == count && chessBoard[x - xPlus, y - yPlus] == 0 && chessBoard[x 4 * xPlus, y 4 * yPlus] == 0)
return true;
}
}
return false;
}//判断两点(x1,y1),(x2,y2)间是否存在活的count
//求两点(x1,y1),(x2,y2)间最长的color色连的棋的数目////////////////////////////////////
private int linkCount(int color, int x1, int y1, int x2, int y2)
{
int x, y, i, j, length, xPlus = 0, yPlus = 0, sum, maxSum = 0;
length = Math.Max(Math.Abs(x1 - x2), Math.Abs(y1 - y2)) 1;
if (x1 != x2) xPlus = 1;
if (y1 != y2) yPlus = (y2 - y1) / Math.Abs(y2 - y1);
for (i = 0; i < length - 4; i )
{
x = x1 i * xPlus;
y = y1 i * yPlus;
sum = 0;
for (j = 0; j < 5; j )
{
if (chessBoard[x j * xPlus, y j * yPlus] == color)
sum ;
else if (chessBoard[x j * xPlus, y j * yPlus] == -color)
{
sum = 0;
break;
}
}
if (maxSum < sum)
maxSum = sum;
}
return maxSum;
}//求两点(x1,y1),(x2,y2)间可能形成五连的color色棋的数目
//(x,y)处放color色棋后是否能在(x1,y1)和(x2,y2)之间形成活count且不被另一色棋时不被破坏////////////////////////////////////
private bool breakLiveCount(int color, int count, int x, int y, int x1, int y1, int x2, int y2)
{
if (!liveCount(color, count, x1, y1, x2, y2)) return false;
if (count == 5) return false;
else if (count == 4) return true;
else
{
bool blnFlag;
chessBoard[x, y] = -color;
blnFlag = !liveCount(color, count - 1, x1, y1, x2, y2);
chessBoard[x, y] = color;
return blnFlag;
}
}//(x,y)处放color色棋后是否能形成活count且放另一色棋时不被破坏
//寻找最好的10个下棋点,如有多个最大值,则采用随机方式给出。找不到就返回false////////////////////////////////////
private bool searchBestPoint(int color, ref int x, ref int y)
{
int[,] weight=new int[15,15];
int[] ww = new int[10];
int[] xx = new int[10];
int[] yy = new int[10];
int max = 0;
for (int i = 0; i < 15; i )
for (int j = 0; j < 15; j )
weight[i, j] = pointWeight(color, i, j);
for (int i = 0; i < 10; i )//找出weight值最高的十个点
{
max = -4;//权值最小也就-3
for (int m = 0; m < 15; m )
for (int n = 0; n < 15; n )
if (max < weight[m, n])
{
max = weight[m, n];
xx[i] = m;
yy[i] = n;
weight[m, n] = -5;
}
ww[i]=max;
}
if (ww[0] < 0)//最高值小于0,说明无子可子
return false;
else
{
int count = 1;
while (count<10&&ww[count] == ww[0]) count ;
Random ra = new Random();
int index=ra.Next(count);
x = xx[index];
y = yy[index];
return true;
}
}
//求color色棋在(x,y)点的权重////////////////////////////////////
private int pointWeight(int color, int x, int y)
{
int totalWeight;
int[] colorLink = new int[6];//下棋方棋连数从0~5
int[] colorLive = new int[6];//下棋方连棋数从0~5
int[] fcolorLink = new int[6];//对手方棋连数从0~5
int[] fcolorLive = new int[6];//对手方棋连数从0~5
int tempLive3 = 0, temp, linkCounts;
Point left = new Point(Math.Max(0, x - 5), y);
Point right = new Point(Math.Min(14, x 5), y);
Point top = new Point(x, Math.Max(0, y - 5));
Point down = new Point(x, Math.Min(14, y 5));
temp = Math.Min(x - left.X, y - top.Y);
Point leftTop = new Point(x - temp, y - temp);
temp = Math.Min(x - left.X, down.Y - y);
Point leftDown = new Point(x - temp, y temp);
temp = Math.Min(right.X - x, y - top.Y);
Point rightTop = new Point(x temp, y - temp);
temp = Math.Min(right.X - x, down.Y - y);
Point rightDown = new Point(x temp, y temp);
if (chessBoard[x, y] != 0) return -3;
else
{
//下方棋连子的情况/////////////////////////////////////////////////////////////
chessBoard[x, y] = color;
//左右方向
linkCounts = linkCount(color, left.X, left.Y, right.X, right.Y);
colorLink[linkCounts] ;
if (liveCount(1, linkCounts, left.X, left.Y, right.X, right.Y))
{
colorLink[linkCounts]--;
colorLive[linkCounts] ;
}
//上下方向
linkCounts = linkCount(color, top.X, top.Y, down.X, down.Y);
colorLink[linkCounts] ;
if (liveCount(1, linkCounts, top.X, top.Y, down.X, down.Y))
{
colorLink[linkCounts]--;
colorLive[linkCounts] ;
}
//左上_右下方向
linkCounts = linkCount(color, leftTop.X, leftTop.Y, rightDown.X, rightDown.Y);
colorLink[linkCounts] ;
if (liveCount(1, linkCounts, leftTop.X, leftTop.Y, rightDown.X, rightDown.Y))
{
colorLink[linkCounts]--;
colorLive[linkCounts] ;
}
//左下_右上方向
linkCounts = linkCount(color, leftDown.X, leftDown.Y, rightTop.X, rightTop.Y);
colorLink[linkCounts] ;
if (liveCount(1, linkCounts, leftDown.X, leftDown.Y, rightTop.X, rightTop.Y))
{
colorLink[linkCounts]--;
colorLive[linkCounts] ;
}
///对方棋连子的情况/////////////////////////////////////////////////////////////
chessBoard[x, y] = -color;
//左右方向
linkCounts = linkCount(-color, left.X, left.Y, right.X, right.Y);
fcolorLink[linkCounts] ;
if (breakLiveCount(-color, linkCounts, x, y, left.X, left.Y, right.X, right.Y))
{
fcolorLink[linkCounts]--;
fcolorLive[linkCounts] ;
}
//上下方向
linkCounts = linkCount(-color, top.X, top.Y, down.X, down.Y);
fcolorLink[linkCounts] ;
if (breakLiveCount(-color, linkCounts, x, y, top.X, top.Y, down.X, down.Y))
{
fcolorLink[linkCounts]--;
fcolorLive[linkCounts] ;
}
//左上_右下方向
linkCounts = linkCount(-color, leftTop.X, leftTop.Y, rightDown.X, rightDown.Y);
fcolorLink[linkCounts] ;
if (breakLiveCount(-color, linkCounts, x, y, leftTop.X, leftTop.Y, rightDown.X, rightDown.Y))
{
fcolorLink[linkCounts]--;
fcolorLive[linkCounts] ;
}
//左下_右上方向
linkCounts = linkCount(-color, leftDown.X, leftDown.Y, rightTop.X, rightTop.Y);
fcolorLink[linkCounts] ;
if (breakLiveCount(-color, linkCounts, x, y, leftDown.X, leftDown.Y, rightTop.X, rightTop.Y))
{
fcolorLink[linkCounts]--;
fcolorLive[linkCounts] ;
}
if (liveCount(-color, 3, left.X, left.Y, right.X, right.Y) && linkCount(-color, left.X, left.Y, right.X, right.Y) <= 3) tempLive3 ;
if (liveCount(-color, 3, top.X, top.Y, down.X, down.Y) && linkCount(-color, top.X, top.Y, down.X, down.Y) <= 3) tempLive3 ;
if (liveCount(-color, 3, leftTop.X, leftTop.Y, rightDown.X, rightDown.Y) && linkCount(-color, leftTop.X, leftTop.Y, rightDown.X, rightDown.Y) <= 3) tempLive3 ;
if (liveCount(-color, 3, leftDown.X, leftDown.Y, rightTop.X, rightTop.Y) && linkCount(-color, leftDown.X, leftDown.Y, rightTop.X, rightTop.Y) <= 3) tempLive3 ;
chessBoard[x, y] = 0;
//开始求权重/////////////////////////////////////////////////////////////////////
if (color == 1)//如果是下棋方是黑子,有禁手
{
if (hasLongLink(x, y))//对不起,长连
return -2;//禁手
else if (colorLink[5] > 0)//自己可以形成5
return 150000;
else if (colorLive[3] > 1 || colorLive[4] colorLink[4] > 1)//四四,活三三,都是禁手
return -1;
else if (fcolorLink[5] > 0)//破坏对方的5
return 140000;
else if (colorLive[4] == 1)//可以形成一个活四
return 130000;
else if (colorLink[4] == 1 && colorLive[3] == 1)//可以形成一个四三
return 120000;
else if (colorLink[4] == 1 && colorLink[3] > 0)
return 110000;
//防守式战略
else if (fcolorLive[4] > 0 || fcolorLink[4] > 1)
return 100000;
else if (fcolorLink[4] == 1 && tempLive3 == 1)
return 90000;
else if (fcolorLive[3] > 1)
return 80000;
else if (fcolorLink[4] == 1 && fcolorLink[3] > 0)
return 70000;
else
{
totalWeight = (colorLink[4] colorLive[3]) * 6250 (colorLink[3] colorLive[2] fcolorLink[4] fcolorLive[3]) * 1250
(colorLink[2] fcolorLink[3] fcolorLive[2]) * 250 colorLive[1] * 50 (colorLink[1] fcolorLink[2] fcolorLive[1]) * 10 fcolorLink[1] * 2;
return totalWeight;
}
}
else//如果是下棋方是白子,考虑黑子的禁手
{
bool isBlackForbiden = (tempLive3 > 1 || colorLive[4] > 1 || hasLongLink(x, y));//黑棋有禁手
bool isBlackLongLink = hasLongLink(x, y);//黑手有长连禁手
if (colorLink[5] > 0)//自已可以形成5
return 150000;
else if (fcolorLink[5] > 0 && !isBlackLongLink)//对方可以形成5,且没有长连禁手限制
return 140000;
//进攻与防守相结合的战略
else if (colorLive[4] > 0 || fcolorLink[4] > 1)//自己可以形成活四,或者对方可以形成两个四连
return 130000;
else if (colorLink[4] == 1 && fcolorLive[3] > 0)
return 120000;
else if (fcolorLive[4] == 1 && !isBlackForbiden || colorLink[4] > 1 && !isBlackForbiden)
return 110000;
else if (colorLink[4] == 1 && fcolorLink[3] > 0)
return 100000;
else if (fcolorLink[4] > 0 && tempLive3 == 1 && !isBlackForbiden)
return 90000;
else if (colorLive[3] > 1)
return 80000;
else if (fcolorLink[4] > 0 && colorLink[3] > 0 && !isBlackForbiden)
return 70000;
else
{
totalWeight = (colorLink[4] colorLive[3]) * 6250 (colorLink[3] colorLive[2] fcolorLink[4] fcolorLive[3]) * 1250
(colorLink[2] fcolorLink[3] fcolorLive[2]) * 250 colorLive[1] * 50 (colorLink[1] fcolorLink[2] fcolorLive[1]) * 10 fcolorLink[1] * 2;
return totalWeight;
}
}
}
}//求color色棋在(x,y)点的权重
}
标签: 五子棋
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论