Click here to Skip to main content
15,867,453 members
Articles / Web Development / HTML

MVC Bricks for ASP.net

Rate me:
Please Sign up or sign in to vote.
4.96/5 (120 votes)
4 May 2011CPOL11 min read 217.2K   6.4K   155   98
Learn how to create a simple game using ASP.net MVC, jQuery, State Machine and CSS3 gradients

Image 1

Table of Contents

Introduction

Image 2Image 3Image 4Image 5Image 6Image 7Image 8Image 9Image 10Image 11

It's been a long time since I wrote my last article on the ASP.Net subject. This time I decided to write something about it, and more specifically, about ASP.Net MVC.

The MVC approach is, by far, my favorite way of doing things in ASP.Net. The simple fact that you don't have the code behind, nor view state, deserves much of my consideration. That goes without saying that you don't care about post backs.

Also, the application uses the awesome jQuery library to make our lives easier. As the readers will see, I tried to use jQuery wherever I could. This library is really a blessing for those of us developers who need to work on web applications.

System Requirements

Image 12Image 13Image 14Image 15Image 16Image 17Image 18Image 19Image 20Image 21

To use the MVC Bricks game provided with this article, if you already have Visual Studio 2010, that's fine. If you don't, you can download the following 100% free development tool directly from Microsoft:

  • Visual Web Developer 2010 Express
  • Also, you MUST open it in a CSS3-enabled browser, because this application uses CSS3 Webkit Gradient.

    Splash Screen

    Image 22

    When the game starts, there is a simple jQuery animation, which makes the "MVC BRICKS" title raise up to the middle of the screen. This is accomplished by animating the top css property of the title div:

    JavaScript
    function showSplashScreen() {
        $('.subTitle').css('visibility', 'hidden');
        $('.press').css('visibility', 'hidden');
        $('.title').animate({
            top: 200
        }, 1000, 'swing', function () {
            // Animation complete.
            $('.subTitle').css('visibility', 'visible');
            $('.press').css('visibility', 'visible');
        });
    }
    

    The above code shows that, when the animation ends, the title reaches the middle of the screen and the subtitle is shown.

    Game Controls

    Image 23Image 24Image 25Image 26Image 27Image 28Image 29Image 30Image 31Image 32

    Image 33

    The game is all controlled by the keyboard. When the game is in Intro mode, you can use the space bar to start a new game. When the game is playing, you use the space bar again if you want to pause the game. And then use the space bar again to resume the game. When the game is over, you push the space bar once again to open the game Intro screen.

    Use the left arrow key and right arrow key to move the falling piece to the left or to the right. Press the up arrow key to rotate the piece 90 degrees. Finally, press the down arrow key to speed up the fall of the piece.

    Key Command
    Space bar Start game / Pause game / Resume game / Restart game
    Left arrow key Move falling piece to the left
    Right arrow key Move falling piece to the right
    Down arrow key Speed up falling piece

    The Game Rules

    Image 34Image 35Image 36Image 37Image 38Image 39Image 40Image 41Image 42Image 43

    You must be very familiar with this kind of game, but I have to explain the game rules anyway.

    Image 44

    Here we have an empty 10 x 16 board, containing 160 empty positions. As soon as the game starts, the game engine will randomly generate one new piece at a time, which will fall from the top of the board, falling at the speed of 1 square per second. When the falling piece find an obstacle (that is, part of another piece that is fixed at the bottom of the board) then it can't fall anymore, so that falling piece gets stuck. Then the game engine will produce new random pieces, and they are piled up until the pile reaches the top of the board, and at this moment the game ends. The user will have to control each falling piece, by moving it to the left, to the right, or rotating it, placing the new piece in the lowest possible empty place in the board where the new piece fits in, in a way to avoid the piled pieces to reach the top of the board. Also, when the user fills any the board rows, these rows are cleared, thus giving some extra space and prolonging the game.

    Image 45 Image 46 Image 47 Image 48
    The "I" shape The "L" shape The "J" shape The "O" shape
    Image 49 Image 50 Image 51
    The "T" shape The "S" shape The "Z" shape

    The game engine can randomly generate any of the above shapes. As we can see, each shape is associated with a letter which resembles it.

    For each cleared line, the user scores a total of 10 multiplied by the game level. That is, each row cleared in the first level will give 10 points. The second level will give 20 points per cleared row, and so on.

    Image 52

    Each level is completed when the user has cleared 10 rows. That is, to reach the 5th level, the user must have cleared 40 rows.

    When the game is over, the game score is compared with the previous high score, and replaces it if there is a new record.

    The Next piece gives the user the opportunity to place the current piece in a way that makes it easier to accomodate the next falling piece.

    Image 53

    Model View Controller

    Image 54Image 55Image 56Image 57Image 58Image 59Image 60Image 61Image 62Image 63

    The beauty of MVC, as I see it, is its adherence to the principle of separation of concerns. Unlike "classic" (non-MVC) ASP.net, you don't put business logic on your views. Instead, you use the views only for presentation logic (such as parsing and rendering of raw data or input validation), and for presentation itself. On the other side, you reserve the Controllers (or another layer, such as Service layer) for your business rules.

    Image 64

    If you look at the javascript in the application, you won't find the business logic. Instead, you'll find out that it is really thin and light. Fortunately, since I already had the Bricks game logic from previous projects, I was able to maintain my managed code almost intact on the server side, and make the view communicate with it through a new ViewModel I designed specifically for this MVC project.

    The Model

    Image 65Image 66Image 67Image 68Image 69Image 70Image 71Image 72Image 73Image 74

    The model is defined by the BoardViewModel and BrickViewModel classes, and contains all information needed by the View to render the game board, the score board and to know whether the game is over or not. As we can see below, most of the properties of BoardViewModel class are native types, except for the Bricks and Next properties, which are 2-dimensional arrays of the BrickViewModel and hold the data for the bricks and empty spaces that forms the current snapshot of the game board and the bricks corresponding to the Next piece that will fall from the top of the game board.

    The low-level BrickViewModel class has informations about each individual brick: row, column and the color name. These values will be used by the View to find the corresponding divs and update their background color accordingly.

    C#
        public class BrickViewModel
        {
            public int Row { get; set; }
            public int Col { get; set; }
            public string Color { get; set; }
        }
    
        public class BoardViewModel
        {
            public BoardViewModel()
            {
                IsGameOver = false;
            }
    
            public BrickViewModel[] Bricks { get; set; }
            public int Score { get; set; }
            public int HiScore { get; set; }
            public int Lines { get; set; }
            public int Level { get; set; }
            public BrickViewModel[] Next { get; set; }
            public bool IsGameOver { get; set; }
        }
    }
    

    The View

    Image 75Image 76Image 77Image 78Image 79Image 80Image 81Image 82Image 83Image 84

    The view really contains no business logic (in our case, no game logic). Here we can see its basic goals:

    • Set up a timer, which calls the Controller every 200 milliseconds to get a ViewModel containing an updated game board snapshot (serialized as JSON).
    • Parse the returned JSON to render the board, score, high score, level and next piece.
    • Set up another timer that calls the Controller every 1000 milliseconds to request a new movement for the falling pieces.
    • Listen to the keyboard events, and calls the Controller to start a new game, to pause of resume the game, to move or rotate the falling piece, or to restart the game.

    This is pretty much what the View does. Notice that, in a traditional (non-MVC) ASP.net application, we would have the code behind class, which would probably hold some business logic. Thanks to MVC, the principle of separation of concerns is maintained, and we can move the business logic away from our View.

    We handle user's gesture by attaching a function to the keydown event of the page document using jQuery syntax:

    JavaScript
    	$(document).keydown(function (event) {
    	switch (event.keyCode) {
    		case 32: //space
    			if (gameState.current_state == 'intro')
    				gameState.process('play');
    			else if (gameState.current_state == 'paused')
    				gameState.process('continue');
    			else if (gameState.current_state == 'gameOver')
    				gameState.process('showIntro');
    			else
    				gameState.process('pause');
    			break;
    		case 37: //left
    			if (gameState.current_state == 'playing')
    				moveLeft();
    			break;
    		case 38: //up
    			if (gameState.current_state == 'playing')
    				moveUp();
    			break;
    		case 39: //right
    			if (gameState.current_state == 'playing')
    				moveRight();
    			break;
    		case 40: //down
    			if (gameState.current_state == 'playing')
    				moveDown();
    			break;
    	}
    });

    The following table shows the events (such as timer ticks or key pressing), the jQuery-like ajax call on the BricksView side and the methods (actions) called on the BricksController side.

    Event / Key The View code The Controller code
            Image 85
            Every 1000 milliseconds
    JavaScript
    $(document).everyTime(1000, function (i) {
    	$.ajax({
    	type: "GET",
    	url: "Tick",
    	cache: false,
    	dataType: "json",
    	error: function (xhr, status, error) {
    		//alert(xhr.status);
    	},
    	success: function (json) {
    	}
    	});
    });
    C#
    public ActionResult Tick()
    {
    	BricksManager.Instance.Presenter.Tick();
    	return new JsonResult() 
    	{ Data = "", 
    	JsonRequestBehavior = 
    	JsonRequestBehavior.AllowGet };
    }
            Image 86
            Every 200 milliseconds
    JavaScript
    $(document).everyTime(200, function (i) {
    if (gameState.current_state == 'playing') {
    
    $.ajax({
    	type: "GET",
    	url: "GetBoard",
    	cache: false,
    	//                    data: {},
    	dataType: "json",
    	error: function (xhr, status, error) {
    		//alert(xhr.status);
    		//alert(error);
    	},
    	success: function (json) {
    		...
    	}
    });
    }
    });
    C#
    public ActionResult GetBoard()
    {
    	return new JsonResult() { Data = 
    	BricksManager.Instance.CurrentBoard, 
    		JsonRequestBehavior = 
    		JsonRequestBehavior.AllowGet };
    }
    Image 87
    JavaScript
    function initializeBoard() {
    $.ajax({
    	type: "GET",
    	url: "InitializeBoard",
    	cache: false,
    	dataType: "json",
    	error: function (xhr, status, error) {
    		alert(xhr.status);
    	},
    	success: function (json) {
    	}
    });
    }
    C#
    public ActionResult InitializeBoard()
    {
    	BricksManager.Instance.InitializeBoard();
    	
    	return new JsonResult() { Data = "", 
    	JsonRequestBehavior = 
    	JsonRequestBehavior.AllowGet };
    }
    Image 88
    JavaScript
    function moveLeft() {
    $.ajax({
    	type: "GET",
    	url: "MoveLeft",
    	cache: false,
    	dataType: "json",
    	error: function (xhr, status, error) {
    		//alert(xhr.status);
    	},
    	success: function (json) {
    	}
    });
    }
    C#
    public ActionResult MoveLeft()
    {
    	BricksManager.Instance.Presenter.MoveLeft();
    	return new JsonResult() { Data = "", 
    	JsonRequestBehavior = 
    	JsonRequestBehavior.AllowGet };
    }
    Image 89
    JavaScript
    function moveRight() {
    $.ajax({
    	type: "GET",
    	url: "MoveRight",
    	cache: false,
    	dataType: "json",
    	error: function (xhr, status, error) {
    	//alert(xhr.status);
    	},
    	success: function (json) {
    	}
    });
    }
    C#
    public ActionResult MoveRight()
    {
    	BricksManager.Instance.Presenter.MoveRight();
    	return new JsonResult() { Data = "", 
    	JsonRequestBehavior = J
    	sonRequestBehavior.AllowGet };
    }
    Image 90
    JavaScript
    function moveDown() {
    $.ajax({
    	type: "GET",
    	url: "MoveDown",
    	cache: false,
    	dataType: "json",
    	error: function (xhr, status, error) {
    		//alert(xhr.status);
    	},
    	success: function (json) {
    	}
    });
    }
    C#
    public ActionResult MoveDown()
    {
    	BricksManager.Instance.Presenter.MoveDown();
    	return new JsonResult() { Data = "", 
    	JsonRequestBehavior = 
    	JsonRequestBehavior.AllowGet };
    }
    Image 91
    JavaScript
    function moveUp() {
    $.ajax({
    	type: "GET",
    	url: "MoveUp",
    	cache: false,
    	dataType: "json",
    	error: function (xhr, status, error) {
    	//alert(xhr.status);
    	},
    	success: function (json) {
    	}
    });
    }
    C#
    public ActionResult MoveUp()
    {
    	BricksManager.Instance.Presenter.Rotate90();
    	return new JsonResult() { Data = "", 
    	JsonRequestBehavior = 
    	JsonRequestBehavior.AllowGet };
    }

    Here goes basically all the html we need for the View. Notice that all elements you see on the game screen are there, except for the bricks:

    HTML
    <body>
        <br />
        <div class="screen">
            <div id="title" class="title">
                <img src="../../Content/images/Title.png" />
                <div class="subTitle">©2011 Marcelo Ricardo de Oliveira<br />
                Made for The Code Project<img src="../../Content/images/Bob.png" class="bob"/></div>
                <br />
                <div class="press">Press SPACE to start game!</div>
            </div>
            <div class="centerPanel">
                <div class="board">
                </div>
                <div class="scorePanel">
                    <div>
                        Score</div>
                        <div id="divScore" class="scoreText">000000</div>
                        <br />
                    <div>
                        HiScore</div>
                        <div id="divHiScore" class="scoreText">000000</div>
                        <br />
                    <div>
                        Lines</div>
                        <div id="divLines" class="scoreText">0</div>
                        <br />
                    <div>
                        Level</div>
                        <div id="divLevel" class="scoreText">0</div>
                        <br />
                    <div>
                        Next</div>
                        <div id="divNext" class="scoreText"></div>
    
                </div>
            </div>
            <div id="gamePaused">
                GAME PAUSED<br />Press SPACE to continue!</div>
            </div>
            <div id="gameOver">
                GAME OVER<br />Press SPACE to restart!</div>
            </div>
        </div>
    </body>
    </html>
    

    This happens because the bricks are divs generated dinamically, when the application starts. Instead of hard-coding this divs into the html, the dinamic generation makes it a lot easier to control how the bricks are generated, how they are rendered and so on.

    Here is the code that generates all the bricks, incluiding the bricks in the "Next" section on the score board. Notice how elegant is the jQuery syntax for appending html to existing html elements:

    JavaScript
    function createCells() {
        for (var row = 0; row < 16; row++) {
            for (var col = 0; col < 10; col++) {
                var divId = 'cell_' + row + '_' + col;
                var imgId = 'img_' + row + '_' + col;
                var divTag = '<div id="' + divId + '" name="brick" class="colorChip clearfix"></div>';
                $(divTag).appendTo('.board');
            }
            $('<div class="clear">').appendTo('.board');
            $('</div>').appendTo('.board');
        }
    
        for (var row = 0; row < 2; row++) {
            for (var col = 0; col < 4; col++) {
                var divId = 'next_' + row + '_' + col;
                var imgId = 'nextImg_' + row + '_' + col;
                var divTag = '<div id="' + divId + '" name="brick" class="colorChip clearfix"></div>';
                $(divTag).appendTo('#divNext');
            }
            $('<div class="clear">').appendTo('#divNext');
            $('</div>').appendTo('#divNext');
        }
    }
    

    One of the most important parts on the BricksView side is the game board rendering. Notice that we don't use images for the bricks; instead, we use the CSS3 Webkit Gradient generator, which works only on CSS3 enabled browsers:

    JavaScript
    $('#divScore').text(json.Score);
    $('#divHiScore').text(json.HiScore);
    $('#divLines').text(json.Lines);
    $('#divLevel').text(json.Level);
    
    $.each(json.Bricks, function (i, val) {
        $('#cell_' + val.Row + '_' + val.Col).css('background-image',
        '-webkit-gradient(linear, left top, right bottom, color-stop(0.0, ' + val.Color + '),
        color-stop(1.0, rgba(0, 0, 0, 0.0)))');
        $('#cell_' + val.Row + '_' + val.Col).css('border-color', val.Color);
    });
    
    for (var row = 0; row < 2; row++) {
        for (var col = 0; col < 4; col++) {
            $('#next_' + row + '_' + col).css('background-image',
            '-webkit-gradient(linear, left top, right bottom, color-stop(0.0, #000), color-stop(1.0, #000))');
            $('#next_' + row + '_' + col).css('border-color', '#333');
        }
    }
    
    $.each(json.Next, function (i, val) {
        $('#next_' + val.Row + '_' + val.Col).css('background-image',
        '-webkit-gradient(linear, left top, right bottom, color-stop(0.0, ' + val.Color + '),
        color-stop(1.0, rgba(0, 0, 0, 0.0)))');
        $('#next_' + val.Row + '_' + val.Col).css('border-color', val.Color);
    });
    

    This is a snapshot of the Json shown by Json viewer. Notice the red bricks represented in Json:

    jsonviewer.png

    And here are the Json data of Score, High Score, Lines and Level information presented in the view:

    jsonviewer2.png

    The Controller

    Image 94Image 95Image 96Image 97Image 98Image 99Image 100Image 101Image 102Image 103

    As we can see below, the Controller is even dumber than the View. Its goal is merely to expose actions that are consumed/called by the view, call the hard-working method on the GameManager side, and return (or not) a JSON-serialized ViewModel.

    C#
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using MVCBricks.Core;
    
    namespace MVCBricks.Controllers
    {
        [System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
        public class BricksController : Controller
        {
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult GetBoard()
            {
                return new JsonResult() { Data = BricksManager.Instance.CurrentBoard, 
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            }
    
            public ActionResult Tick()
            {
                BricksManager.Instance.Presenter.Tick();
                return new JsonResult() { Data = "", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            }
    
            public ActionResult MoveLeft()
            {
                BricksManager.Instance.Presenter.MoveLeft();
                return new JsonResult() { Data = "", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            }
    
            public ActionResult MoveUp()
            {
                BricksManager.Instance.Presenter.Rotate90();
                return new JsonResult() { Data = "", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            }
    
            public ActionResult MoveRight()
            {
                BricksManager.Instance.Presenter.MoveRight();
                return new JsonResult() { Data = "", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            }
    
            public ActionResult MoveDown()
            {
                BricksManager.Instance.Presenter.MoveDown();
                return new JsonResult() { Data = "", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            }
    
            public ActionResult InitializeBoard()
            {
                BricksManager.Instance.InitializeBoard();
                
                return new JsonResult() { Data = "", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            }
        }
    }

    The Finite State Machine

    Image 104

    As you might expect, the game must have a means to control the states, so that you don't have falling pieces before the game has started, or after the game is over. Also, the score shouldn't be displayed while in the Intro mode.

    At first I was using boolean variables on the javascript side to handle the game state (i.e. "isPlaying", "isPaused", "isGameOver", and so on), but this didn't seem elegant nor efficient. So, at the middle of the development I noticed the application had to use a better state management, such as a finite state machine (FSM). So I searched and finally found out a simple, easy-to-use finite state machine for JavaScript, written by Anthony Blackshaw.

    The implementation for Blackshaw's FSM is quite simple. First, you declare a state machine object (in our case, gameState). Then you add transitions to the state machine instance. Each transition defines:

    • FSM.prototype.add_transition = function ( action, state, callback, next_state )

    1. The action name, which is invoked to process the transition.
    2. The initial state the machine must hold for the transition to work.
    3. The callback function which is called when the transition occurs.
    4. The next state to which the state machine is switched at the end of the transition.

    And here is the real implementation:

    JavaScript
    <script type="text/javascript">
    
        //Finite State Machine for JavaScript
        //by Anthony Blackshaw
        //http: //antsdev.wordpress.com/2008/06/18/a-simple-js-finite-state-machine/
    
        var gameState = new FSM("intro");
    
        gameState.add_transition("play", "intro", changeIntroToPlaying, "playing");
        gameState.add_transition("pause", "playing", changePlayingToPaused, "paused");
        gameState.add_transition("continue", "paused", changePausedToPlaying, "playing");
        gameState.add_transition("end", "playing", changePlayingToGameOver, "gameOver");
        gameState.add_transition("showIntro", "gameOver", changeGameOverToIntro, "intro");
    

    Image 105

    The play action hides the subtitle, and animates the top of the title o the position 0 (top of the screen). Besides, both the scorePanel and the boar are made visible thanks to an fade-in effect animation on their opacity css property..

    JavaScript
    function changeIntroToPlaying() {
        initializeBoard();
        $('.subTitle').css('visibility', 'hidden');
        $('.press').css('visibility', 'hidden');
    
        $('.title').animate({
            top: 0
        }, 1000, 'swing', function () {
            // Animation complete.
            $('.scorePanel').animate({
                opacity: 1.0
            }, 1000, 'swing', function () {
                $('.scorePanel').css('visibility', 'visible');
            });
    
            $('.board').animate({
                opacity: 1.0
            }, 1000, 'swing', function () {
                $('.board').css('visibility', 'visible');
            });
        });
    }
    

    Image 106

    The pause action just shows the gamePaused div over the game board.

    JavaScript
    function changePlayingToPaused () {
        $('#gamePaused').css('visibility', 'visible');
    }
    

    The pause itself in the game play happens because the state is switched to "paused" and as we can see below, the controller's action is not called unless the game state machine is on the "playing" state:

    JavaScript
    ...
    $(document).everyTime(200, function (i) {
    
        if (gameState.current_state == 'playing') {
    
            $.ajax({
                type: "GET",
                url: "GetBoard",
    ...
    

    Image 107

    The continue action just hides the gamePaused div over the game board.

    JavaScript
    function changePausedToPlaying() {
        $('#gamePaused').css('visibility', 'hidden');
    }
    

    Since the state is switched back to "playing", the game continues because the controller's action can now be called.

    Image 108

    The end action just shows the gameOver div over the game board, indicating that the pile of bricks reached the top of the board.

    JavaScript
    function changePlayingToGameOver () {
        $('#gameOver').css('visibility', 'visible');
    }
    

    Image 109

    The showIntro action fades-out both the score panel and the game board, and animates the title back to the center of the screen. In addition, the subtitle credits are shown again.

    JavaScript
    function changeGameOverToIntro() {
        $('#gameOver').css('visibility', 'hidden');
    
        $('.scorePanel').animate({
            opacity: 0.0
        }, 1000, 'swing', function () {
            $('.scorePanel').css('visibility', 'hidden');
        });
    
        $('.board').animate({
            opacity: 0.0
        }, 1000, 'swing', function () {
            // Animation complete.
            $('.board').css('visibility', 'hidden');
            $('.title').animate({
                top: 200
            }, 1000, 'swing', function () {
                // Animation complete.
                $('.subTitle').css('visibility', 'visible');
                $('.press').css('visibility', 'visible');
            });
        });
    }
    

    The Game Manager

    Image 110Image 111Image 112Image 113Image 114Image 115Image 116Image 117Image 118Image 119

    The GameManager is a class that holds all methods needed by the BricksController so that the BricksView requests can be communicated to the game engine, and the responses can be sent back to the BricksView.

    C#
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace MVCBricks.Core
    {
        public class GameManager : MVCBricks.Core.IView
        {
            private static GameManager instance = null;
            private static BricksPresenter presenter = null;
            private static BoardViewModel currentBoard = null;
    
            private GameManager()
            {
                currentBoard = new BoardViewModel();
                currentBoard.Bricks = new BrickViewModel[] { };
    
                presenter = new BricksPresenter(this);
                presenter.InitializeBoard();
                presenter.Tick();
            }
    

    When the DisplayScore is called, all the scoreboard data are gathered so that they can be consumed by the view through a single call from the controller.

    C#
    public void DisplayScore(int score, int hiScore, int lines,
    int level, MVCBricks.Core.Shapes.IShape next)
    {
        currentBoard.Score = score;
        currentBoard.HiScore = hiScore;
        currentBoard.Lines = lines;
        currentBoard.Level = level;
        currentBoard.Next = GetBricksArray(next.ShapeArray.GetUpperBound(1) + 1,
        next.ShapeArray.GetUpperBound(0) + 1, next.ShapeArray);
    }
    

    The GetBricksArray method converts both the game board bricks array and the next shape array into a system of colors which the view can understand.

    C#
    private BrickViewModel[] GetBricksArray(int rowCount, int colCount, IBrick[,] array)
    {
        var bricksList = new List<BrickViewModel>();
    
        for (var row = 0; row < rowCount; row++)
        {
            for (var col = 0; col < colCount; col++)
            {
                var b = array[col, row];
                if (b != null)
                {
                    bricksList.Add(new BrickViewModel()
                    {
                        Row = row,
                        Col = col,
                        Color = b.Color.ToString().Replace("Color [", "").Replace("]", "")
                    });
                }
                else
                {
                    bricksList.Add(new BrickViewModel()
                    {
                        Row = row,
                        Col = col,
                        Color = "rgba(0, 0, 0, 1.0)"
                    });
                }
            }
        }
        return bricksList.ToArray();
    }
    

    Final Considerations

    Image 120Image 121Image 122Image 123Image 124Image 125Image 126Image 127Image 128Image 129

    Thanks a lot for reading my MVC Bricks article. I hope it may be useful for you in some way, either by the MVC concepts covered here, or the jQuery syntax which makes the javascript section thin and elegant, or even because the fun of the game itself. Feel free to comment below. Please share your ideas, complaints, advices so the next articles will get better and better.

    History

    • 2011-04-23: Initial version.
    • 2011-04-29: Images corrected. 
    • 2011-05-03: Json viewer images attached. 
    • 2011-05-05: Game Manager explained.

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


    Written By
    Instructor / Trainer Alura Cursos Online
    Brazil Brazil

    Comments and Discussions

     
    GeneralParabéns! Pin
    georani31-May-11 2:42
    georani31-May-11 2:42 
    GeneralRe: Parabéns! Pin
    Marcelo Ricardo de Oliveira31-May-11 4:30
    mvaMarcelo Ricardo de Oliveira31-May-11 4:30 
    GeneralRe: Parabéns! Pin
    georani31-May-11 6:14
    georani31-May-11 6:14 
    GeneralCongratulation Pin
    ambarishtv30-May-11 23:09
    ambarishtv30-May-11 23:09 
    GeneralRe: Congratulation Pin
    Marcelo Ricardo de Oliveira31-May-11 4:25
    mvaMarcelo Ricardo de Oliveira31-May-11 4:25 
    GeneralGot my 5 Pin
    Mike Hankey30-May-11 14:57
    mveMike Hankey30-May-11 14:57 
    GeneralRe: Got my 5 Pin
    Marcelo Ricardo de Oliveira30-May-11 15:00
    mvaMarcelo Ricardo de Oliveira30-May-11 15:00 
    GeneralMy vote of 5 Pin
    Wild-Programmer22-May-11 22:27
    Wild-Programmer22-May-11 22:27 
    I love Bricks game. Thanks for sharing this great article.
    GeneralRe: My vote of 5 Pin
    Marcelo Ricardo de Oliveira23-May-11 3:39
    mvaMarcelo Ricardo de Oliveira23-May-11 3:39 
    GeneralMy vote of 5 Pin
    Dr.Luiji13-May-11 10:30
    professionalDr.Luiji13-May-11 10:30 
    GeneralRe: My vote of 5 Pin
    Marcelo Ricardo de Oliveira13-May-11 11:54
    mvaMarcelo Ricardo de Oliveira13-May-11 11:54 
    GeneralMy vote of 5 Pin
    asheesh goja12-May-11 13:54
    asheesh goja12-May-11 13:54 
    GeneralRe: My vote of 5 Pin
    Marcelo Ricardo de Oliveira12-May-11 16:16
    mvaMarcelo Ricardo de Oliveira12-May-11 16:16 
    GeneralExcellent work! Pin
    Naveen Karamchetti11-May-11 8:21
    professionalNaveen Karamchetti11-May-11 8:21 
    GeneralRe: Excellent work! Pin
    Marcelo Ricardo de Oliveira12-May-11 7:06
    mvaMarcelo Ricardo de Oliveira12-May-11 7:06 
    GeneralRe: Excellent work! Pin
    Marcelo Ricardo de Oliveira13-May-11 6:33
    mvaMarcelo Ricardo de Oliveira13-May-11 6:33 
    GeneralMy vote of 5 Pin
    Naveen Karamchetti11-May-11 8:20
    professionalNaveen Karamchetti11-May-11 8:20 
    GeneralMy vote of 5 Pin
    Yasser Azeem11-May-11 2:27
    Yasser Azeem11-May-11 2:27 
    GeneralRe: My vote of 5 Pin
    Marcelo Ricardo de Oliveira11-May-11 2:54
    mvaMarcelo Ricardo de Oliveira11-May-11 2:54 
    GeneralMy vote of 5 Pin
    Abhijit Jana10-May-11 22:31
    professionalAbhijit Jana10-May-11 22:31 
    GeneralRe: My vote of 5 Pin
    Marcelo Ricardo de Oliveira11-May-11 2:54
    mvaMarcelo Ricardo de Oliveira11-May-11 2:54 
    GeneralMy vote of 5 Pin
    Bourlesque10-May-11 2:35
    Bourlesque10-May-11 2:35 
    GeneralRe: My vote of 5 Pin
    Marcelo Ricardo de Oliveira10-May-11 2:48
    mvaMarcelo Ricardo de Oliveira10-May-11 2:48 
    GeneralMy vote of 5 Pin
    Rhuros4-May-11 21:57
    professionalRhuros4-May-11 21:57 
    GeneralRe: My vote of 5 Pin
    Marcelo Ricardo de Oliveira5-May-11 3:29
    mvaMarcelo Ricardo de Oliveira5-May-11 3:29 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.