Giter Club home page Giter Club logo

freshplanet's Introduction

This is a minesweeper game I'm coding using Symfony and PHP.

Time spent for now:

 * Symfony installation: 2 hours
 * Initial game design: 1 hour
 * Yaml schema design: 2 hours
 * Symfony understanding and application building: 5 hours
 * Basic authentification system: 3 hours
 * Hiscore saving/listings: 3 hours
 * Class modeling + UT/TDD: 2 hours
 * CSS tweaking: 1 hour
 * Board display: 3 hour
 * Ajax+JSON: 8 hours
 * Optimizations: 4 hours

 Total: 34 hours

Suppositions:

 * There can be 1 million users and 1 billion hiscores for a start
 * A user can only play one game at a time
 * A minesweeper game board is squared

Rules:

 * A player loose when he clicks a mined square
 * A player wins when he uncover the last empty square and flag all the mines

Constants:

 * Minimum width of a board: 5
 * Maximum width of a board: 50
 * Percentage of mines: 10

Data structures:

 * Users
 	 * id (PK)
 	 * Email (VARCHAR(255) NOT NULL)
	 * Firstname (VARCHAR(255) NOT NULL)
	 * Lastname (VARCHAR(255) NOT NULL)
	 * created_at (DATETIME NOT NULL)
	 * updated_at (DATETIME NOT NULL)
	 * Current game (BLOB)
	 	 * BLOB board consisting of squares of 3 bits each
		 	 * 1st bit: SQUARE_MINED (1) or SQUARE_EMPTY (0)
			 * 2nd and 3rd bit
			 	 * USER_UNTOUCHED (00)
				 * USER_FLAGGED (01)
				 * USER_QUESTIONED (10)
				 * USER_REVEALED (11)
	 * Game start time (DATETIME)

 * Hiscores
 	 * id (PK)
 	 * user_id (FK Users.id)
	 * Time (Time spent in seconds to win the game) (INT NOT NULL)
	 * Boardwidth (width of the board played and won) (BYTE NOT NULL)
	 * created_at (when the hiscore occured) (DATETIME NOT NULL)

Indexes:

 * On User.Email: needed to look for a specific user at login
 * On User.created_at: needed to list the latest users (for admin purpose)
 * On Hiscores.user_id: used for the join between Users and Hiscores
 * On Hiscores.boardwidth and Hiscores.time: used to get the hiscores with the same board size from best to worst
 * On Hiscores.created_at: used to get the latest hiscores (for admin purpose)

Data structure of the board game:
 * A game board is a list of 3 bits long values
 * A game board is stored as a binary string in the database
 * Each byte of the binary string contains 2 tiles: 0AAA0BBB, AAA being the 3 bits of the first tile and BBB the 3 bits of the second
 * If the number of tiles of a gameboard is odd, the last tile value is prefixed with a 1. eg. 0AAA1000 (we don't care about the tile value as it does not exist)
 * The game board binary string is inflated (compressed) before being saved in the database
 * All this leads to less space used in the database for the gameboard. As we won't ever need to query and index the tiles individually, we are ok with that.

Choices:

 * As a user can only play 1 game at a time, I chose to not make a separate table for the user's game board in order to save the JOIN cost between the User table and the supposed game table

Application/modules/actions:

 * frontend
   * user
   * game
   * hiscore
   * json
 * backend
   * admin

Data exchanged with JSON:

The frontend/game module of the application will make requests to the frontend/json application using HTTP requests.
The frontend/json module will update the game data and send back the data to the frontend/game module with JSON.

The possible actions will be the requests:
 * clickTile?offset=123 - discover a tile and get every tile state that was changed by this action
 * flagTile?offset=456 - flag or unflag an undiscovered tile and get its new state
 * questionTile?offset=789 - question or unquestion an undiscovered tile and get its new state

An example of full game board sent back with JSON (never really used):
{
				"result": 0, // Result code depending on the effect of the last action: Boom, Won, Discovered, ...
				"board": [
								 {"offset": 0, "state": 1},
								 {"offset": 1, "state": 1},
								 {"offset": 2, "state": 1},
								 {"offset": 3, "state": 3},
								 {"offset": 4, "state": 4},
								 {"offset": 5, "state": 1},
								 					[...]
								 {"offset": 97, "state": 1},
								 {"offset": 98, "state": 0},
								 {"offset": 99, "state": 1}
				]
}


An exemple of some squares updated sent back using JSON:
{
				"result": 3, // Result code depending on the effect of the last action: Boom, Won, Discovered, ...
				"board": [
								 {"offset": 53, "state": 1},
								 {"offset": 62, "state": 1},
								 {"offset": 63, "state": 1},
								 {"offset": 64, "state": 1},
								 {"offset": 73, "state": 1},
								 {"offset": 83, "state": 1}
				]
}

In production, in the JSON message we prefer to use the following shorter names:
 * result: r
 * board: b
 * offset: o
 * state: s

Possible memcache usage:

 * Build a hash list of users for keeping gameboards (example: set user_12345 $data) and 'unsaved_X' keys for keeping a list of unsaved users, by using the append command. X is used to split the lists because of the 1MB memcached limit for a key. X being saved in the max_x key, which is incremeted with the inc command at each split.
 * When saving a game (at each user interaction), save the game in the gameboard list, and push the user_id in the unsaved user list if it's not there already (no need to check it in memcache, we'll just unique the list when we'll use it)
 * When reading a game, read it from memcache, and if it's not there, read it from the DB and save it to memcache
 * Asynchronically (cron), unique the unsaved_X lists. For each user in the uniqued unsaved user list from memcache, save their memcache gameboard in the DB, then remove the user from the unsaved list.

freshplanet's People

Contributors

lra avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.