实例介绍
【实例截图】
【核心代码】
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小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论