java实训五子棋_Java实践(十一)——五子棋

本文介绍了使用Java实现五子棋程序的实践,包括GUI界面设计、鼠标事件监听,以及棋盘类、棋子类和主框架类的详细实现。通过实例展示了如何处理棋盘上的落子、检查游戏胜负及实现悔棋功能。
摘要由CSDN通过智能技术生成

一、实践目标:

1.掌握JavaGUI界面设计

2.掌握鼠标事件的监听(MouseListener,MouseMotionListener)

二、实践内容:

设计一个简单的五子棋程序,能够实现五子棋下棋过程。如下图所示

1352725519_9187.jpg

五子棋运行界面

1.五子棋棋盘类package cn.edu.ouc.fiveChess;

import java.awt.Color;

import java.awt.Cursor;

import java.awt.Dimension;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.Image;

import java.awt.RadialGradientPaint;

import java.awt.RenderingHints;

import java.awt.Toolkit;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

import java.awt.event.MouseMotionListener;

import java.awt.geom.Ellipse2D;

import javax.swing.*;

/**

* 五子棋--棋盘类

*/

public class ChessBoard extends JPanel implements MouseListener {

public static final int MARGIN=30;//边距

public static final int GRID_SPAN=35;//网格间距

public static final int ROWS=15;//棋盘行数

public static final int COLS=15;//棋盘列数

Point[] chessList=new Point[(ROWS+1)*(COLS+1)];//初始每个数组元素为null

boolean isBlack=true;//默认开始是黑棋先

boolean gameOver=false;//游戏是否结束

int chessCount;//当前棋盘棋子的个数

int xIndex,yIndex;//当前刚下棋子的索引

Image img;

Image shadows;

Color colortemp;

public ChessBoard(){

// setBackground(Color.blue);//设置背景色为橘黄色

img=Toolkit.getDefaultToolkit().getImage("board.jpg");

shadows=Toolkit.getDefaultToolkit().getImage("shadows.jpg");

addMouseListener(this);

addMouseMotionListener(new MouseMotionListener(){

public void mouseDragged(MouseEvent e){

}

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;

//游戏已经结束不能下

//落在棋盘外不能下

//x,y位置已经有棋子存在,不能下

if(x1<0||x1>ROWS||y1<0||y1>COLS||gameOver||findChess(x1,y1))

setCursor(new Cursor(Cursor.DEFAULT_CURSOR));

//设置成默认状态

else setCursor(new Cursor(Cursor.HAND_CURSOR));

}

});

}

//绘制

public void paintComponent(Graphics g){

super.paintComponent(g);//画棋盘

int imgWidth= img.getWidth(this);

int imgHeight=img.getHeight(this);//获得图片的宽度与高度

int FWidth=getWidth();

int FHeight=getHeight();//获得窗口的宽度与高度

int x=(FWidth-imgWidth)/2;

int y=(FHeight-imgHeight)/2;

g.drawImage(img, x, y, null);

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

//网格交叉点x,y坐标

int xPos=chessList[i].getX()*GRID_SPAN+MARGIN;

int yPos=chessList[i].getY()*GRID_SPAN+MARGIN;

g.setColor(chessList[i].getColor());//设置颜色

// g.fillOval(xPos-Point.DIAMETER/2, yPos-Point.DIAMETER/2,

//Point.DIAMETER, Point.DIAMETER);

//g.drawImage(shadows, xPos-Point.DIAMETER/2, yPos-Point.DIAMETER/2, Point.DIAMETER, Point.DIAMETER, null);

colortemp=chessList[i].getColor();

if(colortemp==Color.black){

RadialGradientPaint paint = new RadialGradientPaint(xPos-Point.DIAMETER/2+25, yPos-Point.DIAMETER/2+10, 20, new float[]{0f, 1f}

, new Color[]{Color.WHITE, Color.BLACK});

((Graphics2D) g).setPaint(paint);

((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT);

}

else if(colortemp==Color.white){

RadialGradientPaint paint = new RadialGradientPaint(xPos-Point.DIAMETER/2+25, yPos-Point.DIAMETER/2+10, 70, new float[]{0f, 1f}

, new Color[]{Color.WHITE, Color.BLACK});

((Graphics2D) g).setPaint(paint);

((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT);

}

Ellipse2D e = new Ellipse2D.Float(xPos-Point.DIAMETER/2, yPos-Point.DIAMETER/2, 34, 35);

((Graphics2D) g).fill(e);

//标记最后一个棋子的红矩形框

if(i==chessCount-1){//如果是最后一个棋子

g.setColor(Color.red);

g.drawRect(xPos-Point.DIAMETER/2, yPos-Point.DIAMETER/2,

34, 35);

}

}

}

public void mousePressed(MouseEvent e){//鼠标在组件上按下时调用

//游戏结束时,不再能下

if(gameOver) return;

String colorName=isBlack?"黑棋":"白棋";

//将鼠标点击的坐标位置转换成网格索引

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;

//如果x,y位置已经有棋子存在,不能下

if(findChess(xIndex,yIndex))return;

//可以进行时的处理

Point ch=new Point(xIndex,yIndex,isBlack?Color.black:Color.white);

chessList[chessCount++]=ch;

repaint();//通知系统重新绘制

//如果胜出则给出提示信息,不能继续下棋

if(isWin()){

String msg=String.format("恭喜,%s赢了!", colorName);

JOptionPane.showMessageDialog(this, msg);

gameOver=true;

}

isBlack=!isBlack;

}

//覆盖mouseListener的方法

public void mouseClicked(MouseEvent e){

//鼠标按键在组件上单击时调用

}

public void mouseEntered(MouseEvent e){

//鼠标进入到组件上时调用

}

public void mouseExited(MouseEvent e){

//鼠标离开组件时调用

}

public void mouseReleased(MouseEvent e){

//鼠标按钮在组件上释放时调用

}

//在棋子数组中查找是否有索引为x,y的棋子存在

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=isBlack?Color.black:Color.white;

if(getChess(x,yIndex,c)!=null){

continueCount++;

}else

break;

}

//横向向东寻找

for(int x=xIndex+1;x<=COLS;x++){

Color c=isBlack?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=isBlack?Color.black:Color.white;

if(getChess(xIndex,y,c)!=null){

continueCount++;

}else

break;

}

//纵向向下寻找

for(int y=yIndex+1;y<=ROWS;y++){

Color c=isBlack?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=isBlack?Color.black:Color.white;

if(getChess(x,y,c)!=null){

continueCount++;

}

else break;

}

//西南寻找

for(int x=xIndex-1,y=yIndex+1;x>=0&&y<=ROWS;x--,y++){

Color c=isBlack?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;x>=0&&y>=0;x--,y--){

Color c=isBlack?Color.black:Color.white;

if(getChess(x,y,c)!=null)

continueCount++;

else break;

}

//东南寻找

for(int x=xIndex+1,y=yIndex+1;x<=COLS&&y<=ROWS;x++,y++){

Color c=isBlack?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 p:chessList){

if(p!=null&&p.getX()==xIndex&&p.getY()==yIndex

&&p.getColor()==color)

return p;

}

return null;

}

public void restartGame(){

//清除棋子

for(int i=0;i

chessList[i]=null;

}

//恢复游戏相关的变量值

isBlack=true;

gameOver=false; //游戏是否结束

chessCount =0; //当前棋盘棋子个数

repaint();

}

//悔棋

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();

}

isBlack=!isBlack;

repaint();

}

//矩形Dimension

public Dimension getPreferredSize(){

return new Dimension(MARGIN*2+GRID_SPAN*COLS,MARGIN*2

+GRID_SPAN*ROWS);

}

}

2.棋子类package cn.edu.ouc.fiveChess;

import java.awt.Color;

/**

* 棋子类

*/

public class Point {

private int x;//棋盘中的x索引

private int y;//棋盘中的y索引

private Color color;//颜色

public static final int DIAMETER=30;//直径

public Point(int x,int y,Color color){

this.x=x;

this.y=y;

this.color=color;

}

public int getX(){//拿到棋盘中x的索引

return x;

}

public int getY(){

return y;

}

public Color getColor(){//获得棋子的颜色

return color;

}

}

3.五子棋主框架类package cn.edu.ouc.fiveChess;

import java.awt.event.*;

import java.awt.*;

import javax.swing.*;

/*

五子棋主框架類,程序啟動類

*/

public class StartChessJFrame extends JFrame {

private ChessBoard chessBoard;

private JPanel toolbar;

private JButton startButton,backButton,exitButton;

private JMenuBar menuBar;

private JMenu sysMenu;

private JMenuItem startMenuItem,exitMenuItem,backMenuItem;

//重新开始,退出,和悔棋菜单项

public StartChessJFrame(){

setTitle("单机版五子棋");//设置标题

chessBoard=new ChessBoard();

Container contentPane=getContentPane();

contentPane.add(chessBoard);

chessBoard.setOpaque(true);

//创建和添加菜单

menuBar =new JMenuBar();//初始化菜单栏

sysMenu=new JMenu("系统");//初始化菜单

//初始化菜单项

startMenuItem=new JMenuItem("重新开始");

exitMenuItem =new JMenuItem("退出");

backMenuItem =new JMenuItem("悔棋");

//将三个菜单项添加到菜单上

sysMenu.add(startMenuItem);

sysMenu.add(exitMenuItem);

sysMenu.add(backMenuItem);

//初始化按钮事件监听器内部类

MyItemListener lis=new MyItemListener();

//将三个菜单注册到事件监听器上

this.startMenuItem.addActionListener(lis);

backMenuItem.addActionListener(lis);

exitMenuItem.addActionListener(lis);

menuBar.add(sysMenu);//将系统菜单添加到菜单栏上

setJMenuBar(menuBar);//将menuBar设置为菜单栏

toolbar=new JPanel();//工具面板实例化

//三个按钮初始化

startButton=new JButton("重新开始");

exitButton=new JButton("退出");

backButton=new JButton("悔棋");

//将工具面板按钮用FlowLayout布局

toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));

//将三个按钮添加到工具面板

toolbar.add(startButton);

toolbar.add(exitButton);

toolbar.add(backButton);

//将三个按钮注册监听事件

startButton.addActionListener(lis);

exitButton.addActionListener(lis);

backButton.addActionListener(lis);

//将工具面板布局到界面”南方“也就是下方

add(toolbar,BorderLayout.SOUTH);

add(chessBoard);//将面板对象添加到窗体上

//设置界面关闭事件

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//setSize(800,800);

pack();//自适应大小

}

private class MyItemListener implements ActionListener{

public void actionPerformed(ActionEvent e){

Object obj=e.getSource();//获得事件源

if(obj==StartChessJFrame.this.startMenuItem||obj==startButton){

//重新开始

//JFiveFrame.this内部类引用外部类

System.out.println("重新开始");

chessBoard.restartGame();

}

else if (obj==exitMenuItem||obj==exitButton)

System.exit(0);

else if (obj==backMenuItem||obj==backButton){

System.out.println("悔棋...");

chessBoard.goback();

}

}

}

public static void main(String[] args){

StartChessJFrame f=new StartChessJFrame();//创建主框架

f.setVisible(true);//显示主框架

}

}

三、总结

1.菜单的设计与实现?

2.鼠标点击棋盘后,如何绘制棋子?如何为刚下的棋子绘制一个红色框?

3.棋谱是如何一个数据结构?

#include<graphics.h> #include<conio.h> #include <mmsystem.h> #pragma comment(lib,"winmm.lib") void Beginning(); //开始图片 void Background(); //显示背景 void ShowPlate(); //显示棋盘 void PlayGame(); //玩游戏 void Judgewin(int,int); //判断输赢 void Blackwin(); //黑棋赢 void Whitewin(); //白棋赢 bool flag=true; //走棋顺序 int piece[16][16]; //棋子变量 int ti,tj; int f=1; void main() { for(int i=0;i<16;i++) for(int j=0;j<16;j++) piece[i][j]=0; //初始化棋子变量 initgraph(965,642); //设置窗口大小 mciSendString("play 2.mp3",0,0,0);//播放背景音乐 Background(); //显示背景 PlayGame(); //玩游戏 getch(); //保持窗口开着 } void Background() { IMAGE img; getimage(&img, "2.jpg"); putimage(0,0, &img); //设置背景图片 } void ShowPlate() { setfillstyle(RGB(213,176,146)); bar(270,30,730,490); //棋盘大小 for(int x=290,y=50;x<=710,y<=470;x+=30,y+=30) //画棋盘线 { setcolor(BLACK); line(x,50,x,470); line(290,y,710,y); } setfillstyle(BLACK); bar(284,44,286,476); bar(284,44,716,46); bar(714,44,716,476); bar(284,474,716,476);//棋盘线周围的一圈粗线 fillellipse(380,140,4,4); fillellipse(620,140,4,4); fillellipse(380,380,4,4); fillellipse(620,380,4,4); fillellipse(500,260,4,4);//棋盘的五个小黑点 setcolor(BLACK); setfillstyle(RGB(213,176,146)); bar3d(800,100,900,140,0,0); bar3d(800,200,900,240,0,0); bar3d(800,300,900,340,0,0); setfont(24,0,"华文行楷"); outtextxy(805,110,"重新开始");//重新开始 按钮 outtextxy(827,210,"悔棋");//悔棋按钮 outtextxy(827,310,"投降");//投降按钮 setcolor(RGB(213,176,146)); setfillstyle(WHITE); fillellipse(820,28,20,20); setcolor(RGB(213,176,146)); setfillstyle(BLACK); fillellipse(880,28,20,20); for(int i=0;i<15;i++) { for(int j=0;j<15;j++) { if(piece[i][j]==-1) { setcolor(WHITE); setfillstyle(WHITE); fillellipse(290+j*30,50+i*30,12,12); } else if(piece[i][j]==1) { setcolor(BLACK); setfillstyle(BLACK); fillellipse(290+j*30,50+i*30,12,12); } } } } void PlayGame() { int h=0; int y=0; int Y; int ti=0,tj=0; while(f) { MOUSEMSG msg=GetMouseMsg(); //得到鼠标输入 while(msg.uMsg==WM_LBUTTONUP) { h++; if(h==1) { ShowPlate(); } else break; } if(h>2) { int a,b,c,d; a=(msg.x-290)%30; b=(msg.y-50)%30; c=(msg.x-290)/30+a/15;//落子点的横坐标 d=(msg.y-50)/30+b/15;//落子点的纵坐标 if(msg.x>800&&msg.x<840&&msg.y>8&&msg.y<48&&y==0) flag=false; else if(msg.x>860&&msg.x<900&&msg.y>8&&msg.y<48&&y==0) flag=true; if(a==15||b==15) //判断是否在两格中间 continue; if(msg.uMsg==WM_LBUTTONUP&&piece[d][c]==0&&(c>=0&&c<15&&d>=0&&d<15)) //判断是否在棋盘内且无棋子 { mciSendString("play 3.mp3",0,0,0); if(flag==true) { piece[d][c]=1; setcolor(BLACK); setfillstyle(BLACK); fillellipse(290+c*30,50+d*30,12,12); flag=false; ti=d; tj=c; y++; } else { piece[d][c]=-1; setcolor(WHITE); setfillstyle(WHITE); fillellipse(290+c*30,50+d*30,12,12); flag=true; ti=d; tj=c; y++; } } Judgewin(c,d); if(msg.uMsg==WM_LBUTTONUP) if((msg.x>=800&&msg.x<=900)&&(msg.y>=300&&msg.y<=340)) //投降 { if(flag==true) Whitewin(); else Blackwin(); } if(msg.uMsg==WM_LBUTTONUP) if((msg.x>=800&&msg.x<=900)&&(msg.y>=100&&msg.y<=140)) //中途重新开始 { y=0; for (c=0;c<16;c++) { for (d=0;d<16;d++) { piece[c][d]=0; } } ShowPlate(); } if(msg.uMsg==WM_LBUTTONUP) { if ((msg.x>=800&&msg.x<=900)&&(msg.y>=200&&msg.y<=240)&&(Y!=y)) //悔棋 { Y=y; if(flag==true) flag=false; else flag=true; piece[ti][tj]=0; ShowPlate(); } } } while(!f) //结束后重新开始 { MOUSEMSG msg=GetMouseMsg(); if(msg.uMsg==WM_LBUTTONUP) if((msg.x>=800&&msg.x<=900)&&(msg.y>=100&&msg.y<=140)) { for (int c1=0;c1<16;c1++) { for (int d1=0;d1<16;d1++) { piece[c1][d1]=0; } } ShowPlate(); f=1; PlayGame(); } } } } void Judgewin(int c,int d) { for(int i=0;i<15;i++)//判断是否五子连珠——横向 { int s=0; for(int j=i;j<i+5;j++) { s=s+piece[d][j]; if(s==5) Blackwin(); if(s==-5) Whitewin(); } } for(int m=0;m<15;m++)//判断是否五子连珠——纵向 { int s=0; for(int n=m;n<m+5;n++) { s=s+piece[n][c]; if(s==5) Blackwin(); if(s==-5) Whitewin(); } } for(int p=d-5,q=c-5;p<15;p++,q++)//判断是否五子连珠——左上到右下 { int s=0; for(int t=0;t<5;t++) { s=s+piece[p+t][q+t]; if(s==5) Blackwin(); if(s==-5) Whitewin(); } } for(int P=d+5,Q=c-5;Q<15;P--,Q++)//判断是否五子连珠——左下到右上 { int s=0; for(int t=0;t<5;t++) { s=s+piece[P-t][Q+t]; if(s==5) Blackwin(); if(s==-5) Whitewin(); } } } void Blackwin() { setcolor(WHITE); setfillstyle(BLACK); fillellipse(500,260,70,30); outtextxy(470,250,"黑子赢"); f=0; mciSendString("play 4.mp3",0,0,0); } void Whitewin() { setcolor(BLACK); setfillstyle(WHITE); fillellipse(500,260,70,30); outtextxy(470,250,"白子赢"); f=0; mciSendString("play 4.mp3",0,0,0); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值