Making digital huarongdao with App designer

Posted by shiranwas on Sun, 27 Feb 2022 16:06:58 +0100

Making digital huarongdao with App designer

After 2048, I suddenly thought of Huarong Road, but Huarong Road is difficult to do. Let's try a digital Huarong Road first.

UI design

The main controls are 16 squares showing numbers, a timing panel, a game victory interface and a new game button. As shown in the figure below.


Different from 2048, the button control is used for the digital box this time. The code for creating the control is as follows (note that the Num type is declared as MATLAB. UI. Control. Button in properties):

function createNum(app)
            for i=1:4
                for j=1:4
                    app.Num(i,j) = uibutton(app.NumHuaRongUIFigure,'push');
                    app.Num(i,j).ButtonPushedFcn = createCallbackFcn(app, @NumButtonPushed,true);
                    app.Num(i,j).BackgroundColor = [0.91 0.77 0.66];
                    app.Num(i,j).Position = [-47.5+j*100 442.5-i*100 95 95];
                    app.Num(i,j).Text = '';
                    app.Num(i,j).FontName = 'Segoe UI Historic';
                    app.Num(i,j).FontSize = 40;
                    app.Num(i,j).FontColor = [1,1,1];
                    app.Num(i,j).Tag = num2str(sub2ind([4 4],i,j));
                end
            end
        end

Create the corresponding callback function:

        function NumButtonPushed(app,event)  
        end  

Create victory panel function:

        function createGameOverLabel(app)
            app.gameOverLabel = uilabel(app.NumHuaRongUIFigure);
            app.gameOverLabel.BackgroundColor = [0.59,0.66,0.64];
            app.gameOverLabel.Position = [50,140,400,200];
            app.gameOverLabel.FontName = 'Ink Free';
            app.gameOverLabel.FontSize = 70;
            app.gameOverLabel.FontColor = [1,1,1];
            app.gameOverLabel.HorizontalAlignment = 'center';
            app.gameOverLabel.Text = "YOU WIN";
            app.gameOverLabel.Visible = 'off';
        end

Other controls are recommended to be created directly using the user interface.

Rule design

  • Game initial matrix
    We need a scrambled matrix to start the game. To achieve this, you can use the randperm() function, which can generate a set of different integers.
            m = randperm(16,16)-1;
            m = reshape(m,4,4);
            app.theMatrix = m;
  • Click the box next to the space to move the box to the space
    There are two main points to realize this rule: one is to judge whether the clicked box is around the space, and the other is to exchange positions. Firstly, the corresponding matrix element of the blank lattice is 0. Its position can be quickly determined by using the find() function, and there are up to 4 positions that can be moved around the blank. We can pass in the clicked box position index and compare it with the blank box index. If the row indexes of the two positions are equal and the column indexes differ by 1, or the column indexes are equal and the row indexes differ by 1, the box can be exchanged with the blank space.
        function f = isMovable(app,i,j)
            [x,y] = find(app.theMatrix == 0);
            if (i==x)&&(abs(j-y)==1)
                f = true;
            elseif  (j==y)&&(abs(i-x)==1)
                f = true;
            else
                f = false;
            end
        end

Secondly, the exchange position is to modify the values of the two positions of the matrix.

function moveNum(app,i,j)
            if app.isMovable(i,j)
            [x,y] = find(app.theMatrix == 0);
            app.theMatrix(x,y) = app.theMatrix(i,j);
            app.theMatrix(i,j) = 0;
            end
end  
  • Make the squares in order, and the last box is a space, that is, declare the victory of the game
    The implementation of this rule only needs the isequal() function to judge whether the two matrices are equal.
        function y = isGameWin(app)
            if isequal(app.theMatrix,app.desMatrix)
                y = true;
            else
                y = false;
            end
        end 

timer

In order to evaluate the game performance, we can add a timer.

  • Create a timer in properties
	theTimer = timer 
  • Create an initialization function of timer
        function timerInit(app)
            app.theTimer.StartDelay = 1;
            app.theTimer.Period = 1;
            app.theTimer.ExecutionMode = 'fixedSpacing';
            app.theTimer.TimerFcn = @(~,~)timerCallback(app);
        end

The above code indicates that the timer will have a start delay of 1s, and it will execute callback every 1s

  • Don't forget to create a callback function for timer
        function timerCallback(app)
        end
  • Modify the value of the timer panel in the callback to realize the timing function
            t = str2double(app.TimerPanel.Value);
            t = t+1;
            app.TimerPanel.Value = string(t);
  • Use start() and stop() to start and stop the timer respectively. Don't forget to delete the timer before closing the APP (in the callback function of UIFigure)
        function NumHuaRongUIFigureCloseRequest(app, event)
            stop(app.theTimer)
            delete(app.theTimer)
            delete(app)            
        end

Perfect each callback, and a simple digital Huarong Road is completed.

Topics: MATLAB app