Skip to content

Instantly share code, notes, and snippets.

@koriroys
Last active November 2, 2016 13:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koriroys/6dff2279c452a782983875c5f676238e to your computer and use it in GitHub Desktop.
Save koriroys/6dff2279c452a782983875c5f676238e to your computer and use it in GitHub Desktop.
Get Ten
import Ember from 'ember';
import Location from '../models/location';
import Grid from '../models/grid';
const { Component, get, set, computed, isEqual, isPresent } = Ember
export default Component.extend({
lastTapped: null,
init() {
this._super(...arguments);
set(this, 'grid', Grid.create());
},
actions: {
restart() {
get(this, 'grid').restart();
},
tapped(location) {
let grid = get(this, "grid");
let lastTapped = get(this, "lastTapped");
if ( isPresent(lastTapped) && isEqual(get(location, "isSelected"), true) ) {
// second tap
set(this, "lastTapped", null);
let matchingNeighbors = grid.matchingNeighbors(location);
if ( matchingNeighbors.length > 0 ) {
grid.combineMatchingNeighbors(matchingNeighbors);
location.incrementProperty("value");
grid.settle();
grid.randomFillEmptySpaces();
}
grid.deselectAll();
} else {
// first tap
grid.deselectAll();
grid.selectMatchingNeighbors(location);
let matchingNeighbors = grid.matchingNeighbors(location);
if ( matchingNeighbors.length > 0 ) {
grid.selectLocation(location);
}
set(this, "lastTapped", location);
}
}
}
});
import Ember from 'ember';
export default Ember.Controller.extend({
appName: 'Get Ten (Ember Style)'
});
import Ember from 'ember';
import Location from './location';
const { get, computed, isEqual, isPresent, observer, set } = Ember;
const MAX_ROW_INDEX = 4;
const MAX_COL_INDEX = 4;
export default Ember.Object.extend({
// required properties
value: null,
row: null,
col: null,
// end required properties
elements: [
[Location.create({ value: 0, row: 0, col: 0 }), Location.create({ value: 0, row: 0, col: 1 }), Location.create({ value: 0, row: 0, col: 2 }), Location.create({ value: 0, row: 0, col: 3 }), Location.create({ value: 0, row: 0, col: 4 })],
[Location.create({ value: 0, row: 1, col: 0 }), Location.create({ value: 0, row: 1, col: 1 }), Location.create({ value: 0, row: 1, col: 2 }), Location.create({ value: 0, row: 1, col: 3 }), Location.create({ value: 0, row: 1, col: 4 })],
[Location.create({ value: 0, row: 2, col: 0 }), Location.create({ value: 0, row: 2, col: 1 }), Location.create({ value: 0, row: 2, col: 2 }), Location.create({ value: 0, row: 2, col: 3 }), Location.create({ value: 0, row: 2, col: 4 })],
[Location.create({ value: 0, row: 3, col: 0 }), Location.create({ value: 0, row: 3, col: 1 }), Location.create({ value: 0, row: 3, col: 2 }), Location.create({ value: 0, row: 3, col: 3 }), Location.create({ value: 0, row: 3, col: 4 })],
[Location.create({ value: 0, row: 4, col: 0 }), Location.create({ value: 0, row: 4, col: 1 }), Location.create({ value: 0, row: 4, col: 2 }), Location.create({ value: 0, row: 4, col: 3 }), Location.create({ value: 0, row: 4, col: 4 })]
],
init() {
this.restart();
this._super(...arguments);
},
flattenedElements: computed('elements', function() {
let elements = get(this, "elements");
let flattenedElements = [];
elements.forEach((row) => {
flattenedElements.pushObjects(row);
});
return flattenedElements;
}),
allValues: computed.mapBy('flattenedElements', 'value'),
currentMax: computed.max('allValues'),
gameOver: observer('currentMax', function() {
let currentMax = get(this, "currentMax");
if ( isEqual(currentMax, 10) ) {
alert("You did it! You got 10!");
this.restart();
}
}),
// utilities functions
deselectAll() {
let elements = get(this, 'elements');
elements.forEach((row) => {
row.forEach((element) => {
set(element, 'isSelected', false);
});
});
},
selectLocation(location) {
set(location, 'isSelected', true);
},
selectMatchingNeighbors(location) {
let row = get(location, 'row');
let col = get(location, 'col');
let value = get(location, 'value');
let elements = get(this, 'elements');
let north = this.northNeighbor(row, col, elements);
let south = this.southNeighbor(row, col, elements);
let east = this.eastNeighbor(row, col, elements);
let west = this.westNeighbor(row, col, elements);
if ( isPresent(north) ) {
this.checkNorth(north, value);
}
if ( isPresent(east) ) {
this.checkEast(east, value);
}
if ( isPresent(west) ) {
this.checkWest(west, value);
}
if ( isPresent(south) ) {
this.checkSouth(south, value);
}
},
checkNorth(location, value) {
let row = get(location, 'row');
let col = get(location, 'col');
let elements = get(this, 'elements');
if ( this.neighborMatches(location, value) ) {
set(location, 'isSelected', true);
let west = this.westNeighbor(row, col, elements);
if ( isPresent(west) && isEqual(get(west, 'isSelected'), false) ) {
this.checkWest(west, value);
}
let north = this.northNeighbor(row, col, elements);
if ( isPresent(north) && isEqual(get(north, 'isSelected'), false) ) {
this.checkNorth(north, value);
}
let east = this.eastNeighbor(row, col, elements);
if ( isPresent(east) && isEqual(get(east, 'isSelected'), false) ) {
this.checkEast(east, value);
}
}
},
checkSouth(location, value) {
let row = get(location, 'row');
let col = get(location, 'col');
let elements = get(this, 'elements');
if ( this.neighborMatches(location, value) ) {
set(location, 'isSelected', true);
let east = this.eastNeighbor(row, col, elements);
if ( isPresent(east) && isEqual(get(east, 'isSelected'), false)) {
this.checkEast(east, value);
}
let south = this.southNeighbor(row, col, elements);
if ( isPresent(south) && isEqual(get(south, 'isSelected'), false) ) {
this.checkSouth(south, value);
}
let west = this.westNeighbor(row, col, elements);
if ( isPresent(west) && isEqual(get(west, 'isSelected'), false)) {
this.checkWest(west, value);
}
}
},
checkEast(location, value) {
let row = get(location, 'row');
let col = get(location, 'col');
let elements = get(this, 'elements');
if ( this.neighborMatches(location, value) ) {
set(location, 'isSelected', true);
let north = this.northNeighbor(row, col, elements);
if ( isPresent(north) && isEqual(get(north, 'isSelected'), false) ) {
this.checkNorth(north, value);
}
let east = this.eastNeighbor(row, col, elements);
if ( isPresent(east) && isEqual(get(east, 'isSelected'), false) ) {
this.checkEast(east, value);
}
let south = this.southNeighbor(row, col, elements);
if ( isPresent(south) && isEqual(get(south, 'isSelected'), false) ) {
this.checkSouth(south, value);
}
}
},
checkWest(location, value) {
let row = get(location, 'row');
let col = get(location, 'col');
let elements = get(this, 'elements');
if ( this.neighborMatches(location, value) ) {
set(location, 'isSelected', true);
let south = this.southNeighbor(row, col, elements);
if ( isPresent(south) && isEqual(get(south, 'isSelected'), false) ) {
this.checkSouth(south, value);
}
let west = this.westNeighbor(row, col, elements);
if ( isPresent(west) && isEqual(get(west, 'isSelected'), false) ) {
this.checkWest(west, value);
}
let north = this.northNeighbor(row, col, elements);
if ( isPresent(north) && isEqual(get(north, 'isSelected'), false) ) {
this.checkNorth(north, value);
}
}
},
neighborMatches(neighbor, value) {
let isMatch = false;
if ( neighbor ) {
let neighborValue = get(neighbor, 'value');
isMatch = neighbor && isEqual(neighborValue, value);
}
return isMatch;
},
northNeighbor(row, col, elements) {
if ( isEqual(row, 0) ) {
return null;
} else {
return elements[row - 1][col];
}
},
southNeighbor(row, col, elements) {
if ( isEqual(row, MAX_ROW_INDEX) ) {
return null;
} else {
return elements[row + 1][col];
}
},
eastNeighbor(row, col, elements) {
if ( isEqual(col, MAX_COL_INDEX) ) {
return null;
} else {
return elements[row][col + 1];
}
},
westNeighbor(row, col, elements) {
if ( isEqual(col, 0) ) {
return null;
} else {
return elements[row][col - 1];
}
},
settle() {
let columnNumbers = [...Array(MAX_COL_INDEX + 1).keys()];
columnNumbers.forEach((columnNumber) => {
this.settleColumn(columnNumber);
});
},
settleColumn(columnNumber) {
let elements = get(this, "elements");
// should probably extract this to an elements method
let column = [...Array(MAX_COL_INDEX + 1).keys()].map((rowNumber) => {
return elements[rowNumber][columnNumber];
});
let values = column.mapBy("value").filter((value) => {
return value !== 0
});
let numberOfBlankSpaces = MAX_COL_INDEX + 1 - values.length;
let blankSpaces = [...Array(numberOfBlankSpaces).keys()].map(() => { return 0 });
// have zero leading array of the values, e.g. [0, 0, 1, 1, 2]
blankSpaces.pushObjects(values);
// shift all location values down and zero fill values above
blankSpaces.forEach((boo, rowNumber) => {
set(elements[rowNumber][columnNumber], "value", boo);
});
},
randomFillEmptySpaces() {
let elements = get(this, "elements");
let currentMax = get(this, "currentMax");
elements.forEach((row) => {
row.forEach((element) =>{
let value = get(element, "value");
if ( value === 0 ) {
let fillerNumber = this.randomInclusive(1, currentMax);
set(element, "value", fillerNumber);
}
});
});
},
combineMatchingNeighbors(matchingNeighbors) {
if ( isEqual(matchingNeighbors.length, 0) ) {
return; // don't combine if it's a single element
}
matchingNeighbors.forEach((element) => {
set(element, "value", 0);
});
},
matchingNeighbors(location) {
let elements = get(this, "elements");
let value = get(location, "value");
let selected = [];
elements.forEach((row) => {
row.forEach((element) => {
let isSelected = get(element, 'isSelected');
if ( isEqual(location, element) ) {
// don't select the clicked on element
} else if ( isEqual(value, get(element, "value")) && isSelected) {
selected.pushObject(element);
}
});
});
return selected;
},
restart() {
let elements = get(this, 'elements');
elements.forEach((row) => {
row.forEach((element) => {
set(element, 'value', this.randomInclusive(1, 2));
set(element, 'isSelected', false);
});
});
},
randomInclusive(min, max) {
return min + Math.floor(Math.random() * (max - min + 1));
}
});
import Ember from 'ember';
const { get, isEqual } = Ember;
export default Ember.Object.extend({
value: null,
row: null,
col: null,
isSelected: false
});
.row {
height: 55px;
}
.location {
cursor: pointer;
display: inline-block;
font-family: Arial;
margin-right: -4px;
height: 55px;
width: 55px;
}
.number {
position: relative;
height: 0px;
left: 23px;
top: 20px;
width: 0px;
}
._1 {
/* GreenYellow */
background-color: rgb(186, 241, 87);
/* LimeGreen */
color: rgb(61, 174, 3);
}
.is-selected._1 {
background-color: rgb(176, 233, 75);
}
._2 {
/* DodgerBlue */
color: rgb(31, 141, 251);
/* LightSkyBlue */
background-color: rgb(91, 193, 249);
}
.is-selected._2 {
background-color: rgb(68, 186, 252);
}
._3 {
/* Tomato */
color: rgb(253, 118, 46);
/* SandyBrown */
background-color: rgb(254, 199, 100);
}
.is-selected._3 {
background-color: rgb(253, 190, 78);
}
._4 {
/* Coral */
background-color: rgb(253, 125, 93);
/* NavajoWhite */
color: rgb(254, 207, 157);
}
.is-selected._4 {
background-color: rgb(253, 111, 86);
}
._5 {
/* DarkCyan */
background-color: rgb(23, 157, 134);
/* LightGreen */
color: rgb(127, 231, 157);
}
.is-selected._5 {
background-color: rgb(21, 148, 126);
}
._6 {
/* MediumSlateBlue */
background-color: rgb(135, 114, 251);
/* Thistle */
color: rgb(205, 190, 253);
}
.is-selected._6 {
background-color: rgb(116, 100, 251);
}
._7 {
background-color: rgb(252, 110, 194);
color: rgb(254, 189, 168);
}
.is-selected._7 {
background-color: rgb(252, 84, 196);
}
._8 {
background-color: rgb(244, 62, 101);
color: rgb(254, 209, 181);
}
.is-selected._8 {
background-color: rgb(233, 41, 67);
}
._9 {
background-color: rgb(254, 245, 74);
color: rgb(207, 91, 57);
}
.is-selected._9 {
background-color: rgb(254, 232, 52);
}
._10 {
/* todo */
}
.is-selected._10 {
/* todo */
}
._11 {
/* todo */
}
.is-selected._11 {
/* todo */
}
._12 {
/* todo ;*/
}
.is-selected._12 {
/* todo ;*/
}
<h1>{{appName}}</h1>
{{get-ten}}
<button {{action "restart"}}>Restart</button>
{{#each grid.elements as |row|}}
<div class="row">
{{#each row as |element|}}
<div class={{concat "location " (concat "_" element.value) (if element.isSelected " is-selected")}} onclick={{action "tapped" element}}>
<div class="number">
{{element.value}}
</div>
</div>
{{/each}}
</div>
{{/each}}
{
"version": "0.10.4",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.7.0",
"ember-data": "2.7.0",
"ember-template-compiler": "2.7.0"
},
"addons": {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment