⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 board.java

📁 Eclipse高级编程3源码(书本源码)
💻 JAVA
字号:
/*******************************************************************************
 * Copyright (c) 2004 Berthold Daum.
 * 
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     Berthold Daum
 *******************************************************************************
 * Hex-7
 *  Version 2.0
 * www.mazeworks.com
 *
 *  Copyright (c) 2002 David Herzog
 *  All Rights Reserved.
 *******************************************************************************/
package com.bdaum.Hex.game;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;

/*******************************************************************************
 * BOARD ****** controls board status, rules of the game, tests for win by
 * either side
 */
public final class Board implements PaintListener, MouseListener {
	static final int SW = 1, SE = 2, E = 3, NE = 4, NW = 5, W = 6, SW_B = 7,
			S_B = 8, SE_B = 9, NE_B = 10, N_B = 11, NW_B = 12;

	private boolean visited[][] = new boolean[Game.SIZE][Game.SIZE];

	private int stack[] = new int[25], stackPtr = 0;

	private int cells[][] = new int[Game.SIZE][Game.SIZE];

	private Canvas canvas;

	private Game game;

	private Display display;

	private Color white, black, gray, green, cyan;

	// Constructor
	public Board(Canvas canvas, Game game) {
		this.game = game;
		this.canvas = canvas;
		display = canvas.getDisplay();
		white = display.getSystemColor(SWT.COLOR_WHITE);
		black = display.getSystemColor(SWT.COLOR_BLACK);
		gray = display.getSystemColor(SWT.COLOR_GRAY);
		green = display.getSystemColor(SWT.COLOR_DARK_GREEN);
		cyan = display.getSystemColor(SWT.COLOR_DARK_CYAN);
		canvas.addPaintListener(this);
		canvas.addMouseListener(this);
	}

	boolean isEmpty(int i, int j) {
		return (cells[i][j] == Game.EMPTY);
	}

	boolean isEmpty(Point h) {
		return (cells[h.x][h.y] == Game.EMPTY);
	}

	boolean isWhite(int i, int j) {
		return (cells[i][j] == Game.WHITE);
	}

	boolean isBlack(int i, int j) {
		return (cells[i][j] == Game.BLACK);
	}

	boolean isColor(int i, int j, int color) {
		return (cells[i][j] == color);
	}

	int getHex(int i, int j) {
		return cells[i][j];
	}

	void setEmpty(int i, int j) {
		cells[i][j] = Game.EMPTY;
	}

	void setEmpty(Point h) {
		cells[h.x][h.y] = Game.EMPTY;
	}

	public boolean setHex(int i, int j, int color) {
		if ((i >= 0) && (i < Game.SIZE) && (j >= 0) && (j < Game.SIZE)
				&& (isEmpty(i, j))) {
			cells[i][j] = color;
			return true;
		} else
			return false;
	}

	public boolean setHex(Point p, int color) {
		return setHex(p.x, p.y, color);
	}

	// make the piece blink for computer move
	void computerMove(Point p, int color) {
		if (setHex(p, color) && (game.getPly() != 1)) {
			draw();
			game.sleep(400);
			setEmpty(p);
			draw();
			game.sleep(400);
			setHex(p, color);
		}
	}

	boolean isVisited(int i, int j) {
		return visited[i][j];
	}

	void setVisited(int i, int j, boolean v) {
		visited[i][j] = v;
	}

	void clearVisited() {
		for (int i = 0; i < Game.SIZE; i++)
			for (int j = 0; j < Game.SIZE; j++)
				visited[i][j] = false;
	}

	// main routine to check for win
	public boolean isWin(int color) {
		clearVisited();
		if (color == Game.WHITE)
			return isWinWhite();
		else
			return isWinBlack();
	}

	private boolean isWinWhite() {
		int x = 0, y = 0;

		for (int i = 0; i < Game.SIZE; i++) {
			if ((cells[i][0] == Game.WHITE) && (!visited[i][0])) {
				x = i;
				y = 0;
				stackPtr = 0;
				visited[x][y] = true;
				if (isWinDFS(x, y, Game.WHITE))
					return true;
			}
		}
		return false;
	}

	private boolean isWinBlack() {
		int x = 0, y = 0;

		for (int j = 0; j < Game.SIZE; j++) {
			if ((cells[0][j] == Game.BLACK) && (!visited[0][j])) {
				x = 0;
				y = j;
				stackPtr = 0;
				visited[x][y] = true;
				if (isWinDFS(x, y, Game.BLACK))
					return true;
			}
		}
		return false;
	}

	private boolean isWinDFS(int x, int y, int color) {
		int direction = 0;

		while (true) {
			// look for a link
			direction = scanLinks(x, y, color);
			if (direction != 0) {
				// found - make it current
				stack[stackPtr++] = direction;
				switch (direction) {
				case SW:
					y++;
					break;
				case SE:
					x++;
					y++;
					break;
				case E:
					x++;
					break;
				case NE:
					y--;
					break;
				case NW:
					x--;
					y--;
					break;
				case W:
					x--;
					break;
				}
				// check for win
				if (color == Game.WHITE) {
					if (y == Game.SIZE - 1)
						return true;
				} else if (x == Game.SIZE - 1)
					return true;
				visited[x][y] = true;
			} else {
				// no path, try next start point
				if (stackPtr == 0)
					return false;
				// at end of path, back up
				direction = stack[--stackPtr];
				switch (direction) {
				case SW:
					y--;
					break;
				case SE:
					x--;
					y--;
					break;
				case E:
					x--;
					break;
				case NE:
					y++;
					break;
				case NW:
					x++;
					y++;
					break;
				case W:
					x++;
					break;
				}
			}
		}
	}

	int scanLinks(int x, int y, int color) {
		int dir = 0;
		// search for unvisited links
		if ((isLinkSW(x, y, color)) && (!visited[x][y + 1]))
			dir = SW;
		else if ((isLinkSE(x, y, color)) && (!visited[x + 1][y + 1]))
			dir = SE;
		else if ((isLinkE(x, y, color)) && (!visited[x + 1][y]))
			dir = E;
		else if ((isLinkNE(x, y, color)) && (!visited[x][y - 1]))
			dir = NE;
		else if ((isLinkNW(x, y, color)) && (!visited[x - 1][y - 1]))
			dir = NW;
		else if ((isLinkW(x, y, color)) && (!visited[x - 1][y]))
			dir = W;
		return dir;
	}

	// links
	boolean isLinkSW(int i, int j, int color) {
		if ((j < Game.SIZE - 1) && (isColor(i, j + 1, color)))
			return true;
		else
			return false;
	}

	boolean isLinkSE(int i, int j, int color) {
		if ((i < Game.SIZE - 1) && (j < Game.SIZE - 1)
				&& (isColor(i + 1, j + 1, color)))
			return true;
		else
			return false;
	}

	boolean isLinkE(int i, int j, int color) {
		if ((i < Game.SIZE - 1) && (isColor(i + 1, j, color)))
			return true;
		else
			return false;
	}

	boolean isLinkNE(int i, int j, int color) {
		if ((j > 0) && (isColor(i, j - 1, color)))
			return true;
		else
			return false;
	}

	boolean isLinkNW(int i, int j, int color) {
		if ((i > 0) && (j > 0) && (isColor(i - 1, j - 1, color)))
			return true;
		else
			return false;
	}

	boolean isLinkW(int i, int j, int color) {
		if ((i > 0) && (isColor(i - 1, j, color)))
			return true;
		else
			return false;
	}

	// Bridge methods are used by static evaluator
	int scanBridges(int x, int y, int color) {
		int dir = 0;
		// search for unvisited bridges
		if ((isBridgeSW(x, y, color)) && (!visited[x - 1][y + 1]))
			dir = SW_B;
		else if ((isBridgeS(x, y, color)) && (!visited[x + 1][y + 2]))
			dir = S_B;
		else if ((isBridgeSE(x, y, color)) && (!visited[x + 2][y + 1]))
			dir = SE_B;
		else if ((isBridgeNE(x, y, color)) && (!visited[x + 1][y - 1]))
			dir = NE_B;
		else if ((isBridgeN(x, y, color)) && (!visited[x - 1][y - 2]))
			dir = N_B;
		else if ((isBridgeNW(x, y, color)) && (!visited[x - 2][y - 1]))
			dir = NW_B;
		return dir;
	}

	// bridges
	boolean isBridgeSW(int i, int j, int color) {
		if ((i > 0) && (j < Game.SIZE - 1) && (isColor(i - 1, j + 1, color))
				&& (isEmpty(i - 1, j)) && (isEmpty(i, j + 1)))
			return true;
		else
			return false;
	}

	boolean isBridgeS(int i, int j, int color) {
		if ((i < Game.SIZE - 1) && (j < Game.SIZE - 2)
				&& (isColor(i + 1, j + 2, color)) && (isEmpty(i, j + 1))
				&& (isEmpty(i + 1, j + 1)))
			return true;
		else
			return false;
	}

	boolean isBridgeSE(int i, int j, int color) {
		if ((i < Game.SIZE - 2) && (j < Game.SIZE - 1)
				&& (isColor(i + 2, j + 1, color)) && (isEmpty(i + 1, j))
				&& (isEmpty(i + 1, j + 1)))
			return true;
		else
			return false;
	}

	boolean isBridgeNE(int i, int j, int color) {
		if ((i < Game.SIZE - 1) && (j > 0) && (isColor(i + 1, j - 1, color))
				&& (isEmpty(i + 1, j)) && (isEmpty(i, j - 1)))
			return true;
		else
			return false;
	}

	boolean isBridgeN(int i, int j, int color) {
		if ((i > 0) && (j > 1) && (isColor(i - 1, j - 2, color))
				&& (isEmpty(i, j - 1)) && (isEmpty(i - 1, j - 1)))
			return true;
		else
			return false;
	}

	boolean isBridgeNW(int i, int j, int color) {
		if ((i > 1) && (j > 0) && (isColor(i - 2, j - 1, color))
				&& (isEmpty(i - 1, j)) && (isEmpty(i - 1, j - 1)))
			return true;
		else
			return false;
	}

	/**
	 * Redraw game board
	 */
	public void draw() {
		canvas.getDisplay().syncExec(new Runnable() {
			public void run() {
				// Signal partial redraw
				canvas.redraw(1, 1, 10000, 10000, false);
			}
		});
	}

	// Edge length of a hexagon (= outer radius)
	private static final int OUTER_RAD = 30;

	// Inner radius of a hexagon
	private static final int INNER_RAD = (int) (Math.sqrt(0.75d) * OUTER_RAD);

	// Outline of a hexagon
	private static final int[] CELL = new int[] { -OUTER_RAD, 0,
			-OUTER_RAD / 2, -INNER_RAD, OUTER_RAD / 2, -INNER_RAD, OUTER_RAD,
			0, OUTER_RAD / 2, INNER_RAD, -OUTER_RAD / 2, INNER_RAD };

	// Horizontal distance between cells
	private static final int XDIST = OUTER_RAD * 3 / 2;

	// Horizontal offset of the game board
	private static final int XOFF = Game.SIZE * OUTER_RAD + 150;

	// Vertical offset of the game board
	private static final int YOFF = 100;

	// Horizontal border width of game board
	private static final int XMARGIN = 20;

	// Vertical border width of game board
	private static final int YMARGIN = 15;

	// Radius of a game button
	private static final int BUTTON_RAD = OUTER_RAD / 2;

	// Corner positions of the game board
	private static final Point TOP = hexToPixel(0, 0);

	private static final Point BOTTOM = hexToPixel(Game.SIZE, Game.SIZE);

	private static final Point RIGHT = hexToPixel(Game.SIZE, 0);

	private static final Point LEFT = hexToPixel(0, Game.SIZE);

	// Outlines of the game board edges
	private static final int[] WHITEBORDER = new int[] { LEFT.x - XMARGIN,
			LEFT.y - INNER_RAD, RIGHT.x + XMARGIN, RIGHT.y - INNER_RAD, TOP.x,
			TOP.y - YMARGIN - INNER_RAD, BOTTOM.x,
			BOTTOM.y + YMARGIN - INNER_RAD };

	private static final int[] BLACKBORDER = new int[] { LEFT.x - XMARGIN,
			LEFT.y - INNER_RAD, TOP.x, TOP.y - YMARGIN - INNER_RAD, BOTTOM.x,
			BOTTOM.y + YMARGIN - INNER_RAD, RIGHT.x + XMARGIN,
			RIGHT.y - INNER_RAD };

	/**
	 * Convert rows and columns into pixel values
	 * 
	 * @param i -
	 *            row
	 * @param j -
	 *            column
	 * @return - (x,y)-coordinate
	 */
	private static Point hexToPixel(int i, int j) {
		return new Point(((i - j) * XDIST) + XOFF, ((i + j) * INNER_RAD) + YOFF);
	}

	/**
	 * Draw Canvas
	 * 
	 * @param e -
	 *            Event object
	 */
	public void paintControl(PaintEvent e) {
		GC gc = e.gc;
		if (e.x != 1 || e.y != 1) {
			// Draw background
			gc.setBackground(gray);
			gc.fillRectangle(canvas.getClientArea());
			// Draw game board edges
			gc.setBackground(white);
			gc.fillPolygon(WHITEBORDER);
			gc.setBackground(black);
			gc.fillPolygon(BLACKBORDER);
		}
		// Draw all hexagon cells
		for (int i = 0; i < Game.SIZE; i++)
			for (int j = 0; j < Game.SIZE; j++)
				drawCellWithButton(gc, i, j, cells[i][j]);
	}

	/**
	 * Draw single cell
	 * 
	 * @param gc -
	 *            Graphic Context
	 * @param i -
	 *            Row
	 * @param j -
	 *            Column
	 * @param buttonColor -
	 *            Color of game button
	 */
	private void drawCellWithButton(GC gc, int i, int j, int buttonColor) {
		Point p = hexToPixel(i, j);
		if (i == Game.SIZE / 2 && j == Game.SIZE / 2)
			drawCell(gc, p.x, p.y, cyan, black);
		else
			drawCell(gc, p.x, p.y, green, black);
		switch (buttonColor) {
		case Game.BLACK:
			drawButton(gc, p.x, p.y, black, white);
			break;
		case Game.WHITE:
			drawButton(gc, p.x, p.y, white, black);
			break;
		}
	}

	/**
	 * Draw cell background
	 * 
	 * @param gc -
	 *            Graphic Context
	 * @param x -
	 *            X-offset
	 * @param y -
	 *            Y-offset
	 * @param cellColor -
	 *            fill color
	 * @param outlineColor -
	 *            outline color
	 */
	private void drawCell(GC gc, int x, int y, Color cellColor,
			Color outlineColor) {
		int[] points = new int[CELL.length];
		for (int k = 0; k < CELL.length; k += 2) {
			points[k] = x + CELL[k];
			points[k + 1] = y + CELL[k + 1];
		}
		gc.setBackground(cellColor);
		gc.setForeground(outlineColor);
		gc.fillPolygon(points);
		gc.drawPolygon(points);
	}

	/**
	 * Draw game button
	 * 
	 * @param gc -
	 *            Graphic Context
	 * @param x -
	 *            X-offset
	 * @param y -
	 *            Y-offset
	 * @param bgColor -
	 *            fill color
	 * @param fgColor -
	 *            outline color
	 */
	private void drawButton(GC gc, int x, int y, Color bgColor, Color fgColor) {
		gc.setBackground(bgColor);
		gc.fillOval(x - BUTTON_RAD, y - BUTTON_RAD, 2 * BUTTON_RAD,
				2 * BUTTON_RAD);
		gc.setForeground(fgColor);
		gc.drawOval(x - BUTTON_RAD, y - BUTTON_RAD, 2 * BUTTON_RAD,
				2 * BUTTON_RAD);
	}

	/**
	 * Doppelklick. Wird ignoriert.
	 * 
	 * @param e -
	 *            Mausereignis
	 */
	public void mouseDoubleClick(MouseEvent e) {
	}

	/*
	 * Mouse button pressed
	 * 
	 * @param e - Event object
	 */
	public void mouseDown(MouseEvent e) {
		Point p = pixelToHex(e.x, e.y);
		game.selectHex(p.x, p.y);
	}

	/**
	 * Convert pixels into row and column
	 * 
	 * @param x -
	 *            X-offset
	 * @param y -
	 *            Y-offset
	 * @return - (row, column)-tuple
	 */
	private static Point pixelToHex(int x, int y) {
		int dist2 = INNER_RAD * INNER_RAD;
		for (int i = 0; i < Game.SIZE; i++) {
			for (int j = 0; j < Game.SIZE; j++) {
				Point p = hexToPixel(i, j);
				int dx = p.x - x;
				int dy = p.y - y;
				if (dx * dx + dy * dy < dist2)
					return new Point(i, j);
			}
		}
		return new Point(-1, -1);
	}

	/*
	 * Maustaste losgelassen. Wird ignoriert.
	 * 
	 * @param e - Mausereignis
	 */
	public void mouseUp(MouseEvent e) {
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -