这是五子棋的最终效果图,棋盘以及棋子均是程序作图。下边奉献个人的源代码。
GoBangGUI.java 这个源文件主要是界面的实现
package game.gobang;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class GoBangGUI extends JFrame{
private JPanel mainframe;
private GoBangBoard board;
private JPanel control;
private GridLayout grid;
private BorderLayout border;
private JButton start;
private JButton end;
private JLabel label;
private int row;
private int column;
private Gobang gobang;
private MouseAdapter mouselistener;
private boolean flag;
private boolean ok;
private ActionListener actionlistener;
public GoBangGUI(){
this("GoBang Game", 10, 10);
}
public GoBangGUI(String title, int row, int column){
super(title);
// this.setUndecorated(true);
this.row = row;
this.column = column;
this.flag = false;
this.ok = false;
initial();
setSize(600, 600);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationByPlatform(true);
this.setVisible(true);
this.requestFocus();
}
private void initial() {
createComponent();
layOut();
listener();
}
private void createComponent() {
mainframe = new JPanel();
control = new JPanel();
border = new BorderLayout();
grid = new GridLayout();
start = new JButton("Start");
label = new JLabel();
gobang = new Gobang(row, column);
board = new GoBangBoard(gobang, row, column);
end = new JButton("Exit");
// gobang.getData()[0][0] = GobangColor.WHITE;
}
private void layOut() {
this.getContentPane().add(mainframe);
// setBackpicture();
// mainframe.setBackground(Color.yellow);
mainframe.setLayout(border);
mainframe.add(board, BorderLayout.CENTER);
// board.setBounds(0, 0, 500, 500);
mainframe.add(control, BorderLayout.EAST);
Box ve = Box.createVerticalBox();
ve.add(start);
ve.add(Box.createVerticalStrut(50));
end.setSize(start.getWidth(), start.getHeight());
ve.add(end);
control.add(ve);
}
private void setBackpicture() {
ImageIcon a = new ImageIcon("/home/qcq/1.jpg");
JLabel p = new JLabel(a);
p.setBounds(0, 0, a.getIconWidth(), a.getIconHeight());
this.getLayeredPane().add(p, Integer.MIN_VALUE);
}
/*
* 判断鼠标落入棋盘窗格的位置索引 (x, y)为当前鼠标的坐标。
*/
private Place judgePlace(int indexx, int indexy, int x, int y, int squre){
for (int i = 0; i < row; i++){
for (int j = 0; j < column; j++){
if (x >= indexx + j * squre && x <= indexx + (j + 1) * squre
&&y >= indexy + i * squre && y <= indexy + (i + 1) * squre){
return new Place(i, j);
}
}
}
return null;
}
private void listener() {
mouselistener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
/*
* (25, 10) is a special coordinate. the board draw begins here,
* when the board added to the this JFrame the begin change to
* (25, 10 + 25), However, I do not know why. just keep it;
* */
if (ok){
Place temp = judgePlace(25, 10, x, y, board.getSqure());
System.out.println(temp);
if (flag){
if (!gobang.check(temp.getX(), temp.getY())){
JOptionPane.showMessageDialog(mainframe, "Change another place");
} else {
gobang.setChess(temp.getX(), temp.getY(), GobangColor.WHITE);
repaint();
if (gobang.isSuccess(new Place(0, 0), new Place(row - 1, column - 1), GobangColor.WHITE)){
// JOptionPane.showMessageDialog(mainframe, "The white player is win");
int choice = JOptionPane.showConfirmDialog(mainframe, "The white player is win", "DO you want try again",
JOptionPane.YES_NO_OPTION);
if (choice == JOptionPane.YES_OPTION){
gobang.initial();
ok = false;
repaint();
}
}
flag = false;
}
} else {
if (!gobang.check(temp.getX(), temp.getY())){
JOptionPane.showMessageDialog(mainframe, "Change another place");
} else {
gobang.setChess(temp.getX(), temp.getY(), GobangColor.BLACK);
repaint();
if (gobang.isSuccess(new Place(0, 0), new Place(row - 1, column - 1), GobangColor.BLACK)){
// JOptionPane.showMessageDialog(mainframe, "The black player is win");
int choice = JOptionPane.showConfirmDialog(mainframe, "The black player is win", "DO you want try again",
JOptionPane.YES_NO_OPTION);
if (choice == JOptionPane.YES_OPTION){
gobang.initial();
ok = false;
repaint();
}
}
flag = true;
}
}
} else {
JOptionPane.showMessageDialog(mainframe, "please start the game");
}
}
};
actionlistener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (((JButton)(e.getSource())).getText().equals("Start")){
ok = true;
} else if (((JButton)(e.getSource())).getText().equals("Exit")){
System.exit(0);
}
}
};
board.addMouseListener(mouselistener);
start.addActionListener(actionlistener);
end.addActionListener(actionlistener);
}
public static void main(String[] args) {
GoBangGUI game = new GoBangGUI(null, 20, 20);
}
}
package game.gobang;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import javax.swing.JPanel;
public class GoBangBoard extends JPanel {
private Gobang gobang;
private int row;
private int column;
private int squre;
public GoBangBoard() {
//this.setBounds(x, y, width, height);
}
public GoBangBoard(Gobang gobang, int row, int column){
this.gobang = gobang;
this.column = column;
this.row = row;
}
public int getSqure(){
return squre;
}
public void paint(Graphics g){
Graphics2D gg = (Graphics2D)g;
squre = (this.getWidth() - 50) / Math.max(row, column);
/**
* from the point (25, 10) draw the game's background.
* */
/*
* below draw the background gird.
* */
int x = 25;
int y = 10;
gg.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 1.0f,new float[]{5f, 5f},0f));
gg.setColor(Color.blue);
for (int i = 0; i < row; i++){
for (int j = 0; j < column; j++){
gg.drawRect(x + j * squre, y + i * squre, squre, squre);
}
}
for (int i = 0; i < gobang.getData().length; i++){
for (int j = 0; j < gobang.getData()[i].length; j++){
if (GobangColor.WHITE == gobang.getData()[i][j]){
gg.setColor(Color.blue);
gg.fillOval(x + j * squre, y + i * squre, squre, squre);
} else if (GobangColor.BLACK == gobang.getData()[i][j]){
gg.setColor(Color.BLACK);
gg.fillOval(x + j * squre, y + i * squre, squre, squre);
}
}
}
gg.setStroke(new BasicStroke(5f));
gg.setColor(Color.blue);
gg.drawRect(x - 1, y - 1, squre * column + 2, squre * row + 2);
gg.dispose();
}
}
GobangColor.java 本文件是棋子颜色的枚举定义。
package game.gobang;
public enum GobangColor {
BLACK,
WHITE,
NULL
}
package game.gobang;
/**
* here lays the snake's body coordinate information.
* */
public class Place {
private int x;
private int y;
public Place(){
this(0, 0);
}
public Place(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
@Override
public String toString() {
return "Place [x=" + x + ", y=" + y + "]";
}
public void setY(int y) {
this.y = y;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Place other = (Place) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
package game.gobang;
import java.util.Scanner;
/**
* Question 19、利用二维数组实现五子棋下棋功能
* */
public class Gobang {
private GobangColor[][] data;
private int row = 10;
private int column = 10;
public Gobang() {
/*
* The default checkerboard is 10 * 10 boxes;
* */
this(10, 10);
initial();
}
/*
* Initial the Game
* */
public void initial(){
for (int i = 0; i < row; i++){
for (int j = 0; j < column; j++){
data[i][j] = GobangColor.NULL;
}
}
}
/*
* The piece move
* */
public void setChess(int row, int column,GobangColor color){
data[row][column] = color;
}
public Gobang(int row, int column){
/*
* set the Chess squre to row * line
* */
this.row = row;
this.column = column;
data = new GobangColor[row][];
for (int i = 0; i < row; i++){
data[i] = new GobangColor[column];
}
initial();
}
public GobangColor[][] getData() {
return data;
}
public void setData(GobangColor[][] data) {
this.data = data;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getColumn() {
return column;
}
public void setColumn(int column) {
this.column = column;
}
/*
* print out the current checkerboard
* */
public void printCheckerBoard(){
/*
* print out the chessboard layout
* */
for (GobangColor[] i: data){
for (GobangColor j : i){
System.out.print(j.toString() + " ");
}
System.out.println();
}
}
/*
* verify the input data to insure the piece is in the range
* and not put this piece in the history place
* 验证棋子在合适的位置上
* */
public boolean check(int x, int y){
if (x < 0 || x >= row || y < 0 || y >= column){
System.out.println("The input is error");
System.out.println("The input should from(0, 0) to (" + (x - 1) + "," + (y - 1) + ")");
return false;
}
if (GobangColor.NULL != data[x][y]){
System.out.println("This place already has one piece!");
return false;
}
return true;
}
/*
* judge if successed, The parameter x and y
* is the range which need to be scanning.
* The Scanning range can zoom in a range which is a circle(a square)
* center in current move, radius is 5.
* 扫描棋盘看是不是有棋子获胜,可以优化扫描方案,将扫描的范围局限于一个以落子处为中心
* 5为半径的棋盘(isSucess的重载方法实现这一个思想)。
*/
public boolean isSuccess(Place x, Place y, GobangColor color){
boolean flag = false;
int counter = 0;
label:
for (int i = (int) x.getX(); i <= (int)y.getX(); i++){
for (int j = (int)x.getY(); j <= (int)y.getY(); j++){
/*
* scanning the [x,y] range in 4 directions.
* */
// check the horizontal
counter = 0;
if (j + 4 <= (int)y.getY()){
for (int index = j; index <= j + 4; index++){
if (color == data[i][index]){
counter++;
}
}
}
if (5 == counter){
flag = true;
break label;
}
// check the vertical
counter = 0;
if (i + 4 <= (int)y.getX()){
for (int index = i; index <= i + 4; index++){
if (color == data[index][j]){
counter++;
}
}
}
if (5 == counter){
flag = true;
break label;
}
//check the dig line
counter = 0;
if ((i + 4 <= (int)y.getX()) && (j + 4 <= (int)y.getY())){
for (int indexX = i, indexY = j; indexX <= i + 4 ;indexX++, indexY++){
if (color == data[indexX][indexY]){
counter++;
}
}
}
if (5 == counter){
flag = true;
break label;
}
//check the reverse dig line
counter = 0;
if ((i + 4 <= (int)y.getX()) && (j - 4 >= (int)x.getY())){
for (int indexX = i, indexY = j; indexX <= i + 4;indexX++, indexY--){
if (color == data[indexX][indexY]){
counter++;
}
}
}
if (5 == counter){
flag = true;
break label;
}
}
}
return flag;
}
/*
* 这是一个重载的方法,与上一个方法不同的是没有使用扫描来实现判定
* 而是基于落子的地方,来基于四个方向进行计数判断。
* */
public boolean isSuccess(Place x, GobangColor color){
boolean flag = false;
/*
* horizontal direction
* */
int counter = 0;
for (int i = x.getY(); i >= Math.min(x.getY() - 4, row); i--){
if (color == data[x.getX()][i]){
counter++;
}else{
break;
}
}
for (int i = x.getY() + 1; i <= Math.min(x.getY() + 4, column - 1); i++){
if (color == data[x.getX()][i]){
counter++;
}else{
break;
}
}
if (5 == counter){
flag = true;
}
/*
* vertical direction
* */
counter = 0;
for (int i = x.getX(); i >= Math.min(x.getX() - 4, row); i--){
if (color == data[i][x.getY()]){
counter++;
}else{
break;
}
}
for (int i = x.getY() + 1; i <= Math.min(x.getY() + 4, column - 1); i++){
if (color == data[i][x.getY()]){
counter++;
}else{
break;
}
}
if (5 == counter){
flag = true;
}
/*
* diagonal direction
* */
counter = 0;
for (int i = x.getX(), j = x.getY(); i >= Math.min(x.getX() - 4, row)
&& j >= Math.min(x.getY() - 4, row); i--, j--){
if (color == data[i][j]){
counter++;
}else{
break;
}
}
for (int i = x.getX() + 1, j = x.getY() + 1; i <= Math.min(x.getX() + 4, column - 1)
&& j <= Math.min(x.getY() + 4, column - 1); i++, j++){
if (color == data[i][j]){
counter++;
}else{
break;
}
}
if (5 == counter){
flag = true;
}
/*
* reverse diagonal direction
* */
counter = 0;
for (int i = x.getX(), j = x.getY(); i <= Math.min(x.getX() + 4, column - 1)
&& j >= Math.min(x.getY() - 4, row); i++, j--){
if (color == data[i][j]){
counter++;
}else{
break;
}
}
for (int i = x.getX() + 1, j = x.getY() + 1; i >= Math.min(x.getX() - 4, row)
&& j <= Math.min(x.getY() + 4, column - 1); i--, j++){
if (color == data[i][j]){
counter++;
}else{
break;
}
}
if (5 == counter){
flag = true;
}
return flag;
}
/*
* The actual game start here, where black first, white second,
* we can optimize the game which do not call
* the method isSuccess in the first segment. such as 8 moves.
* and we can narrow the scanning the range to a square just talk above.
* */
public void playChess(){
Scanner in = new Scanner(System.in);
Place x = new Place(0, 0);
Place y = new Place(row - 1, column - 1);
label:
while (true){
//The input should like 1,2
while (in.hasNext()){
String[] str = in.next().split(",");
int indexX = Integer.valueOf(str[0]);
int indexY = Integer.valueOf(str[1]);
if (!check(indexX, indexY)){
System.out.println("please input again");
continue;
}else{
setChess(indexX, indexY, GobangColor.BLACK);
printCheckerBoard();
// if (isSuccess(x, y, GobangColor.BLACK)){
if (isSuccess(new Place(indexX, indexY), GobangColor.BLACK)){
System.out.println("The Black is win");
break label;
}
break;
}
}
while (in.hasNext()){
String[] str = in.next().split(",");
int indexX = Integer.valueOf(str[0]);
int indexY = Integer.valueOf(str[1]);
if (!check(indexX, indexY)){
System.out.println("please input again");
continue;
}else{
setChess(indexX, indexY, GobangColor.WHITE);
printCheckerBoard();
// if (isSuccess(x, y, GobangColor.WHITE)){
if (isSuccess(new Place(indexX, indexY), GobangColor.WHITE)){
System.out.println("The White is win");
break label;
}
break;
}
}
}
in.close();
}
public static void main(String[] args) {
Gobang chess = new Gobang();
chess.playChess();
}
}
GitHub最新源码