Plotting matrix on grid of squares

19 次查看(过去 30 天)
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)

回答(1 个)

chicken vector
chicken vector 2023-4-22
编辑:chicken vector 2023-4-22
I learned to code these kind of applications by studying Brian Moore's File Exchange.
In particular, you can check his very nice version of Minesweeper.
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 个评论
chicken vector
chicken vector 2023-4-22
编辑:chicken vector 2023-4-22
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.
Also, if you are interested, you can check the Mastermind game I created .

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Migrate GUIDE Apps 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by