public class Board {
public static int rows;//行数
public static int cols;//列数
public static int size;//格子大小
public static int margin;//边距
static {
rows = 20;
cols = 20;
size = 30;
margin = 30;
}
/**
* 物理坐标(像素)转换成逻辑坐标
* @param x 物理坐标横坐标
* @param y 物理坐标纵坐标
* @return 转换后的逻辑坐标,如果非法逻辑坐标则返回null
*/
public static Point convert(int x,int y){
int row = (y-Board.margin+Board.size/2)/Board.size;
int col = (x-Board.margin+Board.size/2)/Board.size;
if(row < 0 || row >= rows){
return null;
}
if(col < 0 || row >= cols){
return null;
}
return new Point(row,col);
}
public static int getWidth(){
return (cols-1)*size+margin*2;
}
public static int getHeight(){
return (rows-1)*size+margin*2;
}
/**
* 判断落点是否合法
* @param p 落点
* @return 是否合法
*/
public static boolean valid(Point p) {
//排除行号越界
if(p.row<0||p.row>=rows){
return false;
}
//排除列号越界
if(p.col<0||p.col>=cols){
return false;
}
return true;
}
}
package 五子棋;
public class Chess {
public final static int NONE = 0;//无子
public final static int BLACK = 1;//黒子
public final static int WHITE = -1;//白子
private int [][]chesses;//存储每个落点的状态
private int turn;//当前落子方
/**
* 构造函数
*/
public Chess(){
//初始化所有落点为无子状态
chesses = new int[Board.rows][Board.cols];
for (int i = 0; i < Board.rows; i++) {
for (int j = 0; j < Board.cols; j++) {
chesses[i][j]=NONE;
}
}
//黑方先手
turn = BLACK;
}
/**
* 判断落点是否有子
* @param p 落点
* @return 是否有子
*/
public boolean exist(Point p){
return getChess(p) !=NONE;
}
/**
* 判断落子产生的输赢结果
* @param p 落点(以此点为中心向四面八方拓展判断)
* @return 0(NONE)-无;1(BLACK)-黑方胜;-1(EHILE)-白方胜
*/
public int isWin(Point p){
//垂直方向
if(expand (p,0)+expand(p,4)>=4){
return getChess(p);
}
//水平方向
if(expand (p,6)+expand(p,2)>=4){
return getChess(p);
}
//对角线方向
if(expand (p,7)+expand(p,3)>=4){
return getChess(p);
}
//反对角线方向
if(expand (p,1)+expand(p,5)>=4){
return getChess(p);
}
/* if(expand1(p)>=5){
return getChess(p);
} if(expand2(p)>=5){
return getChess(p);
}*/
return NONE;
}
/**
* 以落点为起点向其它方向拓展
* @param p 落点
* @param direction 方向:0-向上;1-右上;2-右;3-右下;4-向下;5-左下;6-向左;7-左上
* @return 同色棋子的个数(不包含起始落点)
*/
private int expand(Point p, int direction) {
int n =0;
Point p1 = new Point(p.row,p.col);//复制
while (true){
//计算出指定方向下一个落点
switch (direction){
case 0: p1.row--; break;
case 1: p1.row--;p1.col++; break;
case 2: p1.col++; break;
case 3: p1.row++;p1.col++; break;
case 4: p1.row++; break;
case 5: p1.row++;p1.col--; break;
case 6: p1.col--; break;
case 7: p1.row--;p1.col--; break;
}
//如果落点不合法则结束
if(!Board.valid(p1)){
break;
}
//如果颜色不同则结束
if(getChess(p1) != getChess(p)){
break;
}
//计算器加1
n++;
}
return n;
}
/**
* 获取指定落点棋子的颜色
* @param p 落点
* @return 颜色
*/
private int getChess(Point p) {
return chesses[p.row][p.col];
}
/* *//*
* 以落点向水平方向拓展
* @param p 落点
* @return 同色棋子的个数
*//*
private int expand1(Point p) {
int n = 1;//计算器
int color = chesses[p.row][p.col];//落点棋子的颜色
//往左拓展
for (int col = p.col-1; col >=0 ; col--) {
if(chesses[p.row][col]==color){
n++;
}else {
break;
}
}
//向右拓展
for (int col = p.col+1; col <=Board.cols-1 ; col++) {
if(chesses[p.row][col]==color){
n++;
}else {
break;
}
}
return n;
}
*//*
* 以落点向垂直方向拓展
* @param p 落点
* @return 同色棋子的个数
*//*
private int expand2(Point p) {
int n = 1;
int color = chesses[p.row][p.col];//落点棋子的颜色
//往上拓展
for (int row = p.col-1; row >=0 ; row--) {
if(chesses[row][p.col]==color){
n++;
}else {
break;
}
}
//向下拓展
for (int row = p.col+1; row <=Board.rows-1 ; row++) {
if(chesses[row][p.col]==color){
n++;
}else {
break;
}
}
return n;
}*/
/**
* 落子
* @param p 落点
* @return 落子方
*/
public int add(Point p){
chesses[p.row][p.col] = turn;//将指定落点的状态设为当前落子方
turn = -turn;//切换
return getChess(p);
}
}
package 五子棋;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Game {
private Frame frame;//窗体
private Canvas canvas;//画布
private Graphics g;//画笔
private Button button;//按钮
private Chess chess;//棋局
/**
* 构造函数
*/
public Game(){
frame = new Frame("五子棋");
frame.setLayout(new FlowLayout());//设置流式布局
frame.setSize(Board.getWidth(),Board.getHeight()+100);
frame.setVisible(true);
canvas = new Canvas();
canvas.setSize(Board.getWidth(),Board.getHeight());
frame.add(canvas);
button = new Button("Start");
frame.add(button);
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent mouseEvent) {
g= canvas.getGraphics();//获得画笔
drawBoard();//画棋盘
canvas.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
handle(e.getX(),e.getY());
super.mouseClicked(e);
}
});
super.mouseClicked(mouseEvent);
}
});
chess = new Chess();//初始化棋局
}
/**
* 处理用户落子指令
* @param x 像素横坐标
* @param y 像素纵坐标
*/
public void handle(int x, int y){
// System.out.printf("单机了棋盘:x=%d,y=%d\n",x,y);
//将物理坐标转换为逻辑坐标,如果逻辑坐标非法(不在棋盘范围内)则不处理
Point p = Board.convert(x,y);
if(null == p){
return;
}
//如果指定位置没有棋子则落子,否则什么也不做。
if(chess.exist(p)){
return;
}
int turn = chess.add(p);//落子
drawChess(p,turn);//画棋子
switch (chess.isWin(p)){
case Chess.BLACK:
System.out.println("黑方胜!");
break;
case Chess.WHITE:
System.out.println("白方胜!");
break;
}
}
/**
* 绘制棋盘
*/
public void drawBoard(){
g.setColor(Color.YELLOW);
g.fillRect(0,0,Board.getWidth(),Board.getHeight());
int startX = Board.margin;//经线的七点
int endX = Board.getWidth()-Board.margin;//经线的终点
int startY = Board.margin;//纬线的起点
int endY = Board.getHeight()-Board.margin;//纬线的终点
g.setColor(Color.RED);
//画经线
for(int x=startX;x<=endX;x+=Board.size){
g.drawLine(x,startY,x,endY);
}
//画纬线
for(int y=startY;y<=endY;y+=Board.size){
g.drawLine(startX,y,endX,y);
}
}
/**
* 绘制棋子
* @param p 落点
* @param turn 黑子/白子
*/
public void drawChess(Point p, int turn){
//计算圆心坐标
int x = p.col*Board.size+Board.margin;
int y = p.row*Board.size+Board.margin;
int r = Board.size/4;//棋子的半径(可以调整)
g.setColor(turn == Chess.BLACK?Color.BLACK:Color.WHITE);
g.fillArc(x-r,y-r,2*r,2*r,0,360);
}
public static void main(String[] args) {
Game game =new Game();
}
}
package 五子棋;
public class Point {
public int row;//行号
public int col;//列号
public Point(int row, int col) {
this.row = row;
this.col = col;
}
}