This will probably be the last BASH game I do. These games have shown how someone can make a different game in BASH. Whether the game is cards, dice or a board game, they can be fun and challenging to make.
I'm not going to cover all the code, I'm just going to go over each function.
Be aware that this game has some logic missing. I did not put the guessing logic for the PC to continue on a specific 'path' when a boat was hit to continue along the column or row to sink the ship. Also, after downloading the script, 'bship.txt' rename it to 'bship.sh'.
The basic logic behind the PC is to randomly choose a spot that has not been guessed before and try it. Because of this, the game is easy to win, but if someone wants to implement the logic, they can add it.
Function screensize
The function is called initially to make sure the screen is the proper minimum size to handle the game. The minimum size is 102x35. If the current terminal size is bigger in one direction or both, then the larger size is left.
The minimum size is set using a 'printf' command that issues the height (row) size by the width (col) size for the window.
Function initcolors
We can change the colors of the text by issuing an 'echo' statement with the color. The colors are initially set with the 'tput setaf <color_value>' set to the color name. For example, 'black' is set to color '0', while 'yellow' is color '3'. Once the colors are initialized, we can simply issue the echo command with the color we want for the text. For example, 'echo "${blue} This text is blue."'. Now, any text printed afterward will also be blue, unless you change the color back or perform a reset with the command '${nc}', which is placed into an echo statement. Keep in mind, the variable does not print anything but only changes the color.
Any other initialization can be performed here as well.
function titlescreen
The function is merely used to display a 'title' or 'splash' screen that is shown when the game first starts, as shown in Figure 1.
FIGURE 1
Using ASCII and colors, there is a picture of a ship on the ocean and below it, a submarine. To make things more interesting, the title 'Battleship' moves across the screen at the bottom.
Once done, the user is prompted to press a key to continue.
function rest
To get the word 'Battleship' to cross the intro screen, the regular speed was too fast. By using the sleep command, the minimum time is 1 second. Moving the word across the screen 1 second at a time took way too long. To fix this, I created a function called 'rest' that we can pass a value of milliseconds to pause. One second is 1000 milliseconds. The rest period was only set to '75', but the value can be played with.
For any other script you have that requires pauses shorter than one second, this script works fairly well.
function instructions
The function displays a basic screen of information. Nothing too fancy, but this can be added to as needed.
Once the player has finished looking over the information, they need only press a key to continue.
function initgridarray
Here, we initialize the three arrays that make up the 10x10 grid. There are three grids set up, 'ugrid', 'pgrid' and 'shoot'. The 'ugrid' holds the information on the placement of the boats. Also, when the PC shoots, it holds the information on hits and misses. The 'pgrid' array holds the PC's ship location and the user's hits and misses.
Let's talk about the arrays real quick. First, the 'shooter' array is not used. I was planning to use this to aid the PC in logic for shooting down a boat once a hit was made. Unfortunately, time does not allow for me to finish it.
Second, the grid is a 2-dimensional grid, but BASH does not allow for a 2-dimensional array. To fix this, the 'y' value, or column, is multiplied by 10, then x, or the row, is added to the result. The top left grid block is '1,1', or '11' in the array. The grid block one to the right is '12'. If we go one down from '1,1', which is '2,1', the array element is '21'. So, the grid is matched to the array from element '11' to element '110'
The values are all set to '0' initially. The ships are set from 1 to 5, depending on the ship. An '8' represents a miss and a '9' is a hit.
Also, I initialized two sets of variables. The 'u' variables are all the boats for the user. They are all set to '1' since the boat exists and is in play. The other set starts with a 'p' for the PC.
function initgridview
The function will clear the screen and display two grids. The left one is for the user. The right one is for the PC. When the user makes a guess, the shot is displayed on the right grid where you cannot see the PC's ship placement. On the left grid, you can see your ship placement and the PC's shots.
The function also shows your boats in blue. Hits are in red and misses are white.
function showplacegrid
This function shows a single grid to allow the user to place their five boats.
Any ships placed will be shown in red when placed. The unplaced boat is blue.
function placeships
Here, the grid is shown, and placed boats. The function allows for input from the user by pressing the '8' key for 'up', '2' key for 'down', '4' key for 'left', and '6' key for right. You can place the boat at the location where the boat is by pressing the 'P' key. It does not have to be capitalized, the script will change it to uppercase.
If you want to switch the current boat from horizontal to vertical, press the '5' key. To change it back, hit the '5' key again.
During this process, you can also press 'X' to exit the game.
The function will also prevent you from placing a boat on top of another boat.
function placepcships
The logic is placed here to allow the PC to randomly place its five ships.
There will be a message at the bottom of the screen to show which ship is being placed.
function checkwin
The script checks to see if all the boats are sunk for a player and declares a winner.
The script also checks if the specific boats have been sunk and lets the user know which ship has been sunk.
Any sunk ships will be shown on the screen by changing the appropriate name from white to red. The list is to the right of each grid.
function redraw
The function allows for the current boat to be placed into the grid.
The current boat is the one in which the values are in place in the variables at the current time.
function getuserinput
This is where the user is prompted to take a shot at the PC's grid. First, you are asked to choose a column (A-J) or press 'X' to exit.
Once you have made a valid choice, you choose a row (1-0), or '1' to '9' or '0' for 10. If the shot has already been made, you are prompted for a different column and row.
A message should appear to let you know if the shot was a 'hit' or 'miss'. A corresponding square should be filled in with a 'white' or 'red' block.
function getpcinput
The PC will make a random guess on the grid, the script checks if the guess was already made. Until the guess is a valid one that has not already been made, the PC will continue guessing. Once a good guess is made, a message will appear to let the player know if it was 'hit' or 'miss'.
main
The main area of the program is used to call all the initializing functions and to continue until there is a winner.
Some of this could have been streamlined just a little better, but the code works.
Conclusion
Linux users can see that the terminal is not as simple as it may seem. These commands used in the terminal can be put together in a script to make fairly interesting games.
Like any programming language, there is quite a bit of power here.
I'm not going to cover all the code, I'm just going to go over each function.
Be aware that this game has some logic missing. I did not put the guessing logic for the PC to continue on a specific 'path' when a boat was hit to continue along the column or row to sink the ship. Also, after downloading the script, 'bship.txt' rename it to 'bship.sh'.
The basic logic behind the PC is to randomly choose a spot that has not been guessed before and try it. Because of this, the game is easy to win, but if someone wants to implement the logic, they can add it.
Function screensize
The function is called initially to make sure the screen is the proper minimum size to handle the game. The minimum size is 102x35. If the current terminal size is bigger in one direction or both, then the larger size is left.
The minimum size is set using a 'printf' command that issues the height (row) size by the width (col) size for the window.
Function initcolors
We can change the colors of the text by issuing an 'echo' statement with the color. The colors are initially set with the 'tput setaf <color_value>' set to the color name. For example, 'black' is set to color '0', while 'yellow' is color '3'. Once the colors are initialized, we can simply issue the echo command with the color we want for the text. For example, 'echo "${blue} This text is blue."'. Now, any text printed afterward will also be blue, unless you change the color back or perform a reset with the command '${nc}', which is placed into an echo statement. Keep in mind, the variable does not print anything but only changes the color.
Any other initialization can be performed here as well.
function titlescreen
The function is merely used to display a 'title' or 'splash' screen that is shown when the game first starts, as shown in Figure 1.
FIGURE 1
Using ASCII and colors, there is a picture of a ship on the ocean and below it, a submarine. To make things more interesting, the title 'Battleship' moves across the screen at the bottom.
Once done, the user is prompted to press a key to continue.
function rest
To get the word 'Battleship' to cross the intro screen, the regular speed was too fast. By using the sleep command, the minimum time is 1 second. Moving the word across the screen 1 second at a time took way too long. To fix this, I created a function called 'rest' that we can pass a value of milliseconds to pause. One second is 1000 milliseconds. The rest period was only set to '75', but the value can be played with.
For any other script you have that requires pauses shorter than one second, this script works fairly well.
function instructions
The function displays a basic screen of information. Nothing too fancy, but this can be added to as needed.
Once the player has finished looking over the information, they need only press a key to continue.
function initgridarray
Here, we initialize the three arrays that make up the 10x10 grid. There are three grids set up, 'ugrid', 'pgrid' and 'shoot'. The 'ugrid' holds the information on the placement of the boats. Also, when the PC shoots, it holds the information on hits and misses. The 'pgrid' array holds the PC's ship location and the user's hits and misses.
Let's talk about the arrays real quick. First, the 'shooter' array is not used. I was planning to use this to aid the PC in logic for shooting down a boat once a hit was made. Unfortunately, time does not allow for me to finish it.
Second, the grid is a 2-dimensional grid, but BASH does not allow for a 2-dimensional array. To fix this, the 'y' value, or column, is multiplied by 10, then x, or the row, is added to the result. The top left grid block is '1,1', or '11' in the array. The grid block one to the right is '12'. If we go one down from '1,1', which is '2,1', the array element is '21'. So, the grid is matched to the array from element '11' to element '110'
The values are all set to '0' initially. The ships are set from 1 to 5, depending on the ship. An '8' represents a miss and a '9' is a hit.
Also, I initialized two sets of variables. The 'u' variables are all the boats for the user. They are all set to '1' since the boat exists and is in play. The other set starts with a 'p' for the PC.
function initgridview
The function will clear the screen and display two grids. The left one is for the user. The right one is for the PC. When the user makes a guess, the shot is displayed on the right grid where you cannot see the PC's ship placement. On the left grid, you can see your ship placement and the PC's shots.
The function also shows your boats in blue. Hits are in red and misses are white.
function showplacegrid
This function shows a single grid to allow the user to place their five boats.
Any ships placed will be shown in red when placed. The unplaced boat is blue.
function placeships
Here, the grid is shown, and placed boats. The function allows for input from the user by pressing the '8' key for 'up', '2' key for 'down', '4' key for 'left', and '6' key for right. You can place the boat at the location where the boat is by pressing the 'P' key. It does not have to be capitalized, the script will change it to uppercase.
If you want to switch the current boat from horizontal to vertical, press the '5' key. To change it back, hit the '5' key again.
During this process, you can also press 'X' to exit the game.
The function will also prevent you from placing a boat on top of another boat.
function placepcships
The logic is placed here to allow the PC to randomly place its five ships.
There will be a message at the bottom of the screen to show which ship is being placed.
function checkwin
The script checks to see if all the boats are sunk for a player and declares a winner.
The script also checks if the specific boats have been sunk and lets the user know which ship has been sunk.
Any sunk ships will be shown on the screen by changing the appropriate name from white to red. The list is to the right of each grid.
function redraw
The function allows for the current boat to be placed into the grid.
The current boat is the one in which the values are in place in the variables at the current time.
function getuserinput
This is where the user is prompted to take a shot at the PC's grid. First, you are asked to choose a column (A-J) or press 'X' to exit.
Once you have made a valid choice, you choose a row (1-0), or '1' to '9' or '0' for 10. If the shot has already been made, you are prompted for a different column and row.
A message should appear to let you know if the shot was a 'hit' or 'miss'. A corresponding square should be filled in with a 'white' or 'red' block.
function getpcinput
The PC will make a random guess on the grid, the script checks if the guess was already made. Until the guess is a valid one that has not already been made, the PC will continue guessing. Once a good guess is made, a message will appear to let the player know if it was 'hit' or 'miss'.
main
The main area of the program is used to call all the initializing functions and to continue until there is a winner.
Some of this could have been streamlined just a little better, but the code works.
Conclusion
Linux users can see that the terminal is not as simple as it may seem. These commands used in the terminal can be put together in a script to make fairly interesting games.
Like any programming language, there is quite a bit of power here.