五子棋程序实现了判赢,禁手,复盘,低级AI(判断还存在许多问题,欢迎指正),继续游戏,夜间模式,悔棋等基本功能
代码可研究不可复制粘贴。
禁手的定义:是为了限制黑方的先手优势而设定的一种比赛规则
禁手的分类:三三禁手(黑棋一子落下同时形成两个或两个以上的活三,此子必须为两个活三共同的构成子)、四四禁手(黑棋一子落下同时形成两个或两个以上的冲四或活四)、长连禁手(黑棋一子落下形成一个或一个以上的长连)。
构成禁手的基本子力要素:活三(本方再走一着可以形成活四的三)、活四(有两个点可以成五的四)、冲四(只有一个点可以成五的四)、长连(在棋盘上的阳线和阴线任意一条线上,形成的5个以上同色棋子不间隔的相连)
关于禁手的规定:黑方五连与禁手同时形成,禁手失效,黑方胜
具体规则参见附件
程序说明:
0表示空位,1表示黑子,-1表示白子,chesses[15][15]保存的棋盘的当前棋局
本程序的长连禁手是和判赢一起判断的,判赢算法中会返回当前下子的位置四周有几颗同颜色子相连,如果是黑子并且长度大于5则为长连禁手。
代码举例:
/** * 计算横向是否 5颗相同颜色的子相连 * @param r 当前下子的横坐标 * @param c 当前下子的纵坐标 * @return */ public static int checkRow(int r, int c) { int count = 1; // 向右找 for (int j = c + 1; j < COLS; j++) { if (chesses[r][c] == chesses[r][j]) { count++; } else { break; } } // 往左走 for (int j = c - 1; j >= 0; j--) { if (chesses[r][c] == chesses[r][j]) { count++; } else { break; } } return count; } public static boolean longlink(int r, int c) { if (chesses[r][c] == 1) { return (SuanFa.checkRow(r, c) > 5 || SuanFa.checkxiezuo(r, c) > 5 || SuanFa.checkCol(r, c) > 5 || SuanFa.checkxieyou(r, c) > 5); } else { return false; }
三三禁手和四四禁手类似,但是四四禁手有一些特殊情况。这里一44禁手为例进行说明
首先,判断禁手,并不需要扫描整个棋盘,只需要扫描当前落子的周围关键位置,比如放了棋子在chesses[r][c]的位置,横向只需要扫描chesses[r-4][c-4]到[r+4][c+4]的位置。选择好范围之后,从[r-4][c-4]开始,每次扫描连续的5个位置看是否构成活四或者重四(三三禁手只有活三),由于采用1,-1来计数,可以直接这样判断:
if (chesses[r][j] + chesses[r][j + 1] + chesses[r][j + 2]+ chesses[r][j + 3] +chesses[r][j + 4] == 4)
如果这5个连续位置相加为4,必然是4个黑子和一个空位。(用1,2标记棋盘黑白子处理相对来说麻烦一点,但原理是一样的,多加几个判断即可。)
依次从各个方向找完之后,我们可以用count来记录找到了几个满足条件的活四或者冲四或者活三。
如果找到两个,已经构成禁手,立即结束查找。
但是,如果你理解了以上过程,你就会发现,现在的情况只能判断特定的一些禁手情况。这里我用图片进行说明:
图片1中这类型禁手已经可以进行判断了,(4,5)为最后一颗黑色落子,他会从(4,5)位置为焦点进行扫描,横向竖向都已经扫到了活三。但是2中的这种情况,以(7,10)进行扫描的话无法扫描出(6,X)横向的活三。
所以在扫描过程中,还需要对(7,10)周围的(6,10)进行扫描,如果以(6,10)为焦点也扫描到了活三,这个时候也是三三禁手。
这里用一个层次来标记一下,方便递归来查找。int cenci=1;如果是SetChesses设置的棋子,那么他的cenci=1;如果是SetChesses设置的棋子为焦点扫描到的活三,活四,冲四,那么该方向其余元素(6,10),(8,10)的层次cenci=0;这样,就不会一直扫描下去。
在这里又出现一个问题,即便用cenci来记录了要找周围元素的活四等等,以(6,10)为例,(6,10)会找到横着的活三,也会找到竖着的活三,这样,竖着的就算重复了,这是非常不合理的,所以得用一个变量标记一下方向,对于层次为0的我们只要找其余三个方向。
活四中还有几种特例:比如:
此处(5,6)构成了四四禁手(三三禁手没有这样的特例),由于这种类型的禁手很少,所以在程序中单独列举出来进行判断。
活四判断代码参考如下:
public static int Four(int r, int c, int cenci, char direction) { if (chesses[r][c] == 1) { int i, j, count4 = 0; if (cenci == 1) { // 判断横向四 for (j = 0; j < 11; j++) { if (chesses[r][j] + chesses[r][j + 1] + chesses[r][j + 2] + chesses[r][j + 3] + chesses[r][j + 4] == 4) { count4++; for (int k = 0; k < 5; k++) { if (chesses[r][j + k] == 1) { count4 += Four(r, j + k, 0, 'a'); if (count4 > 1) { return 2; } } } break; } } // 判断纵向四 for (i = 0; i < 11; i++) { if (chesses[i][c] + chesses[i + 1][c] + chesses[i + 2][c] + chesses[i + 3][c] + chesses[i + 4][c] == 4) { count4++; for (int k = 0; k < 5; k++) { if (chesses[i + k][c] == 1) { count4 += Four(i + k, c, 0, 'b'); if (count4 > 1) { return 2; } } } break; } } // 判断“\”向四 if (c > r) { for (i = 0, j = c - r; i < (11 - c + r); i++, j++) { if (chesses[i][j] + chesses[i + 1][j + 1] + chesses[i + 2][j + 2] + chesses[i + 3][j + 3] + chesses[i + 4][j + 4] == 4) { count4++; for (int k = 0; k < 5; k++) { if (chesses[i + k][j + k] == 1) { count4 += Four(i + k, j + k, 0, 'c'); if (count4 > 1) { return 2; } } } break; } } } else { for (i = r - c, j = 0; i < 11; i++, j++) { // 判断“\”向“活三” if (chesses[i][j] + chesses[i + 1][j + 1] + chesses[i + 2][j + 2] + chesses[i + 3][j + 3] + chesses[i + 4][j + 4] == 4) { count4++; for (int k = 0; k < 5; k++) { if (chesses[i + k][j + k] == 1) { count4 += Four(i + k, j + k, 0, 'c'); if (count4 > 1) { return 2; } } } break; } } } if (r + c < 15) { for (i = r + c, j = 0; i >= 4; i--, j++) { // 判断“/”向“活三” if (chesses[i][j] + chesses[i - 1][j + 1] + chesses[i - 2][j + 2] + chesses[i - 3][j + 3] + chesses[i - 4][j + 4] == 4) { count4++; for (int k = 0; k < 5; k++) { if (chesses[i - k][j + k] == 1) { count4 += Four(i - k, j + k, 0, 'd'); if (count4 > 1) { return 2; } } } break; } } } else { for (i = 14, j = r + c - 14; j < 11; i--, j++) { // 判断“/”向“活三” if (chesses[i][j] + chesses[i - 1][j + 1] + chesses[i - 2][j + 2] + chesses[i - 3][j + 3] + chesses[i - 4][j + 4] == 4) { count4++; for (int k = 0; k < 5; k++) { if (chesses[i - k][j + k] == 1) { count4 += Four(i - k, j + k, 0, 'd'); if (count4 > 1) { return 2; } } } break; } } } if (count4 > 1) { return 2; } } else { if (direction != 'a') { // 判断横向四 for (j = 0; j < 11; j++) { if (chesses[r][j] + chesses[r][j + 1] + chesses[r][j + 2] + chesses[r][j + 3] + chesses[r][j + 4] == 4) { return 1; } } } if (direction != 'b') { // 判断纵向四 for (i = 0; i < 11; i++) { if (chesses[i][c] + chesses[i + 1][c] + chesses[i + 2][c] + chesses[i + 3][c] + chesses[i + 4][c] == 4) { return 1; } } } if (direction != 'c') { // 判断“\”向四 if (c > r) { for (i = 0, j = c - r; i < (11 - c + r); i++, j++) { if (chesses[i][j] + chesses[i + 1][j + 1] + chesses[i + 2][j + 2] + chesses[i + 3][j + 3] + chesses[i + 4][j + 4] == 4) { return 1; } } } else { for (i = r - c, j = 0; i < 11; i++, j++) { // 判断“\”向“活三” if (chesses[i][j] + chesses[i + 1][j + 1] + chesses[i + 2][j + 2] + chesses[i + 3][j + 3] + chesses[i + 4][j + 4] == 4) { return 1; } } } } if (direction != 'd') { if (r + c < 15) { for (i = r + c, j = 0; i >= 4; i--, j++) { // 判断“/”向“活三” if (chesses[i][j] + chesses[i - 1][j + 1] + chesses[i - 2][j + 2] + chesses[i - 3][j + 3] + chesses[i - 4][j + 4] == 4) { return 1; } } } else { for (i = 14, j = r + c - 14; j < 11; i--, j++) { // 判断“/”向“活三” if (chesses[i][j] + chesses[i - 1][j + 1] + chesses[i - 2][j + 2] + chesses[i - 3][j + 3] + chesses[i - 4][j + 4] == 4) { return 1; } } } } } // 横向特殊四四 if (c > 2 && c < 12 && chesses[r][c - 3] == 1 && chesses[r][c - 2] == 0 && chesses[r][c - 1] == 1 && chesses[r][c + 3] == 1 && chesses[r][c + 2] == 0 && chesses[r][c + 1] == 1) { return 2; } else if (c > 2 && c < 11 && chesses[r][c - 3] == 1 && chesses[r][c - 2] == 1 && chesses[r][c - 1] == 0 && chesses[r][c + 4] == 1 && chesses[r][c + 3] == 1 && chesses[r][c + 2] == 0 && chesses[r][c + 1] == 1) { return 2; } else if (c > 3 && c < 11 && chesses[r][c - 4] == 1 && chesses[r][c - 3] == 1 && chesses[r][c - 2] == 1 && chesses[r][c - 1] == 0 && chesses[r][c + 4] == 1 && chesses[r][c + 3] == 1 && chesses[r][c + 2] == 1 && chesses[r][c + 1] == 0) { return 2; } else if (c > 3 && c < 11 && chesses[r][c - 4] == 1 && chesses[r][c - 3] == 1 && chesses[r][c - 2] == 0 && chesses[r][c - 1] == 1 && chesses[r][c + 4] == 1 && chesses[r][c + 3] == 1 && chesses[r][c + 2] == 0 && chesses[r][c + 1] == 1) { return 2; } // 纵向特殊四四 if (r > 2 && r < 12 && chesses[r - 3][c] == 1 && chesses[r - 2][c] == 0 && chesses[r - 1][c] == 1 && chesses[r + 3][c] == 1 && chesses[r + 2][c] == 0 && chesses[r + 1][c] == 1) { return 2; } else if (r > 2 && r < 11 && chesses[r - 3][c] == 1 && chesses[r - 2][c] == 1 && chesses[r - 1][c] == 0 && chesses[r + 4][c] == 1 && chesses[r + 3][c] == 1 && chesses[r + 2][c] == 0 && chesses[r + 1][c] == 1) { return 2; } else if (r > 3 && r < 11 && chesses[r - 4][c] == 1 && chesses[r - 3][c] == 1 && chesses[r - 2][c] == 1 && chesses[r - 1][c] == 0 && chesses[r + 4][c] == 1 && chesses[r + 3][c] == 1 && chesses[r + 2][c] == 1 && chesses[r + 1][c] == 0) { return 2; } else if (r > 3 && r < 11 && chesses[r - 4][c] == 1 && chesses[r - 3][c] == 1 && chesses[r - 2][c] == 0 && chesses[r - 1][c] == 1 && chesses[r + 4][c] == 1 && chesses[r + 3][c] == 1 && chesses[r + 2][c] == 0 && chesses[r + 1][c] == 1) { return 2; } // "\"向特殊四四 if (c > 2 && c < 12 && r > 2 && r < 12 && chesses[r - 3][c - 3] == 1 && chesses[r - 2][c - 2] == 0 && chesses[r - 1][c - 1] == 1 && chesses[r + 3][c + 3] == 1 && chesses[r + 2][c + 2] == 0 && chesses[r + 1][c + 1] == 1) { return 2; } else if (c > 2 && c < 11 && r > 2 && r < 11 && chesses[r - 3][c - 3] == 1 && chesses[r - 2][c - 2] == 1 && chesses[r - 1][c - 1] == 0 && chesses[r + 4][c + 4] == 1 && chesses[r + 3][c + 3] == 1 && chesses[r + 2][c + 2] == 0 && chesses[r + 1][c + 1] == 1) { return 2; } else if (c > 3 && c < 11 && r > 3 && r < 11 && chesses[r - 4][c - 4] == 1 && chesses[r - 3][c - 3] == 1 && chesses[r - 2][c - 2] == 1 && chesses[r - 1][c - 1] == 0 && chesses[r + 4][c + 4] == 1 && chesses[r + 3][c + 3] == 1 && chesses[r + 2][c + 2] == 1 && chesses[r + 1][c + 1] == 0) { return 2; } else if (c > 3 && c < 11 && r > 3 && r < 11 && chesses[r - 4][c - 4] == 1 && chesses[r - 3][c - 3] == 1 && chesses[r - 2][c - 2] == 0 && chesses[r - 1][c - 1] == 1 && chesses[r + 4][c + 4] == 1 && chesses[r + 3][c + 3] == 1 && chesses[r + 2][c + 2] == 0 && chesses[r + 1][c + 1] == 1) { return 2; } // "/"向特殊四四 // 101 1 101 if (c > 2 && c < 12 && r > 2 && r < 12 && chesses[r - 3][c + 3] == 1 && chesses[r - 2][c + 2] == 0 && chesses[r - 1][c + 1] == 1 && chesses[r + 3][c - 3] == 1 && chesses[r + 2][c - 2] == 0 && chesses[r + 1][c - 1] == 1) { return 2; } // 110 1 1011 else if (c > 3 && c < 12 && r > 3 && r < 11 && chesses[r - 3][c + 3] == 1 && chesses[r - 2][c + 2] == 1 && chesses[r - 1][c + 1] == 0 && chesses[r + 4][c - 4] == 1 && chesses[r + 3][c - 3] == 1 && chesses[r + 2][c - 2] == 0 && chesses[r + 1][c - 1] == 1) { return 2; } // 1110 1 0111 else if (c > 3 && c < 11 && r > 3 && r < 11 && chesses[r - 4][c + 4] == 1 && chesses[r - 3][c + 3] == 1 && chesses[r - 2][c + 2] == 1 && chesses[r - 1][c + 1] == 0 && chesses[r + 4][c - 4] == 1 && chesses[r + 3][c - 3] == 1 && chesses[r + 2][c - 2] == 1 && chesses[r + 1][c - 1] == 0) { return 2; } // 1101 1 011 else if (c > 3 && c < 11 && r > 3 && r < 11) { if (chesses[r - 4][c + 4] == 1 && chesses[r - 3][c + 3] == 1 && chesses[r - 2][c + 2] == 0 && chesses[r - 1][c + 1] == 1 && chesses[r + 4][c - 4] == 1 && chesses[r + 3][c - 3] == 1 && chesses[r + 2][c - 2] == 0 && chesses[r + 1][c - 1] == 1) { return 2; } } } return 0; }
函数调用如下:
/** * 判赢有禁手 * @param r 最后一次下子的行数 * @param c 最后一次下子的列数 */ public boolean JudgeWinWithJinshou(int r, int c) { if (Main.count == -1) {// 白子 if (SuanFa.beFive(r, c)) { javax.swing.JOptionPane.showMessageDialog(mu, "白子赢了!!"); ReDisplayChesseBoard(); return true; } } else if (Main.count == 1) {// 黑子 if (SuanFa.Five(r, c)) {// 五子 javax.swing.JOptionPane.showMessageDialog(mu, "黑子赢了!!"); ReDisplayChesseBoard(); return true; } else if (SuanFa.LiveThree(r, c, 1, 'e') > 1) { javax.swing.JOptionPane.showMessageDialog(mu, "三三禁手!黑子输了!!"); ReDisplayChesseBoard(); return true; } else if (SuanFa.Four(r, c, 1, 'e') > 1) { javax.swing.JOptionPane.showMessageDialog(mu, "四四禁手!黑子输了!!"); ReDisplayChesseBoard(); return true; } else if (SuanFa.longlink(r, c)) {// 长连 javax.swing.JOptionPane.showMessageDialog(mu, "长连禁手!黑子输了!!"); ReDisplayChesseBoard(); return true; } } return false; }
相关推荐
6. **游戏逻辑**:实现五子棋的规则,包括合法落子判断、五子连珠的检测、游戏结束条件的判定等。 7. **用户交互**:提供友好的界面,如提示、悔棋、重置游戏等功能。 8. **错误处理**:良好的错误处理机制可以...
首先,"禁手"是五子棋中的一个重要概念,它是为了平衡双方实力而引入的规则。在专业比赛中,禁手规则通常包括“三禁手”和“四禁手”。三禁手是指黑方不能连续下三颗子形成活三,即三个连续的黑子加上一个空位可以...
7. **游戏逻辑**:理解游戏规则的实现,如落子合法性检查、胜负判断、悔棋功能等。 通过研究这个项目,不仅可以提升Java编程技能,还能学习到如何将抽象概念转化为直观的游戏体验,对于有志于游戏开发的初学者来说...
【标题】"java五子棋&斗地主源码.rar" 涉及到的是两个经典游戏——五子棋和斗地主的Java实现。在Java编程领域,开发游戏是学习面向对象编程、图形用户界面设计以及算法的重要实践。下面我们将深入探讨这两个项目中的...
本文将深入探讨一个基于Java的五子棋博弈系统,该系统是在Java面向对象程序设计课程设计任务中实现的,利用了Eclipse IDE作为开发工具,并融入了人工智能的元素。我们将详细介绍其核心技术和实现过程。 首先,Java...
5. Pente.cpp:这很可能是五子棋游戏的核心逻辑类,包含了游戏规则、玩家操作、胜负判断等功能的实现。 6. BestDlg.cpp:从名字推测,这可能涉及到最佳走法或AI算法的实现,比如基于最小-最大搜索或者Alpha-Beta...
此外,游戏还需要考虑“禁手规则”,例如“三三禁手”和“四四禁手”,以避免无尽的循环和不公平的游戏结果。 游戏可能还包括一些额外的功能,如AI模式,让计算机与玩家对弈。在这种情况下,开发者可能使用了简单的...
五子棋游戏想必大家都非常熟悉,游戏规则十分简单。游戏开始后,玩家在游戏设置中选择人机对战,则系统执黑棋,玩家自己执白棋。双方轮流下一棋,先将横、竖或斜线的5个或5个以上同色棋子连成不间断的一排者为胜。 ...
2. **棋盘逻辑**:在Java代码中实现棋盘的逻辑,包括棋子的落点判断、胜负检测、禁手规则等。这部分是游戏的核心,需要良好的数据结构和算法支持。可以使用二维数组来表示棋盘,每个元素代表一个位置的状态(空、...
此外,为了提高用户体验,可能会实现复盘、悔棋、保存和加载游戏进度等功能。 总的来说,这篇毕业设计论文及其源代码涵盖了Android应用开发的多个方面,对于想要学习Android游戏开发的学生和开发者来说,是一个宝贵...
总的来说,安卓五子棋人机对战游戏的开发涵盖了安卓应用的基础架构、AI算法的实现、用户界面的设计以及游戏逻辑的控制等多个方面,是一个综合性的编程实践项目。对于想要学习安卓开发和AI算法的初学者来说,这是一个...
五子棋,这古老的智力游戏,以其简洁的规则和深邃的策略吸引着无数爱好者。在这个数字化的时代,一款名为“五子棋(AI人机对战,人人对战,国际化,读设残局)”的软件应运而生,为玩家提供了更为丰富的对弈体验。该...
总的来说,“wuziqi.rar”中的Java五子棋代码实现涵盖了许多基础和高级的编程技术,包括数据结构、图形用户界面、事件处理、游戏逻辑以及软件设计原则。通过分析和理解这段代码,开发者可以增进对Java编程以及游戏...
本程序主要是建立一个具有完整规则的五子棋局域网对战平台,使两台不同计算机的使用者通过局域网的连接达到网络对战五子棋的效果。主要通过基于TCP/IP协议的套接字Socket,基于Java语言和GUI框架,采用Eclipse编写。...