Java棋类游戏实践之单机版五子棋_java

本文实例讲述了java实现的五子棋游戏代码,分享给大家供大家参考,具体代码如下

一、实践目标
       1.掌握JavaGUI界面设计
       2.掌握鼠标事件的监听(MouseListener,MouseMotionListener)
二、实践内容
      设计一个简单的五子棋程序,能够实现五子棋下棋过程。如下图所示

 

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<chessCount;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.length;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.棋谱是如何一个数据结构?

以上就是本文的全部内容,希望对大家学习java程序设计有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索Java棋类游戏
, Java单机版五子棋
Java五子棋
五子棋单机版、五子棋大师单机版、五子棋单机版下载、五子棋单机版在线玩、双人五子棋单机版,以便于您获取更多的相关知识。

时间: 2024-08-03 02:38:41

Java棋类游戏实践之单机版五子棋_java的相关文章

Java棋类游戏实践之中国象棋_java

本文实例讲述了java实现的中国象棋游戏代码,分享给大家供大家参考,具体代码如下 一.实践目的: 1.鼠标点击.拖动等事件的应用与区别 2.棋谱文件的保存与读取 3.完善象棋的规则. 二.实践内容: 中国象棋历史悠久,吸引了无数的人研究,现对中国象棋的对战和实现棋谱的制作做如下的设计和说明,供大家参考学习. 1.机机对弈,红方先手.在符合规则的情况下拖动棋子到目的地,松鼠标落子. 人人对弈图 2.制作棋谱,选择制作棋谱菜单后,对弈开始,并记录了下棋过程. 选择"制作棋谱"菜单 棋谱制作

java-如题比如我下了一个JAVA小游戏源代码照着写就能运行了吗

问题描述 如题比如我下了一个JAVA小游戏源代码照着写就能运行了吗 比如说俄罗斯方块,五子棋 等我该注意什么问题呢,大神们我知道我的问题对你们来说都是小问题,新手求科普 解决方案 看来你还没有做过游戏方面的东西吧.一般而言,游戏不止有代码,同样的还必须有图片资源,你想一下不然游戏的美工不就只有喝西北风了!!当然也有例外,比如你完全只是调用一些简单的几何图形函数就不会用到图片资源.但是这种游戏几乎没有!所以你要看代码中调用图片资源没有,如果有,还要找到图片资源,同时还要看用到其他的库没有,如果用到

Java 理论与实践: 处理 InterruptedException(转)

  很多 Java 语言方法,例如 Thread.sleep() 和 Object.wait(),都可以抛出InterruptedException.您不能忽略这个异常,因为它是一个检查异常(checked exception).但是应该如何处理它呢?在本月的 Java 理论与实践中,并发专家 Brian Goetz 将解释 InterruptedException 的含义,为什么会抛出 InterruptedException,以及在捕捉到该异常时应该怎么做. 这样的情景您也许并不陌生:您在编

Java棋牌游戏平台

问题描述 一.Java棋牌桌卡游戏平台说明:棋牌游戏厅项目,包含了2款游戏:1)五子棋,每厅200人2)双人麻将,每厅200人使用了Applet.MINA.Spring等技术,支持IE.火狐.谷歌3种浏览器,客户端要求安装JavaJRE,1.6以上版本,在一台客户端主机上一种浏览器只能同时打开一个,该项目暂时没有提供数据库支持,仅用于交流学习.如需交流请发送邮箱:HotStrong@yeah.net下载地址:http://download.csdn.net/source/3005676 解决方案

Java 理论与实践: 哈希

每个Java对象都有hashCode()和 equals()方法.许多类忽略(Override)这些方法的缺省实施,以在对象实例之间提供更深层次的语义可比性.在Java理念和实践这一部分,Java开发人员Brian Goetz向您介绍在创建Java类以有效和准确定义hashCode()和equals()时应遵循的规则和指南.您可以在讨论论坛与作者和其它读者一同探讨您对本文的看法.(您还可以点击本文顶部或底部的讨论进入论坛.) 虽然Java语言不直接支持关联数组 -- 可以使用任何对象作为一个索引

Java 理论与实践:变还是不变?

不变对象具有许多能更方便地使用它们的特性,包括不严格的同步需求和不必考虑数据讹误就能自由地共享和高速缓存对象引用.尽管不变性可能未必对于所有类都有意义,但大多数程序中至少有一些类将受益于不可变.在本月的 Java 理论与实践中,Brian Goetz 说明了不变性的一些长处和构造不变类的一些准则.请在附带的论坛中与作者和其他读者分享您关于本文的心得.(也可以单击文章顶部或底部的"讨论"来访问论坛.) 不变对象是指在实例化后其外部可见状态无法更改的对象.Java 类库中的 String.

Java 理论与实践: JDK 5.0 中更灵活、更具可伸缩性的锁定机制

伸缩 内容: synchronized 快速回顾 对 synchronized 的改进 比较 ReentrantLock 和 synchronized 的可伸缩性 条件变量 这不公平 结束语 参考资料 关于作者 对本文的评价 相关内容: Java 理论与实践 系列 Synchronization is not the enemy Reducing contention IBM developer kits for the Java platform (downloads) 订阅: develop

Java并发基础实践:退出任务II

在本系列的上一篇中所述的退出并发任务的方式都是基于JDK 5之前的API,本文将介绍使用由JDK 5引入的并发工具包中的API来退出任务.(2013.10.08最后更新) 在本系列的前一篇中讲述了三种退出并发任务的方式--停止线程:可取消的任务:中断,但都是基于JDK 5之前的API.本篇将介绍由JDK 5引入的java.concurrent包中的Future来取消任务的执行. 1. Future模式 Future是并发编程中的一种常见设计模式,它相当于是Proxy模式与Thread-Per-M

Java并发基础实践:退出任务I

计划写一个"Java并发基础实践"系列,算作本人对Java并发学习与实践的简单总结.本文是该系列的第一篇,介绍了退出并发任务的最简单方法. 在一个并发任务被启动之后,不要期望它总是会执行完成.由于时间限制,资源限制,用户操作,甚至是任务中的异常(尤其是运行时异常),...都可能造成任务不能执行完成.如何恰当地退出任务是一个很常见的问题,而且实现方法也不一而足. 1. 任务 创建一个并发任务,递归地获取指定目录下的所有子目录与文件的绝对路径,最后再将这些路径信息保存到一个文件中,如代码清