没搞过项目,大概就是敲很多很多代码来实现某个完全的功能。
这里记录开发一下过程、学到的技术和一些遇到的难题、解决方法。
画个大纲(跟随慢慢开发过程不断完善)
用户
两个用户对战 一黑一白
用户可以是人,也可以是AI。对战模式支持人人,人机,机机。
属性
执棋颜色
用户名
游戏得分
方法
下棋
输赢
比赛规则
一黑一白交替轮流下棋
可以决定哪个玩家先手
不可以重复下棋到同一个位置
不可以将棋子下到边界外
可以撤回刚刚下的棋,不可以撤回上一步的棋
哪一方横竖斜到达5个棋子赢一局
游戏界面
设置棋盘
刷新窗体,背景图、棋盘、棋子不消失
设置计分板(记录目前双方赢得局数)
设置当前局数计时器
设置菜单栏(包含开始游戏、暂停游戏、继续游戏)
乱七八糟的功能
第一天 —— 实现棋盘界面
实现:背景图、棋子位置校正、轮流下棋、不下到棋盘之外,开始游戏菜单界面
实现方式
- 背景图:UI声明对象,在paint方法先于棋盘绘制。
- 棋子位置校正:在监听器放置棋子时,得到鼠标点击的坐标——>最终放置棋子圆心坐标转化过程。将棋盘的一个格子分成4块,在某片区域就归属于这个点,在边线上的点归左、归上。
-
轮流下棋:设置棋子计数器,奇数下白子,偶数下黑子。(为使个数不会加到很大做%2操作。也有很多其他方式可用)
遇到的问题
在实现约束棋子不下到棋盘外面时:想要通过单独为棋盘设置一个JPanel面板,但是画笔分配出现问题,现在确定三个位置:
在开始为面板设置位置时,位置坐标基于:什么地方设置。
鼠标监听器鼠标点击等操作获得的坐标基于:谁加入监听器就是谁
画笔绘图坐标基于:谁产生画笔就基于谁
但是paint方法重写的时候是继承的窗体JFrame,因此paint传进来的画笔是窗体产生的画笔,是从最左上的开始的。那么棋盘、背景图都是基于窗体最左上绘制的。
只有面板也是基于窗体最左上的点开始,和棋盘、背景图设置成同一个位置才能重合,但是面板的位置设置并不是这样。有错位。
一个简单的解决方法
将约束设置在监听器中实现,当获得的坐标必须在棋盘范围之内才能点棋子,否则不做任何操作。
代码
//BiangGoBangInterface.java
/**
* 五子棋接口 设置固定参数
* 属性
* 1.SIZE:棋盘间距 & 棋子直径
* 2.棋盘左上角坐标 X
* 3.棋盘左上角坐标 Y
* 4.棋盘行列数 ROW LINE
* 5.右拉栏宽度
* 6.按钮的宽度 btnWidth
* 7.按钮的高度 btnHeight
*/
public interface BiangGoBangInterface {
int SIZE = 30;
int X = 100;
int Y = 100;
int ROW = 16;
int LINE = 16;
int rightWidth = 200;
int btnWidth = 100;
int btnHeight = 50;
}
//BiangGoBang.java
/**
* GoBang界面
* 继承JFRame ,重写paint方法
*
* 属性:
* 1.bgimg 背景图
* 2.mylis GoBang棋盘操作监听器 ———— BiangGoBangListener mylis
*
* 方法:
* 1.initBiangGoBangUI() 初始化界面方法
*
* 重写方法:
* 1.paint() 实现窗体刷新之后重画 背景图 棋盘
*/
public class BiangGoBangUI extends JFrame implements BiangGoBangInterface {
public static final Image bgimg = new ImageIcon("img/bg50.jpg").getImage();
public BiangGoBangListener mylis = new BiangGoBangListener();
public void initBiangGoBangUI() {
//JFrame bgb = new JFrame("Biang's五子棋v 1.0");
this.setTitle("Biang's 五子棋 v1.0");
this.setSize(SIZE * LINE, SIZE * ROW);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel rightBar = new JPanel();
rightBar.setBackground(Color.GRAY);
Dimension dim = new Dimension(rightWidth,rightWidth);
rightBar.setPreferredSize(dim);
JButton BeginBtn = new JButton("Begin");
BeginBtn.setBackground(Color.WHITE);
BeginBtn.setSize(btnWidth,btnHeight);
rightBar.add(BeginBtn);
JButton StopBtn = new JButton("Stop");
StopBtn.setBackground(Color.WHITE);
StopBtn.setSize(btnWidth,btnHeight);
rightBar.add(StopBtn);
this.add(rightBar,BorderLayout.EAST);
//BeginBtn.addActionListener(mylis);
// 实现下棋子下在面板之内:特别为棋盘设置面板画笔不一致,需要重新写继承JPanel的paint方法,所以换在监听器里实现
// this.setLayout(null);
// JPanel chessBoard = new JPanel();
// chessBoard.setLocation(X,Y);
// Dimension dim = new Dimension(SIZE*ROW,SIZE*LINE);
// //chessBoard.setPreferredSize(dim);
// chessBoard.setSize(SIZE*ROW,SIZE*LINE);
// chessBoard.setBackground(Color.BLUE);
// this.add(chessBoard);
this.setVisible(true);
this.addMouseListener(mylis);
Graphics pen = this.getGraphics();
mylis.setGraphics(pen);
}
@Override
public void paint(Graphics g){
super.paint(g);
g.drawImage(bgimg,X-SIZE,Y-SIZE,(ROW+2)*SIZE,(LINE+2)*SIZE,null);
for(int i=0;i<=ROW;i++){
g.drawLine(X,Y+i*SIZE,X+SIZE*LINE,Y+i*SIZE); //y不变,画横线
g.drawLine(X+i*SIZE,Y,X+i*SIZE,Y+SIZE*ROW); //x不变,画竖线
}
}
}
//BiangGoBangListener.java
/**
* 棋盘操作下棋监听器 (实现鼠标 鼠标拖动接口)
* 属性:
* 1.chessX chessY当前下棋的坐标
* 2.pen 绘制棋子的画笔组件
*
* 方法:
* 1.void setGraphics(Graphics pen) 向监听器传入界面的画笔对象
*
* 重写的方法:
* 1.mousePressed 实现点击下棋 棋子校正 控制下棋范围
* 2.
*
*/
public class BiangGoBangListener implements MouseListener , MouseMotionListener ,BiangGoBangInterface{
int chessX,chessY;
Graphics pen;
int controlColor=0;
public void setGraphics(Graphics pen){
this.pen = pen;
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if(x>X-SIZE && x<X+SIZE*ROW+SIZE && y>Y-SIZE && y<Y+SIZE*LINE+SIZE){
//棋子校正:点中间线归上左
int baseX = X + ((x - X) / SIZE) * SIZE;
int baseY = Y + ((y - Y) / SIZE) * SIZE;
if ((x - baseX) > (SIZE / 2))
chessX = baseX + SIZE;
else
chessX = baseX;
if ((y - baseY) > (SIZE / 2))
chessY = baseY + SIZE;
else
chessY = baseY;
if((controlColor%2)==0)
pen.setColor(Color.BLACK);
else
pen.setColor(Color.WHITE);
System.out.println(controlColor);
controlColor=(controlColor+1)%2;
pen.fillOval(chessX - SIZE / 2, chessY - SIZE / 2, SIZE, SIZE);
}
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
}
}
//StartGameUI.java
public class StartGameUI {
public static void main(String[] args){
BiangGoBangUI goBangUI = new BiangGoBangUI();
goBangUI.initBiangGoBangUI();
}
}