BSQ Epitech Project
Authorized functions
The list of authorized functions are only :
Description
The goal of the project is to find the biggest square on a map while avoiding obstacles.
The file map is passed as parameter to the program.
Note
A first line indicate the height of the map.
Character
'.'
in the map is an empty place.Character
'o'
in the map is an obstacle.The map contains at least one map’s line
Every lines have the same length excepted the indicator at the first line.
Each line is ended by a
'\n'
.
Goal
The goal of the project is to find the biggest square of '.'
in the map and replace it by 'x'
.
Info
Tutorial
The project is splited into 3 parts:
Load the map.
Search inside the map the biggest square.
Display with good performences.
First of all, I would precise that the project can be done by two 2 different way :
By using string.
By using array.
Using string is really hard because you need to have a perfect master’s degree of calculation handling for locating hisself in the map. This method let generally place to a lot of mistakes, but in case of success, it is really powerfull and generate great performances.
Using arrays is really easy because you can locating yourself easily in the map. This method don’t let generally place to mistakes and have great performances.
Note
I would remember you how to create a structure and call it !
|
|
|
|
or
|
|
Depend of what you want to do.
Lets see now how to realise the BSQ project with the array method !
Load
First of all you will have to use the open
and read
functions, so check the man open
and man read
.
Create a function that will open the file, generate an array based on the readed file and realise an error gestion.
The prototype of the function can be written like so : unsigned short **load_map(char *file_path)
. In case of error the function will return NULL
.
Info
- Why an unsigned short ** ?
Because you are going to store the map like you have integers in it.
- But why unsigned short?
Because the biggest map (10k x 10k) tested can be stored in an unsigned short, so you don’t need a surplus of memory by using unsigned int or long.
So lets begin your load_map
function !
Open, read and stat file
To read the entire map stocked in a file you will need to get the file size.
The stat
structure give you a lot of information about a file. For more information about stat, check the documentation.
|
|
Info
-84
because the size of the file can be egal to 84
.Here you get the size of the file thanks to buf.st_size. You every time sould carefull of return values.
The next step is to open the file with readable option O_RDONLY
.
|
|
Danger
- Don’t forget to
close
your fd when you will not use it anymore !! In the contrary case it will causes leak of memory !!
Now, you have a valid fd, the size of the file. You only need to read the file and stock it in a string.
|
|
Danger
Don’t forget to malloc
with (size + 1)
for the '\0'
.
Don’t forget the '\0'
at the end of your map ! Without it you are going to have memory error in the future.
Info
Every string is ended by a
'\0'
.Every array of string is ended by a
NULL
.
Create your array
Now you have your map stocked in a string and you want to transform it into an array. So, you should extract the first line and code a string to unsigned short **
function.
I let you find the way to get the first line of your map and stock it in a variable, and how to get the length of your map’s lines.
Lets create your array:
|
|
Danger
- You should everytime verify your malloc !
The code is a bit complexe but it is a great optimisation, because you allocate and fill the content into the allocated memory dirrectly. In the first for
loop you’re alocating the map with the line’s width
. In the second for
loop you are putting characters in the map.
Info
'.'
are represented by a1
.'o'
are represented by a0
.To be easier in the future, you can keep some values in a structure like width, height and size.
Now your load_map
function should look something like this:
|
|
If you print the content of your map you should have this result without colors:
Search
Now that you have stocked your map, the emplementation of the reverse minesweeper
will be easier.
The principle of the reverse minesweeper is to look specific arounded cases to determine possibilities. We could represent this like that:
Info
- The
'L'
represents what you are looking.
What I mean here is that you need first to check if the central case is a valid case and after check the validity of every left, top and left top surronding cases.
In your case you have a unsigned short **
map, that we will represent by this exemple:
A 3 length biggest square.
An obstacle.
So now lets implement the algorithm !
As we said previously you need to look around specific cases, I lied. You can’t look every surronding cases, because if you look in a part of the array that doesn’t exit, you are going to crash (segfault). So lets start at a position where you are not going to crash !
You’re going to create two for
loops, one to travel into the unsigned short **
and another to travel into the unsigned short *
.
|
|
Info
- The
'H'
represents where you are.
Like so, thanks to these two loops you can easily travel in your array. All you need now is to look around. So create a function that will look on the left, top and left top cases. This function need to find the minimum short in these tree cases to put it in the current case and increment it by one. Look the exemple below and you will understand.
|
|
Info
- You don’t need a return value because the tab is allocated so it will change it directly into the memory address.
All you need now is to put this in the loop and it is practically done ! If I represent it you would have:
Info
Don’t you find something strange ?!
Don’t you searched for a 3 square max length ?
Now you have an unsigned short **
resolved biggest square, but you want to print only the biggest one in a map ! So, you need to keep in memory the place where you founded the biggest one. You can put in a struct the variables i
and j
from where you founded the biggest square.
|
|
Perfect ! You have an index on the biggest square. You can now display the map !
Display
Display your map is quite easy but also quite difficult because it is where the performance will be the worst. So, you have three choices:
Display character by character
Display line by line
Display the whole map
For best performances you have choose the whole map ! 😂 You are going to use the map from the begining, but before you need to change your map with the founded square !
Remember, you have an unsigned short **map
(wich is usless now), a char *map
(from the loading), a struct with i
, j
and the length of the biggest square, the height of your map and the width of each line. Thank to that you can create a formula to access each element of your string you want. It is going to be two for
loop.
|
|
Info
*
(mean pointer) because you will not change values inside. But for beginner difficulties of comprehension, I prefer to let a *
.Tip
- Where does the formula comes ?
See you the light at the end of the tunnel ?
All you need now is to my_putstr(map)
or printf("%s", map)
.
You have finished your project well done !
Bonus ideas
Print the position of the biggest square
Print in color
Print with a grafical library
Do for other shapes
Optimisation by using multiple hearts of your processor