这个小游戏是我和我姐们儿的JAVA课程设计,也是我做的第一个JAVA项目,适合初学者,希望能帮到那些被JAVA课设所困扰的孩纸们~~~
一、该游戏需要的实现的:
1、设计主框架,界面。
2、利用ActionListener接口实现按钮事件的监听。
3、重新开始功能的实现。
4、悔棋功能的实现。
5、退出功能的实现。
6、棋盘中棋子点类的定义。
7,利用MouseListener接口实现事件监听,并实现接口里的所有方法。
8,当鼠标移动到棋盘上的交点上,且该点上无棋子时能够变成小手形状。
9,点击棋盘时,利用if语句判断该点是否点在交点上,并利用foreach语句和棋子类中的getX(),getY()方法遍历每一个棋子的位置判断该点是否有棋子。
10,当判断到可以在所点击的点上下子时,画棋子时利用for循环遍历已有的每一个点并利用Graphics类的setColor设置颜色,利用Graphics类的fillOval方法设置形状大小。
11,当画完棋子时要及时判断输赢,用棋子所在索引和for循环遍历最后一个棋子的各个方向,如果有在同一条直线上的棋子个数大于等于五的即当前棋子所代表的那方赢。
12,胜负已定的时候,能够弹出相应的信息。
二、功能代码实现
2.1进入游戏
public static void main(String[] args) {
StartChessJFrame f=new StartChessJFrame();//创建主框架
f.setVisible(true);//显示主框架
}
2.2初始化,定义一些要用到的量。
private ChessBoard chessBoard;//对战面板
private Panel toolbar;//工具条面板
private Button startButton;//设置开始按钮
private Button backButton;//设置悔棋按钮
private Button exitButton;//设置退出按钮
2.3界面的构造方法(游戏的框架)
public StartChessJFrame(){
setTitle("单机版五子棋");//设置标题
chessBoard=new ChessBoard();//初始化面板对象,创建和添加菜单
MyItemListener lis=new MyItemListener();//初始化按钮事件监听器内部类
toolbar=new Panel();//工具面板栏实例化
startButton=new Button("重新开始");
backButton=new Button("悔棋");
exitButton=new Button("退出");//三个按钮初始化
toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));//将工具面板按钮用FlowLayout布局
toolbar.add(backButton);
toolbar.add(startButton);
toolbar.add(exitButton);//将三个按钮添加到工具面板上
startButton.addActionListener(lis);
backButton.addActionListener(lis);
exitButton.addActionListener(lis);//将三个按钮事件注册监听事件
add(toolbar,BorderLayout.SOUTH);//将工具面板布局到界面南方也就是下面
add(chessBoard);//将面板对象添加到窗体上
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置界面关闭事件
pack();//自适应大小
}
2.4按钮的实现与监听(构造方法内部)
MyItemListener lis=new MyItemListener();//初始化按钮事件监听器内部类
toolbar=new Panel();//工具面板栏实例化
startButton=new Button("重新开始");
backButton=new Button("悔棋");
exitButton=new Button("退出");//三个按钮初始化
toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));//将工具面板按钮用FlowLayout布局
toolbar.add(backButton);
toolbar.add(startButton);
toolbar.add(exitButton);//将三个按钮添加到工具面板上
startButton.addActionListener(lis);
backButton.addActionListener(lis);
exitButton.addActionListener(lis);//将三个按钮事件注册监听事件
2.5按钮事件的监听
private class MyItemListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
Object obj=e.getSource();//获取事件源
if(obj==startButton){
System.out.println("重新开始...");//重新开始
//JFiveFrame.this内部类引用外部类
chessBoard.restartGame();
}else if(obj==exitButton){
System.exit(0);//结束应用程序
}else if(obj==backButton){
System.out.println("悔棋...");//悔棋
chessBoard.goback();
}
}
}
2.6重新开始按钮的功能实现
public void restartGame(){//清除棋子
for(int i=0;i
2.7悔棋按钮的功能实现
public void goback(){
if(chessCount==0)
return ;
chessList[chessCount-1]=null;
chessCount--;
if(chessCount>0){
xIndex=chessList[chessCount-1].getX();
yIndex=chessList[chessCount-1].getY();
}
isBack=!isBack;
repaint();
}
2.8当棋盘根据需要变大或变小时窗口应随之发生改变
//Dimension:矩形ChessBoard类内部
public Dimension getPreferredSize(){
return new Dimension(MARGIN*2+GRID_SPAN*COLS,MARGIN*2+GRID_SPAN*ROWS);
}
pack();//自适应大小StartChessBoard类内部
2.9定义棋子类
import java.awt.*;
public class Point {
private int x;//棋子在棋盘中的x索引值
private int y;//棋子在棋盘中的y索引值
private Color color;//颜色
public static int DIAMETER=30;//直径
public Point(int x,int y,Color color){
this.x=x;
this.y=y;
this.color=color;
}
//得到棋子在棋盘中的x索引值
public int getX(){
return x;
}
//得到棋子在棋盘中的y索引值
public int getY(){
return y;
}
//得到棋子颜色
public Color getColor(){
return color;
}
}
3.1初始化,定义一些要用到的量。
public static int MARGIN=30;//边距
public static int GRID_SPAN=35;//网格间距
public static int ROWS=18;//棋盘行数
public static int COLS=18;//棋盘列数
Point[] chessList=new Point[(ROWS+1)*(COLS+1)];//初始化每个数组元素为null
boolean isBack=true;//默认开始是黑棋先下
boolean gameOver=false;//游戏是否结束
int chessCount;//当前棋盘的棋子个数
int xIndex,yIndex;//当前刚下棋子的索引
3.2棋盘对象的构造方法
public ChessBoard(){
setBackground(Color.LIGHT_GRAY);//设置背景颜色为灰色
addMouseListener(this);//添加事件监听器
addMouseMotionListener(new MouseMotionListener() {//匿名内部类
@Override
public void mouseMoved(MouseEvent e) {
int x1=(e.getX()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
int y1=(e.getY()-MARGIN+GRID_SPAN/2)/GRID_SPAN;//将鼠标单击的坐标位置转化为网格索引
if(x1<0||x1>ROWS||y1<0||y1>COLS||gameOver||findChess(x1,y1)){//游戏已经结束,不能下;落在棋盘外,不能下;x,y位置已经有棋子存在,不能下
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));//设置成默认形状
}else{
setCursor(new Cursor(Cursor.HAND_CURSOR));//设置成手型
}
}
@Override
public void mouseDragged(MouseEvent e) {
}
});
}
3.3设置鼠标监听器,变小手(在构造方法内部)
addMouseMotionListener(new MouseMotionListener() {//匿名内部类
@Override
public void mouseMoved(MouseEvent e) {
int x1=(e.getX()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
int y1=(e.getY()-MARGIN+GRID_SPAN/2)/GRID_SPAN;//将鼠标单击的坐标位置转化为网格索引
if(x1<0||x1>ROWS||y1<0||y1>COLS||gameOver||findChess(x1,y1)){//游戏已经结束,不能下;落在棋盘外,不能下;x,y位置已经有棋子存在,不能下
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));//设置成默认形状
}else{
setCursor(new Cursor(Cursor.HAND_CURSOR));//设置成手型
}
}
@Override
public void mouseDragged(MouseEvent e) {
}
});
3.4点击棋盘时的鼠标按压事件
public void mousePressed(MouseEvent e) {//鼠标按键在组件上按下时调用
if(gameOver)//游戏已经结束,不能下
return ;
String colorName=isBack ? "黑棋" : "白棋";
xIndex=(e.getX()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
yIndex=(e.getY()-MARGIN+GRID_SPAN/2)/GRID_SPAN;//将鼠标单击的坐标位置转化为网格索引
if(xIndex<0||xIndex>ROWS||yIndex<0||yIndex>COLS)//棋子落在棋盘外,不能下
return ;
if(findChess(xIndex,yIndex))//x,y位置已经有棋子存在,不能下
return ;
Point ch=new Point(xIndex,yIndex,isBack ? Color.black : Color.white);
chessList[chessCount++]=ch;
repaint();//通知系统重新绘制
if(isWin()){
String msg=String.format("恭喜,%s赢啦~", colorName);
JOptionPane.showMessageDialog(this, msg);
gameOver=true;
}
else if(chessCount==(COLS+1)*(ROWS+1))
{
String msg=String.format("棋鼓相当,棒棒哒~");
JOptionPane.showMessageDialog(this,msg);
gameOver=true;
}
isBack=!isBack;
}
3.5绘制棋盘,棋子还有红框框
public void paintComponent(Graphics g){
super.paintComponent(g);//画棋盘
for(int i=0;i<=ROWS;i++){//画横线
g.drawLine(MARGIN, MARGIN+i*GRID_SPAN, MARGIN+COLS*GRID_SPAN, MARGIN+i*GRID_SPAN);
}
for(int i=0;i<=COLS;i++){//画直线
g.drawLine(MARGIN+i*GRID_SPAN, MARGIN, MARGIN+i*GRID_SPAN,MARGIN+ROWS*GRID_SPAN);
}
/*画棋子*/
for(int i=0;i
3.6判断输赢
/*判断哪方赢*/
private boolean isWin(){
int continueCount=1;//连续棋子的个数
for(int x=xIndex-1;x>=0;x--){//横向向左寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,yIndex,c)!=null){
continueCount++;
}else
break;
}
for(int x=xIndex+1;x<=ROWS;x++){//横向向右寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,yIndex,c)!=null){
continueCount++;
}else
break;
}
if(continueCount>=5){//判断记录数大于等于五,即表示此方获胜
return true;
}else
continueCount=1;
//
for(int y=yIndex-1;y>=0;y--){//纵向向上寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(xIndex,y,c)!=null){
continueCount++;
}else
break;
}
for(int y=yIndex+1;y<=ROWS;y++){//纵向向下寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(xIndex,y,c)!=null){
continueCount++;
}else
break;
}
if(continueCount>=5){//判断记录数大于等于五,即表示此方获胜
return true;
}else
continueCount=1;
//
for(int x=xIndex+1,y=yIndex-1;y>=0&&x<=COLS;x++,y--){//右下寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
for(int x=xIndex-1,y=yIndex+1;y<=ROWS&&x>=0;x--,y++){//左上寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
if(continueCount>=5){//判断记录数大于等于五,即表示此方获胜
return true;
}else
continueCount=1;
//
for(int x=xIndex-1,y=yIndex-1;y>=0&&x>=0;x--,y--){//左下寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
for(int x=xIndex+1,y=yIndex+1;y<=ROWS&&x<=COLS;x++,y++){//右上寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
if(continueCount>=5){//判断记录数大于等于五,即表示此方获胜
return true;
}else
continueCount=1;
return false;
}
3.7弹出相应消息框(在鼠标按压函数内部)
if(isWin()){
String msg=String.format("恭喜,%s赢啦~", colorName);
JOptionPane.showMessageDialog(this, msg);
gameOver=true;
}
else if(chessCount==(COLS+1)*(ROWS+1))//平局
{
String msg=String.format("棋鼓相当,棒棒哒~");
JOptionPane.showMessageDialog(this,msg);
gameOver=true;
}
3.8上面用到的一个判断某点是否有棋子的函数
private boolean findChess(int x,int y){
for(Point c:chessList){
if(c!=null&&c.getX()==x&&c.getY()==y)
return true;
}
return false;
}
3.9因为该棋盘类实现了鼠标监听接口MonseListener,所以要重写该接口内的所有方法,其它方法如下
@Override
public void mouseClicked(MouseEvent e) {//鼠标按键在组件上单击(按下并释放)时调用
}
@Override
public void mouseReleased(MouseEvent e) {////鼠标按键在组件上释放时调用
}
@Override
public void mouseEntered(MouseEvent e) {//鼠标进入组件时调用
}
@Override
public void mouseExited(MouseEvent e){//鼠标离开组件时调用
}
该游戏总共建了三个类,一个是界面StartChessJFrame,一个是棋盘类ChessBoard,一个是棋子类Point
5.1StartChessJFrame类
package chess.lcc.com;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
/*
* 五子棋的主框架,程序启动类
*/
public class StartChessJFrame extends JFrame {
private ChessBoard chessBoard;//对战面板
private Panel toolbar;//工具条面板
private Button startButton;//设置开始按钮
private Button backButton;//设置悔棋按钮
private Button exitButton;//设置退出按钮
public StartChessJFrame(){
setTitle("单机版五子棋");//设置标题
chessBoard=new ChessBoard();//初始化面板对象,创建和添加菜单
MyItemListener lis=new MyItemListener();//初始化按钮事件监听器内部类
toolbar=new Panel();//工具面板栏实例化
startButton=new Button("重新开始");
backButton=new Button("悔棋");
exitButton=new Button("退出");//三个按钮初始化
toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));//将工具面板按钮用FlowLayout布局
toolbar.add(backButton);
toolbar.add(startButton);
toolbar.add(exitButton);//将三个按钮添加到工具面板上
startButton.addActionListener(lis);
backButton.addActionListener(lis);
exitButton.addActionListener(lis);//将三个按钮事件注册监听事件
add(toolbar,BorderLayout.SOUTH);//将工具面板布局到界面南方也就是下面
add(chessBoard);//将面板对象添加到窗体上
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置界面关闭事件
pack();//自适应大小
}
private class MyItemListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
Object obj=e.getSource();//获取事件源
if(obj==startButton){
System.out.println("重新开始...");//重新开始
//JFiveFrame.this内部类引用外部类
chessBoard.restartGame();
}else if(obj==exitButton){
System.exit(0);//结束应用程序
}else if(obj==backButton){
System.out.println("悔棋...");//悔棋
chessBoard.goback();
}
}
}
public static void main(String[] args) {
StartChessJFrame f=new StartChessJFrame();//创建主框架
f.setVisible(true);//显示主框架
}
}
5.2ChessBoard类
package chess.lcc.com;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;
/*五子棋-棋盘类*/
public class ChessBoard extends JPanel implements MouseListener{
public static int MARGIN=30;//边距
public static int GRID_SPAN=35;//网格间距
public static int ROWS=15;//棋盘行数
public static int COLS=15;//棋盘列数
Point[] chessList=new Point[(ROWS+1)*(COLS+1)];//初始化每个数组元素为null
boolean isBack=true;//默认开始是黑棋先下
boolean gameOver=false;//游戏是否结束
int chessCount;//当前棋盘的棋子个数
int xIndex,yIndex;//当前刚下棋子的索引
public ChessBoard(){
setBackground(Color.LIGHT_GRAY);//设置背景颜色为黄色
addMouseListener(this);//添加事件监听器
addMouseMotionListener(new MouseMotionListener() {//匿名内部类
@Override
public void mouseMoved(MouseEvent e) {
int x1=(e.getX()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
int y1=(e.getY()-MARGIN+GRID_SPAN/2)/GRID_SPAN;//将鼠标单击的坐标位置转化为网格索引
if(x1<0||x1>ROWS||y1<0||y1>COLS||gameOver||findChess(x1,y1)){//游戏已经结束,不能下;落在棋盘外,不能下;x,y位置已经有棋子存在,不能下
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));//设置成默认形状
}else{
setCursor(new Cursor(Cursor.HAND_CURSOR));//设置成手型
}
}
@Override
public void mouseDragged(MouseEvent e) {
}
});
}
/*绘制*/
public void paintComponent(Graphics g){
super.paintComponent(g);//画棋盘
for(int i=0;i<=ROWS;i++){//画横线
g.drawLine(MARGIN, MARGIN+i*GRID_SPAN, MARGIN+COLS*GRID_SPAN, MARGIN+i*GRID_SPAN);
}
for(int i=0;i<=COLS;i++){//画直线
g.drawLine(MARGIN+i*GRID_SPAN, MARGIN, MARGIN+i*GRID_SPAN,MARGIN+ROWS*GRID_SPAN);
}
/*画棋子*/
for(int i=0;iROWS||yIndex<0||yIndex>COLS)//棋子落在棋盘外,不能下
return ;
if(findChess(xIndex,yIndex))//x,y位置已经有棋子存在,不能下
return ;
Point ch=new Point(xIndex,yIndex,isBack ? Color.black : Color.white);
chessList[chessCount++]=ch;
repaint();//通知系统重新绘制
if(isWin()){
String msg=String.format("恭喜,%s赢啦~", colorName);
JOptionPane.showMessageDialog(this, msg);
gameOver=true;
}
else if(chessCount==(COLS+1)*(ROWS+1))
{
String msg=String.format("棋鼓相当,棒棒哒~");
JOptionPane.showMessageDialog(this,msg);
gameOver=true;
}
isBack=!isBack;
}
@Override
public void mouseClicked(MouseEvent e) {//鼠标按键在组件上单击(按下并释放)时调用
}
@Override
public void mouseReleased(MouseEvent e) {////鼠标按键在组件上释放时调用
}
@Override
public void mouseEntered(MouseEvent e) {//鼠标进入组件时调用
}
@Override
public void mouseExited(MouseEvent e){//鼠标离开组件时调用
}
private boolean findChess(int x,int y){
for(Point c:chessList){
if(c!=null&&c.getX()==x&&c.getY()==y)
return true;
}
return false;
}
/*判断那方赢*/
private boolean isWin(){
int continueCount=1;//连续棋子的个数
for(int x=xIndex-1;x>=0;x--){//横向向左寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,yIndex,c)!=null){
continueCount++;
}else
break;
}
for(int x=xIndex+1;x<=ROWS;x++){//横向向右寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,yIndex,c)!=null){
continueCount++;
}else
break;
}
if(continueCount>=5){//判断记录数大于等于五,即表示此方获胜
return true;
}else
continueCount=1;
//
for(int y=yIndex-1;y>=0;y--){//纵向向上寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(xIndex,y,c)!=null){
continueCount++;
}else
break;
}
for(int y=yIndex+1;y<=ROWS;y++){//纵向向下寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(xIndex,y,c)!=null){
continueCount++;
}else
break;
}
if(continueCount>=5){//判断记录数大于等于五,即表示此方获胜
return true;
}else
continueCount=1;
//
for(int x=xIndex+1,y=yIndex-1;y>=0&&x<=COLS;x++,y--){//右下寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
for(int x=xIndex-1,y=yIndex+1;y<=ROWS&&x>=0;x--,y++){//左上寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
if(continueCount>=5){//判断记录数大于等于五,即表示此方获胜
return true;
}else
continueCount=1;
//
for(int x=xIndex-1,y=yIndex-1;y>=0&&x>=0;x--,y--){//左下寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
for(int x=xIndex+1,y=yIndex+1;y<=ROWS&&x<=COLS;x++,y++){//右上寻找
Color c=isBack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
if(continueCount>=5){//判断记录数大于等于五,即表示此方获胜
return true;
}else
continueCount=1;
return false;
}
private Point getChess(int xIndex,int yIndex,Color color){
for(Point c:chessList){
if(c!=null&&c.getX()==xIndex&&c.getY()==yIndex&&c.getColor()==color)
return c;
}
return null;
}
public void restartGame(){//清除棋子
for(int i=0;i0){
xIndex=chessList[chessCount-1].getX();
yIndex=chessList[chessCount-1].getY();
}
isBack=!isBack;
repaint();
}
//Dimension:矩形
public Dimension getPreferredSize(){
return new Dimension(MARGIN*2+GRID_SPAN*COLS,MARGIN*2+GRID_SPAN*ROWS);
}
}
package chess.lcc.com;
import java.awt.*;
public class Point {
private int x;//棋子在棋盘中的x索引值
private int y;//棋子在棋盘中的y索引值
private Color color;//颜色
public static int DIAMETER=30;//直径
public Point(int x,int y,Color color){
this.x=x;
this.y=y;
this.color=color;
}
//得到棋子在棋盘中的x索引值
public int getX(){
return x;
}
//得到棋子在棋盘中的y索引值
public int getY(){
return y;
}
//得到棋子颜色
public Color getColor(){
return color;
}
}