Java写五子棋小游戏
来源:互联网 发布:python 语音处理 编辑:程序博客网 时间:2024/04/28 12:48
Java写五子棋小游戏
最近用Java写了个五子棋小游戏,遇到了许多细节问题,在此不得不总结一下,以便有同样需求朋友参考。
1.】面板发生变化,重绘棋盘与棋局问题:
必须调用父类的paint方法,因为如果不调,界面会出问题,比如组件不显示; JPanel实例化之后就会开始绘制;面板发生变化(大小,位置),paint方法会自动调用;
final JPanel panel_show = new JPanel() { // 面板发生变化,paint方法自动调用; public void paint(Graphics g) { super.paint(g); //写你想执行的操作 } };
2.】JPanel面板对象的大小设置问题:
不能用setSize,setBounds这一类方法,只能用setPreferredSize(new Dimension(470, 490));
panel_show.setPreferredSize(new Dimension(470, 490));
3.】多个监听,不同要求,却用同一个ActionListener对象问题;
添加监听本不是一个难题,但是对于多个按钮都添加动作监听,我们应该本着节约资源的原则,只实例化一个ActionListener对象;
ActionListener arg0 = new ActionListener() { public void actionPerformed(ActionEvent arg0) { String string = arg0.getActionCommand(); switch (string) { //"开始"和"悔棋"代表想要添加监听的对象上的文字; //补充一点,eclipse在1.7版本可以在case后写字符串了; case "开始": { //写你想执行的操作 break; } case "悔棋": { //写你想执行的操作 break; } default: break; } } };
4.】得到画布与窗口可见性位置问题:
每一块面板都有一块画布,而得到画布也不能在任意地方写,就像窗口的可见性要写在最后,而得到画布要写在窗口可见性的后面;
// 设置窗口可见性 setVisible(true); // 得到画板 graphics = panel_show.getGraphics();
5.】重绘棋局与棋盘问题:
repaint方法调用后,自动调用update方法,然后再调用paint方法;
当然棋盘上的棋子是,可以直接遍历整个棋盘,然后画出来;但是这太费时间,因此我们想到用一个ArrayList集合存放棋子,主要是考虑到ArrayList的一些特性:动态数组;
repaint();
6.】画棋子的问题:
graphics.fillOval(x,y,i,j)中,(x,y)指的是所画圈的左上角的坐标,i和j指的是所画圈的外切矩形的长和宽;因为我们是要画一个圆,所以i=j;
// 设置棋子的颜色 graphics.setColor(color); // 在制定位置画制定大小的棋子,俩个30是指画的是个圆,而且是圆的外切矩形的长和宽; graphics.fillOval(x * 50 - 5, y * 50 - 5, 30, 30);
7.】得到鼠标所在位置问题:
对整个棋盘进行鼠标监听,鼠标监听会有方法得到鼠标所在的位置;但是我们写程序一大重要点就是整个程序的容错性,所以我们需要根据鼠标监听得到的位置准确定位到棋盘上的位置;
MouseListener mouse_show = new MouseListener() { public void mouseReleased(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseClicked(MouseEvent e) { //这里的50是因为棋盘每一行,每一列的间距是50 int x = e.getX() / 50; int x1 = e.getX() % 50; int y = e.getY() / 50; int y1 = e.getY() % 50; //x++,与y++则是当用户没有在棋盘每行每列的任一交叉点下棋时,做的预判断; if (x1 < 50 / 3) { ; } else { x++; } if (y1 < 50 / 3) { ; } else { y++; } } };
8.】判断输赢问题:
其实每一次判断输赢,都只需要判断当前这一棵棋子;因为只有当前这一棵棋子的加入会改变棋局,而其他棋子在每一次下的时候已经判断过了;
对于判断每一棵棋子的加入导致的棋局的变化,就是判断当前棋子所在直线是否已经连成5~7棵,也就是说横、竖、左斜、右斜,即一个米字;
判断横的方向输赢代码展示(其他方向的判断是一个原理):
private void is_win(int x, int y) { //判断横的方向; for (int i = -4; i < 5; i++) { if (leap && x + i >= 0 && x + i <= 10) { if (temp[x + i][y] == 2) { count_white++; if (count_white >= 5) { JOptionPane.showMessageDialog(null, "白棋赢了"); } } else { count_white = 0; } } if (!leap && x + i >= 0 && x + i <= 10) { if (temp[x + i][y] == 1) { count_black++; if (count_black >= 5) { JOptionPane.showMessageDialog(null, "黑棋赢了"); } } else { count_black = 0; } } } count_black = 0; count_white = 0; }
9.】代码展示(虽然直接贴代码很不道德,但是回想当初那只想翻一个有注释的完整代码的苦不堪言的日子的时候,我此刻只想贴完整代码):
//棋子类package server_exchange;import java.awt.Color;import java.awt.Graphics;public class Chess { // 代表坐标值 int x, y; Color color; public Chess(int x, int y, Color color) { this.x = x; this.y = y; this.color = color; } public void draw(Graphics graphics) { // 设置棋子的颜色 graphics.setColor(color); // 在制定位置画制定大小的棋子,俩个30是指画的是个圆,而且是圆的外切矩形的长和宽; graphics.fillOval(x * 50 - 5, y * 50 - 5, 30, 30); }}//界面类package server_exchange;import java.awt.Color;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.Graphics;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.util.ArrayList;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JOptionPane;import javax.swing.JPanel;public class fiveChess extends JFrame { private static final long serialVersionUID = 1L; // 定义一个棋子类; Chess chess; // 集合:数组性质,但是长度可变; ArrayList<Chess> list = new ArrayList<>(); // 标志变量:二维数组。i,j标志坐标;改点值位0,代表该点没有棋子;值为1,代表该点下了一棵黑棋;值为2,代表该点下了一棵白棋; private int[][] temp = new int[11][11]; // 每一块面板都有自己的画布; Graphics graphics = null; // 标志变量。leap值为true,下黑棋;值为false,下白棋; boolean leap = true; // 计数器 int count_black = 0; int count_white = 0; // 判断是否按了开始按钮,按了值为1,没按值为0; int temp_start = 0; /* * 此处的showUI不能改成show;虽然说方法名,除了构造方法的名字不能随意,其他的都无所谓,可以随意取; * 当然为了有意义,我们一般会取这个方法的用处对应的英文名; 回到主题,为什么不能用show呢,你可以自己先尝试一下,看看效果; * 其实主要是因为我继承了JFrame,而JFrame中有一个show方法; * 当然你们同样会问即使我继承了,但是我也重写了这个方法,所以应该没问题的,毕竟人家调用的是我重写的嘛; * 但是问题就出在重载上,重载会发生意外(不细说,不细说); 哈哈,主要是我也在这上面坑了好多次; */ public void showUI() { // 设置窗口名称 setTitle("五子棋游戏!!!"); // 设置窗口大小 setSize(600, 510); // 设置窗口可关性;其实括号里的内容换成3,也是实现了可关性的; // 当然括号里也可以写成EXIT_ON_CLOSE,毕竟你继承了JFrame,而EXIT_ON_CLOSE是JFrame类的一个静态的共有属性; setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置窗口布局,JFrame面板默认BorderLayout布局; setLayout(new FlowLayout()); // 添加面板对象,JPanel面板默认FlowLayout布局; // 这种写法是内部类; final JPanel panel_show = new JPanel() { // JPanel实例化之后就会开始绘制; // 面板发生变化,paint方法自动调用; public void paint(Graphics g) { /* * 必须调用父类的paint方法 因为如果不调,界面会出问题,比如组件不显示 */ super.paint(g); // 画棋盘 for (int i = 0; i < 10; i++) { g.drawLine(10, 10 + 50 * i, 460, 10 + 50 * i); g.drawLine(10 + 50 * i, 10, 10 + 50 * i, 460); } // 当面板发生变化是,重绘之前棋盘上已有棋子 for (int i = 0; i < list.size(); i++) { Chess chess = list.get(i); chess.draw(g); } } }; JPanel panel_function = new JPanel(); add(panel_show); add(panel_function); // 设置面板大小 panel_show.setPreferredSize(new Dimension(470, 490)); panel_function.setPreferredSize(new Dimension(90, 480)); // 添加功能面板的按钮对象 JButton button_start = new JButton("开始"); JButton button_everybody = new JButton("人人"); JButton button_huamanComputer = new JButton("人机"); JButton button_regret = new JButton("悔棋"); JButton button_about = new JButton("关于"); panel_function.add(button_start); panel_function.add(button_everybody); panel_function.add(button_huamanComputer); panel_function.add(button_regret); panel_function.add(button_about); // 设置按钮大小 button_start.setPreferredSize(new Dimension(86, 86)); button_everybody.setPreferredSize(new Dimension(86, 86)); button_huamanComputer.setPreferredSize(new Dimension(86, 86)); button_regret.setPreferredSize(new Dimension(86, 86)); button_about.setPreferredSize(new Dimension(86, 86)); // 监听对象 ActionListener arg0 = new ActionListener() { public void actionPerformed(ActionEvent arg0) { String string = arg0.getActionCommand(); switch (string) { case "开始": { // System.out.println(" ***"); temp_start = 1; list.removeAll(list); repaint(); fuzhi(); leap = true; break; } case "悔棋": { if (list.size() > 0) { if (leap) { leap = false; } else { leap = true; } int x = list.get(list.size() - 1).x; int y = list.get(list.size() - 1).y; temp[x][y] = 0; list.remove(list.size() - 1); /* * repaint方法调用后,自动调用update方法,然后再调用paint方法; */ repaint(); } break; } default: break; } } }; // 对开始按钮监听 button_start.addActionListener(arg0); button_regret.addActionListener(arg0); MouseListener mouse_show = new MouseListener() { public void mouseReleased(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseClicked(MouseEvent e) { if (temp_start == 1) { int x = e.getX() / 50; int x1 = e.getX() % 50; int y = e.getY() / 50; int y1 = e.getY() % 50; if (x1 < 50 / 3) { ; } else { x++; } if (y1 < 50 / 3) { ; } else { y++; } if (temp[x][y] == 0) { if (leap) { chess = new Chess(x, y, Color.black); temp[x][y] = 1; leap = false; } else { chess = new Chess(x, y, Color.white); temp[x][y] = 2; leap = true; } chess.draw(graphics); list.add(chess); } // 判断输赢; is_win(x, y); } } }; // 对棋盘进行监听 panel_show.addMouseListener(mouse_show); // 设置窗口可见性 setVisible(true); // 得到画板 graphics = panel_show.getGraphics(); } public static void main(String[] args) { fiveChess chess = new fiveChess(); chess.fuzhi(); chess.showUI(); } /** * 重新开始下棋是,标志哪些位置上有棋子的标志变量应该还原成初始值,即0; */ public void fuzhi() { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { temp[i][j] = 0; } } } /** * 判断输赢 * * @param x * 横坐标 * @param y * 竖坐标 */ private void is_win(int x, int y) { // 右斜方向(斜向下)的判断; for (int i = -4; i < 5; i++) { if (leap && x + i >= 0 && x + i <= 10 && y + i >= 0 && y + i <= 10) { if (temp[x + i][y + i] == 2) { count_white++; if (count_white >= 5) JOptionPane.showMessageDialog(null, "白棋赢了"); } else { count_white = 0; } } if (!leap && x + i >= 0 && x + i <= 10 && y + i >= 0 && y + i <= 10) { if (temp[x + i][y + i] == 1) { count_black++; if (count_black >= 5) { JOptionPane.showMessageDialog(null, "黑棋赢了"); } } else { count_black = 0; } } } count_black = 0; count_white = 0; // 左斜方向(斜向上)的判断; for (int i = -4; i < 5; i++) { if (leap && x + i >= 0 && x + i <= 10 && y - i >= 0 && y - i <= 10) { if (temp[x + i][y - i] == 2) { count_white++; if (count_white >= 5) JOptionPane.showMessageDialog(null, "白棋赢了"); } else { count_white = 0; } } if (!leap && x + i >= 0 && x + i <= 10 && y - i >= 0 && y - i <= 10) { if (temp[x + i][y - i] == 1) { count_black++; if (count_black >= 5) { JOptionPane.showMessageDialog(null, "黑棋赢了"); } } else { count_black = 0; } } } count_black = 0; count_white = 0; // 竖直方向的判断; for (int i = -4; i < 5; i++) { if (leap && y + i >= 0 && y + i <= 10) { if (temp[x][y + i] == 2) { count_white++; if (count_white >= 5) { JOptionPane.showMessageDialog(null, "白棋赢了"); } } else { count_white = 0; } } if (!leap && y + i >= 0 && y + i <= 10) { if (temp[x][y + i] == 1) { count_black++; if (count_black >= 5) { JOptionPane.showMessageDialog(null, "黑棋赢了"); } } else { count_black = 0; } } } count_black = 0; count_white = 0; // 水平方向的判断; for (int i = -4; i < 5; i++) { if (leap && x + i >= 0 && x + i <= 10) { if (temp[x + i][y] == 2) { count_white++; if (count_white >= 5) { JOptionPane.showMessageDialog(null, "白棋赢了"); } } else { count_white = 0; } } if (!leap && x + i >= 0 && x + i <= 10) { if (temp[x + i][y] == 1) { count_black++; if (count_black >= 5) { JOptionPane.showMessageDialog(null, "黑棋赢了"); } } else { count_black = 0; } } } count_black = 0; count_white = 0; }}
- Java写五子棋小游戏
- 【java】五子棋小游戏
- 【java】五子棋小游戏
- java----五子棋小游戏
- Java编写的五子棋小游戏
- Java程序实现五子棋小游戏
- 基于java的五子棋小游戏
- java课程设计五子棋小游戏(1)
- java小游戏第四弹 五子棋
- [001]新手,用java面向过程思维写的五子棋小游戏。
- 五子棋--小游戏
- 小游戏-五子棋
- java-----五子棋小游戏(一)-----背景图片制作
- java-----五子棋小游戏(三)-----判断输赢
- java小游戏之控制台下五子棋!
- java小游戏-双人五子棋小案例
- java swing实现五子棋小游戏项目源码
- JS写怀旧小游戏系列(三)五子棋
- UML——时序图
- HDU1058 Humble Numbers
- 4002: [JLOI2015]有意义的字符串
- js调用百度地图API
- 一元多项式求和
- Java写五子棋小游戏
- 【模板】树状数组
- Mysql数据增删改查
- python2和3使用过程中的(重要)不同点记录
- 机器学习(二)Apriori算法
- js实现的图片轮播
- latch: cache buffers chains故障处理总结(转载)
- cron表达式
- JAVA集合