Im designing a game of battleship, but. im trying to use a code to prevent the user from placing a ship out of bounds

19 views (last 30 days)
in my game of battleship the board is 6 by 6, so when the user wants to place a (1X2) ship on grid 6 and chooses a horizontal orientation the ship will be placed out of bounds. My code for just placing the ships is:
startingGrid= input(' Please choose the grid number you want your ship to start in : ');
if startingGrid == 1
while true
orientation = input(' Please enter v if you want your ship to be placed vertically or h if you want it horizontally', 's');
if ismember(orientation,{'v' 'h'})
break;
end
disp(' please choose v or h only and make sure to use small letters ');
end
if strcmp(orientation,'v')
% fill grids 1 and 7
else
%fill grids 1 and 2
end
and i have an if statement like this for each of the 36 "starting grids".
I also wrote this code to not allow a ship to be placed out of bounds,( for example starting grid of 6 and orientation of h.
validChoice = false; % set flag up front, false so we enter the loop at least once
while ~validChoice
startingGrid= input('Enter top-left grid square number','s');
startingGrid = str2double( startingGrid );
orientation = input('Enter v or h for vertical or horizontal','s');
if (startingGrid==6 && strcmpi(orientation,'h'))
% This is invalid
disp( 'Invalid choice, cannot fit ship in chosen location, try again...' );
else
% Input is OK, set the flag to true so the loop exits
validChoice = true;
end
end
now is there a way to somehow use this code inside my if statement, so
if startingGrid ==6
.......
if v
%fill grids 6 and 12
else
%use above code to let the user enter a starting grid again.
end
  4 Comments
Tariq Hammoudeh
Tariq Hammoudeh on 1 Jan 2022
i tried something like that, but then it doesnt process the input again, as in check if startingGrid == 1 and so on, so is there a way i can make that work

Sign in to comment.

Answers (2)

DGM
DGM on 1 Jan 2022
Edited: DGM on 1 Jan 2022
I generally can't stand things written to be so tediously interactive like this, but maybe this is a simplified start.
% i assume you have some sort of equivalent variables defined
shipsize = 2;
boardsize = [6 6];
N = prod(boardsize);
board = false(boardsize); % assuming the board is empty at this point
% get valid placement information from user
while true
shiplocation = requestshiplocation(N);
orientation = requestorientation();
[m n] = ind2sub(boardsize,shiplocation);
if strcmp(orientation,'v') && m + (shipsize-1) > boardsize(1)
fprintf(' Ship can''t fit this close to the bottom edge of the board in this orientation\n')
elseif strcmp(orientation,'h') && n + (shipsize-1) > boardsize(2)
fprintf(' Ship can''t fit this close to the right edge of the board in this orientation\n')
else
break;
end
end
% place this ship on the board
if strcmp(orientation,'v')
board(m:m+shipsize-1,n) = true;
else
board(m,n:n+shipsize-1) = true;
end
board
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function shiplocation = requestshiplocation(N)
while true
shiplocation = input(sprintf('Specify where this ship is located (grid position between 1 and %d): ',N));
if isscalar(shiplocation) && (shiplocation >= 1 && shiplocation <= N)
break;
end
fprintf(' please choose a valid location between 1 and %d \n',N);
end
end
function orientation = requestorientation()
while true
ostring = input('Specify ship orientation (''v'' or ''h''): ', 's');
orientation = lower(ostring(1)); % ignore case, length
if ismember(orientation,{'v' 'h'})
break;
end
fprintf(' %s is not a valid orientation\n',ostring)
end
end
Points to consider:
Given the convention of asking only for an index and (one of two) orientations, a ship can be placed at an index where neither orientation is valid. This is why I simply chose to reject both the location and orientation when either is invalid.
Asking the user for the ship location as a linear index is cumbersome and nonintuitive. The actual game uses row and column subscripts, so it would make more sense to at least use that convention. Doing so would also obviate the need to use ind2sub().
Nothing in this approach prevents ships from being placed on top of each other.
  7 Comments
Walter Roberson
Walter Roberson on 6 Jan 2022
You do not need to use randsample(). You can find the number of files, and use randi() on the number of files.
Unless, that is, you have a reason to pick between the files with different probabilities. If you wanted, for example, that one particular special board should show up 10 times its normal probability, then randsample() makes that slightly easier to code than using randi() [but it isn't difficult to arrange with randi either]
Tariq Hammoudeh
Tariq Hammoudeh on 6 Jan 2022
I just put the names of the files in an array and now i just want to select a random element of this array. so
A=random element of array
Then Ill use
if A= file1
......
So i just need to be able to pick a random element from my array

Sign in to comment.


Meg Noah
Meg Noah on 2 Jan 2022
Here is a solution with user interaction/prompting:
flagInteractive = 1; % prompt user for ship placement
flagRepeatable = 0;
if (~flagInteractive && flagRepeatable)
iseed = 24; % change this to get a different random outcome
s = RandStream('mt19937ar','Seed',iseed);
RandStream.setGlobalStream(s)
end
% index, name, size
% one for each ship to be placed (multiple ships of same type/length are
% uniquely included
Ships = {
1,'Carrier',5; ...
2,'Battleship',4; ...
3,'Cruiser',3; ...
4,'PatrolBoat1',2; ...
5,'PatrolBoat2',2};
shipTable = cell2table(Ships,'VariableNames',{'idx','shipName','shipLength'});
nShip = numel(shipTable.idx);
shipTable.flagV = nan(nShip,1); % orientation of the ships (1=vertical, 0=horizontal)
% starting row and column of the ship on the gameboard
shipTable.iRow = nan(nShip,1);
shipTable.iCol = nan(nShip,1);
% board size
nrows = 10;
ncols = 10;
% create a board table
% empty values are 0
% filled values have shipIndex where the player has placed a ship
imBoard = zeros(nrows,ncols);
% row column indices for each tile
[C2X,R2X] = meshgrid(1:ncols,1:nrows);
for iShip = 1:nShip
fprintf(1,'\n\Current Gameboard\n');
for irow = 1:nrows
for icol = 1:ncols
if (imBoard(irow,icol) == 0)
fprintf(1,'R%2.2dC%2.2d ',irow,icol);
else
% not allowed
fprintf(1,'--%2.2d-- ',imBoard(irow,icol));
end
end
fprintf(1,'\n');
end
% prompt user for vertical or horizontal placement
if (~flagInteractive)
shipTable.flagV(iShip) = randi(2,1)-1;
else
list = {'Horizontal','Vertical'};
[indx,tf] = listdlg('ListString',list,'PromptString', ...
horzcat('Orientation of ',shipTable.shipName{iShip}), ...
'SelectionMode','single');
shipTable.flagV(iShip) = indx - 1;
end
nTiles = shipTable.shipLength(iShip);
maskV = vertcat(zeros(nTiles-1,1),ones(nTiles,1));
maskH = horzcat(zeros(1,nTiles-1),ones(1,nTiles));
if (shipTable.flagV(iShip) == 0)
% find the horizontal locations allowed
imAllowedLocations = ones(nrows,ncols);
imAllowedLocations(imBoard > 0) = 0;
imAllowedLocations = imerode(imAllowedLocations,maskH);
imAllowedLocations(C2X > ncols - nTiles + 1) = 0;
else
% find the vertical locations allowed
imAllowedLocations = ones(nrows,ncols);
imAllowedLocations(imBoard > 0) = 0;
imAllowedLocations = imerode(imAllowedLocations,maskV);
imAllowedLocations(R2X > nrows - nTiles + 1) = 0;
end
fprintf(1,'\nallowed locations for %s\n',shipTable.shipName{iShip});
list = {}; listRow = []; listCol = [];
for irow = 1:nrows
if (irow == 1)
fprintf(1,' ');
for icol = 1:ncols
fprintf(1,'C%2.2d ',icol);
end
fprintf(1,'\n');
end
fprintf(1,'R%2.2d ',irow);
for icol = 1:ncols
if (imAllowedLocations(irow,icol) == 1)
fprintf(1,'( ) ');
list = vertcat(list,sprintf('R%2.2dC%2.2d',irow,icol));
listRow = vertcat(listRow,irow);
listCol = vertcat(listCol,icol);
else
% not allowed
fprintf(1,'XXX ');
end
end
fprintf(1,'\n');
end
if (~flagInteractive)
% prompt for irow, icol - this is a random draw so replace the next
% three lines with your user interface - how you want to propmpt
idxAllowed = find(imAllowedLocations > 0);
idxChosen = idxAllowed(randi(numel(idxAllowed),1));
[thisRow,thisCol] = ind2sub(size(imAllowedLocations),idxChosen);
else
[indx,tf] = listdlg('ListString',list, ...
'PromptString',horzcat('Location of\n ',shipTable.shipName{iShip}), ...
'SelectionMode','single');
thisRow = listRow(indx);
thisCol = listCol(indx);
end
% populate the ship table and the game board for this player.
shipTable.iRow(iShip) = thisRow;
shipTable.iCol(iShip) = thisCol;
if (shipTable.flagV(iShip) == 0)
imBoard(thisRow,thisCol:thisCol+nTiles-1) = iShip;
else
imBoard(thisRow:thisRow+nTiles-1,thisCol) = iShip;
end
end
fprintf(1,'\n\nFinal Gameboard\n');
for irow = 1:nrows
for icol = 1:ncols
if (imBoard(irow,icol) == 0)
fprintf(1,'R%2.2dC%2.2d ',irow,icol);
else
% not allowed
fprintf(1,'--%2.2d-- ',imBoard(irow,icol));
end
end
fprintf(1,'\n');
end

Categories

Find more on Board games in Help Center and File Exchange

Products


Release

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!