赞
踩
组长:郭瀚文 202203010057
组员:关乾春 202203010058 邓国岩 202203010059
项目完整代码:https://gitee.com/memoryee/gobang
一个简易的五子棋游戏,能够实现离线和联网对战。
离线模式能够支持本地双人对战。
联网模式需要用户登录并等待服务器匹配对手
通过socket编程,GUI设计,mysql等技术的学习,来实现一个联网的多人五子棋小游戏
socket编程,GUI设计,mysql
java
能够在本地实现双人对战
同时也能通过服务器联网实现异地对战
通过二维数组存储棋子在棋盘上的位置,在绘制棋盘,实现落子的功能
代码如下:
//在Mouse类中,通过重写mosueclicked方法来获取鼠标点击位置与棋盘格子的关系 public void mouseClicked(MouseEvent e) { int x = e.getX();// 鼠标点击处获取x、y坐标 int y = e.getY(); // 获取落子坐标,此处进行判断让获取的坐标位于棋盘线交点处 if ((x - x0) % size > size / 2) { x1 = (x - x0) / size + 1; } else if ((x - x0) % size <= size / 2) { x1 = (x - x0) / size; } if ((y - y0) % size > size / 2) { y1 = (y - y0) / size + 1; } else if ((y - y0) % size <= size / 2) { y1 = (y - y0) / size; } // System.out.println(y1 + " " + x1); // System.out.println(chessArr[y1][x1]); //判断本地游戏是否开始 if (start) { // 判断棋子是否会越出棋盘界 if (0 <= x1 && x1 <= 14 && 0 <= y1 && y1 <= 14) { // 判断只有空位置才能下棋 if (chessArr[y1][x1] == 0) { if (count % 2 == 0) { //static1.black.paintIcon(chessPanel, g, x1 * size - 25 + x0, y1 * size - 25 + y0); chessArr[y1][x1] = 1;// 记录棋盘上每颗棋子的颜色,黑色记1,白色记-1 chesses[count++] = new Chess(x1, y1, 1); } else { //static1.white.paintIcon(chessPanel, g, x1 * size - 25 + x0, y1 * size - 25 + y0); chessArr[y1][x1] = -1; chesses[count++] = new Chess(x1, y1, -1); } historyArea.refresh(y1, x1, chessArr[y1][x1]); chessPanel.repaint(); } } else { System.out.print("超出棋盘边界"); } int winner = win.checkWin(x1, y1);//获得谁是赢家 if(winner != 0) { winner(winner); } } }
定义chess类来存储一个棋子的坐标及颜色,定义一个chess的一位数组,用于表示第几步的棋
子是什么颜色以及坐标是多少,悔棋的时候按倒序依次取出棋子然后重新绘制棋盘,从而实现
悔棋的效果
代码如下:
//Mouse类中的方法 public void regret() { if(start && count >= 1) { -- count; int x = chesses[count].getX(); int y = chesses[count].getY(); chessArr[y][x] = 0; historyArea.setText(""); for(int i = 0; i < count; i ++ ) { x = chesses[i].getX(); y = chesses[i].getY(); int color = chesses[i].getColor(); historyArea.refresh(y, x, color); } chessPanel.repaint(); } }
原理同(2),按照顺序依次取出棋子,然后按顺序绘制在棋盘上。
为了实现复盘的效果,同时新建一个计时器类,设定固定的时间间隔来实现依次下棋的效果。
代码如下:
public void repeat() { timer = new Timer(); timer.schedule(new TimerTask() { int x, y, color, idx = 0; @Override public void run() { if(idx < count) { Chess thisChess = chesses[idx]; x = thisChess.getX(); y = thisChess.getY(); color = thisChess.getColor(); chessArr[y][x] = color; historyArea.refresh(y, x, color); chessPanel.repaint(); ++ idx; } else { timer.cancel(); } } }, 1000, 1000); //复盘后要禁止下棋,不用清零count因为开始时count一定为0 start = false; }
当某一方下棋后,判断该棋子各个方向的同色棋子是否达到五个
每个方向单独计数
某个方向的同色棋子数达到五个,判定游戏结束,禁止下棋
public class Win { private int[][] chessArr = new int[15][15]; private int count = 0; public Win(int[][] chessArr) { this.chessArr = chessArr; } //判断四个方向是否连成五个的判断函数 //水平 public int countchessX(int x1, int y1) { count = 1; for (int i = x1 + 1; i < chessArr.length; i++) { if (chessArr[y1][x1] == chessArr[y1][i]) { count++; } else { break; } } for (int i = x1 - 1; i >= 0; i--) { if (chessArr[y1][x1] == chessArr[y1][i]) { count++; } else { break; } } // System.out.println("X" + count); return count; } //竖直 public int countchessY(int x1, int y1) { count = 1; for (int i = y1 + 1; i < chessArr.length; i++) { if (chessArr[y1][x1] == chessArr[i][x1]) { count++; } else { break; } } for (int i = y1 - 1; i >= 0; i--) { if (chessArr[y1][x1] == chessArr[i][x1]) { count++; } else { break; } } // System.out.println("Y" + count); return count; } //y = x public int countchessM(int x1, int y1) { count = 1; for (int i = x1 + 1, j = y1 + 1; i < chessArr.length && j < chessArr.length; i++, j++) { if (chessArr[y1][x1] == chessArr[j][i]) { count++; } else { break; } } for (int i = x1 - 1, j = y1 - 1; i >= 0 && j >= 0; i--, j--) { if (chessArr[y1][x1] == chessArr[j][i]) { count++; } else { break; } } // System.out.println("M" + count); return count; } //y = -x public int countchessN(int x1, int y1) { count = 1; for (int i = x1 + 1, j = y1 - 1; i < chessArr.length && j >= 0; i++, j--) { if (chessArr[y1][x1] == chessArr[j][i]) { count++; } else { break; } } for (int i = x1 - 1, j = y1 + 1; i >= 0 && j < chessArr.length; i--, j++) { if (chessArr[y1][x1] == chessArr[j][i]) { count++; } else { break; } } return count; } //判断输赢的函数,返回哪个颜色获胜 public int checkWin(int x1, int y1) { int ret = 0; if (countchessX(x1, y1) >= 5 || countchessY(x1, y1) >= 5 || countchessM(x1, y1) >= 5 || countchessN(x1, y1) >= 5) { if (chessArr[y1][x1] == 1) { //最后下黑棋 ret = 1; } else if (chessArr[y1][x1] == -1) { //最后下白棋 ret = -1; } } return ret; } }
当用户点击联网对战按钮的时候,会弹出一个登陆界面,如果账号第一次登录则需要注册
如果,已经注册过,则会显示登陆成功,并显示当前用户的用户名
客户端及服务端的代码,请移步git仓库
https://gitee.com/memoryee/gobang
当用户登录成功后,就会于服务端去连接,当服务端的连接人数位两人时,游戏就会开始,就
可以开始下棋了,最先链接进入服务端的用户为先手,也就是黑棋
同上
客户端及服务端的代码,请移步git仓库
https://gitee.com/memoryee/gobang
1、主界面
2、游戏界面
3、用户登录界面
网络通信:实现网络通信是五子棋联网游戏的关键难点。需要在客户端和服务器端之间建立可靠的通信
连接,以保证双方可以实时传递游戏状态和数据信息。
游戏同步:在对弈双方进行游戏时,需要将游戏状态同步给对方,确保对弈双方看到的游戏状态是一致
且同步的。若游戏状态出现了不一致的情况,则会影响游戏的公平性和可玩性。
网络延迟:由于网络的延迟,可能会出现客户端和服务器端的数据不同步,或是造成游戏时间的卡顿。
为了减轻这种情况的影响,需要对网络延迟进行优化,采用更稳定的网络协议和传输方式进行数据传输。
算法优化:五子棋的算法较为复杂,需要进行深度优化,以避免游戏卡顿和影响游戏操作。此外,还需
要处理好游戏结束后的胜负判断、计分等问题。
安全性:网络游戏涉及到用户的个人信息和账号信息,需要考虑网络安全问题,防止信息被篡改或者泄
露。
总之,五子棋联网游戏,在实现过程中需要结合以上难点,采用合适的技术手段进行实现。同时,也需
要不断对游戏性能和用户体验进行优化,以提升游戏体验和用户满意度。
代码结构和可读性:实现五子棋联网游戏需要编写复杂的代码,对代码结构和可读性的要求十分高。
一个好的代码结构可以使代码更易于维护和修改,同时提高代码质量和可靠性。在编写代码时应尽量
避免重复代码和冗余代码,同时注重代码的格式和注释,让代码更加易懂。
网络通信:网络通信是现代软件设计中一个必不可少的重要模块。在实现五子棋联网游戏时,需要使
用网络通信技术实现客户端和服务器之间的数据传输。理解网络通信原理和技术可以为实现其他类型
的网络应用提供帮助。
算法优化:五子棋算法的优化需要经过多次实践和不断调整才能达到最佳效果,能够通过学习不同算
法和技巧来提高算法的效率。算法的优化对于软件设计和实现来说都是非常重要的一步,可以提高软
件的性能、稳定性和可靠性。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。