Skip to content
Snippets Groups Projects
Commit 4ad417af authored by bionic85's avatar bionic85
Browse files

het doet ten minste iets

parent 796d00dd
No related branches found
No related tags found
No related merge requests found
......@@ -215,21 +215,8 @@ namespace PuzzlePlayer_Namespace
return null;
}
///*
// shuffle the choices in the list around to get different results every time
// First answer from: https://stackoverflow.com/questions/273313/randomize-a-listt
Random random = new Random();
int n = choices.Count;
while (n > 1)
{
n--;
int rand = random.Next(n + 1);
Move copy = choices[rand];
choices[rand] = choices[n];
choices[n] = copy;
}
//*/
choices.Shuffle(); //shuffle the choices around for random results everytime
//(Shuffle methode from the extentions class in the Board.cs file
// do the algorithm for every move
foreach (Move m in choices)
......
......@@ -72,10 +72,11 @@ namespace PuzzlePlayer_Namespace
return false;
}
}
public abstract void Draw(Graphics gr, Rectangle r);
// a methode for solving the whole board. It uses the private SolveStep methode untill the whole board is solved
// it has one parameter. setting this to true will only give a return value without changing the current boardState
public SOLUTIONS Solve(bool CheckOnly)
public virtual SOLUTIONS Solve(bool CheckOnly)
{
// two variables for storing the result and the next solveStep
int[,] result = (int[,])boardState.Clone();
......@@ -136,4 +137,26 @@ namespace PuzzlePlayer_Namespace
// performs a left/right (X) click on tile P, changing its value
public virtual void TileClick(Point p, int x) { }
}
// static class for extentions
public static class Extensions
{
private static readonly Random rng = new Random();
// shuffle the elements in a list around to get different results every time from the generator algoritms
// First answer from: https://stackoverflow.com/questions/273313/randomize-a-listt
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
}
......@@ -4,18 +4,21 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Xml.XPath;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace PuzzlePlayer_Namespace
{
/*
* all the info about the maze is stored in the mazeState int[,]
* this way the boardState can be used to keep track off the spaces that the player has visited
* all the info about where the walls in the maze are is stored in the mazeState int[,]
* the info of wich cells are already visited by the generator methode are stored in the visitedCells
* the boardState is used to keep track of the spaces that the player has visited while solving the maze
*
* if the player has not yet visited a space then it is equal to the emptyspace constant
* if the player did visit the space then it is equal to 1
* if the player/generator has not yet visited a space then it is equal to the emptyspace constant
* if the player/generator did visit the space then it is equal to 1
*
* The maze board consists of cells with a number between 1 and 15
* the number represents where the walls are
......@@ -36,13 +39,17 @@ namespace PuzzlePlayer_Namespace
class Maze : Board
{
int[,] mazeState;
int[,] visitedCells;
public Maze(int size = 3)
public Maze(int size = 6)
{
// init all 2D array's
boardState = GetClearBoard(size);
mazeState = GetClearBoard(size);
visitedCells = GetClearBoard(size);
// example thingy
/*
// example thingy (DELETE LATER)
mazeState[0, 0] = 5;
mazeState[1, 0] = 3;
mazeState[2, 0] = 11;
......@@ -54,20 +61,21 @@ namespace PuzzlePlayer_Namespace
mazeState[2, 2] = 5;
boardState[0, 2] = 1;
*/
}
// two funcions to go from number to walls and back
private int getNumberFromWalls(bool top, bool right, bool bottom, bool left)
private int getNumberFromWalls((bool top, bool right, bool bottom, bool left) cell)
{
int result = 0;
if (top)
if (cell.top)
result++;
if (right)
if (cell.right)
result += 2;
if (bottom)
if (cell.bottom)
result += 4;
if (left)
if (cell.left)
result += 8;
if (result == 0)
......@@ -79,7 +87,8 @@ namespace PuzzlePlayer_Namespace
private (bool,bool,bool,bool) getWallsFromNumber(int number)
{
if(number == emptySpace)
return (false,false,false,false); //if the place is empty then there are no walls
return (true,true,true,true); //if the place is empty then it is completly walled in,
//so that the walls can be removed when generating the maze
// bitwise and opperations to check each bit
bool top = (number & 1) != 0;
......@@ -92,6 +101,9 @@ namespace PuzzlePlayer_Namespace
public override void Draw(Graphics gr, Rectangle r)
{
// clear screen
gr.FillRectangle(Brushes.DarkGreen, r);
Size tilesize = new Size(r.Width / boardState.GetLength(0), r.Height / boardState.GetLength(1));
Pen wall = new Pen(Color.Black, tilesize.Width / 5);
......@@ -127,15 +139,126 @@ namespace PuzzlePlayer_Namespace
gr.DrawString("END", SettingForm.mainFont, Brushes.Red, r.Right - tilesize.Width / 4, r.Bottom - tilesize.Height / 2);
}
protected override List<Move> GetSolveList(int[,] boardToSolve)
// this methode generates a Maze starting with an empty board
// it uses the randomized depth first search algoritm as described on this wiki page:
// https://en.wikipedia.org/wiki/Maze_generation_algorithm#Randomized_depth-first_search
public override void Generate()
{
throw new NotImplementedException();
// clear visitedCells
visitedCells = GetClearBoard(mazeState.GetLength(0));
Random rnd = new Random();
int x = rnd.Next(mazeState.GetLength(0));
int y = rnd.Next(mazeState.GetLength(0));
RND_Recursive_DepthFirstSearchMaze(x,y);
}
// https://en.wikipedia.org/wiki/Maze_generation_algorithm#Randomized_depth-first_search
public override void Generate()
private bool RND_Recursive_DepthFirstSearchMaze(int x, int y)
{
throw new NotImplementedException();
visitedCells[x, y] = 1; // mark current cell as visited (this is needed for the first cell)
// get a list of all the unvisited neigbour cells
List<(int, int)> validNeigbours = getNeigbours(x, y, emptySpace);
if (validNeigbours.Count == 0)
return false; // backtrack
validNeigbours.Shuffle(); //shuffle the neigbours around for random results everytime
//(Shuffle methode from the extentions class in the Board.cs file
foreach ((int nx,int ny) neighbour in validNeigbours)
{
visitedCells[neighbour.nx,neighbour.ny] = 1; // mark as visited and update all the walls that are effected
UpdateWalls(x,y, neighbour.nx,neighbour.ny);
if(RND_Recursive_DepthFirstSearchMaze(neighbour.nx,neighbour.ny)) //recursion
return true; // if true then the maze is finished and this cell should return true too
}
return false; // backtrack if all the neighbours are already visited
}
// update the walls between two cells
private void UpdateWalls(int x, int y, int x2, int y2)
{
// get the walls from the two cells
(bool top, bool right, bool bottom, bool left) first = getWallsFromNumber(mazeState[x, y]);
(bool top, bool right, bool bottom, bool left) second = getWallsFromNumber(mazeState[x2, y2]);
int dx = x - x2;
int dy = y - y2;
if(dx == -1)
{
first.right = false;
second.left = false;
}
else if (dx == 1)
{
first.left = false;
second.right = false;
}
else if (dy == -1)
{
first.bottom = false;
second.top = false;
}
else if (dy == 1)
{
first.top = false;
second.bottom = false;
}
// update the walls
mazeState[x, y] = getNumberFromWalls(first);
mazeState[x2, y2] = getNumberFromWalls(second);
}
// checks all the neighbours for the checkFor param (this is used to get either the visited or the unvisited neighbours)
private List<(int,int)> getNeigbours(int x, int y, int checkFor)
{
List<(int,int)> result = new List<(int,int)> ();
if(x-1 >= 0)
if(visitedCells[x-1,y] == checkFor)
result.Add((x-1,y));
if (y - 1 >= 0)
if (visitedCells[x, y - 1] == checkFor)
result.Add((x, y - 1));
if (x + 1 < visitedCells.GetLength(0))
if (visitedCells[x + 1, y] == checkFor)
result.Add((x + 1, y));
if (y + 1 < visitedCells.GetLength(1))
if (visitedCells[x, y + 1] == checkFor)
result.Add((x, y + 1));
/*
for (int checkX = x-1;checkX <= x+1; checkX++)
for(int checkY = y-1;checkY <= y+1;checkY++)
{
// check if checkX/Y are within bounds
if(checkX >= 0 && checkY >=0 && checkX < visitedCells.GetLength(0) && checkY < visitedCells.GetLength(1))
if(visitedCells[checkX,checkY] == checkFor)
result.Add((checkX,checkY));
}
*/
return result;
}
// overrite the Solve methode because a maze and an ordinary board puzzle like a sudoku or binary puzzle
// don't have much in common in regards to solving. So most of the code in the abstract Board class is to no use for us here
public override SOLUTIONS Solve(bool CheckOnly)
{
List<Move> shortestPath = new List<Move>();
return SOLUTIONS.NONE;
}
// this methode is not needed because we write our own Solve methode
protected override List<Move> GetSolveList(int[,] boardToSolve)
{
return null;
}
public override void TileInput(Point p, int x)
......
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