当前位置:   article > 正文

Java单机版五子棋的设计与实现(团队)_五子连珠游戏设计与实现

五子连珠游戏设计与实现

前言
五子棋是一种两人对弈的纯策略型棋类游戏,亦称串珠连,五子是中国民间非常熟知的一个古老棋种,它因操作简单、逻辑性强,深受大家喜爱。本项目基于Java技术,开发了一个操作简单、界面简洁、功能较完整的“五子棋”游戏。该游戏具有良好的用户界面和良好的用户体验,游戏AI设计也更为合理,可以实现双人模式的游戏。

效果展示

一 游戏界面

二 悔棋与重开功能

 

三 功能架构图

项目简介

开发的五子棋游戏,其要具有以下特点:系统操作简单,界面友好。界面灵活缩放,可随窗体大小绘制游戏界面,界面美观大方。黑白子轮流下棋,支持游戏悔棋的功能等。

总体需求

本程序主要完成五子棋游戏的简单操作,用户通过鼠标完成游戏过程。需要满足以下几点要求:
1.实现五子棋简易窗口界面。
2.实现黑白棋轮流下棋功能。
3.实现自动判断获胜方功能。
4.实现悔棋与重开游戏功能。

实现过程

1.绘制窗体对象。 

2.UI设计(包括游戏区域、黑白棋子、按钮和标题区域)。


3.使用鼠标监听事件实现下棋。

4.连成五子判定获胜的实现。

代码展示

写窗口、棋盘面板、控制面板

  1. import java.awt.BorderLayout;
  2. import java.awt.Toolkit;
  3. import java.awt.event.ActionEvent;
  4. import java.awt.event.ActionListener;
  5. import javax.swing.JButton;
  6. import javax.swing.JFrame;
  7. import javax.swing.JMenu;
  8. import javax.swing.JMenuBar;
  9. import javax.swing.JMenuItem;
  10. import javax.swing.JPanel;
  11. public class FiveFrame extends JFrame{
  12. public static final int WIDTH=300;
  13. public static final int HEIGH=400;
  14. private JPanel toolBar; //工具栏里面的三个按钮
  15. private JButton startButton,backButton,exitButton;
  16. private DrawPanel drawPanel; //棋盘的面板
  17. private JMenuBar menuBar;
  18. private JMenu sysMenu;
  19. private JMenuItem startMenuItem,backMenuItem,exitMenuItem;
  20. private MyListener listener;
  21. public FiveFrame(){
  22. }
  23. public void init(){
  24. listener=new MyListener();
  25. this.setTitle("单机版五子棋游戏");
  26. toolBar=new JPanel();
  27. sysMenu=new JMenu("系统");
  28. startButton=new JButton("开始");
  29. startButton.addActionListener(listener);
  30. backButton=new JButton("悔棋");
  31. backButton.addActionListener(listener);
  32. exitButton=new JButton("退出");
  33. exitButton.addActionListener(listener);
  34. drawPanel=new DrawPanel();
  35. menuBar=new JMenuBar();
  36. sysMenu=new JMenu("系统");
  37. startMenuItem=new JMenuItem("开始");
  38. startMenuItem.addActionListener(listener);
  39. backMenuItem=new JMenuItem("悔棋");
  40. backMenuItem.addActionListener(listener);
  41. exitMenuItem=new JMenuItem("退出");
  42. exitMenuItem.addActionListener(listener);
  43. this.setJMenuBar(menuBar); //设置窗口菜单栏
  44. menuBar.add(sysMenu);
  45. sysMenu.add(startMenuItem);
  46. sysMenu.add(backMenuItem);
  47. sysMenu.add(exitMenuItem);
  48. toolBar.add(startButton);
  49. toolBar.add(backButton);
  50. toolBar.add(exitButton);
  51. this.setLayout(new BorderLayout());
  52. this.add(toolBar,BorderLayout.NORTH);
  53. this.add(drawPanel,BorderLayout.CENTER);
  54. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  55. // this.setResizable(false);
  56. this.setSize(WIDTH,HEIGH);
  57. //窗口出现在界面的中间
  58. this.setLocation(Toolkit.getDefaultToolkit().getScreenSize().width/2-400,Toolkit.getDefaultToolkit().getScreenSize().height/2-340);
  59. pack(); //固定棋盘大小的功能
  60. this.setVisible(true);
  61. }
  62. private class MyListener implements ActionListener{
  63. @Override
  64. public void actionPerformed(ActionEvent e){
  65. if(e.getSource()==startButton||e.getSource()==startMenuItem){
  66. drawPanel.restartGame();
  67. }
  68. if(e.getSource()==backButton||e.getSource()==backMenuItem){
  69. drawPanel.goback();
  70. }
  71. if(e.getSource()==exitButton||e.getSource()==exitMenuItem){
  72. System.exit(0);
  73. }
  74. }
  75. }
  76. }

绘制棋盘,画棋子

  1. import java.awt.Color;
  2. import java.awt.Dimension;
  3. import java.awt.Graphics;
  4. import java.awt.event.MouseEvent;
  5. import java.awt.event.MouseListener;
  6. import javax.swing.JOptionPane;
  7. import javax.swing.JPanel;
  8. public class DrawPanel extends JPanel implements MouseListener{
  9. public static final int MARGIN=30; //边距
  10. public static final int GRID_SPAN=35; //网格间距
  11. public static final int ROWS=15;
  12. public static final int COLS=15;
  13. private int x_index,y_index;
  14. private boolean isBlack=true;
  15. private Chess[] chessList=new Chess[(ROWS+1)*(COLS+1)];//装棋子的组数
  16. private int chessCount=0; //棋子的个数
  17. //游戏是否结束的标志
  18. private boolean gameOver=false;
  19. public DrawPanel() {
  20. super();
  21. this.setBackground(Color.pink);
  22. this.addMouseListener(this);
  23. }
  24. @Override //注解是用来指定方法重写的,只能修饰方法并且只能用于方法重写,不能修饰其它的元素。 它可以强制一个子类必须重写父类方法或者实现接口的方法。
  25. public void paint(Graphics g){ //画笔
  26. super.paint(g); //调用父类的这个方法才能把设置的东西显示出来
  27. //画棋盘-横线
  28. for(int i=0;i<=ROWS;i++){
  29. g.drawLine(MARGIN, MARGIN+i*GRID_SPAN, MARGIN+COLS*GRID_SPAN,MARGIN+i*GRID_SPAN);
  30. }
  31. //画棋盘-竖线
  32. for(int i=0;i<=COLS;i++){
  33. g.drawLine(MARGIN+i*GRID_SPAN, MARGIN, MARGIN+i*GRID_SPAN, MARGIN+ROWS*GRID_SPAN);
  34. }
  35. //画棋子
  36. for(int i=0;i<chessCount;i++){
  37. int xPos=chessList[i].getX()*GRID_SPAN+MARGIN;
  38. int yPos=chessList[i].getY()*GRID_SPAN+MARGIN;
  39. g.setColor(chessList[i].getColor());
  40. g.fillOval(xPos-Chess.DIAMETER/2,yPos-Chess.DIAMETER/2, Chess.DIAMETER, Chess.DIAMETER);
  41. //最后一颗棋子上画红色框
  42. if(i==chessCount-1){
  43. g.setColor(Color.red);
  44. g.drawRect(xPos-Chess.DIAMETER/2, yPos-Chess.DIAMETER/2, Chess.DIAMETER, Chess.DIAMETER);
  45. }
  46. }
  47. }
  48. @Override
  49. public Dimension getPreferredSize(){
  50. return new Dimension(MARGIN*2+GRID_SPAN*ROWS,MARGIN*2+GRID_SPAN*COLS);
  51. }
  52. @Override
  53. public void mouseClicked(MouseEvent e) {
  54. // TODO Auto-generated method stub
  55. }
  56. @Override
  57. public void mousePressed(MouseEvent e) {
  58. // TODO Auto-generated method stub
  59. x_index=(e.getX()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
  60. y_index=(e.getY()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
  61. System.out.print("("+x_index+","+y_index+")");
  62. //是不是一个可用的棋子

游戏规则

先定义Chess类,得到棋盘中棋子的索引值和颜色,为判断五子连珠做准备

  1. package game06;
  2. import java.awt.Color;
  3. public class Chess {
  4. private int x; //棋盘中x的索引值
  5. private int y;
  6. private Color color;//棋子颜色
  7. static final int DIAMETER=30;
  8. public Chess(int x, int y, Color color) {
  9. super();
  10. this.x = x;
  11. this.y = y;
  12. this.color = color;
  13. }
  14. public int getX() {
  15. return x;
  16. }
  17. public void setX(int x) {
  18. this.x = x;
  19. }
  20. public int getY() {
  21. return y;
  22. }
  23. public void setY(int y) {
  24. this.y = y;
  25. }
  26. public Color getColor() {
  27. return color;
  28. }
  29. public void setColor(Color color) {
  30. this.color = color;
  31. }
  32. }

限定棋子所能下的位置,判断棋子是否可用。

  1. //1.游戏结束不能下棋
  2. if(gameOver){
  3. return;
  4. }
  5. //2.落在棋盘外面,不能下
  6. if(x_index<0||x_index>COLS||y_index>ROWS){
  7. return;
  8. }
  9. //3.位置上已有棋子存在,不能下
  10. if(findChess(x_index,y_index)){
  11. return;
  12. }

记录黑白方走棋,实现回合交换

  1. Chess ch=new Chess(x_index,y_index,isBlack?Color.black:Color.white);
  2. chessList[chessCount++]=ch;
  3. System.out.print("棋子子个数: "+chessCount);
  4. this.repaint();

判断赢的方法,四个方向(从西南到东北,从西北到东南,水平方向,垂直方向)只要实现五子连珠,即赢。

  1. //位置上是否有棋子
  2. private boolean findChess(int x,int y){
  3. for(Chess c:chessList){
  4. if(c!=null&&c.getX()==x&&c.getY()==y){
  5. return true;
  6. }
  7. }
  8. return false;
  9. }
  10. //得到棋盘上的棋子
  11. private Chess getChess(int x,int y,Color color){
  12. for(Chess c:chessList){
  13. if(c!=null&&c.getX()==x&&c.getY()==y&&c.getColor()==color){
  14. return c;
  15. }
  16. }
  17. return null;
  18. }
  19. // 赢棋的方法,需要四个方向
  20. private boolean isWin(){
  21. return search1()||search2()||search3()||search4();
  22. }
  23. //1.从西南到东北方向
  24. private boolean search1(){
  25. int continueCount=1; //连续棋子的个数
  26. //斜向上寻找
  27. for(int x=x_index+1,y=y_index-1;x<=COLS&&y>=0;x++,y--){
  28. Color c=isBlack?Color.black:Color.white;
  29. if(getChess(x,y,c)!=null){
  30. continueCount++;
  31. }else{
  32. break;
  33. }
  34. }
  35. //斜向下寻找
  36. for(int x=x_index-1,y=y_index+1;x<=ROWS&&x>=0;x--,y++){
  37. Color c=isBlack?Color.black:Color.white;
  38. if(getChess(x,y,c)!=null){
  39. continueCount++;
  40. }else{
  41. break;
  42. }
  43. }
  44. //五子连珠
  45. if(continueCount>=5){
  46. return true;
  47. }else{
  48. continueCount=1;
  49. }
  50. return false;
  51. }
  52. //2.水平左右-西东
  53. private boolean search2(){
  54. int continueCount=1; //连续棋子的个数
  55. //寻找-西方向
  56. for(int x=x_index-1;x>=0;x--){
  57. Color c=isBlack?Color.black:Color.white;
  58. if(getChess(x,y_index,c)!=null){
  59. continueCount++;
  60. }else{
  61. break;
  62. }
  63. }
  64. //寻找-东方向
  65. for(int x=x_index+1;x<=COLS;x++){
  66. Color c=isBlack?Color.black:Color.white;
  67. if(getChess(x,y_index,c)!=null){
  68. continueCount++;
  69. }else{
  70. break;
  71. }
  72. }
  73. //五子连珠
  74. if(continueCount>=5){
  75. return true;
  76. }else{
  77. continueCount=1;
  78. }
  79. return false;
  80. }
  81. //西北到东南
  82. private boolean search3(){
  83. int continueCount=1; //连续棋子的个数
  84. //斜向上寻找
  85. for(int x=x_index-1,y=y_index-1;x>=0&&y>=0;x--,y--){
  86. Color c=isBlack?Color.black:Color.white;
  87. if(getChess(x,y,c)!=null){
  88. continueCount++;
  89. }else{
  90. break;
  91. }
  92. }
  93. //斜向下寻找
  94. for(int x=x_index+1,y=y_index+1;x<=COLS&&y<ROWS;x++,y++){
  95. Color c=isBlack?Color.black:Color.white;
  96. if(getChess(x,y,c)!=null){
  97. continueCount++;
  98. }else{
  99. break;
  100. }
  101. }
  102. //五子连珠
  103. if(continueCount>=5){
  104. return true;
  105. }else{
  106. continueCount=1;
  107. }
  108. return false;
  109. }
  110. //垂直向下
  111. private boolean search4(){
  112. int continueCount=1; //连续棋子的个数
  113. //寻找-向上的方向
  114. for(int y=y_index-1;y>=0;y--){
  115. Color c=isBlack?Color.black:Color.white;
  116. if(getChess(x_index,y,c)!=null){
  117. continueCount++;
  118. }else{
  119. break;
  120. }
  121. }
  122. //寻找-向下的方向
  123. for(int y=y_index+1;y<=ROWS;y++){
  124. Color c=isBlack?Color.black:Color.white;
  125. if(getChess(x_index,y,c)!=null){
  126. continueCount++;
  127. }else{
  128. break;
  129. }
  130. }
  131. //五子连珠
  132. if(continueCount>=5){
  133. return true;
  134. }else{
  135. continueCount=1;
  136. }
  137. return false;
  138. }

游戏功能:重开

  1. public void restartGame(){
  2. //清除棋子
  3. for(int i=0;i<chessList.length;i++){
  4. chessList[i]=null;
  5. }
  6. //恢复游戏相关的变量
  7. isBlack=true;
  8. gameOver=false;
  9. chessCount=0;
  10. this.repaint();
  11. }

游戏功能:悔棋

  1. void goback(){
  2. //棋盘中没有棋子,不能悔棋
  3. if(chessCount==0){
  4. return;
  5. }
  6. chessList[chessCount-1]=null;
  7. chessCount--;
  8. if(chessCount>0){
  9. x_index=chessList[chessCount-1].getX();
  10. y_index=chessList[chessCount-1].getY();
  11. }
  12. isBlack=!isBlack;
  13. this.repaint();
  14. }

git提交代码

git链接 https://github.com/8768z/game.git

心得

通过此次任务,我对swing的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。对java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,我又多了更深层次的领悟。

考虑到游戏体验的优化,我们在游戏模式设计时应做多样化的考虑,对玩家需求进行探索。在AI算法方还有更多的优化空间,例如可适时根据玩家的走棋进行优化的算法。随着学习程度的进一步加深,希望能开发出更多新的玩法,带来更好的体验。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/326363
推荐阅读
相关标签
  

闽ICP备14008679号