15 puzzle game: Difference between revisions

Content added Content deleted
(Add IsSolvable method in C#)
(Last fix C#. Ideal now :D)
Line 3,993: Line 3,993:
private int Moves = 0;
private int Moves = 0;
private DateTime Start;
private DateTime Start;

private Control HighlightNormalSolve;
private Control HighlightAltSolve;


public class Puzzle
public class Puzzle
{
{
private int mOrderedNumer;
private int mOrderedNumer;
private int mAltOrderedNumer;


public int CurrentNumber;
public int CurrentNumber;
Line 4,019: Line 4,015:
{
{
mOrderedNumer = OrderedNumer;
mOrderedNumer = OrderedNumer;

mAltOrderedNumer = OrderedNumer - 1;
if (mOrderedNumer == 0) mAltOrderedNumer = BlockCount - 1;


CurrentNumber = OrderedNumer;
CurrentNumber = OrderedNumer;
Line 4,034: Line 4,027:
}
}


public bool IsMaxPuzzle
public bool IsEmptyPuzzle
{
{
get { return CurrentNumber >= (BlockCount - 1); }
get { return CurrentNumber >= (BlockCount - 1); }
}
public bool IsTruePlace
{
get { return (CurrentNumber == mOrderedNumer); }
}
}
public bool NearestWith(Puzzle OtherPz)
public bool NearestWith(Puzzle OtherPz)
Line 4,047: Line 4,044:


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


Line 4,093: Line 4,082:
Form.Text = "Fifteen";
Form.Text = "Fifteen";
Form.ClientSize = new Size(FormWidth, FormHeigth);
Form.ClientSize = new Size(FormWidth, FormHeigth);
Form.FormBorderStyle = FormBorderStyle.FixedSingle;
Form.MaximizeBox = false;
Form.SuspendLayout();
Form.SuspendLayout();

// panels for highlight true solution
int HSize = 4;

HighlightNormalSolve = new Panel();
HighlightNormalSolve.Size = new Size(HSize, HSize);
HighlightNormalSolve.Location = new Point(FormWidth - FormEdge, FormWidth - FormEdge);
HighlightNormalSolve.Visible = false;
HighlightNormalSolve.BackColor = Color.Navy;
Form.Controls.Add(HighlightNormalSolve);

HighlightAltSolve = new Panel();
HighlightAltSolve.Size = new Size(HSize, HSize);
HighlightAltSolve.Location = new Point(FormEdge - HSize, FormEdge - HSize);
HighlightAltSolve.Visible = false;
HighlightAltSolve.BackColor = Color.Navy;
Form.Controls.Add(HighlightAltSolve);


for (int i = 0; i < BlockCount; i++)
for (int i = 0; i < BlockCount; i++)
Line 4,130: Line 4,104:


Bt.Enabled = false;
Bt.Enabled = false;
if (Pz.IsMaxPuzzle) Bt.Visible = false;
if (Pz.IsEmptyPuzzle) Bt.Visible = false;


Bt.Click += new EventHandler(MovePuzzle);
Bt.Click += new EventHandler(MovePuzzle);
Line 4,146: Line 4,120:
private void NewGame(object Sender, EventArgs E)
private void NewGame(object Sender, EventArgs E)
{
{
do
for (int i = 0; i < Puzzles.Count; i++)
{
{
Button Bt1 = Puzzles[R.Next(i, Puzzles.Count)];
for (int i = 0; i < Puzzles.Count; i++)
Button Bt2 = Puzzles[i];
{
Swap(Bt1, Bt2);
Button Bt1 = Puzzles[R.Next(i, Puzzles.Count)];
Button Bt2 = Puzzles[i];
Swap(Bt1, Bt2);
}
}
}
while (!IsSolvable());

for (int i = 0; i < Puzzles.Count; i++)
for (int i = 0; i < Puzzles.Count; i++)
{
{
Puzzles[i].Enabled = true;
Puzzles[i].Enabled = true;
}

bool IsNormalSolve = IsSolvable(Puzzles.ConvertAll<Puzzle>(Bt => (Puzzle)Bt.Tag));
if (IsNormalSolve)
{
HighlightNormalSolve.Visible = true;
HighlightAltSolve.Visible = false;
}
else // alt solve
{
HighlightNormalSolve.Visible = false;
HighlightAltSolve.Visible = true;
}
}


Line 4,178: Line 4,145:
Puzzle Pz1 = (Puzzle)Bt1.Tag;
Puzzle Pz1 = (Puzzle)Bt1.Tag;


Button Bt2 = Puzzles.Find(Bt => ((Puzzle)Bt.Tag).IsMaxPuzzle);
Button Bt2 = Puzzles.Find(Bt => ((Puzzle)Bt.Tag).IsEmptyPuzzle);
Puzzle Pz2 = (Puzzle)Bt2.Tag;
Puzzle Pz2 = (Puzzle)Bt2.Tag;


Line 4,193: Line 4,160:
{
{
Button WrongPuzzle = Puzzles.Find(Bt => !((Puzzle)Bt.Tag).IsTruePlace);
Button WrongPuzzle = Puzzles.Find(Bt => !((Puzzle)Bt.Tag).IsTruePlace);
bool UWin = (WrongPuzzle == null);
Button AltWrongPuzzle = Puzzles.Find(Bt => !((Puzzle)Bt.Tag).IsAltTruePlace);

bool UWin = ((WrongPuzzle == null) || (AltWrongPuzzle == null));


if (UWin)
if (UWin)
Line 4,203: Line 4,168:
Puzzles[i].Enabled = false;
Puzzles[i].Enabled = false;
}
}

HighlightNormalSolve.Visible = false;
HighlightAltSolve.Visible = false;


TimeSpan Elapsed = DateTime.Now - Start;
TimeSpan Elapsed = DateTime.Now - Start;
Line 4,226: Line 4,188:
Bt1.Visible = true;
Bt1.Visible = true;
Bt1.Text = Pz1.ToString();
Bt1.Text = Pz1.ToString();
if (Pz1.IsMaxPuzzle) Bt1.Visible = false;
if (Pz1.IsEmptyPuzzle) Bt1.Visible = false;


Bt2.Visible = true;
Bt2.Visible = true;
Bt2.Text = Pz2.ToString();
Bt2.Text = Pz2.ToString();
if (Pz2.IsMaxPuzzle) Bt2.Visible = false;
if (Pz2.IsEmptyPuzzle) Bt2.Visible = false;
}
}


private bool IsSolvable(List<Puzzle> Puzzles)
private bool IsSolvable()
{
{
// WARNING: size of puzzle board MUST be even(like 4)!
// WARNING: size of puzzle board MUST be even(like 4)!
// For explain see: https://www.geeksforgeeks.org/check-instance-15-puzzle-solvable/
// For explain see: https://www.geeksforgeeks.org/check-instance-15-puzzle-solvable/


// Count inversions in given puzzle
int InvCount = 0;
int InvCount = 0;
for (int i = 0; i < Puzzles.Count - 1; i++)
for (int i = 0; i < Puzzles.Count - 1; i++)
Line 4,244: Line 4,205:
for (int j = i + 1; j < Puzzles.Count; j++)
for (int j = i + 1; j < Puzzles.Count; j++)
{
{
if (Puzzles[i].IsMaxPuzzle) continue;
Puzzle Pz1 = (Puzzle)Puzzles[i].Tag;
if (Puzzles[j].IsMaxPuzzle) continue;
if (Pz1.IsEmptyPuzzle) continue;

Puzzle Pz2 = (Puzzle)Puzzles[j].Tag;
if (Pz2.IsEmptyPuzzle) continue;


if (Puzzles[i].CurrentNumber > Puzzles[j].CurrentNumber) InvCount++;
if (Pz1.CurrentNumber > Pz2.CurrentNumber) InvCount++;
}
}
}
}


Puzzle EmptyPuzzle = Puzzles.Find(Pz => Pz.IsMaxPuzzle);
Button EmptyBt = Puzzles.Find(Bt => ((Puzzle)Bt.Tag).IsEmptyPuzzle);
Puzzle EmptyPz = (Puzzle)EmptyBt.Tag;


bool Result = false;
bool Result = false;
if ((EmptyPuzzle.InvY + 1) % 2 == 0) // is even
if ((EmptyPz.InvY + 1) % 2 == 0) // is even
{
{
// is odd
// is odd