Plotting matrix on grid of squares
21 views (last 30 days)
Show older comments
I have coded the first part to a random minesweeper game generator, though my results are limited to a 9x9 matrix. I would like to display my matrix as a grid of boxes that I can label/assign values to. My code to produce a random minesweeper matrix is below.
function difficulty = Modeselect
%This is for choosing the difficulty/number of bombs
answer = questdlg('What level of difficulty would you like?',...
'Mode Selector','Easy','Medium','Difficult','Difficult');
switch answer
case 'Easy'
difficulty=3;
case 'Medium'
difficulty=6;
case 'Difficult'
difficulty=9;
end
function minesweeper
difficulty=Modeselect;
%Generating random bomb positions
ArrayX=[1 2 3 4 5 6 7 8 9];
ArrayY=[1 2 3 4 5 6 7 8 9];
Bombx=zeros(1,difficulty);
Bomby=zeros(1,difficulty);
for i=1:difficulty
Bombx(i)=randsample(ArrayX,1);
ArrayX(ArrayX==Bombx(i))=[];
Bomby(i)=randsample(ArrayY,1);
ArrayY(ArrayY==Bomby(i))=[];
end
mines=false(9,9);
for j=1:difficulty
mines(Bombx(j),Bomby(j))=true;
end
grid=convn(mines,ones(3,3),'same');
grid(mines)=9;
disp(grid)
Answers (1)
chicken vector
on 22 Apr 2023
Edited: chicken vector
on 22 Apr 2023
I find his codes to be very readable thanks to the comments in almost every line and, therefore, highly instructive.
As an example, if you check his CreateGUI function, you can see that he creates the squares using patch
% Create board squares (unclicked/invisible by default)
this.borderCoords.x = [0 sw * this.nCols]; % Bounding box
this.borderCoords.y = [0 sw * this.nRows]; % Bounding box
this.sqCoords.x = @(i) sw * (i - 1); % Coordinate fcn
this.sqCoords.y = @(j) sw * (this.nRows - j); % Coordinate fcn
for i = 1:this.nCols
for j = 1:this.nRows
% Square patch
x0 = this.sqCoords.x(i);
y0 = this.sqCoords.y(j);
this.board(i,j).ph = patch(x0 + this.unclicked.X, ...
y0 + this.unclicked.Y, ...
this.unclicked.C, ...
'edgecolor','none');
% Square images
this.board(i,j).imh = image(1,'Visible','off');
end
end
The mouse interaction is coded using the event scattering:
'WindowButtonDownFcn',@(s,e)MouseDown(this)
Then you can retrieve the coordinate of the click with:
xy = get(this.ax,'CurrentPoint');
And with that, determine the square clicked.
Although less aesthetically pleasing, a valid alternative consists in creating a grid of pushbuttons.
Personaly I prefer to use the conventional figure with uicontrol, but you could also use uifigure and uibutton.
An advantage of using uibutton over uicontrol is that you can use images as buttons background.
The disadvantage is that uibutton have rounded corners, therefore uicontrol are more suited to display grids.
I suggest you to start with pushbuttons because is easier.
You can use the following code as starting point.
I use UserData(3) as a trigger to check if the square is on or off.
You can store in there a number from -1 to 8, where -1 corresponds to a mine and the other to the number of mines in the vicinity.
% Number of squares along X and Y:
gridSizeX = 20;
gridSizeY = 10;
% Initialise figure:
fig = figure('Position', [100 100 875 500], 'Units', 'Pixels');
% Set squares boundaries inside figure in pixels:
gridPosition = [.1 .1 .8 .7] .* repmat(fig.Position(3:4), 1, 2);
% Compute square size:
buttonSizeX = gridPosition(3) / gridSizeX ;
buttonSizeY = gridPosition(4) / gridSizeY;
% Get squares coordiantes in pixels:
[X,Y] = meshgrid(gridPosition(1) : buttonSizeX : sum(gridPosition([1,3])) - buttonSizeX, ...
gridPosition(2) : buttonSizeY : sum(gridPosition([2,4])) - buttonSizeY);
% Loop over the grid just defined:
for col = 1 : gridSizeX
for row = 1 : gridSizeY
% Get position:
position = [X(row, col), Y(row, col), buttonSizeX, buttonSizeY];
% Create square as pushbutton:
uicontrol(fig, ...
'BackgroundColor','g', ...
'Position', position, ...
'Units', 'Pixels', ...
'UserData', [row, col, 1], ...
'Callback', @click);
end
end
function click(obj,~)
% Check if button was on or off and change color:
if obj.UserData(3)
obj.BackgroundColor = 'r';
obj.UserData(3) = 0;
else
obj.BackgroundColor = 'g';
obj.UserData(3) = 1;
end
end
Result:
1 Comment
chicken vector
on 22 Apr 2023
Edited: chicken vector
on 22 Apr 2023
With very few adjustments you can obtain the following:
This still requires to check when the game ends, and the appearance of the GUI can be easily improved.
If you request it I can share the code, but I encurage you to try to create your own version.
See Also
Categories
Find more on Migrate GUIDE Apps in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!