
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдЪрд░рдг рджрд░ рдЪрд░рдг рд╕рдордЭрд╛рдКрдВрдЧрд╛ рдХрд┐ рдПрдЪрдЯреАрдПрдордПрд▓ 5 рдХреИрдирд╡рд╕, рдПрдЯрдореЙрдЬ рдФрд░ рд▓рд┐рдмреНрдХрдирд╡рд╛рд╕ рдЯрд╛рдЗрд▓ рдЗрдВрдЬрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рд╕рдмрд╕реЗ рд╕рд╛рдзрд╛рд░рдг, рдХреНрд▓рд╛рд╕рд┐рдХ рд╕реИрдкрд░ рдХреИрд╕реЗ рд▓рд┐рдЦреЗрдВред
рдФрд░ рдирд┐рд░рдВрддрд░рддрд╛ рднреА рджреЗрдЦреЗрдВ - "
LibCanvas (html5) рдкрд░ рдЖрдЗрд╕реЛрдореЗрдЯреНрд░рд┐рдХ рд╕реИрдкрд░ "
рд╣рдо рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдХреЗ "рдкреНрд░рд╛рд░рдВрдн" рдХреЗ рд▓рд┐рдП рдорд╛рдирдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рд╕рдВрдмрдВрдзрд┐рдд рдХрдХреНрд╖рд╛рдУрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж js рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдирд╛ рди рднреВрд▓реЗрдВред
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>LibCanvas :: Mines</title> <link href="/files/styles.css" rel="stylesheet" /> <script src="/files/js/atom.js"></script> <script src="/files/js/libcanvas.js"></script> </head> <body> <p><a href="/">Return to index</a></p> <script> new function () { LibCanvas.extract(); atom.dom(function () { new Mines.Controller(); }); }; </script> <script src="js/controller.js"></script> </body> </html>
рдореИрдВрдиреЗ рджреЛ рддрд╕реНрд╡реАрд░реЗрдВ рдЦреАрдВрдЪреАрдВ - рдЦрджрд╛рдиреЗрдВ рдФрд░ рдПрдХ рдЭрдВрдбрд╛ред рдмрд╛рдХреА рд╕рдм рдХреБрдЫ рд╣рдо рд╕реАрдзреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ "рдореИрдиреНрдпреБрдЕрд▓" рдХрд░реЗрдВрдЧреЗред рдЖрд╡реЗрджрди рд╢реБрд░реВ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдХрдо рдХрд░рдиреЗ рдФрд░ рдкреНрд░реАрд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕реНрдкреНрд░рд╛рдЗрдЯ рдореЗрдВ рдорд┐рд▓рд╛рдпрд╛ред рдХреЛрдб рдореЗрдВ, рдЖрдк
atom.ImagePreloader рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрд▓рд╛рдЗрд╕рд┐рдВрдЧ рднреА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:
atom.declare( 'Mines.Controller', { initialize: function () { atom.ImagePreloader.run({ flag: 'flag-mine.png [48:48]{0:0}', mine: 'flag-mine.png [48:48]{1:0}' }, this.start.bind(this) ); }, start: function (images) { this.images = images; } });
рдбреНрд░рд╛рдЗрдВрдЧ
рдореБрдЭреЗ рдиреЗрддреНрд░рд╣реАрди рджреЗрдЦрдирд╛ рдкрд╕рдВрдж рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдЖ рд░рд╣рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╣реА рддрд░реНрдХ рдкрд░ рдЖрдЧреЗ рдмрдврд╝рддрд╛ рд╣реВрдВред рд╣рдорд╛рд░реЗ рдХреЛрдб рдХреЛ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо
LibCanvas.Engines.Tile
рдЙрдкрдпреЛрдЧ
LibCanvas.Engines.Tile
ред
View
рдХреНрд▓рд╛рд╕ рдЬреЛрдбрд╝реЗрдВ, рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдЕрдкрдирд╛ рдЗрдВрдЬрди рдмрдирд╛рдПрдВрдЧреЗред рд╣рдореЗрдВ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдФрд░
TileEngine.Element.app
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрдВрдЬрди рдХреЛ рдмрд╛рдВрдзрдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рдПрдХ рдмрдВрдж рд╕реЗрд▓ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдЧрд╛ред рд╣рдорд╛рд░реЗ рдХрдВрдЯреНрд░реЛрд▓рд░ рдореЗрдВ рдпрд╣
View
рдмрдирд╛рдирд╛ рди рднреВрд▓реЗрдВред
atom.declare( 'Mines.View', { initialize: function (controller, fieldSize) { this.images = controller.images; this.engine = new TileEngine({ size: fieldSize, cellSize: new Size(24, 24), cellMargin: new Size(0, 0), defaultValue: 'closed' }) .setMethod( this.createMethods() ); this.app = new App({ size : this.engine.countSize(), simple: true }); this.element = TileEngine.Element.app( this.app, this.engine ); },
/** @class Mines.Controller */ // ... start: function (images) { this.images = images; this.view = new Mines.View( this, new Size(15,8) ); }
рдЗрд╕ рдХреЛрдб рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рд╕рдордп рд▓реЗрдВ, рд╣рдордиреЗ рдЕрднреА рддрдХ
View
рдХреНрд▓рд╛рд╕ рдХреА
createMethods
рд╡рд┐рдзрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред рдЖрдЗрдП рддрдп рдХрд░реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреА рд╕реЗрд▓ рдЕрд╡рд╕реНрдерд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред
рдЦреЗрд▓ рдХреЗ рджреМрд░рд╛рди, рд╣рдо рдЗрд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:
1. рдирдВрдмрд░ 1 рд╕реЗ 8 рддрдХред
2. рдмрдВрдж рд╕реЗрд▓
3. рдПрдХ рдЦреБрд▓реА рд▓реЗрдХрд┐рди рдЦрд╛рд▓реА рд╕реЗрд▓
4. рдЪреЗрдХ рдмреЙрдХреНрд╕
рдЗрд╕рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж - рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд:
1. рд╕рднреА рдЦрд╛рдиреЛрдВ
2. рдпрджрд┐ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдкрд░ рдЙрдбрд╝рд╛ - рдпрд╣ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ
3. рдЕрдЧрд░ рдХрд╣реАрдВ рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рдЭрдВрдбрд╛ рд▓рдЧрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ
рдХреБрд▓, 8 + 3 + 3 = 14 рд╡рд┐рднрд┐рдиреНрди рд░рд╛рдЬреНрдпред рд╣рдо рдЙрди рд╕рднреА рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВрдЧреЗ:
/** @class Mines.View */ // ... createMethods: function () { return { 1: this.number.bind(this, 1), 2: this.number.bind(this, 2), 3: this.number.bind(this, 3), 4: this.number.bind(this, 4), 5: this.number.bind(this, 5), 6: this.number.bind(this, 6), 7: this.number.bind(this, 7), 8: this.number.bind(this, 8), explode : this.explode.bind(this), closed : this.closed .bind(this), mine : this.mine .bind(this), flag : this.flag .bind(this), empty : this.empty .bind(this), wrong : this.wrong .bind(this) }; },
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдо рдЙрдЪрд┐рдд
View
рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВрдЧреЗ, рдЙрдиреНрд╣реЗрдВ рд╡рд░реНрддрдорд╛рди рд╕рдВрджрд░реНрдн рдореЗрдВ рд╕рдВрд▓рдЧреНрди рдХрд░реЗрдВрдЧреЗред рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╣рдореЗрдВ рдХреНрдпрд╛ рдорд┐рд▓рддрд╛ рд╣реИ, рдЖрдкрдХреЛ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдЙрдкрдпреБрдХреНрдд рд╕реЗрд▓ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
/** @class Mines.Controller */ // ... start: function (images) { // ... // todo: remove after debug '1 2 3 4 5 6 7 8 empty mine flag explode wrong closed' .split(' ') .forEach(function (name, i) { this.view.engine .getCellByIndex(new Point(i, 3)) .value = name; }.bind(this));
рд╣рдордиреЗ рд╕рд┐рд░реНрдл рд╕рднреА рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреЛ рд▓рд┐рдпрд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЗ рдмрджрд▓реЗ рдореЗрдВ рд╕реМрдВрдкрд╛ред рдЕрдм рдбреНрд░рд╛рдЗрдВрдЧред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдзрд┐ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рдЖрд╡рд╢реНрдпрдХ рд░рдВрдЧ рдХреЗ рд╕рд╛рде рд╕реЗрд▓ рдХреЛ рднрд░реЗрдВ рдФрд░ рд╕рд░реНрдХрд▓ рдХрд░реЗрдВред рдпрджрд┐ рдкреВрд░реНрдгрд╛рдВрдХ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдореЗрдВ 1 рдкрд┐рдХреНрд╕реЗрд▓ рдХреА рдЪреМрдбрд╝рд╛рдИ рд╡рд╛рд▓реА рдПрдХ рд░реЗрдЦрд╛ рдЦреАрдВрдЪреА рдЬрд╛рдПрдЧреА - рддреЛ рдпрд╣ рдкрд▓рдХ
рдЭрдкрдХреЗрдВрдЧреА (рджреЗрдЦреЗрдВ htmlbook.ru/html5/canvas , рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ "Q. рд╣рдо x рдФрд░ yc 0.5 рдХреНрдпреЛрдВ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ 0 рдХреЗ рд╕рд╛рде рдирд╣реАрдВ?") , рдЗрд╕рд▓рд┐рдП рд╣рдо рдкреНрд░рд╛рдпреЛрдЧрд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ
? snapToPixel
рдЖрдпрдд
snapToPixel
/** @class Mines.View */ // ... color: function (ctx, cell, fillStyle, strokeStyle) { var strokeRect = cell.rectangle.clone().snapToPixel(); return ctx .fill( cell.rectangle, fillStyle) .stroke( strokeRect, strokeStyle ); },
рдЕрдм рд╣рдо рдмрджрд▓реЗ рдореЗрдВ рд░реЗрдВрдбрд░рд┐рдВрдЧ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдЦрд╛рд▓реА рд╕реЗрд▓ - рдмрд╕ рдкреЗрдВрдЯ:
/** @class Mines.View */ // ... empty: function (ctx, cell) { return this.color(ctx, cell, '#999', '#aaa'); },
рдореЗрд░рд╛ рдФрд░ рдЭрдВрдбрд╛ рдПрдХ рдЦрд╛рд▓реА рд╕реЗрд▓ рдкрд░ рд╕рд┐рд░реНрдл рдЪрд┐рддреНрд░ рд╣реИрдВ:
/** @class Mines.View */ // ... mine: function (ctx, cell) { return this .empty(ctx, cell) .drawImage( this.images.get('mine'), cell.rectangle ); }, flag: function (ctx, cell) { return this .empty(ctx, cell) .drawImage( this.images.get('flag'), cell.rectangle ); },
рдореАрдирд╛, рдЬрд┐рд╕ рдкрд░ рд╣рдордиреЗ рд╡рд┐рд╕реНрдлреЛрдЯ рдХрд┐рдпрд╛ рдерд╛, рдПрдХ рд▓рд╛рд▓ рдкреГрд╖реНрдарднреВрдорд┐ рдХреЗ рд╕рд╛рде рдЦреАрдВрдЪреА рдЧрдИ рд╣реИ:
/** @class Mines.View */ // ... explode: function (ctx, cell) { return this .color(ctx, cell, '#c00', '#aaa') .drawImage( this.images.get('mine'), cell.rectangle ); },
рдЧрд▓рдд рдЭрдВрдбрд╛ рд╕реЗрдЯ - рд▓рд╛рд▓ рдХреНрд░реЙрд╕ред рдЗрд╕реЗ рдЦреАрдВрдЪрдирд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо
clip
рд╕рд╛рде рдЕрдкрдиреЗ рдЖрдпрдд рдХреЗ рднреАрддрд░ рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЛ рд╕реАрдорд┐рдд рдХрд░рддреЗ рд╣реИрдВред
рдЗрд╕реЗ рдкреГрд╖реНрдарднреВрдорд┐ рдХреЗ рд╕рд╛рде рднрд░реЗрдВ, рдФрд░ рдлрд┐рд░ рджреЛ рд▓рд╛рд▓ рд░реЗрдЦрд╛рдПрдВ рдЦреАрдВрдЪреЗрдВ - рдКрдкрд░реА-рдмрд╛рдПрдВ рд╕реЗ рдирд┐рдЪрд▓реЗ-рджрд╛рдПрдВ рдФрд░ рдирд┐рдЪрд▓реЗ-рдмрд╛рдПрдВ рдХреЛрдиреЗ рд╕реЗ рдКрдкрд░реА-рджрд╛рдПрдВ рддрдХред
/** @class Mines.View */ // ... wrong: function (ctx, cell) { var r = cell.rectangle; return this.empty(ctx, cell) .save() .clip( r ) .set({ lineWidth: Math.round(cell.rectangle.width / 8) }) .stroke( new Line( r.from , r.to ), '#900' ) .stroke( new Line( r.bottomLeft, r.topRight ), '#900' ) .restore(); },
рдПрдХ рдмрдВрдж рд╕реЗрд▓ рднреА рдХрд╛рдлреА рд╕рд░рд▓рддрд╛ рд╕реЗ рдЦреАрдВрдЪреА рдЧрдИ рд╣реИ - рдЕрдВрдзреЗрд░реЗ рд╕реЗ рдкреНрд░рдХрд╛рд╢ рддрдХ, рдврд╛рд▓ рдХреЗ рдКрдкрд░-рдмрд╛рдПрдВ рдХреЛрдиреЗ рд╕реЗ рдиреАрдЪреЗ-рджрд╛рдПрдВ рддрдХред
/** @class Mines.View */ // ... closed: function (ctx, cell) { return ctx.fill( cell.rectangle, ctx.createGradient(cell.rectangle, { 0: '#eee', 1: '#aaa' }) ); },
рдФрд░, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдВрдЦреНрдпрд╛ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЕрдВрдХ рдХреЗ рд▓рд┐рдП рд░рдВрдЧреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдЬреЛрдбрд╝реЗрдВред рдХреЛрдИ рд╢реВрдиреНрдп рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рд╢реВрдиреНрдп рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрд╣рд▓рд╛ рддрд░реНрдХ
number
ред рдпрд╣ рд╡рд╣ рдерд╛ рдЬреЛ рд╣рдо
createMethods
рд╡рд┐рдзрд┐ рдореЗрдВ
createMethods
ред
рдЙрд╕рдХреЗ рдмрд╛рдж рд╣рдо рд╕реЗрд▓ рдХреЛ рдЦрд╛рд▓реА рдХреЗ рд░реВрдк рдореЗрдВ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рд╢реАрд░реНрд╖ рдкрд░, рдкрд╛рда рдореЗрдВ, рдПрдХ рд╕рдВрдЦреНрдпрд╛ рд▓рд┐рдЦрддреЗ рд╣реИрдВред
/** @class Mines.View */ // ... numberColors: [null, '#009', '#060', '#550', '#808', '#900', '#555', '#055', '#000' ], number: function (number, ctx, cell) { var size = Math.round(cell.rectangle.height * 0.8); return this.empty(ctx, cell) .text({ text : number, color : this.numberColors[number], size : size, lineHeight: size, weight: 'bold', align : 'center', to : cell.rectangle }); }
рд╣рдорд╛рд░рд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣рдореЗрдВ рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХрд╛ рдЖрдХрд╛рд░ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдФрд░ рд╡реЗ рд╡реИрд╕реЗ рднреА рдмрд╣реБрдд рдЕрдЪреНрдЫреЗ рджрд┐рдЦреЗрдВрдЧреЗ:

рдиреНрдпреВрдирддрдо рдЬрдирд░реЗрдЯрд░
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдкреНрд░рддрд┐рдкрд╛рджрди рдкреВрд░реА рддрд░рд╣ рд╕реЗ рддреИрдпрд╛рд░ рд╣реИред рдЕрдм рд╣рдореЗрдВ рдмрд╕ рдПрдХ рд╕рд░рд▓ рдХреНрд░рд┐рдпрд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рд╕реЗрд▓ рдЕрдкрдирд╛ рд╕реНрд╡рд░реВрдк рдмрджрд▓ рджреЗрдЧрд╛ред
рд╣рдорд╛рд░рд╛ рдбрд┐рдмрдЧ рдХреЛрдб рд╣рдЯрд╛рдПрдВ рдФрд░ рдЬрдирд░реЗрдЯрд░ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдПрдВ:
// .. start: function (images) { this.images = images; this.size = new Size(15, 8); this.mines = 20; this.view = new Mines.View( this, this.size ); this.generator = new Mines.Generator( this.size, this.mines ); }
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдХреНрд╖реЗрддреНрд░ рднрд░ рдореЗрдВ рдЦрд╛рдиреЛрдВ рдХреЛ рдмрд┐рдЦреЗрд░рдирд╛ рд╕реАрдЦреЗрдВред рдмреЗрд╢рдХ, рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдВрджрд┐рдЧреНрдз рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рд╣рдореЗрдВ рдЙрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдкрд╣рд▓реЗ рдХреНрд▓рд┐рдХ рдХреЗ рдмрд╛рдж рдПрдХ рдХреНрд╖реЗрддреНрд░ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рддрд╛рдХрд┐ рд╡рд╣ рддреБрд░рдВрдд рдПрдХ рдЦрджрд╛рди рдореЗрдВ рди рдЖрдПред

рдореЗрд░рд╛ рдкреАрдврд╝реА рдХрд╛ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдмрд╣реБрдд рд╕рд░рд▓ рд╣реЛрдЧрд╛ - рдорд╛рдиреНрдп рдмрд┐рдВрджреБрдУрдВ рдХреА рд╕реВрдЪреА рдмрдирд╛рдПрдВ (рдЬрд┐рд╕ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдЙрд╕реЗ рдЫреЛрдбрд╝рдХрд░ рд╕рдм рдХреБрдЫ) -
snapshot
рд╡рд┐рдзрд┐, рдЙрд╕рдХреЗ рдмрд╛рдж рд╣рдо рдЙрдирдореЗрдВ рд╕реЗ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреА рдЖрд╡рд╢реНрдпрдХ рд╕рдВрдЦреНрдпрд╛ -
createMines
рд╡рд┐рдзрд┐:
atom.declare( 'Mines.Generator', { mines: null, initialize: function (fieldSize, minesCount) { this.fieldSize = fieldSize; this.minesCount = minesCount; }, snapshot: function (ignore) { var x, y, point, result = [], size = this.fieldSize; for (y = size.height; y--;) for (x = size.width; x--;) { point = new Point(x, y); if (!point.equals(ignore)) { result.push(point); } } return result; }, createMines: function (count, ignore) { var snapshot = this.snapshot( ignore ); return atom.array.create(count, function () { return snapshot.popRandom(); }); } });
рдЕрдЧрд▓рд╛ рдЪрд░рдг рдПрдХ рдПрдкрд┐ рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝рдирд╛ рд╣реИ рдЬреЛ рдЗрди рдЦрд╛рдиреЛрдВ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдФрд░ рддреНрд╡рд░рд┐рдд рдкрд╣реБрдВрдЪ рдХреЗ рд▓рд┐рдП рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рджрд░реНрдЬ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред 1 рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рджреЛ рдЖрдпрд╛рдореА рд╣реИрд╢ рдмрдирд╛рдПрдВ, рдЬрд╣рд╛рдВ рдПрдХ рдЦрджрд╛рди рдФрд░ 0 рд╣реИ, рдЬрд╣рд╛рдВ рдХреЛрдИ рдЦрджрд╛рдиреЗрдВ рдирд╣реАрдВ рд╣реИрдВред рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЗрдВрдЯреЗрдЧрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдЗрд╕рдХрд╛ рдХрд╛рд░рдг рд╣рдо рдиреАрдЪреЗ рджреЗрдЦреЗрдВрдЧреЗред рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдПрдХ рддреНрд╡рд░рд┐рдд рд╡рд┐рдзрд┐ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╕рдордиреНрд╡рдп рджреНрд╡рд╛рд░рд╛ рдПрдХ рдЦрджрд╛рди рд╣реИред рдпрджрд┐ рдХреЛрдИ рдорд╛рдЗрдирдлрд╝реАрд▓реНрдб рдкрд╣рд▓реЗ рд╣реА рдЬреЗрдирд░реЗрдЯ рд╣реЛ рдЧрдпрд╛ рд╣реЛ, рддреЛ рдмрд╛рд╣рд░реА рд╡рд░реНрдЧреЛрдВ рдХреЛ рдмрддрд╛рдиреЗ рдХреЗ рд▓рд┐рдП
isReady
рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
/** @class Mines.Generator */ // .. isReady: function () { return this.mines != null; }, isMine: function (point) { return this.mines[point.y][point.x]; }, generate: function (ignore) { var mines, minesIndex, size = this.fieldSize; mines = this.createMines(this.minesCount, ignore); minesIndex = atom.array.fillMatrix(size.width, size.height, 0); mines.forEach(function (point) { minesIndex[point.y][point.x] = 1; }); this.mines = minesIndex; },
рдЕрдЧрд▓рд╛ рдХрджрдо рд╕реЗрд▓ рдХреА рд╡реИрд▓реНрдпреВ рд╣реИ рдЕрдЧрд░ рдореЗрд░рд╛ рдирд╣реАрдВ рд╣реИред рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ - рд╣рдо рд╕рднреА рдкрдбрд╝реЛрд╕рд┐рдпреЛрдВ рдХреЛ рд▓реЗрддреЗ рд╣реИрдВ рдЬреЛ рдХреНрд╖реЗрддреНрд░ рд╕реЗ рдкрд░реЗ рдирд╣реАрдВ рдЬрд╛рддреЗ рд╣реИрдВ, рд╣рдо рдЙрдирдХреЗ рдореВрд▓реНрдпреЛрдВ рдХрд╛ рдпреЛрдЧ рдорд╛рдирддреЗ рд╣реИрдВред рдпрд╣ рдЗрд╕ рдЬрдЧрд╣ рдореЗрдВ рд╣реИ рдХрд┐ рдореЗрд░рд╛ рдПрдХ рдЗрдВрдЯрдЬрд░ рд╣реИ рдФрд░ рдпрд╣ рдХрд╛рдо рдЖрдпрд╛ред
// .. initialize: function (fieldSize, minesCount) { // , this.bindMethods([ 'isValidPoint', 'isMine' ]); // .. getValue: function (point) { // return this.getNeighbours(point) // (1 0) .map(this.isMine) // .sum(); }, // , isValidPoint: function (point) { return point.x >= 0 && point.y >= 0 && point.x < this.fieldSize.width && point.y < this.fieldSize.height; }, // - , , getNeighbours: function (point) { return point.neighbours.filter( this.isValidPoint ); },
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рд╣рднрд╛рдЧрд┐рддрд╛
рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЧреЗрдо рдЗрдВрдЬрди рд╣реИ, рдЕрдм рд╣рдореЗрдВ рдПрдХ рдЧреЗрдо рдХреЗ рд╕рд╛рде рдпрд╣ рд╕рдм рдХрд░рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ, рди рдХрд┐ рдХреЗрд╡рд▓ рддрд░реНрдХред рд╣рдо рдПрдХ
Action
рдХреНрд▓рд╛рд╕ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬреЛ рд╕рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛ред рдкрд╣рд▓реА рдЪреАрдЬ рдЬреЛ рд╣рдо рдХрд░реЗрдВрдЧреЗ рд╡рд╣ рд╣реИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рдХреНрд▓рд┐рдХ рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ред
TileEngine.Mouse
рд╕рд╛рде
TileEngine.Mouse
рд╣рдо рдХреНрд╖реЗрддреНрд░ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдорд╛рдЙрд╕ рдШрдЯрдирд╛рдУрдВ рдХреЛ рд╕реБрдиреЗрдВрдЧреЗред рд╣рдо
Mouse.prevent
рдХреЛ
'contextmenu'
Mouse.prevent
'contextmenu'
рдИрд╡реЗрдВрдЯ рдкрд░
Mouse.prevent
рддрд╛рдХрд┐ рдХрд╖реНрдЯрдкреНрд░рдж рдореЗрдиреВ рдкреЙрдк рди рд╣реЛред рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╕рдордп, рд╣рдо рдмрдЯрди рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВред рдмрд╛рдпрд╛рдБ рдорд╛рдЙрд╕ рдмрдЯрди 0 рд╣реИ, рдордзреНрдп рд╡рд╛рд▓рд╛ 1 рд╣реИ, рджрд╛рдпреЗрдВ рд╡рд╛рд▓рд╛ 2 рд╣реИред рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдореВрд▓ рдЦреЗрд▓ рдореЗрдВ, рдПрдХ рдмрд╛рдПрдБ рдХреНрд▓рд┐рдХ рдХрд╛ рдорддрд▓рдм рдПрдХ рд╕реЗрд▓ рдЦреЛрд▓рдирд╛ рд╣реИ, рдПрдХ рдордзреНрдп рдЪреАрдЦ рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЙрди рд╕рднреА рдХреЛ рдЦреЛрд▓рдирд╛, рдФрд░ рдПрдХ рд░рд╛рдЗрдЯ рдХреНрд▓рд┐рдХ рдХрд╛ рдЕрд░реНрде рд╣реИ рдПрдХ рдЦрджрд╛рди рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ред
// .. start: function (images) { // .. this.action = new Mines.Action(this); }
atom.declare( 'Mines.Action', { actions: [ 'open', 'all', 'close' ], initialize: function (controller) { this.controller = controller; this.bindMouse(); }, bindMouse: function () { var view, mouse; view = this.controller.view; mouse = new Mouse(view.app.container.bounds); new App.MouseHandler({ mouse: mouse, app: view.app }) .subscribe( view.element ); mouse.events.add( 'contextmenu', Mouse.prevent ); new TileEngine.Mouse( view.element, mouse ).events .add( 'click', function (cell, e) { this.activate(cell, e.button); }.bind(this)); }, activate: function (cell, actionCode) { console.log( cell.point.dump(), actionCode ); } });
рдкрд╣рд▓реА рдЕрдиреНрддрд░рдХреНрд░рд┐рдпрд╛рд╢реАрд▓рддрд╛ рдЬреЛрдбрд╝реЗрдВред рд╣рдореЗрдВ рдЗрдВрдбреЗрдХреНрд╕ рджреНрд╡рд╛рд░рд╛ рдХреЙрд▓ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рд╡рд┐рдзрд┐ рдХрд╛ рдирд╛рдо рдорд┐рд▓реЗрдЧрд╛ рдФрд░ рдЙрд╕реА рд╕рдордп, рд╣рдо рд╕рдмрд╕реЗ рд╕рд░рд▓ рд╡рд┐рдзрд┐ рд▓рд┐рдЦреЗрдВрдЧреЗ -
close
ред рдпрджрд┐ рдХрдХреНрд╖ рдмрдВрдж рд╣реИ, рддреЛ рдЙрд╕ рдкрд░ рдПрдХ рдзреНрд╡рдЬ рд╕реЗрдЯ рдХрд░реЗрдВ, рдпрджрд┐ рдзреНрд╡рдЬ рдкрд╣рд▓реЗ рд╕реЗ рд╕реЗрд▓ рдкрд░ рд╣реИ, рддреЛ рдЗрд╕реЗ рдмрдВрдж рдХрд░реЗрдВред рдЕрдм рдЖрдк рдкрд╣рд▓реА рдЗрдВрдЯрд░реИрдХреНрд╢рди рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ - рд╕реЗрд▓ рдкрд░ рдПрдХ рдЭрдВрдбрд╛ рд╕рд╣реА рдорд╛рдЙрд╕ рдмрдЯрди рдХреЗ рд╕рд╛рде рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИред
/** @class Mines.Action */ // ... activate: function (cell, actionCode) { if (typeof actionCode == 'number') { actionCode = this.actions[actionCode]; } this[actionCode](cell); }, close: function (cell) { if (cell.value == 'closed') { cell.value = 'flag'; } else if (cell.value == 'flag') { cell.value = 'closed'; } }, open: function (cell) { }, all: function (cell) { }
рдЕрдм рд╣рдо рд╕реЗрд▓ рдХреЗ рдЙрджреНрдШрд╛рдЯрди рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП, рдХреЗрд╡рд▓ рдЙрди рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЛ рдЦреЛрд▓реЗрдВ рдЬреЛ рдмрдВрдж рд╣реИрдВред рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рд░ рд╕рдВрдЦреНрдпрд╛ рдФрд░ рдЭрдВрдбреЗ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИред рджреВрд╕рд░реЗ, рд╣рдо рдЬрд╛рдВрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рд╣рдорд╛рд░реА рдЦрджрд╛рдиреЗрдВ рддреИрдпрд╛рд░ рд╣реИрдВ рдФрд░ рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдЬрдирд░реЗрдЯрд░ рд╢реБрд░реВ рдХрд░реЗрдВред
рдпрджрд┐ рдЦрджрд╛рди рдЦреБрд▓реА рд╣реИ, рддреЛ
lose
рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВ, рдЬрд╣рд╛рдВ рд╣рдо рд╕реЗрд▓ рдХреЛ рд╡рд┐рд╕реНрдлреЛрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВред
рдпрджрд┐ рд╕реЗрд▓ рдореЗрдВ рдХреЛрдИ рд╕рдВрдЦреНрдпрд╛ рд╣реИ, рддреЛ рдмрд╕ рдЗрд╕реЗ рд▓рд┐рдЦреЗрдВ, рдЗрд╕ рд╕реЗрд▓ рдХреЗ рд╕рд╛рде рдХреЛрдИ рдЕрдиреНрдп рдХрд╛рд░реНрдп рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдпрджрд┐ рд╕реЗрд▓ рдЦрд╛рд▓реА рд╣реИ, рддреЛ рд╣рдореЗрдВ рдЪрд╛рд░реЛрдВ рдУрд░ рдХреА рд╕рднреА рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЛ рдкреБрди: рдЦреЛрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЕрдм рд╣рдо рдПрдХ рд╡рд┐рдзрд┐ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рд╕реЗрд▓ рдХреЛ рдЦрд╛рд▓реА рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВред
/** @class Mines.Action */ // ... open: function (cell) { if (cell.value != 'closed') return; var value, gen = this.controller.generator; if (!gen.isReady()) { gen.generate(cell.point); } if (gen.isMine(cell.point)) { this.lose(cell); } else { value = gen.getValue(cell.point); if (value) { cell.value = value; } else { this.openEmpty(cell); } } }, lose: function () { cell.value = 'explode'; }, openEmpty: function (cell) { cell.value = 'empty'; },
рдЦрд╛рд▓реА рдПрдХ рдХреЗ рдЖрд╕рдкрд╛рд╕ рд╕рднреА рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЛ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рд┐рд░реНрдл рдкрдбрд╝реЛрд╕рд┐рдпреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ
open
рд╡рд┐рдзрд┐ рдореЗрдВ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЦрд╛рд▓реА рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЗ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдЙрджреНрдШрд╛рдЯрди рдФрд░ рдордзреНрдп рдорд╛рдЙрд╕ рдмрдЯрди рджреНрд╡рд╛рд░рд╛ рддреНрд╡рд░рд┐рдд рдЙрджреНрдШрд╛рдЯрди рдХреЗ рд▓рд┐рдП рдХрд░реЗрдВрдЧреЗред
/** @class Mines.Action */ // ... openNeighbours: function (cell) { this.controller.generator .getNeighbours(cell.point) .forEach(function (point) { this.open( this.getCell(point) ); }.bind(this)); }, openEmpty: function (cell) { cell.value = 'empty'; this.openNeighbours(cell); }, getCell: function (point) { return this.controller.view.engine.getCellByIndex(point); }, all: function (cell) { if (parseInt(cell.value)) { this.openNeighbours(cell); } },
рд╣рдо рдиреБрдХрд╕рд╛рди рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ - рд╣рдо рдЙрди рд╕рднреА рдХреЛрд╢рд┐рдХрд╛рдУрдВ рд╕реЗ рдЧреБрдЬрд░рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рд╣рдордиреЗ рдЗрд╕реЗ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рдерд╛ рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдореЗрд░рд╛ рдерд╛ - рд╣рдо рдПрдХ рдЦрджрд╛рди рдЦреАрдВрдЪрддреЗ рд╣реИрдВред рдЬрд╣рд╛рдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЭрдВрдбрд╛ рдерд╛, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЛрдИ рдЦрджрд╛рди рдирд╣реАрдВ рд╣реИрдВ - рд╣рдо рдПрдХ рддреНрд░реБрдЯрд┐ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рд╣рд╛рд░рдиреЗ рдХреЗ рдмрд╛рдж
open
рдФрд░
close
рддрд░реАрдХреЛрдВ рдХреЛ рднреА рд░реЛрдХрддреЗ рд╣реИрдВред
/** @class Mines.Action */ // ... lost: false, lose: function (cell) { this.lost = true; cell.value = 'explode'; this.controller.view.engine.cells .forEach(this.checkCell.bind(this)); }, checkCell: function (cell) { if (cell.value == 'closed' || cell.value == 'flag') { var isMine = this.controller.generator.isMine(cell.point); if (isMine && cell.value == 'closed') { cell.value = 'mine'; } if (!isMine && cell.value == 'flag') { cell.value = 'wrong'; } } }, // ... close: function (cell) { if (this.lost) return; // ... open: function (cell) { if (this.lost) return; // ...

рдЬреАрдд!
рдпрд╣ рдЬреАрдд, рдмреАрддрд╛ рд╣реБрдЖ рд╕рдордп рдФрд░ рдЦрд╛рдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред рд╣рдо рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдкрд░реЗрд╢рд╛рди рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рд╣рдо рдЧреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди
atom.trace
рдХрд╛рдо рдХрд░
atom.trace
ред рдорд┐рдирдЯ рдХреА рд╕рдВрдЦреНрдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред рдЪрд▓реЛ рдЦрд╛рд▓реА рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдЧрд┐рдирддреЗ рд╣реИрдВ - рдпрд╣ рдХреБрд▓ рдорд┐рдирдЯреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╣реИред рд╣рд░ рдмрд╛рд░ рдЬрдм рдЖрдк рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЛ рдЦреЛрд▓рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдЦрд╛рд▓реА рдореВрд▓реНрдп рдХреЛ рдПрдХ рд╕реЗ рдХрдо рдХрд░ рджреЗрдВрдЧреЗред рдЬрдм рд╡реЗ рд╢реВрдиреНрдп рддрдХ рдкрд╣реБрдВрдЪрддреЗ рд╣реИрдВ - рдЦреЗрд▓ рдЬреАрддрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдЗрдП рдХреИрдирд╡рд╛рд╕ рдХреЛ рдбреНрд░рд╛ рдХрд░реЗрдВ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдереЛрдбрд╝реА рджреЗрд░реА рдХреЗ рд╕рд╛рде рдЕрд▓рд░реНрдЯ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВред
/** @class Mines.Action */ // ... initialize: function (controller) { // ... this.startTime = null; this.minesLeft = controller.mines; this.minesTrace = atom.trace(0); this.changeMines(0); this.emptyCells = controller.size.width * controller.size.height - this.minesLeft; }, changeMines: function (delta) { this.minesLeft += delta; this.minesTrace.value = "Mines: " + this.minesLeft; }, // ... open: function (cell) { // ... if (!gen.isReady()) { // ... this.startTime = Date.now(); } if (gen.isMine(cell.point)) { // ... } else { // ... if (--this.emptyCells == 0) { this.win(); } } }, // ... win: function () { var time = Math.round( (Date.now()-this.startTime) / 1000 ); alert.delay(100, window, ['Congratulations! Mines has been neutralized in '+ time +' sec!']); }, // ... close: function (cell) { // ... if (cell.value == 'closed') { // ... this.changeMines(-1); } else if (cell.value == 'flag') { // ... this.changeMines(+1); } },