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 |
const int GridSize = 4; //Standard 15 puzzle is 4x4 |
||
const |
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; |
|||
static readonly Random R = new Random(); |
|||
{ |
|||
private List<Button> Puzzles = new List<Button>(); |
|||
private int Moves = 0; |
|||
private DateTime Start; |
|||
Application.Run(f); |
|||
} |
|||
private class Puzzle |
|||
public FifteenPuzzle() |
|||
{ |
{ |
||
private int mOrderedNumer; |
|||
private int OrderedNumer |
|||
{ |
|||
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; |
|||
public int Y; |
|||
Text = "Fifteen", |
|||
public Puzzle(int OrderedNumer) |
|||
ClientSize = new Size(width: size, height: size + buttonMargin * 2 + startButton.Height) |
|||
{ |
|||
mOrderedNumer = OrderedNumer; |
|||
CurrentNumber = OrderedNumer; |
|||
Button button = new Button { |
|||
X = OrderedNumer % GridSize; |
|||
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) |
|||
{ |
{ |
||
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++; |
|||
} |
|||
} |
} |
||
public bool NearestWith(Puzzle OtherPz) |
|||
{ |
|||
TimeSpan elapsed = DateTime.Now - start; |
|||
int dx = (X - OtherPz.X); |
|||
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 |
int ButtonSize = 50; |
||
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 |
private void NewGame(object Sender, EventArgs E) |
||
{ |
{ |
||
for (int i = 0; i < |
for (int i = 0; i < Puzzles.Count; i++) |
||
{ |
|||
Button Bt1 = Puzzles[R.Next(i, Puzzles.Count)]; |
|||
Button Bt2 = Puzzles[i]; |
|||
Swap(Bt1, Bt2); |
|||
} |
} |
||
for (int i = 0; i < |
for (int i = 0; i < Puzzles.Count; i++) |
||
{ |
|||
Puzzles[i].Enabled = true; |
|||
} |
} |
||
if (!Solvable()) Swap(0, 1); //Swap any 2 blocks |
|||
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 |
bool UWin = true; |
||
for (int i = 0; i < |
for (int i = 0; i < Puzzles.Count; i++) |
||
{ |
|||
for (int j = i + 1; j < blockCount - 1; j++) { |
|||
Puzzle Pz = (Puzzle)Puzzles[i].Tag; |
|||
if (!Pz.IsTruePlace) |
|||
{ |
|||
UWin = false; |
|||
break; |
|||
} |
} |
||
} |
} |
||
if (evenSized && positionOf[last] / gridSize % 2 == 0) parity = !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( |
private void Swap(Button Bt1, Button Bt2) |
||
{ |
{ |
||
if (Bt1 == Bt2) return; |
|||
buttons[a].Location = buttons[b].Location; |
|||
Puzzle Pz1 = (Puzzle)Bt1.Tag; |
|||
Puzzle Pz2 = (Puzzle)Bt2.Tag; |
|||
int g = Pz1.CurrentNumber; |
|||
Pz1.CurrentNumber = Pz2.CurrentNumber; |
|||
Pz2.CurrentNumber = g; |
|||
Bt1.Visible = true; |
|||
Bt1.Text = Pz1.ToString(); |
|||
if (Pz1.IsMaxPuzzle) Bt1.Visible = false; |
|||
Bt2.Visible = true; |
|||
Bt2.Text = Pz2.ToString(); |
|||
if (Pz2.IsMaxPuzzle) Bt2.Visible = false; |
|||
} |
} |
||
}</syntaxhighlight> |
}</syntaxhighlight> |