Skip to content
Snippets Groups Projects
Commit 9ccefc85 authored by PowerfulShuffle's avatar PowerfulShuffle
Browse files

Merge branch 'MinesweeperController'

parents 177e130e efd6f4eb
No related branches found
No related tags found
No related merge requests found
......@@ -126,7 +126,7 @@ namespace PuzzlePlayer_Namespace
}
// changes tile P to value X
public abstract bool TileInput(Point? p, Keys k);
public virtual bool TileInput(Point? p, Keys k) { return false; }
// performs a left/right (X) click on tile P, changing its value
public virtual bool TileClick(Point p, int x) { return false; }
......
......@@ -40,14 +40,14 @@ namespace PuzzlePlayer_Namespace
Point playerPos;
List<Point> shortestPath;
public Maze(int sizeX = 6, int sizeY = 4)
public Maze(int sizeX = 32, int sizeY = 24)
{
drawFactor = 1;
// init all 2D array's
Reset(sizeX, sizeY);
lastGeneratedBoard = GetClearBoard(sizeX, sizeY);
description = "Maze is played on a grid containing walls. You need to navigate through the maze until you reach the end. Use the arrow keys or WASD to move the blue square to the end goal";
description = "Maze is played on a grid containing walls. You have to navigate through the maze until you reach the end. Use the arrow keys or WASD to move the blue square to the end!";
}
private void Reset(int sizeX, int sizeY)
......
......@@ -14,9 +14,9 @@ namespace PuzzlePlayer_Namespace
{
private static Random random = new Random();
private bool[,] mineState;
private bool[,] mineState;
private bool isFirstClick;
public Minesweeper(int width = 6, int height = 6)
public Minesweeper(int width = 16, int height = 12)
{
if (width <= 1 || height <= 1) throw new ArgumentOutOfRangeException(); // breedte 1 mag niet door optimisatie bij Reveal()
boardState = GetClearBoard(width, height);
......@@ -24,7 +24,7 @@ namespace PuzzlePlayer_Namespace
mineState = new bool[width, height];
isFirstClick = false;
description = "zoek het uit";
description = "In Minesweeper, the number of a tile indicates the amount of adjacent mines.\r\n● You can place flags on suspected mines with right-click\r\n● Unlike the classic version of minesweeper, there is not a set number of mines and you will survive after clicking on a mine, at the cost of gaining less points \r\n● The first click is always safe!";
drawFactor = 1;
}
......@@ -71,7 +71,7 @@ namespace PuzzlePlayer_Namespace
case -2:
gr.DrawString("⚑",
new Font("Verdana", stringsize),
Brushes.Black,
Brushes.DarkRed,
(int)(r.X + ((double)i + 0.5) * tilesize.Width),
(int)(r.Y + ((double)j + 0.5) * tilesize.Height),
stringFormat);
......@@ -81,13 +81,26 @@ namespace PuzzlePlayer_Namespace
gr.DrawString("✸",
new Font("Verdana", stringsize),
Brushes.Black,
(int)(r.X + ((double)i + 0.5) * tilesize.Width),
(int)(r.Y + ((double)j + 0.5) * tilesize.Height),
(int)(r.X + ((double)i + 0.52) * tilesize.Width),
(int)(r.Y + ((double)j + 0.54) * tilesize.Height),
stringFormat);
break;
}
}
/*gr.DrawLine(Pens.Red,
(int)(r.X + ((double)i + 0.5) * tilesize.Width),
(int)(r.Y + ((double)j + 0.0) * tilesize.Height),
(int)(r.X + ((double)i + 0.5) * tilesize.Width),
(int)(r.Y + ((double)j + 1.0) * tilesize.Height)
);
gr.DrawLine(Pens.Red,
(int)(r.X + ((double)i + 0.0) * tilesize.Width),
(int)(r.Y + ((double)j + 0.5) * tilesize.Height),
(int)(r.X + ((double)i + 1.0) * tilesize.Width),
(int)(r.Y + ((double)j + 0.5) * tilesize.Height)
);*/
gr.DrawRectangle(Pens.DarkGray,
r.X + i * tilesize.Width,
r.Y + j * tilesize.Height,
......@@ -102,7 +115,7 @@ namespace PuzzlePlayer_Namespace
boardState = GetClearBoard(mineState.GetLength(0), mineState.GetLength(1));
for (int i = 0; i < mineState.GetLength(0); i++) for (int j = 0; j < mineState.GetLength(1); j++)
{
mineState[i, j] = random.Next(6) == 0; // het getal P in de Next methode geeft elke tile een 1/P kans om een bom te zijn
mineState[i, j] = random.Next(6) == 0; // the number P, the Next method parameter indicates that there is a 1/P chance for a tile to have a mine
}
isFirstClick = true;
}
......@@ -111,10 +124,6 @@ namespace PuzzlePlayer_Namespace
{
return SOLUTIONS.UNIQUE;
}
public override bool TileInput(Point? p, Keys k)
{
return false;
}
public override bool TileClick(Point p, int x)
{
if (x == 0)
......@@ -128,7 +137,7 @@ namespace PuzzlePlayer_Namespace
}
return false;
bool Reveal(Point p, bool ForceOpen)
bool Reveal(Point p, bool ForceOpen) //opens the cell at the given Point and returns whether or not the game is finished after reveal. ForceOpen dictates whether or not the cell should be opened if a flag has been placed on it.
{
if (ForceOpen && boardState[p.X, p.Y] == -2) { boardState[p.X, p.Y] = emptySpace; Reveal(p, false); }
if (boardState[p.X, p.Y] != emptySpace) return false;
......@@ -144,21 +153,35 @@ namespace PuzzlePlayer_Namespace
return false;
} else { if (isFirstClick) isFirstClick = false; }
int result = 0;
List<Size> directions = new List<Size> { new(-1, -1), new(0, -1), new(1, -1), new(-1, 0),
new(1, 0), new(-1, 1), new(0, 1), new(1, 1)};
if (p.X == 0) { directions.Remove(new(-1, -1)); directions.Remove(new(-1, 0)); directions.Remove(new(-1, 1)); }
else { if (p.X == boardState.GetLength(0) - 1) { directions.Remove(new(1, -1)); directions.Remove(new(1, 0)); directions.Remove(new(1, 1)); } }
if (p.Y == 0) { directions.Remove(new(-1, -1)); directions.Remove(new(0, -1)); directions.Remove(new(1, -1)); }
else { if (p.Y == boardState.GetLength(1) - 1) { directions.Remove(new(-1, 1)); directions.Remove(new(0, 1)); directions.Remove(new(1, 1)); } }
List<Size> directions = GetAdjacents(p);
foreach (Size s in directions) if (mineState[(p + s).X, (p + s).Y]) result++;
boardState[p.X, p.Y] = result;
if (result == 0) foreach (Size s in directions) Reveal(p + s, true);
return IsBoardSolved();
}
bool Chord(Point p)
bool Chord(Point p) //attempts to execute a "chord" on cell P, assumes P is legal to "chord" on, but behaves normally if not legal anyway
{
List<Size> directions = GetAdjacents(p);
int adjacents = directions.Count;
for (int i = 0; i < directions.Count; i++)
{
Point cell = p + directions[i];
if (boardState[cell.X, cell.Y] == -2 || boardState[cell.X, cell.Y] == -3) { directions.RemoveAt(i); i--; }
}
if (adjacents - directions.Count == boardState[p.X, p.Y]) { foreach (Size s in directions) Reveal(p + s, true); return IsBoardSolved(); }
else return false;
}
List<Size> GetAdjacents(Point p) //returns direction vectors that point to all valid neighbors of cell P
{
return false;
List<Size> res = new List<Size> { new(-1, -1), new(0, -1), new(1, -1), new(-1, 0),
new(1, 0), new(-1, 1), new(0, 1), new(1, 1)};
if (p.X == 0) { res.Remove(new(-1, -1)); res.Remove(new(-1, 0)); res.Remove(new(-1, 1)); }
else { if (p.X == boardState.GetLength(0) - 1) { res.Remove(new(1, -1)); res.Remove(new(1, 0)); res.Remove(new(1, 1)); } }
if (p.Y == 0) { res.Remove(new(-1, -1)); res.Remove(new(0, -1)); res.Remove(new(1, -1)); }
else { if (p.Y == boardState.GetLength(1) - 1) { res.Remove(new(-1, 1)); res.Remove(new(0, 1)); res.Remove(new(1, 1)); } }
return res;
}
}
......
......@@ -12,7 +12,7 @@ namespace PuzzlePlayer_Namespace.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.11.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.12.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
......
......@@ -55,13 +55,7 @@ namespace PuzzlePlayer_Namespace
titlebox = new Label();
informationbox = new Label();
boardspace = new Rectangle(220, 55, 400, 400);
this.Paint += (object o, PaintEventArgs pea) =>
{
board.Draw(bufferedGraphics.Graphics, boardspace);
//bufferedGraphics.Graphics.FillRectangle(Brushes.LightCoral, boardspace.X, boardspace.Y, this.Width - 350, this.Height - 125);
//bufferedGraphics.Graphics.FillRectangle(Brushes.DarkRed, boardspace);
bufferedGraphics.Render();
};
this.Paint += (object o, PaintEventArgs pea) => Draw();
this.Resize += (object o, EventArgs ea) => UpdateUI();
this.Move += (object o, EventArgs ea) => this.Focus();
this.PreviewKeyDown += (object o, PreviewKeyDownEventArgs e) => e.IsInputKey = true;
......@@ -80,6 +74,13 @@ namespace PuzzlePlayer_Namespace
CreateUI();
}
private void Draw()
{
board.Draw(bufferedGraphics.Graphics, boardspace);
//bufferedGraphics.Graphics.FillRectangle(Brushes.LightCoral, boardspace.X, boardspace.Y, this.Width - 350, this.Height - 125);
//bufferedGraphics.Graphics.FillRectangle(Brushes.DarkRed, boardspace);
bufferedGraphics.Render();
}
private void CreateUI() //sets up ui elements
{
MenuStrip menuStrip = new MenuStrip
......@@ -140,28 +141,29 @@ namespace PuzzlePlayer_Namespace
generatebutton.MouseClick += (object sender, MouseEventArgs mea) =>
{
Board.Generate();
this.Invalidate();
Draw();
};
CreateButton(hintbutton);
hintbutton.Text = "Hint";
hintbutton.MouseClick += (object sender, MouseEventArgs mea) =>
{
MessageBox.Show("Hint: geef op");
this.Invalidate();
Draw();
};
CreateButton(solvebutton);
solvebutton.Text = "Solve";
solvebutton.MouseClick += (object sender, MouseEventArgs mea) =>
{
Board.Solve(false);
this.Invalidate();
if (Board.IsBoardSolved()) Win();
Draw();
};
CreateButton(restartbutton);
restartbutton.Text = "Restart";
restartbutton.MouseClick += (object sender, MouseEventArgs mea) =>
{
Board.Restart();
this.Invalidate();
Draw();
};
//CreateButton(UPDATEBUTTON);
......@@ -208,7 +210,7 @@ namespace PuzzlePlayer_Namespace
public static Size FitBoard(Size gamesize, Size maxboardsize, int drawfactor) //returns the largest rectangle smaller than MaxBoardSize that fits the given GameSize well
{
int TileLength = Math.Min(maxboardsize.Width / gamesize.Width, maxboardsize.Height / gamesize.Height) / drawfactor * drawfactor;
return new Size(Math.Max(6,gamesize.Width*TileLength), Math.Max(6,gamesize.Height*TileLength)); //dw dw
return new Size(Math.Max(2*gamesize.Width,gamesize.Width*TileLength), Math.Max(2*gamesize.Height,gamesize.Height*TileLength)); //dw dw
//after each of the divisions in this method, the value should be rounded down,
//as the end value cannot exceed the size given by maxboardsize.
//however, C# rounds divisions of Int values down by default, so this does not have to be explicitly done.
......@@ -230,11 +232,11 @@ namespace PuzzlePlayer_Namespace
return;
case Keys.H:
MessageBox.Show("Hint: geef op");
this.Invalidate();
Draw();
return;
case Keys.Space:
Board.Solve(false);
this.Invalidate();
Draw();
return;
case Keys.Up:
case Keys.Left:
......@@ -245,7 +247,7 @@ namespace PuzzlePlayer_Namespace
case Keys.S:
case Keys.D:
if (Board.TileInput(null, k)) Win();
this.Invalidate();
Draw();
return;
}
Point tile = GetTile(new Size(Board.boardState.GetLength(0), Board.boardState.GetLength(1)), boardspace, Control.MousePosition);
......@@ -255,28 +257,28 @@ namespace PuzzlePlayer_Namespace
{
case Keys.Back:
Board.boardState[tile.X, tile.Y] = Board.emptySpace;
this.Invalidate();
Draw();
return;
case Keys.LButton:
case Keys.RButton:
if (Board.TileClick(tile, (int)k - 1)) Win();
this.Invalidate();
Draw();
return;
case Keys.OemOpenBrackets:
case Keys.OemCloseBrackets:
if (Board.TileClick(tile, ((int)k - 219)/2)) Win();
this.Invalidate();
Draw();
return;
default:
if (Board.TileInput(tile, k)) Win();
this.Invalidate();
Draw();
return;
}
}
public void Win()
{
this.Invalidate();
Draw();
MessageBox.Show("oi oi oi");
}
}
......
......@@ -11,7 +11,6 @@ namespace PuzzlePlayer_Namespace
{
internal static void Main(string[] args)
{
//Application.Run(new ShopMenu());
Application.Run(new MainForm());
}
}
......
......@@ -12,8 +12,8 @@ namespace PuzzlePlayer_Namespace
{
internal class Sudoku : Board
{
private static int boardLength;
private static int rootBoardLength;
private readonly int boardLength;
private readonly int rootBoardLength;
private static Random random = new Random();
private double removeDensity = 0.5;
public Sudoku(int boardSize = 4)
......@@ -37,44 +37,32 @@ namespace PuzzlePlayer_Namespace
};
Size tilesize = new Size(r.Width / boardState.GetLength(0), r.Height / boardState.GetLength(1));
Pen border = new Pen(Color.Black, 2);
Brush textcolor;
gr.FillRectangle(Brushes.Beige, r.X, r.Y, tilesize.Width * boardState.GetLength(0), tilesize.Height * boardState.GetLength(1));
for (int i = 0; i < boardState.GetLength(0); i++)
{
for (int j = 0; j < boardState.GetLength(1); j++)
{
gr.DrawRectangle(Pens.LightGray,
r.X + i * tilesize.Width,
r.Y + j * tilesize.Height,
tilesize.Width,
tilesize.Height);
if (boardState[i,j] != -1)
if (boardState[i,j] != emptySpace)
{
if (lastGeneratedBoard[i, j] != Board.emptySpace)
{
gr.DrawString(
(boardState[i, j]).ToString(),
new Font("Arial", tilesize.Width / 2),
Brushes.Black,
(int)(r.X + (i + 0.27) * tilesize.Width + tilesize.Width / 4),
(int)(r.Y + (j + 0.33) * tilesize.Height + tilesize.Height / 4),
format);
}
else
{
gr.DrawString(
(boardState[i, j]).ToString(),
new Font("Arial", tilesize.Width / 2),
Brushes.DarkBlue,
(int)(r.X + (i + 0.27) * tilesize.Width + tilesize.Width / 4),
(int)(r.Y + (j + 0.33) * tilesize.Height + tilesize.Height / 4),
format);
}
if (lastGeneratedBoard[i, j] == Board.emptySpace) textcolor = Brushes.DarkBlue; else textcolor = Brushes.Black;
gr.DrawString(
(boardState[i, j]).ToString(),
new Font("Arial", tilesize.Width / 2),
textcolor,
(int)(r.X + (i + 0.52) * tilesize.Width),
(int)(r.Y + (j + 0.54) * tilesize.Height),
format);
}
}
}
for (int i = 1; i < Math.Sqrt(boardState.GetLength(0)); i++)
for (int i = 1; i < Math.Sqrt(boardState.GetLength(0)); i++) //draws box lines
{
gr.DrawLine(Pens.Black,
r.X + i * (int)Math.Sqrt((double)boardState.GetLength(0)) * tilesize.Width,
......@@ -184,7 +172,7 @@ namespace PuzzlePlayer_Namespace
{
for (int i = 0; i < boardLength; i++)
{
if(num == boardState[i, j])
if( num == boardState[i, j])
{
return true;
}
......@@ -265,7 +253,7 @@ namespace PuzzlePlayer_Namespace
if (p == null) return false;
int num = (int)k - 48;
if (num >= 1 && num <= boardLength) boardState[((Point)p).X, ((Point)p).Y] = num;
return false;
return IsBoardSolved();
}
public override bool TileClick(Point p, int x)
{
......@@ -317,6 +305,33 @@ namespace PuzzlePlayer_Namespace
}
}
public override bool IsBoardSolved()
{
foreach (int n in boardState) if (n == emptySpace) return false; //first checks if all squares have been filled to prevent algoritm from requiring extra checks and running after each input
for (int i = 0; i < boardLength; i++) // simultaneous row/column check
{
HashSet<int> SetColumn = [];
HashSet<int> SetRow = [];
for (int j = 0; j < boardLength; j++)
{
if (!SetColumn.Add(boardState[i, j])) return false;
if (!SetRow.Add(boardState[j, i])) return false;
}
}
for (int i = 0; i < rootBoardLength; i++) for (int j = 0; j < rootBoardLength; j++) //box check
{
HashSet<int> Set = [];
for (int a = 0; a < rootBoardLength; a++) for (int b = 0; b < rootBoardLength; b++)
{
if (!Set.Add(boardState[i * rootBoardLength + a, j * rootBoardLength + b])) return false;
}
}
return true;
}
private void RemoveSpaces(int k)
{
for(int i = 0; i < k; i++)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment