实现一个Java五子棋
五子棋手把手教你写:
写在前面的话:
回想起从前初学代码的五子棋简直写的不像样子。今天闲来无事就写了个五子棋的小程序。
一来呢回忆一下很久以前写代码时的感觉。
二来呢顺便帮下诸位有需求的学生,顺利的Ctrl+C。
五子棋的运行效果如下。

开发环境:
这个小程序是基于Java实现的。因此呢需要提前安装JDK环境。(老油条忽略此条信息)
开发环境jdk1.8 + eclipse
eclipse 目录结构如下所示

棋盘数据结构核心:
无论你做数据库开发还是做一些小程序,第一时间考虑的必须是需求+建模。把核心设计出来。
此次我们用一个二维数组作为棋盘,每条线交叉的地方设为二维数组的值,并约定:
0=空
1=白棋
2=黑棋
然后对应的把下棋,悔棋,判断输赢(横竖斜)和清盘的算法都实现出来。
具体展现如下:
悔棋时候我们需要用一个栈来保存我们之前下棋的信息:
/**
* 在该位置下棋 1:white 2:black
* @param x 横坐标
* @param y 纵坐标
* @param var 棋子种类
* @return 1:white 赢 2:black赢
*/
public int ChessIt(int x,int y,int var) {
if(__CanInput(x,y)) {
core[x][y] =var;
Chess chess = new Chess(x,y);
stack.push(chess);
return checkVictory(x, y, var);
}
else return -;
} //悔棋
public boolean RetChess() {
if(stack.isEmpty()) return false;
Chess chess = stack.pop();
core[chess.x][chess.y]= ;
return true;
}
判断输赢:
private int checkVictory(int x,int y,int var) {
//横向判断
int trans = ;
for(int i=x-;i<x+;i++) {
if(i<||i>=this.x) continue;
if(core[i][y]==var) {
trans++;
}
else {
trans=;
}
if(trans==) return var;
}
//纵向判断
int longitudinal = ;
for(int i=y-;i<y+;i++) {
if(i<||i>=this.y) continue;
if(core[x][i]==var) {
longitudinal++;
}
else {
longitudinal=;
}
if(longitudinal==) return var;
}
//从左上到右下
int leftUPToDown = ;
for(int i=x-,j=y+;i<x+&&j>y-;i++,j--) {
if(i<||i>=this.x||j<||j>=this.y) continue;
if(core[i][j]==var) {
leftUPToDown++;
}else {
leftUPToDown=;
}
if(leftUPToDown==) return var;
}
//从左下到右上
int leftDownToUP = ;
for(int i=x+,j=y+;i>x-&&j>y-;i--,j--) {
if(i<||i>=this.x||j<||j>=this.y) continue;
if(core[i][j]==var) {
leftDownToUP++;
}else {
leftDownToUP=;
}
if(leftDownToUP==) return var;
}
return ;
}
总体:Core.java 的代码如下·:
package main; import java.util.Stack; /**
* @author GodofOrange
* 棋盘数据结构
*/
public class Core {
//棋盘大小
private int[][] core;
private int x;
private int y;
//记录下棋的类
class Chess{
int x;
int y;
public Chess(int x,int y) {
this.x=x;
this.y=y;
}
}
//栈
Stack<Chess> stack;
//构造方法
public Core(int x,int y) {
stack = new Stack<>();
core = new int[x][y];
this.x=x;
this.y=y;
}
//检查该地是否有空位置
private boolean __CanInput(int x,int y) {
if(core[x][y]==) return true;
else return false;
}
//判断输赢
private int checkVictory(int x,int y,int var) {
//横向判断
int trans = ;
for(int i=x-;i<x+;i++) {
if(i<||i>=this.x) continue;
if(core[i][y]==var) {
trans++;
}
else {
trans=;
}
if(trans==) return var;
}
//纵向判断
int longitudinal = ;
for(int i=y-;i<y+;i++) {
if(i<||i>=this.y) continue;
if(core[x][i]==var) {
longitudinal++;
}
else {
longitudinal=;
}
if(longitudinal==) return var;
}
//从左上到右下
int leftUPToDown = ;
for(int i=x-,j=y+;i<x+&&j>y-;i++,j--) {
if(i<||i>=this.x||j<||j>=this.y) continue;
if(core[i][j]==var) {
leftUPToDown++;
}else {
leftUPToDown=;
}
if(leftUPToDown==) return var;
}
//从左下到右上
int leftDownToUP = ;
for(int i=x+,j=y+;i>x-&&j>y-;i--,j--) {
if(i<||i>=this.x||j<||j>=this.y) continue;
if(core[i][j]==var) {
leftDownToUP++;
}else {
leftDownToUP=;
}
if(leftDownToUP==) return var;
}
return ;
}
/**
* 在该位置下棋 1:white 2:black
* @param x 横坐标
* @param y 纵坐标
* @param var 棋子种类
* @return 1:white 赢 2:black赢
*/
public int ChessIt(int x,int y,int var) {
if(__CanInput(x,y)) {
core[x][y] =var;
Chess chess = new Chess(x,y);
stack.push(chess);
return checkVictory(x, y, var);
}
else return -;
}
//悔棋
public boolean RetChess() {
if(stack.isEmpty()) return false;
Chess chess = stack.pop();
core[chess.x][chess.y]= ;
return true;
}
//获得棋盘状态
public int[][] getCore(){
return this.core;
}
//重新开始
public void Restart() {
for(int i=;i<this.x;i++) {
for(int j=;j<this.y;j++) {
this.core[i][j]=;
}
}
this.stack.clear();
}
}
Windows的前端代码
在上一步我们把一个五子棋的数据结构实现了之后,我们下一步就需要用JavaSwing的知识来画前端。
首先我们定义一个类来继承JFrame,从而包含JFrame的所有功能。
以下是JFrame常用的方法。
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭JFrame时运行System.exit(0)
jFrame.setLocationRelativeTo(null);//屏幕中央显示
jFrame.setVisible(true);//可见
其次我们需要单击屏幕进行下棋,所以我们需要符合鼠标单击事件的接口。因此我们去接上MouseListener的接口。
关于MouseListener接口的介绍如下:
鼠标监听器MouseListener
监听鼠标事件MouseEvent。 相应事件和处理方法
鼠标事件 处理方法
MOUSE_CLICKED MouseClicked (MouseEvent) 鼠标点击(单或双)
MOUSE_PRESSED MousePressed (MouseEvent) 鼠标按下
MOUSE_RELEASED MouseReleased(MouseEvent) 鼠标松开
MOUSE_ENTERED MouseEntered (MouseEvent) 鼠标进入(某组件区域)
MOUSE_EXITED MouseExited (MouseEvent) 鼠标离开(某组件区域)
鼠标事件MouseEvent常用方法
int getClickCount() 得到点击次数1 OR ;
int getX(), int getY() 得到鼠标的(象素)位置。 鼠标监听器MouseMotionListener
对于鼠标的移动和拖放,另外用鼠标运动监听器MouseMotionListener。
因为许多程序不需要监听鼠标运动,把两者分开可简化程序。
相应事件和处理方法
鼠标事件 处理方法
MOUSE_MOVED MouseMoved (MouseEvent) 鼠标在移动
MOUSE_DRAGGED MouseDragged(MouseEvent) 鼠标被拖动
再然后我们重写JFrame里的paint方法来画画。
具体体现:如下
其中横线和竖线都是调用的Graphics中的drawLine方法。
画圈圈用的是drawOval和fillOval分别是画空心圆和画实心圆。
@Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
// 横
for (int i = ; i < ; i++)
g.drawLine(, + i * , , + i * );
// 竖线
for (int i = ; i < ; i++)
g.drawLine( + i * , , + i * , ); int[][] board = core.getCore();
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
if (board[i][j] == )
g.drawOval( + i * , + j * , , );
if(board[i][j]==)
g.fillOval(+i*, +j*, , );
}
}
g.drawRect(,, , );
g.drawString("悔棋",,);
g.drawRect(,,, );
g.drawString("开始",,);
g.drawRect(,,, );
g.drawString("设置",,);
g.drawString("Code by 秃桔子 QQ:1243137612", ,);
}
再然后我们需要确定每次鼠标单击的事件和信息。
具体实现如下:
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
if (e.getX() < && e.getY() < ) {
int a = core.ChessIt(_CgetX(e.getX()), (_CgetY(e.getY())), var);
this.repaint();
if (a == ) {
JOptionPane.showMessageDialog(null,"白的赢了", "恭喜", JOptionPane.DEFAULT_OPTION);;
}
if(a==) {
JOptionPane.showMessageDialog(null,"黑的赢了", "恭喜", JOptionPane.DEFAULT_OPTION);;
}
if(a!=-) {
if(var==) var=;
else if(var==) var=;
}
}
else if(e.getX()>&&e.getX()<&&e.getY()>&&e.getY()<) {
core.RetChess();
if(var==) var=;
else if(var==) var=;
this.repaint();
}
if(e.getX()>&&e.getX()<&&e.getY()>&&e.getY()<) {
core.Restart();
this.repaint();
}
if(e.getX()>&&e.getX()<&&e.getY()>&&e.getY()<) {
Object[] options = {"白先","黑先"};
int n = JOptionPane.showOptionDialog(null,"红先还是黑先?","游戏设置",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE, null,options,options[]);
if(n==) this.var=;
if(n==) this.var=;
this.core.Restart();
this.repaint();
}
}
这里面我调用了一个JOptionPane的组件。该组件的使用的方法一般如下
JOptionPane.showMessageDialog(null, "消息");
JOptionPane.showMessageDialog(null, "消息", "标题",JOptionPane.WARNING_MESSAGE);
JOptionPane.showMessageDialog(null, "消息.", "标题",JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(null, "消息.", "标题",JOptionPane.PLAIN_MESSAGE);
再然后每次单击的时候进行repaint重绘将代码重写出来。
这些东西我也不记得,看api就好了。
下面是总体源码:
package main; import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import javax.swing.JFrame;
import javax.swing.JOptionPane;
/**
*
* @author GodofOrange
* @see 图形界面
*/
public class Windows extends JFrame implements MouseListener {
public Core core;
private static final long serialVersionUID = 1L;
private int var = ;
public Windows(String title) {
super(title);
core = new Core(, );
this.setSize(, );
this.setLocation(, );
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
this.addMouseListener(this);
} @Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
// 横
for (int i = ; i < ; i++)
g.drawLine(, + i * , , + i * );
// 竖线
for (int i = ; i < ; i++)
g.drawLine( + i * , , + i * , ); int[][] board = core.getCore();
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
if (board[i][j] == )
g.drawOval( + i * , + j * , , );
if(board[i][j]==)
g.fillOval(+i*, +j*, , );
}
}
g.drawRect(,, , );
g.drawString("悔棋",,);
g.drawRect(,,, );
g.drawString("开始",,);
g.drawRect(,,, );
g.drawString("设置",,);
g.drawString("Code by 秃桔子 QQ:1243137612", ,);
} @Override
public void mouseClicked(MouseEvent arg0) { } @Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub } @Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub } @Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
if (e.getX() < && e.getY() < ) {
int a = core.ChessIt(_CgetX(e.getX()), (_CgetY(e.getY())), var);
this.repaint();
if (a == ) {
JOptionPane.showMessageDialog(null,"白的赢了", "恭喜", JOptionPane.DEFAULT_OPTION);;
}
if(a==) {
JOptionPane.showMessageDialog(null,"黑的赢了", "恭喜", JOptionPane.DEFAULT_OPTION);;
}
if(a!=-) {
if(var==) var=;
else if(var==) var=;
}
}
else if(e.getX()>&&e.getX()<&&e.getY()>&&e.getY()<) {
core.RetChess();
if(var==) var=;
else if(var==) var=;
this.repaint();
}
if(e.getX()>&&e.getX()<&&e.getY()>&&e.getY()<) {
core.Restart();
this.repaint();
}
if(e.getX()>&&e.getX()<&&e.getY()>&&e.getY()<) {
Object[] options = {"白先","黑先"};
int n = JOptionPane.showOptionDialog(null,"红先还是黑先?","游戏设置",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE, null,options,options[]);
if(n==) this.var=;
if(n==) this.var=;
this.core.Restart();
this.repaint();
}
} @Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub } private int _CgetX(int x) {
x -= ;
if (x % <= )
return x / ;
else
return x / + ;
} private int _CgetY(int y) {
y -= ;
if (y % <= )
return y / ;
else
return y / + ;
}
}
然后就是启动函数了
这个函数放哪都行-.-。。。。。一看就懂吧?
package main;
public class Main {
/** 启动函数
* @param args
*/
public static void main(String[] args) {
new Windows("五子棋");
}
}
总结:
其实五子棋的小程序对于初学者来说并不简单。不适合做练手项目,不过当代码量积累到一定程度,写这个小程序简直不要太轻松。完成起来分分钟钟。一定要打好数据结构的基础并加大代码量。
实现一个Java五子棋的更多相关文章
- Java五子棋小游戏(控制台纯Ai算法)
Java五子棋小游戏(控制台纯Ai算法) 继续之前的那个五子棋程序 修复了一些已知的小Bug 这里是之前的五子棋程序 原文链接 修复了一些算法缺陷 本次增加了AI算法 可以人机对战 也可以Ai对Ai看 ...
- 一个Java文件至多包含一个公共类
编写一个java源文件时,该源文件又称为编译单元.一个java文件可以包含多个类,但至多包含一个公共类,作为编译时该java文件的公用接口,公共类的名字和源文件的名字要相同,源文件名字的格式为[公共类 ...
- 一个java源文件中为什么只能有一个public类。
我们都遇到过一个源文件中有多个java类,但当第一个类使用public修饰时,如果下面还有类使用public修饰,会报错.也就是是说一个java源文件最多只能有一个public类. 当有一个publi ...
- webmagic的设计机制及原理-如何开发一个Java爬虫
之前就有网友在博客里留言,觉得webmagic的实现比较有意思,想要借此研究一下爬虫.最近终于集中精力,花了三天时间,终于写完了这篇文章.之前垂直爬虫写了一年多,webmagic框架写了一个多月,这方 ...
- Java基础-一个java文件多个类的问题
一个.java文件当然可以包括多个类.但这些类有一个特殊的类与其它的不同,,这个类是带public 属性的类.一个.java类文件中仅有一个public属性的类.而且这个类与文件名相同.
- 在Eclipse中,如何把一个java项目变成web项目
经常在eclipse中导入web项目时,出现转不了项目类型的问题,导入后就是一个java项目.解决步骤:1.进入项目目录,可看到.project文件,打开.2.找到<natures>... ...
- 搭建java开发环境、使用eclipse编写第一个java程序
搭建java开发环境.使用eclipse编写第一个java程序 一.Java 开发环境的搭建 1.首先安装java SDK(简称JDK). 点击可执行文件 jdk-6u24-windows-i586. ...
- 分享:写了一个 java 调用 C语言 开发的动态库的范例
分享:写了一个 java 调用 C语言 开发的动态库的范例 cfunction.h 代码#pragma once#ifdef __cplusplusextern "C" {#e ...
- java程序保护如何知识产权,特别提供一个java 开发的java 源代码级的混淆器
java程序保护如何知识产权,特别提供一个java 开发的java 源代码级的混淆器 下载地址:http://yunpan.cn/QXhEcGNYLgwTD 运行方式:java -jar Encryp ...
随机推荐
- LINUX下实现按秒执行计划任务
由于linux最小单位为分,但是很多需求上需要按秒执行,如30秒请求一个URL地址之类的,思路很简单就是修改计划任务脚本用循环控制,代码如下: #!/bin/bash PATH=/bin:/sbin: ...
- Three Steps to Migrate Group Policy Between Active Directory Domains or Forests Using PowerShell
Three Steps Ahead Have you ever wished that you had three legs? Imagine how much faster you could ru ...
- leetcode 【 Trapping Rain Water 】python 实现
题目: Given n non-negative integers representing an elevation map where the width of each bar is 1, co ...
- Windows核心编程小结3
内存映射和堆栈 内存映射文件 内存映射文件可以用于3个不同的目的: 系统使用内存映射文件,以便加载和执行.exe和DLL文件.这可以大大节省页文件空间和应用程序启动运行所需的时间. 可以使用内存映射文 ...
- python 学习分享-装饰器篇
本篇内容为偷窃的~哈哈,借用一下,我就是放在自己这里好看. 引用地址:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 第一步: ...
- RHCE认证经典考题
1:按要求创建用户组及多个用户,设置用户的候选组,设置用户的默认shell. 创建组adminuser. 创建用户natasha和harry属于该组(该组为他们的第二个组). 创建用户sarah,不属 ...
- Visual C++ 连连看游戏源代码
点击下载
- Android之操作相册
获取手机中的图片的绝对路径并且区分出每个文件夹下的路径: 存放图片绝对路径的文件夹的名字和存放绝对路径的List 实体类如下: import java.util.ArrayList; import j ...
- [luogu1357] 花园 [dp+矩阵快速幂]
题面: 传送门 思路: 把P形花圃记录为0,C形记录为1,那么一段花圃就可以状态压缩成一个整数 那么,我们可以有这样的状压dp: dp[i][S]表示前i个花圃,最后m个的状态为S的情况 如果这是一条 ...
- [BZOJ2957] 楼房重建 (线段树,递归)
题目链接 Solution 经典的一道线段树题,难点在于如何合并节点. 由于题目要求直线要求不相交,则斜率均大于前面的点即为答案. 所以以斜率为权值. 考虑线段树每一个节点维护两个值: \(Max\) ...