The game is quite straightforward but before we get to the code, you need to see what it looks like and how it is played.
First we have a setup for the player (Computer’s ships get generated automatically). After clicking one of the button, the user can click anywhere on the map to add the ship of selected size. Once all the ships are added, it will change to the game view.
When the game begins, you will see maps for both player and computer.
The squares that are still hidden will be in blue, the ships are in black, destroyed ships in red and empty square are white.
The project is a Blazor WebAssembly project and in it we have five files added to make this work. There are three component files, which are used two represent three different maps — one for setup, the other two for player and AI. If you want to learn Blazor, you can do it here.
In the setup, as well as other maps, we use svg tag in which we generate our rectangles (rect). We will look at the model that is used, but basically everything is based on squares and what parameters they have.
In the setup we also have a few buttons, which will select the ship that is being inserted.
To make it all work, we need a few variables. The Boolean values are for checking which ships are already added and the integer is to determine which ship type is being added.
Finally, we have the Add method, which takes the selected square and from that generates the ship according to details. For more details, watch the video. If every ship is created, then it invokes OnComplete custom event. With that, we can take a look at the square model and how the ships get generated.
The Square class model is the backbone of this whole arrangement, each square will have an id which you will see used later. With that, there are three Boolean values and they determine what the square is — a ship, destroyed ship, empty square or if all are false then a simple not yet checked square. Finally, we have X and Y for the coordinates and that works in increments of 25.
Everything is based on those squares, so to do anything else we must first generate the squares for each player. First, a list is established and the initial coordinates are set. The map is 10x10 and therefore we will need 100 squares to fill one, for that we have a for loop that will loop 100 times. The idea is quite simple, on every cycle we increase the x coordinates by 25 (everything is based on 25 increments) and every 10 squares we increase the y by 25, in other words - we go to next line.
Once the maps are arranged, we still need to add some ships, they can be vertical, or horizontal. In order to add a ship, we must first verify if it fits and if it does not collide with the other ships. The first square is our starting point, from there we will be increasing the the coordinate value by 25 to either add or check for another square in the ship. What the video to understand this and the other algorithms better.
The computer has to have its’ map setup automatically and for that we use GenerateShips method, which takes the list of square for the computer. In the example, this is not randomized — but that is a task for you. You can see X and Y coordinate multiplications and you can see the rnd — randomizer. Try to add a feature that randomizes ship positions, if you want to practice with Blazor. If you want to learn more or practice more with Blazor then take a look this course.
In the Index.razor, we have everything coming together. Everything is wrapped in status integers and in there we also need to have different states for setup and for the gameplay itself.
There are three statuses, one for when game is running and the others to display the winner. After that, we have lives left integers, those will be subtracted whenever a ship is destroyed. With all that, we have the lists of squares for each side and a reference for the player’s map — this will be used to execute AI’s turns. Finally, on the initialization we generate the maps and add ships for the AI map.
We also have a couple of tasks that will be executed on EndTurn events for each map. The EndTurn provides a boolean which states wether a ship was destroyed (true) or missed (false), in turn we either subtract a life or we leave it be. Once the count drops to 0, the game ends and the winner is displayed.
Every time the player takes a turn, automatically the AI takes one as well. To do it, we select the available squares (ones not known to be empty or destroyed) and from there we pick a random one and check it. That is why we need the reference, because the method to do the check is in the map component. Also, since we are accessing something inside the map, we must use StateHasChanged in order for it to work. You can learn more about it, in this course.
The player’s map takes the squares list from the players and you have to remember that lists work as references. We also have EndTurn custom event, which is invoked after user executes SelectSquare task method.
The squares are generated inside a loop and then for different types we provide different colors. Also, we set onclick events to execute the SelectSquare task on specific square types, but you only need that in the AI map, as the player’s squares are “clicked” automatically. With that, in normal operation you do not need to display ships for the AI map, but for testing it will be needed as you need to see the ships.
Take a look at the video for more details on this project, you will also find other videos about Blazor, different programming topics and business topics as well.
Stripe course: learn.conficienssolutio.com/coursepreviewpage/94c08051-fb80–4042–816b-4533048df218?refid=hubships
API development course: https://learn.conficienssolutio.com/coursepreviewpage/dd448051-fd50-4042-816b-4533048df283?refid=hubships
Taurius on SkillShare:
Support this channel and find great deals on patreon: