完全个人操作版五子棋

** 仿照网上的实例,自己重塑了代码,并且对其中很多内容进行了注释,更加详细,很适合初学者查看。
功能:重新开始,设置时间,显示黑白两方时间,游戏说明,退出游戏,悔棋,认输,显示游戏信息
体会:刚开始写代码就是想到什么,通过这次写五子棋,知道了写一个项目之前得先想好整体格局,需要用到什么变量,需要记录什么,都先布置好格式。**

package com.dy.lkd17;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.*;
import java.awt.image.BufferedImage;

import javax.print.attribute.ResolutionSyntax;
import javax.swing.*;

public class FiveChessFrame extends JFrame implements MouseListener, Runnable {
    // 游戏界面大小
    int width = Toolkit.getDefaultToolkit().getScreenSize().width;
    int height = Toolkit.getDefaultToolkit().getScreenSize().height;
    // 保存鼠标的坐标
    int x, y;
    // 保存棋盘,0为无子,1表示黑棋,2表示白棋
    int[][] allChess = new int[15][15];
    // 保存当下子是白棋还是黑棋,true表示黑棋,false表示白棋
    boolean isBlack = true;
    // 标志当前游戏是否结束
    boolean canPlay = true;
    // 保存游戏信息
    String message = "黑方先行";
    // 保存棋谱
    int[] chessX = new int[255];
    int[] chessY = new int[255];
    int countX, countY;
    // 保存最大时间
    int maxTime = 0;
    // 游戏时间设定的信息
    String blackMessage = "无限制";
    String whiteMessage = "无限制";
    // 保存黑白方所剩余时间
    int blackTime = 0;
    int whiteTime = 0;
    // 游戏倒计时线程
    Thread timer = new Thread(this);

    @SuppressWarnings("deprecation")
    public FiveChessFrame() {
        setTitle("五子棋");
        setSize(500, 500);
        setLocation((width - 500) / 2, (height - 500) / 2); // 窗口居中
        setResizable(false); // 窗口大小不可变
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口
        setVisible(true);
        repaint();
        addMouseListener(this);
        timer.start();
        timer.suspend();
    }

    public void paint(Graphics g) {
        // 双缓冲
        BufferedImage bi = new BufferedImage(500, 500,
                BufferedImage.TYPE_INT_RGB);
        Graphics g2 = bi.createGraphics();
        g2.setColor(new Color(0, 169, 158));
        g2.fill3DRect(43, 60, 375, 375, true);
        // 表格左上角坐标(43,60)
        // 表格大小为25
        for (int i = 0; i <= 15; i++) {
            g2.setColor(Color.white);
            g2.drawLine(43, i * 25 + 60, 375 + 43, 60 + i * 25);
            g2.drawLine(i * 25 + 43, 60, 43 + i * 25, 375 + 60);
        }
        g2.setFont(new Font("楷体", Font.BOLD, 20)); // 加粗
        g2.drawString("游戏信息:" + message, 50, 50);
        g2.drawRect(30, 440, 180, 40);     //画黑棋时间矩形框架
        g2.drawRect(250, 440, 180, 40);    //画白棋时间矩形框架
        g2.setFont(new Font("宋体", 0, 12));
        g2.drawString("黑方时间:" + blackMessage, 40, 465);
        g2.drawString("白方时间:" + whiteMessage, 260, 465);

        // 重新开始按钮
        g2.drawRect(428, 66, 54, 20);
        g2.drawString("重新开始", 432, 80);

        // 游戏设置按钮
        g2.drawRect(428, 106, 54, 20);
        g2.drawString("游戏设置", 432, 120);

        // 游戏说明按钮
        g2.drawRect(428, 146, 54, 20);
        g2.drawString("游戏说明", 432, 160);

        // 退出游戏按钮
        g2.drawRect(428, 186, 54, 20);
        g2.drawString("退出游戏", 432, 200);

        // 悔棋
        g2.drawRect(428, 246, 54, 20);
        g2.drawString("悔棋", 442, 260);

        // 认输
        g2.drawRect(428, 286, 54, 20);
        g2.drawString("认输", 442, 300);

        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                // 黑子
                if (allChess[i][j] == 1) {
                    int tempX = i * 25 + 55;
                    int tempY = j * 25 + 72;
                    g2.setColor(Color.BLACK);
                    g2.fillOval(tempX - 8, tempY - 8, 16, 16);
                }
                // 白子
                if (allChess[i][j] == 2) {
                    int tempX = i * 25 + 55;
                    int tempY = j * 25 + 72;
                    g2.setColor(Color.WHITE);       //填充为白色圆
                    g2.fillOval(tempX - 8, tempY - 8, 16, 16);
                    g2.setColor(Color.BLACK);       //白色实心圆的外边框为黑色
                    g2.drawOval(tempX - 8, tempY - 8, 16, 16);
                }
            }
        }
        g.drawImage(bi, 0, 0, this);
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        if (maxTime > 0) {
            while (true) {
                if (isBlack) {
                    blackTime--;
                    if (blackTime == 0) {
                        JOptionPane.showMessageDialog(this, "黑方超时,游戏结束!");
                    }
                } else {
                    whiteTime--;
                    if (whiteTime == 0) {
                        JOptionPane.showMessageDialog(this, "白方超时,游戏结束!");
                    }
                }
                blackMessage = blackTime / 3600 + ":"
                        + (blackTime / 60 - blackTime / 3600 * 60) + ":"
                        + (blackTime - blackTime / 60 * 60); //记录秒数,例如600秒,将10分钟总秒数减去9分钟的秒数,剩余一分钟递减
                whiteMessage = whiteTime / 3600 + ":"
                        + (whiteTime / 60 - whiteTime / 3600 * 60) + ":"
                        + (whiteTime - whiteTime / 60 * 60);
                this.repaint();
                try {
                    Thread.sleep(1000);        //休眠一秒
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();     //在命令行打印异常信息在程序中出错的位置及原因
                }
                // System.out.println(blackTime + " -- " + whiteTime);
            }
        }
    }

    @Override
    public void mouseClicked(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseEntered(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub
        boolean checkWin = false;
        if (canPlay) {
            x = e.getX();        //获取鼠标点击坐标
            y = e.getY();
            if (x >= 55 && x <= 405 && y >= 72 && y <= 420) {
                if ((x - 55) % 25 > 12)
                    x = (x - 55) / 25 + 1;
                else
                    x = (x - 55) / 25;
                if ((y - 72) % 25 > 12)
                    y = (y - 72) / 25 + 1;
                else
                    y = (y - 72) / 25;
                if (allChess[x][y] == 0) { // 所点击的位置无子

                    chessX[countX++] = x; // 记录位置信息
                    chessY[countY++] = y;
                    if (isBlack) {
                        allChess[x][y] = 1;
                        isBlack = false;
                        message = "白方下子";
                    } else {
                        allChess[x][y] = 2;
                        isBlack = true;
                        message = "黑方下子";
                    }
                    this.repaint();
                    checkWin = isWin();       //下子后检查是否胜利
                    if (checkWin) {
                        if (allChess[x][y] == 1)
                            JOptionPane.showMessageDialog(this, "游戏结束,黑方胜利");
                        else
                            JOptionPane.showMessageDialog(this, "游戏结束,白方胜利");
                        canPlay = false;
                    }
                }
            }
        }
        // 重新开始游戏
        if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 66
                && e.getY() <= 86) {
            int result = JOptionPane.showConfirmDialog(this, "是否重新开始游戏?");
            if (result == 0) {
                for (int i = 0; i < 15; i++)
                    for (int j = 0; j < 15; j++)
                        allChess[i][j] = 0;
                for (int i = 0; i < 15; i++) {
                    chessX[i] = 0;
                    chessY[i] = 0;
                }
                countX = 0;
                countY = 0;
                message = "黑方先行";
                blackMessage = "无限制";
                whiteMessage = "无限制";
                blackTime = maxTime;
                whiteTime = maxTime;
                isBlack = true;
                canPlay = true;
                this.repaint();
            }
        }

        // 游戏计时器设置
        if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 106
                && e.getY() <= 126) {
            String input = JOptionPane
                    .showInputDialog("请输入游戏的最大时间(分钟),如果输入0,表示时间没有限制:");
            maxTime = Integer.parseInt(input) * 60;
            System.out.println(maxTime);
            if (maxTime < 0) {
                JOptionPane.showMessageDialog(this, "输入的时间有误,请重新设置");
            } else if (maxTime == 0) {
                int result = JOptionPane.showConfirmDialog(this,
                        "游戏时间设置成功,是否开始游戏?");
                if (result == 0) {
                    for (int i = 0; i < 15; i++)
                        for (int j = 0; j < 15; j++)
                            allChess[i][j] = 0;
                    for (int i = 0; i < 15; i++) {
                        chessX[i] = 0;
                        chessY[i] = 0;
                    }
                    countX = 0;
                    countY = 0;
                    message = "黑方先行";
                    blackMessage = "无限制";
                    whiteMessage = "无限制";
                    blackTime = maxTime;
                    whiteTime = maxTime;
                    isBlack = true;
                    canPlay = true;
                    this.repaint();
                }
            } else if (maxTime > 0) {
                int result = JOptionPane.showConfirmDialog(this,
                        "游戏时间设置成功,是否开始游戏?");
                if (result == 0) {
                    if (result == 0) {
                        for (int i = 0; i < 15; i++)
                            for (int j = 0; j < 15; j++)
                                allChess[i][j] = 0;
                        for (int i = 0; i < 15; i++) {
                            chessX[i] = -1;
                            chessY[i] = -1;
                        }
                        countX = 0;
                        countY = 0;
                        message = "黑方先行";
                        isBlack = true;
                        blackMessage = maxTime / 3600 + ":" 
                                + (maxTime / 60 - maxTime / 3600 * 60) + ":"
                                + (maxTime - maxTime / 60 * 60);
                        whiteMessage = maxTime / 3600 + ":"
                                + (maxTime / 60 - maxTime / 3600 * 60) + ":"
                                + (maxTime - maxTime / 60 * 60);
                        blackTime = maxTime;
                        whiteTime = maxTime;
                        System.out
                                .println(blackMessage + " - -" + whiteMessage);
                        timer.resume();   //开始计时
                        this.canPlay = true;
                        this.repaint();
                    }
                }
            }
        }
        // 游戏说明
        if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 146
                && e.getY() <= 166) {
            JOptionPane.showMessageDialog(this, "简单一句:横竖斜先连成五子者获胜!");
        }

        // 退出游戏
        if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 186
                && e.getY() <= 206) {
            int result = JOptionPane.showConfirmDialog(this, "是否退出游戏?");
            if (result == 0) {
                System.exit(0);
            }
        }

        // 悔棋
        if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 246
                && e.getY() <= 266) {
            int result = JOptionPane.showConfirmDialog(this,     //判断接下来为哪一方下棋,如果轮到黑方,则说悔棋的就是白方
                    (isBlack == true ? "白方悔棋,黑方是否同意?" : "黑方悔棋,白方是否同意?"));
            if (result == 0) {
                allChess[chessX[--countX]][chessY[--countY]] = 0;   //将当前位置改为无子,并且将坐标返回一次
                isBlack = (isBlack == true) ? false : true;  //悔棋的一方重新下子,如果轮到黑方,则应该返回false,白方下棋
                this.repaint();
            }
        }

        // 认输
        if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 286
                && e.getY() <= 306) {
            int result = JOptionPane.showConfirmDialog(this, "是否认输?");
            if (result == 0) {
                JOptionPane.showMessageDialog(this, "游戏结束,"
                        + (isBlack == true ? "黑方认输,白方获胜!" : "白方认输,黑方获胜!"));
            }
        }

    }

    private boolean isWin() {
        // TODO Auto-generated method stub
        boolean flag = false;
        // 保存共有多少种颜色的棋子相连
        int count = 1;
        // 判断横向是否有5个棋子相连,特点纵坐标相同,即allChess[x][y]中y值是相同
        int color = allChess[x][y];
        // 判断横向
        count = this.checkCount(1, 0, color);
        if (count >= 5) {
            flag = true;
        } else {
            // 判断纵向
            count = this.checkCount(0, 1, color);
            if (count >= 5) {
                flag = true;
            } else {
                // 判断右上,左下
                count = this.checkCount(1, -1, color);
                if (count >= 5) {
                    flag = true;
                } else {
                    // 判断右下,左上
                    count = this.checkCount(1, 1, color);
                    if (count >= 5) {
                        flag = true;
                    }
                }
            }
        }
        return flag;
    }

    private int checkCount(int xChange, int yChange, int color) {
        int count = 1;
        int tempX = xChange;     //为向另外个方向记录坐标
        int tempY = yChange;
        while (x + xChange >= 0 && x + xChange <= 14 && y + yChange >= 0
                && y + yChange <= 14
                && color == allChess[x + xChange][y + yChange]) {
            count++;
            if (xChange != 0)
                xChange++;
            if (yChange != 0) {
                if (yChange > 0)
                    yChange++;
                else {
                    yChange--;
                }
            }

        }
        xChange = tempX;
        yChange = tempY;
        while (x - xChange >= 0 && x - xChange <= 14 && y - yChange >= 0
                && y - yChange <= 14
                && color == allChess[x - xChange][y - yChange]) {
            count++;
            if (xChange != 0)
                xChange++;
            if (yChange != 0) {
                if (yChange > 0)
                    yChange++;
                else {
                    yChange--;
                }
            }
        }
        return count;
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    public static void main(String[] args) { // 主方法
        new FiveChessFrame();
    }
}

接下来是一些效果图,随意贴上几张效果图,其他效果由自己开发再去检验效果吧:
完全个人操作版五子棋_第1张图片
完全个人操作版五子棋_第2张图片
完全个人操作版五子棋_第3张图片
完全个人操作版五子棋_第4张图片
完全个人操作版五子棋_第5张图片

你可能感兴趣的:(java)