15 puzzle game: Difference between revisions

Content added Content deleted
(Most cleared realization in C#)
Line 3,979: Line 3,979:
{{works with|C sharp|6}}
{{works with|C sharp|6}}
<syntaxhighlight lang="csharp">using System;
<syntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing;
using System.Linq;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Forms;


public class FifteenPuzzle
public class FifteenPuzzle
{
{
const int gridSize = 4; //Standard 15 puzzle is 4x4
const int GridSize = 4; //Standard 15 puzzle is 4x4
const bool evenSized = gridSize % 2 == 0;
const int BlockCount = 16;
const int blockCount = gridSize * gridSize;
const int last = blockCount - 1;
const int buttonSize = 50;
const int buttonMargin = 3; //default = 3
const int formEdge = 9;
static readonly Random rnd = new Random();
static readonly Font buttonFont = new Font("Arial", 15.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
readonly Button[] buttons = new Button[blockCount];
readonly int[] grid = new int[blockCount];
readonly int[] positionOf = new int[blockCount];
int moves = 0;
DateTime start;


public static void Main(string[] args)
static readonly Random R = new Random();

{
FifteenPuzzle p = new FifteenPuzzle();
private List<Button> Puzzles = new List<Button>();
Form f = p.BuildForm();
private int Moves = 0;
private DateTime Start;
Application.Run(f);
}


private class Puzzle
public FifteenPuzzle()
{
{
for (int i = 0; i < blockCount; i++) {
private int mOrderedNumer;
grid[i] = i;
private int OrderedNumer
positionOf[i] = i;
{
get { return mOrderedNumer; }
}
}
}


public int CurrentNumber;
Form BuildForm()
{
Button startButton = new Button {
Font = new Font("Arial", 9.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0))),
Size = new Size(86, 23),
Location = new Point(formEdge,
(buttonSize + buttonMargin * 2) * gridSize + buttonMargin + formEdge),
Text = "New Game",
UseVisualStyleBackColor = true
};
startButton.Click += (sender, e) => Shuffle();


public int X;
int size = buttonSize * gridSize + buttonMargin * gridSize * 2 + formEdge * 2;
Form form = new Form {
public int Y;

Text = "Fifteen",
public Puzzle(int OrderedNumer)
ClientSize = new Size(width: size, height: size + buttonMargin * 2 + startButton.Height)
};
{
form.SuspendLayout();
mOrderedNumer = OrderedNumer;
for (int index = 0; index < blockCount; index++) {
CurrentNumber = OrderedNumer;

Button button = new Button {
Font = buttonFont,
X = OrderedNumer % GridSize;
Size = new Size(buttonSize, buttonSize),
Y = OrderedNumer / GridSize;
//Margin = new Padding(buttonMargin),
Text = (index + 1).ToString(),
UseVisualStyleBackColor = true
};
SetLocation(button, index);
form.Controls.Add(button);
buttons[index] = button;
int i = index;
button.Click += (sender, e) => ButtonClick(i);
}
}
form.Controls.Add(startButton);
form.ResumeLayout();
return form;
}


public bool IsMaxPuzzle
void ButtonClick(int i)
{
{
if (buttons[last].Visible) return;
get { return CurrentNumber >= (BlockCount - 1); }
int target = positionOf[i];
if (positionOf[i] / gridSize == positionOf[last] / gridSize) {
while (positionOf[last] < target) {
Swap(last, grid[positionOf[last] + 1]);
moves++;
}
while (positionOf[last] > target) {
Swap(last, grid[positionOf[last] - 1]);
moves++;
}
} else if (positionOf[i] % gridSize == positionOf[last] % gridSize) {
while (positionOf[last] < target) {
Swap(last, grid[positionOf[last] + gridSize]);
moves++;
}
while (positionOf[last] > target) {
Swap(last, grid[positionOf[last] - gridSize]);
moves++;
}
}
}
if (Solved()) {
public bool NearestWith(Puzzle OtherPz)
{
TimeSpan elapsed = DateTime.Now - start;
elapsed = TimeSpan.FromSeconds(Math.Round(elapsed.TotalSeconds, 0));
int dx = (X - OtherPz.X);
buttons[last].Visible = true;
int dy = (Y - OtherPz.Y);

MessageBox.Show($"Solved in {moves} moves. Time: {elapsed}");
if ((dx == 0) && (dy <= 1) && (dy >= -1)) return true;
if ((dy == 0) && (dx <= 1) && (dx >= -1)) return true;

return false;
}
public bool IsTruePlace
{
get { return (mOrderedNumer == CurrentNumber); }
}

public override string ToString()
{
return (CurrentNumber + 1).ToString();
}
}
}
}


public static void Main(string[] args)
bool Solved() => Enumerable.Range(0, blockCount - 1).All(i => positionOf[i] == i);
{
FifteenPuzzle Game = new FifteenPuzzle();
Application.Run(Game.CreateForm());
}


private Form CreateForm()
static void SetLocation(Button button, int index)
{
{
int row = index / gridSize, column = index % gridSize;
int ButtonSize = 50;
button.Location = new Point(
int ButtonMargin = 3;
int FormEdge = 9;
(buttonSize + buttonMargin * 2) * column + buttonMargin + formEdge,

(buttonSize + buttonMargin * 2) * row + buttonMargin + formEdge);
Font ButtonFont = new Font("Arial", 15.75F, FontStyle.Regular);

Button StartButton = new Button();
StartButton.Location = new Point(FormEdge, (GridSize * (ButtonMargin + ButtonSize)) + FormEdge);
StartButton.Size = new Size(86, 23);
StartButton.Font = new Font("Arial", 9.75F, FontStyle.Regular);
StartButton.Text = "New Game";
StartButton.UseVisualStyleBackColor = true;
StartButton.TabStop = false;

StartButton.Click += new EventHandler(NewGame);

int FormWidth = (GridSize * ButtonSize) + ((GridSize - 1) * ButtonMargin) + (FormEdge * 2);
int FormHeigth = FormWidth + StartButton.Height;

Form Form = new Form();
Form.Text = "Fifteen";
Form.ClientSize = new Size(FormWidth, FormHeigth);
Form.SuspendLayout();

for (int i = 0; i < BlockCount; i++)
{
Button Bt = new Button();
Puzzle Pz = new Puzzle(i);

int PosX = FormEdge + (Pz.X) * (ButtonSize + ButtonMargin);
int PosY = FormEdge + (Pz.Y) * (ButtonSize + ButtonMargin);
Bt.Location = new Point(PosX, PosY);

Bt.Size = new Size(ButtonSize, ButtonSize);
Bt.Font = ButtonFont;

Bt.Text = Pz.ToString();
Bt.Tag = Pz;
Bt.UseVisualStyleBackColor = true;
Bt.TabStop = false;

Bt.Enabled = false;
Bt.Click += new EventHandler(MovePuzzle);

Puzzles.Add(Bt);
Form.Controls.Add(Bt);
}

Form.Controls.Add(StartButton);
Form.ResumeLayout();

return Form;
}
}


void Shuffle()
private void NewGame(object Sender, EventArgs E)
{
{
for (int i = 0; i < blockCount; i++) {
for (int i = 0; i < Puzzles.Count; i++)
int r = rnd.Next(i, blockCount);
{
int g = grid[r];
Button Bt1 = Puzzles[R.Next(i, Puzzles.Count)];
grid[r] = grid[i];
Button Bt2 = Puzzles[i];
grid[i] = g;
Swap(Bt1, Bt2);
}
}
for (int i = 0; i < blockCount; i++) {
for (int i = 0; i < Puzzles.Count; i++)
positionOf[grid[i]] = i;
{
SetLocation(buttons[grid[i]], i);
Puzzles[i].Enabled = true;
}
}
if (!Solvable()) Swap(0, 1); //Swap any 2 blocks


buttons[last].Visible = false;
Moves = 0;
moves = 0;
Start = DateTime.Now;
start = DateTime.Now;
}
}
private void MovePuzzle(object Sender, EventArgs E)
{
Button Bt1 = (Button)Sender;
Puzzle Pz1 = (Puzzle)Bt1.Tag;
// Dirty! Try way get a empty spase check Puzzle inside Button.
Button Bt2 = Puzzles.SingleOrDefault(Bt => !Bt.Visible);
Puzzle Pz2 = (Puzzle)Bt2.Tag;


if (Pz1.NearestWith(Pz2))
bool Solvable()
{
Swap(Bt1, Bt2);
Moves++;
}

CheckWin();
}

private void CheckWin()
{
{
bool parity = true;
bool UWin = true;
for (int i = 0; i < blockCount - 2; i++) {
for (int i = 0; i < Puzzles.Count; i++)
{
for (int j = i + 1; j < blockCount - 1; j++) {
if (positionOf[j] < positionOf[i]) parity = !parity;
Puzzle Pz = (Puzzle)Puzzles[i].Tag;

if (!Pz.IsTruePlace)
{
UWin = false;
break;
}
}
}
}

if (evenSized && positionOf[last] / gridSize % 2 == 0) parity = !parity;
return parity;
if (UWin)
{
for (int i = 0; i < Puzzles.Count; i++)
{
Puzzles[i].Enabled = false;
}

TimeSpan Elapsed = DateTime.Now - Start;
Elapsed = TimeSpan.FromSeconds(Math.Round(Elapsed.TotalSeconds, 0));
MessageBox.Show(String.Format("Solved in {0} moves. Time: {1}", Moves, Elapsed));
}
}
}


void Swap(int a, int b)
private void Swap(Button Bt1, Button Bt2)
{
{
Point location = buttons[a].Location;
if (Bt1 == Bt2) return;

buttons[a].Location = buttons[b].Location;
buttons[b].Location = location;
Puzzle Pz1 = (Puzzle)Bt1.Tag;
Puzzle Pz2 = (Puzzle)Bt2.Tag;

int g = Pz1.CurrentNumber;
Pz1.CurrentNumber = Pz2.CurrentNumber;
Pz2.CurrentNumber = g;


int p = positionOf[a];
Bt1.Visible = true;
positionOf[a] = positionOf[b];
Bt1.Text = Pz1.ToString();
positionOf[b] = p;
if (Pz1.IsMaxPuzzle) Bt1.Visible = false;


grid[positionOf[a]] = a;
Bt2.Visible = true;
grid[positionOf[b]] = b;
Bt2.Text = Pz2.ToString();
if (Pz2.IsMaxPuzzle) Bt2.Visible = false;
}
}
}</syntaxhighlight>
}</syntaxhighlight>