import React from 'react'; import GridField from './grid-field'; import UserControl from '../user/user-control'; class GridControl extends React.Component { constructor(props) { super(props); this.state = { env: props.env, webPlayer: null, grid: null, updatedFieldCache: [], bombFieldCache: [], foundUserMineCache: 0, playBomb: false, lastClicked: { red: null, blue: null } }; } refString(row, col) { return 'gridField_' + row + '_' + col; } checkMine(row, col) { return typeof this.state.grid[row] !== 'undefined' && typeof this.state.grid[row][col] !== 'undefined' && this.state.grid[row][col] !== 'm'; } getBombRadius(row, col) { var isBombTargetCenter = row > 1 && row < this.state.grid.length - 2 && col > 1 && col < this.state.grid[row].length - 2; /** if the (5x5) target not fits the grid */ if (!isBombTargetCenter) { if (col < 2) { col = 2; } if (row < 2) { row = 2; } if (row > this.state.grid.length - 3) { row = this.state.grid.length - 3; } if (col > this.state.grid[0].length - 3) { col = this.state.grid[0].length - 3; } } return [ [row, col], [row - 2, col - 2], [row - 2, col], [row - 2, col + 2], [row, col - 2], [row, col + 2], [row + 2, col - 2], [row + 2, col], [row + 2, col + 2], [row - 2, col + 1], [row - 2, col - 1], [row - 1, col - 2], [row - 1, col - 1], [row - 1, col], [row - 1, col + 1], [row - 1, col + 2], [row, col - 1], [row, col + 1], [row + 1, col - 2], [row + 1, col - 1], [row + 1, col], [row + 1, col + 1], [row + 1, col + 2], [row + 2, col - 1], [row + 2, col + 1] ]; } checkNeighbourItem(row, col) { if (this.checkMine(row, col)) { var currentField = this.refs[this.refString(row, col)]; currentField.setState({ currentImage: this.state.grid[row][col], currentObj: this.state.grid[row][col], active: true }); /** * It must be cached because the GridField.state not updated until * all showAppropriateFields() method runned out!! */ if (this.state.updatedFieldCache.indexOf(this.refString(row, col)) < 0 && !currentField.state.active) { this.state.updatedFieldCache.push(this.refString(row, col)); if (this.state.grid[row][col] === 0) { return { row: row, col: col }; } } } return false; } checkNeighbours(row, col) { var anotherFields = []; anotherFields.push(this.checkNeighbourItem(row - 1, col)); anotherFields.push(this.checkNeighbourItem(row - 1, col - 1)); anotherFields.push(this.checkNeighbourItem(row - 1, col + 1)); anotherFields.push(this.checkNeighbourItem(row, col - 1)); anotherFields.push(this.checkNeighbourItem(row, col + 1)); anotherFields.push(this.checkNeighbourItem(row + 1, col)); anotherFields.push(this.checkNeighbourItem(row + 1, col + 1)); anotherFields.push(this.checkNeighbourItem(row + 1, col - 1)); return anotherFields; } showAppropriateFields(currentField, row, col) { currentField.setState({ currentObj: this.state.grid[row][col], active: true }); if (this.state.updatedFieldCache.indexOf(this.refString(row, col)) < 0) { this.state.updatedFieldCache.push(this.refString(row, col)); } if (this.state.grid[row][col] === 0) { var neighbours = this.checkNeighbours(row, col); neighbours .filter((i) => { return i !== false; }) .forEach((element, index, array) => { var currentField = this.refs[this.refString(element.row, element.col)]; this.showAppropriateFields(currentField, element.row, element.col); }); } } bombClear() { if (this.state.bombFieldCache.length) { for (var i = 0, j = this.state.bombFieldCache.length; i < j; i++) { var cacheItem = this.state.bombFieldCache[i]; this.refs[this.refString(cacheItem[0], cacheItem[1])] .setState({bombTargetArea: null}); } this.state.bombFieldCache = []; } } bombCreate(row, col) { var bombFieldSymbols = [ [null, null], [0, 0], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2], [1, 2], [2, 2], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null] ], bombFields = this.getBombRadius(row, col); for (var i = 0, j = bombFields.length; i < j; i++) { this.state.bombFieldCache.push(bombFields[i]); this.refs[this.refString(bombFields[i][0], bombFields[i][1])] .setState({bombTargetArea: bombFieldSymbols[i]}); } } /** * Player control method * * @param currentObject {int|string} Current object from Grid class * @param x {int} * @param y {int} * @param justOnFirstIteration {int} When bomb is being used check the whole explosion area */ handleGridField(currentObject, x, y, justOnFirstIteration = 0) { var userControl = this.refs.userControl, gridFieldControl = this.refs[this.refString(x, y)], activePlayer = userControl.state.activePlayer ? 'blue' : 'red', inactivePlayer = userControl.state.activePlayer ? 'red' : 'blue'; /** if the clicked field is NEVER CLICKED */ if (!gridFieldControl.state.active) { /** update LAST CLICKED grid field */ if (!justOnFirstIteration) { if (this.state.lastClicked[activePlayer] !== null) { this.refs[this.refString(this.state.lastClicked[activePlayer][0], this.state.lastClicked[activePlayer][1])].setState({ lastClickedRed: false, lastClickedBlue: false }); } } this.state.lastClicked[activePlayer] = [x, y]; /** if you found mine */ if (currentObject === 'm') { this.state.foundUserMineCache++; if (!justOnFirstIteration) { /** set last clicked field w/ color */ this.state.lastClicked[activePlayer] = [x, y]; } /** set current image in field */ gridFieldControl.setState({ currentImage: gridFieldControl.state.icons.root + gridFieldControl.state.icons.flag[activePlayer] }); } else { if (!justOnFirstIteration) { /** set __ACTIVE__ player in the UserControl !!!! */ userControl.setState({ activePlayer: userControl.state.activePlayer ? 0 : 1 }); userControl.refs[activePlayer].setState({ active: false }); userControl.refs[inactivePlayer].setState({ active: true }); } /** set current image in field - WHEN it is a number */ if (!isNaN(currentObject)) { gridFieldControl.setState({ currentImage: currentObject }); } } /** * set bombs status - we must add one mine (currentObject === 'm' ? 1 : 0) to current mine * when it found NOW because the status is not refreshed unless the handleGridField() ends */ userControl.refs[activePlayer].setState({ enabledBomb: userControl.refs[activePlayer].state.mines + (currentObject === 'm' ? 1 : 0) <= userControl.refs[inactivePlayer].state.mines }); userControl.refs[inactivePlayer].setState({ enabledBomb: userControl.refs[activePlayer].state.mines + (currentObject === 'm' ? 1 : 0) >= userControl.refs[inactivePlayer].state.mines }); /** set-up last clicked */ if (!justOnFirstIteration) { gridFieldControl.setState({ lastClickedRed: activePlayer === 'red', lastClickedBlue: activePlayer === 'blue' }); } } } stepEvent(coords) { var activePlayer = this.refs.userControl.state.activePlayer ? 'blue' : 'red'; this.state.foundUserMineCache = 0; this.state.playBomb = true; /** Field selected w/ BOMB */ if (this.refs.userControl.state.bombSelected) { var radius = this.getBombRadius(coords[0], coords[1]); for (var i = 0, j = radius.length; i < j; i++) { this.handleGridField( this.state.grid[radius[i][0]][radius[i][1]], radius[i][0], radius[i][1], i ); this.showAppropriateFields( this.refs[this.refString(radius[i][0], radius[i][1])], radius[i][0], radius[i][1] ); } /** remove BOMB from activePlayer */ this.refs.userControl.refs[activePlayer].setState({ haveBomb: false }); } else { this.handleGridField( this.state.grid[coords[0]][coords[1]], coords[0], coords[1], 0 ); this.showAppropriateFields( this.refs[this.refString(coords[0], coords[1])], coords[0], coords[1] ); } /** Reset mine caches */ if (this.state.foundUserMineCache) { /** remove the found mines from global */ this.refs.userControl.setState({ mines: this.refs.userControl.state.mines - this.state.foundUserMineCache, foundMines: true }, () => { this.refs.userControl.setState({foundMines: false}); /** add the found mines to the active Player */ this.refs.userControl.refs[activePlayer].setState({ mines: this.refs.userControl.refs[activePlayer].state.mines + this.state.foundUserMineCache }); }); } /** Reset BOMB status */ if (this.refs.userControl.state.bombSelected) { /** reset bomb selected status */ this.refs.userControl.setState({bombSelected: false}); /** clear cache, reset symbols */ this.bombClear(); } } /** * On Hover when you want to drop BOMB * @param coords */ onHoverWithBomb(coords) { if (this.refs.userControl.state.bombSelected) { /** clear cache, reset symbols */ this.bombClear(); /** new cache && field activate */ this.bombCreate(coords[0], coords[1]); } } render() { var grid = []; if (this.state.grid) { for (var i = 0, j = this.state.grid.length; i < j; i++) { for (var k = 0, l = this.state.grid[i].length; k < l; k++) { grid.push( ); } } } return (
{/*{this.renderGridFields()}*/} {grid}
{/*{this.playingSound()}*/}
); } } export default GridControl;