界面设计
五子棋的界面主要包括棋盘、棋子、按钮。
首先设置一个接口用以储存棋盘的基本数据:棋盘的位置、线数、线距。
public interface Config {
public static final int LINE=11;//线数
public static final int X0=50;
public static final int Y0=100;
public static final int SIZE=50;//线距
}
棋盘信息储存:
为了避免窗口改变的时候,棋盘和棋子消失,需要保存棋盘数据并重写paint方法。
使用一个二维数组,记录下棋情况,未下为0,黑棋为1,白棋为2。
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
public class MyFrame extends JFrame implements Config{
int[][]arr=new int[LINE][LINE];
public void paint(Graphics g) {
super.paint(g);
//纵向线条绘制
for (int i=0;i<=LINE;i++) {
g.setColor(Color.black);
g.drawLine(i*SIZE+X0,Y0,i*SIZE+X0,LINE*SIZE+Y0);
}
//横向线条绘制
for (int i=0;i<=LINE;i++) {
g.setColor(Color.black);
g.drawLine(X0,i*SIZE+Y0,LINE*SIZE+X0,i*SIZE+Y0);
}
//把保存的数组输出为棋子
for(int i=0;i<11;i++) {
for(int j=0;j<11;j++) {
//数据为1,表示为黑棋
if(arr[i][j]==1) {
g.setColor(Color.black);
g.fillOval(i*SIZE+X0-10, j*SIZE+X0-10, 20, 20);
}
//数据为2,表示为白棋
if(arr[i][j]==2) {
g.setColor(Color.white);
g.fillOval(i*SIZE+X0-10, j*SIZE+X0-10, 20, 20);
}
}
}
}
}
棋盘界面设计
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import csl0420.MyFrame;
public class GameUI implements Config {
public static MyFrame jf;
public static void main(String[] args) {
GameUI ga=new GameUI();
ga.init();
}
public void init() {
//设置一个窗体,名称、尺寸、关闭方式、布局
jf=new MyFrame();
jf.setTitle("五子棋");
jf.setSize((LINE+2)*SIZE,(LINE+3)*SIZE);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout fl=new FlowLayout();
jf.setLayout(fl);
//设置按钮并且添加监听器
Chess l=new Chess();
String JB[]= {"开始","悔棋"};
for(int i=0;i<2;i++) {
JButton jb=new JButton(JB[i]);
jf.add(jb);
jb.addActionListener(l);
}
//设置可见性
jf.setVisible(true);
//设置画笔,给窗体添加
Graphics g=jf.getGraphics();
jf.addMouseListener(l);
//传画笔和数组
l.g=g;
jf.arr=l.arr;
}
}
落子操作
用鼠标点击棋盘上的位置
根据点击位置判断最近的落点以及数组中对应的位置
根据落子数的奇偶性判断棋子颜色以及数组对应的值
用一个新的数组保存棋子数与对应的棋子颜色
public void mousePressed(MouseEvent e) {
//获取落点坐标
x=e.getX();
y=e.getY();
if(x<=X0+LINE*SIZE+SIZE/2&&x>=25&&y<=Y0+LINE*SIZE+SIZE/2&&y>=25) {
//寻找最近的落点
m=(x-X0+SIZE/2)/SIZE;
n=(y-Y0+SIZE/2)/SIZE;
//判断是否有棋子落下
if(arr[m][n]==0) {
//黑子先行,则奇数颗为黑子
if(count%2==1) {
g.setColor(Color.black);
//给数组赋值
arr[m][n]=1;
//绘制棋子
g.fillOval(m*SIZE+X0-10, n*SIZE+Y0-10, 20, 20);
//储存棋子的位置
countn[count]=m*100+n;
// System.out.println(count+" "+countn[count]);
count++;
//判断是否胜利
if (winOrlose(m,n,1)==1) {
System.out.println("黑棋赢了");
//弹出提示框
int res=JOptionPane.showConfirmDialog(null,"是否继续","黑棋胜利",
JOptionPane.YES_NO_OPTION);
if(res==JOptionPane.YES_OPTION) {
initlize();
my.paint(g);
}
}
//显示下一颗棋子的颜色
g.setColor(Color.white);
g.fillOval(80,60,10,10);
}
else if(count%2==0) {
g.setColor(Color.white);
arr[m][n]=2;
g.fillOval(m*SIZE+X0-10, n*SIZE+Y0-10, 20, 20);
countn[count]=m*100+n;
// System.out.println(count+" "+countn[count]);
count++;
if (winOrlose(m,n,2)==1) {
System.out.println("白棋赢了");
int res=JOptionPane.showConfirmDialog(null,"是否继续","白棋胜利",
JOptionPane.YES_NO_OPTION);
if(res==JOptionPane.YES_OPTION) {
initlize();
my.paint(g);
}
}
g.setColor(Color.BLACK);
g.fillOval(80,60,10,10);
}
}
}
}
胜利
判定
在一颗棋子落下之后,判断四个方向是否达到获胜条件。
以判断水平方向为例,从落点左边第四颗棋子开始判断,从第一颗与落点棋子颜色相同的棋子开始计数,向右遍历,棋子颜色相同则加1,不同则清零。若计数到5,则判定胜利。
如图,三角标注的棋子为当前落子,从左边第四颗遍历到右边第四颗。计数依次为010123401,最大为4,为达到胜利条件。
其他方向(竖直,左上右下,左下右上)同理。
public int winOrlose(int m,int n,int var) {
int value=0;
//水平
for(int i=m-4,j=n,num=0;i<=m+4;i++) {
if(i<0||i>10||j<0||j>10)continue;
if(arr[i][j]==var) {
num++;
}
else {
num=0;
}
if(num>=5) {
value=1;
return value;
}
else {
value=0;
}
}
//左上右下
for(int i=m-4,j=n-4,num=0;i<=m+4;i++,j++) {
if(i<0||i>10||j<0||j>10)continue;
if(arr[i][j]==var) {
num++;
}
else {
num=0;
}
if(num>=5) {
value=1;
num=0;
return value;
}
else value=0;
}
//竖直
for(int i=m,j=n-4,num=0;j<=n+4;j++) {
if(j<0||j>10||i<0||i>10)continue;
if(arr[i][j]==var) {
num++;
}
else {
num=0;
}
if(num>=5) {
value=1;
num=0;
return value;
}
else value=0;
}
//左下右上
for(int i=m-4,j=n+4,num=0;i<=m+4;i++,j--) {
if(j<0||j>10||i<0||i>10)continue;
if(arr[i][j]==var) {
num++;
}
else {
num=0;
}
if(num>=5) {
value=1;
num=0;
return value;
}
else value=0;
}
return value;
}
public void initlize() {
for (int i=0;i<arr.length;i++) {
for(int j=0;j<arr[0].length;j++) {
arr[i][j]=0;
}
}
}
开始与悔棋
按下开始按钮,棋盘重置。
即把储存棋子的数组初始化为0,再重绘。
//开始
if(e.getActionCommand().equals("开始")){
initlize();
my.paint(g);
}
按下悔棋按钮,把上一步棋子清除。
if(e.getActionCommand().equals("悔棋")){
if(count>1) {
count--;
arr[countn[count]/100[countn[count]%100]=0;
my.paint(g);
}
}
完整代码
代码结构
package csl0420;
import java.awt.Color;
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 javax.swing.JOptionPane;
public class Chess implements MouseListener ,ActionListener,Config{
int[][]arr=new int[LINE+1][LINE+1];
MyFrame my=GameUI.jf;
int x=0;
int y=0;
int m=0;
int n=0;
int count=1;
int countn[]= new int[1000];
int restart=0;
int command;
Graphics g;
String bottomname;
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("开始")){
initlize();
my.paint(g);
}
if(e.getActionCommand().equals("悔棋")){
if(count>1) {
count--;
arr[countn[count]/100][countn[count]%100]=0;
my.paint(g);
}
}
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
x=e.getX();
y=e.getY();
if(x<=X0+LINE*SIZE+SIZE/2&&x>=25&&y<=Y0+LINE*SIZE+SIZE/2&&y>=25) {
m=(x-X0+SIZE/2)/SIZE;
n=(y-Y0+SIZE/2)/SIZE;
if(arr[m][n]==0) {
if(count%2==1) {
g.setColor(Color.black);
arr[m][n]=1;
g.fillOval(m*SIZE+X0-10, n*SIZE+Y0-10, 20, 20);
countn[count]=m*100+n;
// System.out.println(count+" "+countn[count]);
count++;
if (winOrlose(m,n,1)==1) {
System.out.println("黑棋赢了");
int res=JOptionPane.showConfirmDialog(null,"是否继续","黑棋胜利",
JOptionPane.YES_NO_OPTION);
if(res==JOptionPane.YES_OPTION) {
initlize();
my.paint(g);
}
}
g.setColor(Color.white);
g.fillOval(80,60,10,10);
}
else if(count%2==0) {
g.setColor(Color.white);
arr[m][n]=2;
g.fillOval(m*SIZE+X0-10, n*SIZE+Y0-10, 20, 20);
countn[count]=m*100+n;
// System.out.println(count+" "+countn[count]);
count++;
if (winOrlose(m,n,2)==1) {
System.out.println("白棋赢了");
int res=JOptionPane.showConfirmDialog(null,"是否继续","白棋胜利",
JOptionPane.YES_NO_OPTION);
if(res==JOptionPane.YES_OPTION) {
initlize();
my.paint(g);
}
}
g.setColor(Color.BLACK);
g.fillOval(80,60,10,10);
}
}
}
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public int winOrlose(int m,int n,int var) {
int value=0;
//水平
for(int i=m-4,j=n,num=0;i<=m+4;i++) {
if(i<0||i>10||j<0||j>10)continue;
if(arr[i][j]==var) {
num++;
}
else {
num=0;
}
if(num>=5) {
value=1;
return value;
}
else {
value=0;
}
}
//左上右下
for(int i=m-4,j=n-4,num=0;i<=m+4;i++,j++) {
if(i<0||i>10||j<0||j>10)continue;
if(arr[i][j]==var) {
num++;
}
else {
num=0;
}
if(num>=5) {
value=1;
num=0;
return value;
}
else value=0;
}
//竖直
for(int i=m,j=n-4,num=0;j<=n+4;j++) {
if(j<0||j>10||i<0||i>10)continue;
if(arr[i][j]==var) {
num++;
}
else {
num=0;
}
if(num>=5) {
value=1;
num=0;
return value;
}
else value=0;
}
//左下右上
for(int i=m-4,j=n+4,num=0;i<=m+4;i++,j--) {
if(j<0||j>10||i<0||i>10)continue;
if(arr[i][j]==var) {
num++;
}
else {
num=0;
}
if(num>=5) {
value=1;
num=0;
return value;
}
else value=0;
}
return value;
}
public void initlize() {
for (int i=0;i<arr.length;i++) {
for(int j=0;j<arr[0].length;j++) {
arr[i][j]=0;
}
}
}
}
package csl0420;
public interface Config {
public static final int LINE=11;
public static final int X0=50;
public static final int Y0=100;
public static final int SIZE=50;
}
package csl0420;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
public class GameUI implements Config {
public static MyFrame jf;
public static void main(String[] args) {
GameUI ga=new GameUI();
ga.init();
}
public void init() {
jf=new MyFrame();
jf.setTitle("五子棋");
jf.setSize((LINE+2)*SIZE,(LINE+3)*SIZE);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout fl=new FlowLayout();
jf.setLayout(fl);
Chess l=new Chess();
String JB[]= {"开始","悔棋"};
for(int i=0;i<2;i++) {
JButton jb=new JButton(JB[i]);
jf.add(jb);
jb.addActionListener(l);
}
jf.setVisible(true);
Graphics g=jf.getGraphics();
jf.addMouseListener(l);
l.g=g;
jf.arr=l.arr;
}
}
package csl0420;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
public class MyFrame extends JFrame implements Config{
int[][]arr=new int[LINE][LINE];
public void paint(Graphics g) {
super.paint(g);
for (int i=0;i<=LINE;i++) {
g.setColor(Color.black);
g.drawLine(i*SIZE+X0,Y0,i*SIZE+X0,LINE*SIZE+Y0);
}
for (int i=0;i<=LINE;i++) {
g.setColor(Color.black);
g.drawLine(X0,i*SIZE+Y0,LINE*SIZE+X0,i*SIZE+Y0);
}
for(int i=0;i<11;i++) {
for(int j=0;j<11;j++) {
if(arr[i][j]==1) {
g.setColor(Color.black);
g.fillOval(i*SIZE+X0-10, j*SIZE+X0-10, 20, 20);
}
if(arr[i][j]==2) {
g.setColor(Color.white);
g.fillOval(i*SIZE+X0-10, j*SIZE+X0-10, 20, 20);
}
}
}
}
}