import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import no.geosoft.cc.geometry.Geometry;
import no.geosoft.cc.graphics.*;
/**
* G demo program. Demonstrates:
*
* <ul>
* <li>A sample interactive game application
* <li>Custom interaction
* <li>Dynamic graphics highlighting
* </ul>
*
* @author <a href="mailto:jacob.dreyer@geosoft.no">Jacob Dreyer</a>
*/
public class Demo13 extends JFrame
implements GInteraction
{
private Reversi reversi_;
public Demo13 (int boardSize)
{
super ("G Graphics Library - Demo 13");
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
// Create the GUI
JPanel topLevel = new JPanel();
topLevel.setLayout (new BorderLayout());
getContentPane().add (topLevel);
// Create the graphic canvas
GWindow window = new GWindow (new Color (220, 220, 220));
topLevel.add (window.getCanvas(), BorderLayout.CENTER);
// Create scene
GScene scene = new GScene (window);
double w0[] = {0.0, 0.0, 0.0};
double w1[] = {boardSize + 2.0, 0.0, 0.0};
double w2[] = {0.0, boardSize + 2.0, 0.0};
scene.setWorldExtent (w0, w1, w2);
// Create the Reversi game and graphics representation
reversi_ = new Reversi (boardSize);
GObject reversiBoard = new ReversiBoard();
scene.add (reversiBoard);
pack();
setSize (new Dimension (500, 500));
setVisible (true);
// Make sure plot can be scrolled
window.startInteraction (this);
}
public void event (GScene scene, int event, int x, int y)
{
if (scene == null) return;
GObject interaction = scene.find ("interaction");
if (interaction == null) {
interaction = new GObject ("interaction");
scene.add (interaction);
}
interaction.removeSegments();
double[] w = scene.getTransformer().deviceToWorld (x, y);
int i = (int) w[1] - 1;
int j = (int) w[0] - 1;
if (i < 0 || i >= reversi_.getSize()|| j < 0 || j >= reversi_.getSize())
return;
switch (event) {
case GWindow.MOTION :
if (reversi_.isLegalMove (i, j)) {
GSegment highlight = new GSegment();
GStyle highlightStyle = new GStyle();
highlightStyle.setBackgroundColor (new Color (1.0f, 1.0f, 1.0f, 0.7f));
highlight.setStyle (highlightStyle);
interaction.addSegment (highlight);
highlight.setGeometryXy (new double[] {j + 1.0, i + 1.0,
j + 2.0, i + 1.0,
j + 2.0, i + 2.0,
j + 1.0, i + 2.0,
j + 1.0, i + 1.0});
}
break;
case GWindow.BUTTON1_UP :
if (reversi_.isLegalMove (i, j)) {
reversi_.move (i, j);
interaction.removeSegments();
scene.redraw();
}
}
scene.refresh();
}
class ReversiBoard extends GObject
{
private GSegment board_;
private GSegment[] grid_;
private List pieces_; // og GSegment
private GStyle[] pieceStyle_;
public ReversiBoard()
{
board_ = new GSegment();
GStyle boardStyle = new GStyle();
boardStyle.setBackgroundColor (new Color (0, 200, 0));
board_.setStyle (boardStyle);
addSegment (board_);
GStyle gridStyle = new GStyle();
gridStyle.setForegroundColor (new Color (0, 0, 0));
gridStyle.setLineWidth (2);
grid_ = new GSegment[(reversi_.getSize() + 1) * 2];
for (int i = 0; i < grid_.length; i++) {
grid_[i] = new GSegment();
grid_[i].setStyle (gridStyle);
addSegment (grid_[i]);
}
pieceStyle_ = new GStyle[2];
pieceStyle_[0] = new GStyle();
pieceStyle_[0].setForegroundColor (new Color (255, 255, 255));
pieceStyle_[0].setBackgroundColor (new Color (255, 255, 255));
pieceStyle_[1] = new GStyle();
pieceStyle_[1].setForegroundColor (new Color (0, 0, 0));
pieceStyle_[1].setBackgroundColor (new Color (0, 0, 0));
pieces_ = new ArrayList();
}
public void draw()
{
int size = reversi_.getSize();
// Board
board_.setGeometryXy (new double[] {1.0, 1.0,
size + 1.0, 1.0,
size + 1.0, size + 1.0,
1.0, size + 1.0,
1.0, 1.0});
// Grid lines
for (int i = 0; i <= size; i++) {
grid_[i*2 + 0].setGeometry (1.0, i + 1.0, size + 1.0, i + 1.0);
grid_[i*2 + 1].setGeometry (i + 1.0, 1.0, i + 1.0, size + 1.0);
}
// Pieces
int[] state = reversi_.getState();
int j = 0;
for (int i = 0; i < state.length; i++) {
if (state[i] != 0) {
double y = i / size + 1.5;
double x = i % size + 1.5;
int[] xy = getTransformer().worldToDevice (x, y);
GSegment piece;
if (j < pieces_.size())
piece = (GSegment) pieces_.get (j);
else {
piece = new GSegment();
pieces_.add (piece);
addSegment (piece);
}
j++;
piece.setStyle (pieceStyle_[state[i] - 1]);
piece.setGeometry (Geometry.createCircle (xy[0], xy[1], 15));
}
}
}
}
class Reversi
{
private int size_;
private int[] state_;
private int player_;
public Reversi (int size)
{
size_ = size;
state_ = new int[size_ * size_];
for (int i = 0; i < state_.length; i++)
state_[i] = 0;
state_[(size_ / 2 - 1) * size_ + size_ / 2 - 1] = 1;
state_[(size_ / 2 - 1) * size_ + size_ / 2] = 2;
state_[(size_ / 2) * size_ + size_ / 2 - 1] = 2;
state_[(size_ / 2) * size_ + size_ / 2] = 1;
player_ = 1;
}
public int getSize()
{
return size_;
}
public int[] getState()
{
return state_;
}
public boolean isLegalMove (int i, int j)
{
return state_[i*size_+j] == 0 && (win (i, j, player_)).length > 0;
}
public void move (int i, int j)
{
int[] win = win (i, j, player_);
for (int s = 0; s < win.length; s++)
state_[win[s]] = player_;
state_[i*size_ + j] = player_;
player_ = player_ == 1 ? 2 : 1;
}
private int[] win (int i, int j, int color)
{
List win = new ArrayList();
win.addAll (win (i, j, color, +1, 0));
win.addAll (win (i, j, color, +1, +1));
win.addAll (win (i, j, color, 0, +1));
win.addAll (win (i, j, color, -1, +1));
win.addAll (win (i, j, color, -1, 0));
win.addAll (win (i, j, color, -1, -1));
win.addAll (win (i, j, color, 0, -1));
win.addAll (win (i, j, color, +1, -1));
int[] a = new int[win.size()];
int s = 0;
for (Iterator t = win.iterator(); t.hasNext(); s++)
a[s] = ((Integer) t.next()).intValue();
return a;
}
private List win (int i, int j, int color, int dx, int dy)
{
List win = new ArrayList();
while (true) {
i += dx;
j += dy;
if (i < 0 || i == size_ || j < 0 || j == size_ ||
state_[i*size_ + j] == 0)
return new ArrayList();
else if (state_[i*size_ + j] == color)
return win;
else if (state_[i*size_ + j] != color)
win.add (new Integer (i*size_ + j));
}
}
}
public static void main (String[] args)
{
int boardSize = 8;
new Demo13 (boardSize);
}
}
|