Advertisement
Guest User

Untitled

a guest
Dec 15th, 2019
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import React from 'react';
  2. import './style.css';
  3. const MINES_TO_COLOURS=['','#00a6ff','#009e0b','#d10000','#861cb0','#d19900'];
  4. class Cell extends React.Component{
  5.     constructor(props){
  6.         super(props);
  7.         this.handleClick = this.handleClick.bind(this);
  8.         this.handleContext = this.handleContext.bind(this);
  9.     }
  10.     handleClick(e){
  11.         e.preventDefault();
  12.         if(e.button === 0){
  13.             this.props.onSearch && this.props.onSearch();
  14.         }
  15.     }
  16.     handleContext(e){
  17.         e.preventDefault();
  18.         this.props.onFlag && this.props.onFlag();
  19.     }
  20.     render(){
  21.         return <div className="cell" style = {{
  22.             backgroundColor: this.props.cell.searched ? '#a1a1a1' : '#c9c9c9',
  23.             borderColor:this.props.cell.searched ? '#828282' : '#404040'
  24.         }} onClick={this.handleClick} onContextMenu={this.handleContext}>
  25.             <img src="./assets/flag.png" style={{
  26.                 width:'100%',
  27.                 height:'100%',
  28.                 position:'absolute',
  29.                 display: (this.props.cell.flagged && (!this.props.gameOver)) ? 'block' : 'none'
  30.             }}/>
  31.             <img src="./assets/mine.png" style={{
  32.                 width:'100%',
  33.                 height:'100%',
  34.                 position:'absolute',
  35.                 display: (this.props.gameOver && this.props.cell.isMine) ? 'block' : 'none'
  36.             }}/>
  37.             <span className="mine-number-display" style={{
  38.                 color:MINES_TO_COLOURS[this.props.cell.mines],
  39.                 display: (this.props.cell.searched && this.props.cell.mines && (!this.props.cell.isMine)) ? 'inline-block' : 'none',
  40.                 fontSize:32,
  41.                 margin:'auto',
  42.                 fontFamily:'Comic Sans MS, sans-serif',
  43.                 width:'100%'
  44.             }}>{this.props.cell.mines.toString()}</span>
  45.         </div>;
  46.     }
  47. }
  48. class Minesweeper extends React.Component {
  49.     constructor(props){
  50.         super(props);
  51.         this.config = props.config;
  52.         this.state = {
  53.             board:[],
  54.             gameOver:false,
  55.             flaggedMines:0
  56.         }
  57.         this.resetGame();
  58.     }
  59.     componentWillUnmount(){
  60.         this.stopTimer();
  61.     }
  62.     stopTimer(){
  63.         clearInterval(this.timer);
  64.     }
  65.     startTimer(){
  66.         this.timer = setInterval(_ => {
  67.             const time = this.state.timer;
  68.             this.setState({
  69.                 timer:time+0.001
  70.             });
  71.         },1)
  72.     }
  73.     resetGame(){
  74.         this.setState({
  75.             gameOver:false,
  76.             timer:0
  77.         });
  78.         this.generateBoard();
  79.     }
  80.     getNeighbours(x,y){
  81.         const v = [[0,1],[1,0],[1,1],[0,-1],[-1,0],[-1,-1],[-1,1],[1,-1]];
  82.         const m = v.map(r => [x+r[0],y+r[1]]);
  83.         const o = m.filter(u=>u[0]>=0 && u[0]<this.config.width && u[1]>=0 && u[1]<this.config.height);
  84.         return o;
  85.     }
  86.     generateBoard(){
  87.         const board = Array(this.config.width).fill().map(r=>Array(this.config.height).fill().map(q=> ({isMine:false,mines:0,flagged:false,searched:false})));
  88.         const addMine = _ => {
  89.             const i = Math.floor(Math.random() * this.config.width * this.config.height);
  90.             const w = Math.floor(i/this.config.height);
  91.             const h = i - w * this.config.height;
  92.             if(board[w][h].isMine){
  93.                 addMine();
  94.             }else{
  95.                 board[w][h].isMine = true;
  96.             }
  97.         };
  98.         for(let x = 0; x<this.config.mines;x++) addMine();
  99.         board.forEach((x,xi)=>{
  100.             x.forEach((y,yi)=>{
  101.                 const neighbours = this.getNeighbours(xi,yi).map(r=>board[r[0]][r[1]]);
  102.                 const mines = neighbours.reduce((acc,v)=>acc+(v.isMine ? 1 :0),0);
  103.                 y.mines = mines;
  104.             });
  105.         });
  106.         this.state.board = board;
  107.         this.setState({board:board});
  108.     }
  109.     searchSquare(x,y){
  110.         if(this.state.gameOver) return;
  111.         const square = this.state.board[x][y];
  112.         if(square.flagged) return;
  113.         if(square.searched) return;
  114.         square.searched = true;
  115.         if(square.isMine){
  116.             this.setState({gameOver:true});
  117.             return;
  118.         }
  119.         const searchNeighbours = (a,b) =>{
  120.             const n = this.getNeighbours(a,b);
  121.             n.forEach(u=>{
  122.                 const s = this.state.board[u[0]][u[1]];
  123.                 const preSearched = !s.searched;
  124.                 s.searched = true;
  125.                 if(s.mines === 0 && preSearched){
  126.                     searchNeighbours(u[0],u[1]);
  127.                 }
  128.             });
  129.         }
  130.         if(square.mines === 0) searchNeighbours(x,y);
  131.         this.setState({board:this.state.board});
  132.     }
  133.     flagSquare(x,y){
  134.         if(this.state.gameOver) return;
  135.         const square = this.state.board[x][y];
  136.         if(square.searched) return;
  137.         square.flagged = !square.flagged;
  138.         this.setState({board:this.state.board});
  139.     }
  140.     renderBoard(){
  141.         return <div className="board">
  142.             {this.state.board.map((x,xi) =>
  143.                 <div className="column">
  144.                     {
  145.                         x.map((y,yi) =>
  146.                             <Cell cell={y} pos = {[xi,yi]} onFlag = {this.flagSquare.bind(this,xi,yi)} onSearch={this.searchSquare.bind(this,xi,yi)} gameOver = {this.state.gameOver}/>
  147.                         )
  148.                     }
  149.                 </div>
  150.             )}
  151.         </div>
  152.     }
  153.     render(){
  154.         return <div className="game">
  155.             <div>{this.state.gameOver ? 'game over' : 'game not over'}</div>
  156.             {this.renderBoard()}
  157.         </div>
  158.     }
  159. }
  160. export {Minesweeper as Minesweeper};
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement