2002-08-06 17:50:25 +00:00
|
|
|
using System;
|
|
|
|
using System.Drawing;
|
|
|
|
|
|
|
|
using Gtk;
|
|
|
|
using Gdk;
|
|
|
|
using Gnome;
|
|
|
|
using GtkSharp;
|
|
|
|
|
|
|
|
|
|
|
|
public class Fifteen
|
|
|
|
{
|
|
|
|
const int PIECE_SIZE = 50;
|
|
|
|
const int SCRAMBLE_MOVES = 256;
|
|
|
|
static Window window = null;
|
|
|
|
static Canvas canvas = null;
|
|
|
|
static BoardPiece [] board;
|
|
|
|
|
|
|
|
static void Main ()
|
|
|
|
{
|
|
|
|
Application.Init ();
|
|
|
|
window = new Window ("Fifteen #");
|
|
|
|
VBox vbox = new VBox (false, 4);
|
|
|
|
vbox.BorderWidth = 4;
|
|
|
|
window.DefaultSize = new Size (300, 300);
|
|
|
|
window.Add (vbox);
|
|
|
|
window.DeleteEvent += new DeleteEventHandler (Window_Delete);
|
|
|
|
|
|
|
|
Alignment alignment = new Alignment (0.5f, 0.5f, 0.0f, 0.0f);
|
|
|
|
vbox.PackStart (alignment, true, true, 0);
|
|
|
|
|
|
|
|
Frame frame = new Frame (String.Empty);
|
|
|
|
frame.ShadowType = ShadowType.In;
|
|
|
|
alignment.Add (frame);
|
|
|
|
|
|
|
|
canvas = new Canvas ();
|
|
|
|
canvas.SetSizeRequest (PIECE_SIZE * 4 + 1, PIECE_SIZE * 4 + 1);
|
|
|
|
canvas.SetScrollRegion (0, 0, PIECE_SIZE * 4 + 1, PIECE_SIZE * 4 + 1);
|
|
|
|
frame.Add (canvas);
|
|
|
|
|
|
|
|
board = new BoardPiece [16];
|
|
|
|
|
|
|
|
for (int i = 0; i < 15; i ++) {
|
|
|
|
int y = i /4;
|
|
|
|
int x = i % 4;
|
|
|
|
|
|
|
|
board [i] = new BoardPiece (canvas.Root ());
|
|
|
|
board [i].X = (x * PIECE_SIZE);
|
|
|
|
board [i].Y = (y * PIECE_SIZE);
|
|
|
|
|
|
|
|
CanvasRect rect = new CanvasRect (board [i]);
|
|
|
|
rect.X1 = 0.0;
|
|
|
|
rect.Y2 = 0.0;
|
|
|
|
rect.X2 = PIECE_SIZE;
|
|
|
|
rect.Y2 = PIECE_SIZE;
|
|
|
|
rect.FillColor = Get_Color (i);
|
|
|
|
rect.OutlineColor = "black";
|
|
|
|
rect.WidthPixels = 0;
|
|
|
|
|
|
|
|
CanvasText text = new CanvasText (board [i]);
|
|
|
|
text.Text = (i + 1).ToString ();
|
|
|
|
text.X = PIECE_SIZE / 2.0;
|
|
|
|
text.Y = PIECE_SIZE / 2.0;
|
|
|
|
text.Font = "Sans Bold 24";
|
|
|
|
text.Anchor = AnchorType.Center;
|
|
|
|
text.FillColor = "black";
|
|
|
|
|
|
|
|
board [i].Number = i;
|
|
|
|
board [i].Position = i;
|
|
|
|
board [i].Text = text;
|
|
|
|
board [i].CanvasEvent += new CanvasEventHandler (Piece_Event);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Scramble button here.
|
|
|
|
Button button = new Button ("Scamble");
|
|
|
|
vbox.PackStart (button, false, false, 0);
|
|
|
|
button.Clicked += new EventHandler (Scramble);
|
|
|
|
|
|
|
|
window.ShowAll ();
|
|
|
|
Application.Run ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static string Get_Color (int piece)
|
|
|
|
{
|
|
|
|
int y = piece / 4;
|
|
|
|
int x = piece % 4;
|
|
|
|
|
|
|
|
int r = ((4 - x) * 255) / 4;
|
|
|
|
int g = ((4 - y) * 255) / 4;
|
|
|
|
int b = 128;
|
|
|
|
|
|
|
|
return String.Format ("#{0:x2}{1:x2}{2:x2}", r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Piece_Event (object o, CanvasEventArgs args)
|
|
|
|
{
|
|
|
|
BoardPiece piece = (BoardPiece) o;
|
|
|
|
Canvas canvas = piece.Canvas;
|
|
|
|
double dx = 0.0, dy = 0.0;
|
|
|
|
|
|
|
|
switch (args.Event.Type) {
|
|
|
|
case EventType.EnterNotify:
|
|
|
|
piece.Text.FillColor = "white";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EventType.LeaveNotify:
|
|
|
|
piece.Text.FillColor = "black";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EventType.ButtonPress:
|
|
|
|
int y = piece.Position / 4;
|
|
|
|
int x = piece.Position % 4;
|
|
|
|
|
|
|
|
bool toMove = false;
|
|
|
|
|
|
|
|
if ((y > 0) && (board [(y - 1) * 4 + x] == null)) {
|
|
|
|
dx = 0.0;
|
|
|
|
dy = 1.0;
|
|
|
|
y --;
|
|
|
|
} else if ((y < 3) && (board [(y + 1) * 4 + x] == null)) {
|
|
|
|
dx = 0.0;
|
|
|
|
dy = 1.0;
|
|
|
|
y ++;
|
|
|
|
} else if ((x > 0) && (board [y * 4 + x - 1] == null)) {
|
|
|
|
dx = -1.0;
|
|
|
|
dy = 0.0;
|
|
|
|
x --;
|
|
|
|
} else if ((x < 3) && (board [y * 4 + x + 1] == null)) {
|
|
|
|
dx = 1.0;
|
|
|
|
dy = 1.0;
|
|
|
|
y ++;
|
|
|
|
} else
|
|
|
|
toMove = false;
|
|
|
|
|
|
|
|
if (toMove) {
|
|
|
|
int new_position = y * 4 + x;
|
|
|
|
board [piece.Position] = null;
|
|
|
|
board [new_position] = piece;
|
|
|
|
piece.Position = new_position;
|
|
|
|
piece.Move (dx * PIECE_SIZE, dy * PIECE_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Scramble (object o, EventArgs args)
|
|
|
|
{
|
|
|
|
Random rand = new Random ();
|
2002-08-06 18:01:49 +00:00
|
|
|
int blank;
|
|
|
|
int position;
|
2002-08-06 17:50:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
// find blank spot
|
|
|
|
for (position = 0; position < 16; position ++)
|
|
|
|
if (board [position] == null)
|
|
|
|
break;
|
|
|
|
|
|
|
|
for (int i = 0; i < SCRAMBLE_MOVES; i++) {
|
|
|
|
retry:
|
|
|
|
int dir = rand.Next ();
|
|
|
|
int x = 0, y = 0;
|
|
|
|
|
|
|
|
if ((dir == 0) && (position > 3)) // up
|
|
|
|
y = -1;
|
|
|
|
else if ((dir == 1) && (position < 12)) // down
|
|
|
|
y = 1;
|
|
|
|
else if ((dir == 2) && ((position % 4) != 0)) // left
|
|
|
|
x = -1;
|
|
|
|
else if ((dir == 3) && ((position % 4) != 3)) // right
|
|
|
|
x = 1;
|
|
|
|
else
|
|
|
|
goto retry;
|
|
|
|
|
|
|
|
int old_position = position + y * 4 + x;
|
|
|
|
board [position] = board [old_position];
|
|
|
|
board [position].Position = position;
|
|
|
|
board [old_position] = null;
|
|
|
|
board [position].Move (-x * PIECE_SIZE, -y * PIECE_SIZE);
|
|
|
|
canvas.UpdateNow ();
|
|
|
|
position = old_position;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Window_Delete (object o, DeleteEventArgs args)
|
|
|
|
{
|
|
|
|
Application.Quit ();
|
|
|
|
args.RetVal = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class BoardPiece : Gnome.CanvasGroup
|
|
|
|
{
|
|
|
|
public int Number;
|
|
|
|
public int Position;
|
|
|
|
public CanvasText Text;
|
|
|
|
|
|
|
|
public BoardPiece (CanvasGroup group)
|
|
|
|
: base (group, CanvasGroup.Type)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|