Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React from 'react';
- import './style.css';
- const MINES_TO_COLOURS=['','#00a6ff','#009e0b','#d10000','#861cb0','#d19900'];
- class Cell extends React.Component{
- constructor(props){
- super(props);
- this.handleClick = this.handleClick.bind(this);
- this.handleContext = this.handleContext.bind(this);
- }
- handleClick(e){
- e.preventDefault();
- if(e.button === 0){
- this.props.onSearch && this.props.onSearch();
- }
- }
- handleContext(e){
- e.preventDefault();
- this.props.onFlag && this.props.onFlag();
- }
- render(){
- return <div className="cell" style = {{
- backgroundColor: this.props.cell.searched ? '#a1a1a1' : '#c9c9c9',
- borderColor:this.props.cell.searched ? '#828282' : '#404040'
- }} onClick={this.handleClick} onContextMenu={this.handleContext}>
- <img src="./assets/flag.png" style={{
- width:'100%',
- height:'100%',
- position:'absolute',
- display: (this.props.cell.flagged && (!this.props.gameOver)) ? 'block' : 'none'
- }}/>
- <img src="./assets/mine.png" style={{
- width:'100%',
- height:'100%',
- position:'absolute',
- display: (this.props.gameOver && this.props.cell.isMine) ? 'block' : 'none'
- }}/>
- <span className="mine-number-display" style={{
- color:MINES_TO_COLOURS[this.props.cell.mines],
- display: (this.props.cell.searched && this.props.cell.mines && (!this.props.cell.isMine)) ? 'inline-block' : 'none',
- fontSize:32,
- margin:'auto',
- fontFamily:'Comic Sans MS, sans-serif',
- width:'100%'
- }}>{this.props.cell.mines.toString()}</span>
- </div>;
- }
- }
- class Minesweeper extends React.Component {
- constructor(props){
- super(props);
- this.config = props.config;
- this.state = {
- board:[],
- gameOver:false,
- flaggedMines:0
- }
- this.resetGame();
- }
- componentWillUnmount(){
- this.stopTimer();
- }
- stopTimer(){
- clearInterval(this.timer);
- }
- startTimer(){
- this.timer = setInterval(_ => {
- const time = this.state.timer;
- this.setState({
- timer:time+0.001
- });
- },1)
- }
- resetGame(){
- this.setState({
- gameOver:false,
- timer:0
- });
- this.generateBoard();
- }
- getNeighbours(x,y){
- const v = [[0,1],[1,0],[1,1],[0,-1],[-1,0],[-1,-1],[-1,1],[1,-1]];
- const m = v.map(r => [x+r[0],y+r[1]]);
- const o = m.filter(u=>u[0]>=0 && u[0]<this.config.width && u[1]>=0 && u[1]<this.config.height);
- return o;
- }
- generateBoard(){
- const board = Array(this.config.width).fill().map(r=>Array(this.config.height).fill().map(q=> ({isMine:false,mines:0,flagged:false,searched:false})));
- const addMine = _ => {
- const i = Math.floor(Math.random() * this.config.width * this.config.height);
- const w = Math.floor(i/this.config.height);
- const h = i - w * this.config.height;
- if(board[w][h].isMine){
- addMine();
- }else{
- board[w][h].isMine = true;
- }
- };
- for(let x = 0; x<this.config.mines;x++) addMine();
- board.forEach((x,xi)=>{
- x.forEach((y,yi)=>{
- const neighbours = this.getNeighbours(xi,yi).map(r=>board[r[0]][r[1]]);
- const mines = neighbours.reduce((acc,v)=>acc+(v.isMine ? 1 :0),0);
- y.mines = mines;
- });
- });
- this.state.board = board;
- this.setState({board:board});
- }
- searchSquare(x,y){
- if(this.state.gameOver) return;
- const square = this.state.board[x][y];
- if(square.flagged) return;
- if(square.searched) return;
- square.searched = true;
- if(square.isMine){
- this.setState({gameOver:true});
- return;
- }
- const searchNeighbours = (a,b) =>{
- const n = this.getNeighbours(a,b);
- n.forEach(u=>{
- const s = this.state.board[u[0]][u[1]];
- const preSearched = !s.searched;
- s.searched = true;
- if(s.mines === 0 && preSearched){
- searchNeighbours(u[0],u[1]);
- }
- });
- }
- if(square.mines === 0) searchNeighbours(x,y);
- this.setState({board:this.state.board});
- }
- flagSquare(x,y){
- if(this.state.gameOver) return;
- const square = this.state.board[x][y];
- if(square.searched) return;
- square.flagged = !square.flagged;
- this.setState({board:this.state.board});
- }
- renderBoard(){
- return <div className="board">
- {this.state.board.map((x,xi) =>
- <div className="column">
- {
- x.map((y,yi) =>
- <Cell cell={y} pos = {[xi,yi]} onFlag = {this.flagSquare.bind(this,xi,yi)} onSearch={this.searchSquare.bind(this,xi,yi)} gameOver = {this.state.gameOver}/>
- )
- }
- </div>
- )}
- </div>
- }
- render(){
- return <div className="game">
- <div>{this.state.gameOver ? 'game over' : 'game not over'}</div>
- {this.renderBoard()}
- </div>
- }
- }
- export {Minesweeper as Minesweeper};
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement