components/Board: block selecting same answer twice

This commit is contained in:
Artur Tamborski 2020-12-27 19:58:48 +01:00
parent d3923cd455
commit db77874786
2 changed files with 25 additions and 9 deletions

View File

@ -22,12 +22,9 @@
} }
.Cell { .Cell {
width: 60px;
height: 60px;
font-weight: bold; font-weight: bold;
font-size: x-large; font-size: x-large;
font-family: monospace; font-family: monospace;
padding: 15px;
background: ghostwhite; background: ghostwhite;
text-align: center; text-align: center;
border: 5px solid #e5e5ea; border: 5px solid #e5e5ea;

View File

@ -31,6 +31,7 @@ interface IBoardProps {
interface IBoardState { interface IBoardState {
score: number; score: number;
wasValid: boolean;
wasSelecting: boolean; wasSelecting: boolean;
selections: Array<Selection>; selections: Array<Selection>;
bar: Bar; bar: Bar;
@ -39,6 +40,7 @@ interface IBoardState {
export default class Board extends React.Component<IBoardProps, IBoardState> { export default class Board extends React.Component<IBoardProps, IBoardState> {
private readonly cells: Array<Array<string>>; private readonly cells: Array<Array<string>>;
private readonly solutions: Array<Solution>; private readonly solutions: Array<Solution>;
private readonly cellSize: number;
constructor(props: IBoardProps) { constructor(props: IBoardProps) {
super(props); super(props);
@ -46,6 +48,7 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
const crosski: any = require(`../../constants/${props.numBoard}.json`) const crosski: any = require(`../../constants/${props.numBoard}.json`)
this.cells = crosski.cells; this.cells = crosski.cells;
this.solutions = crosski.solutions; this.solutions = crosski.solutions;
this.cellSize = 60;
const selections = [...new Array(this.solutions.length)].map(() => const selections = [...new Array(this.solutions.length)].map(() =>
Object.assign({}, { Object.assign({}, {
@ -57,6 +60,7 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
this.state = { this.state = {
score: 0, score: 0,
selections, selections,
wasValid: false,
wasSelecting: false, wasSelecting: false,
bar: {start: {x: 0, y: 0}, end: {x: 0, y: 0}}, bar: {start: {x: 0, y: 0}, end: {x: 0, y: 0}},
} }
@ -67,8 +71,10 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
} }
updateSelection(pos: Point, isSelecting: boolean, isMoving: boolean = false): void { updateSelection(pos: Point, isSelecting: boolean, isMoving: boolean = false): void {
const [parse, str] = [JSON.parse, JSON.stringify];
let score = this.state.score; let score = this.state.score;
const selections = this.state.selections.slice(); const selections: Array<Selection> = parse(str(this.state.selections));
const s = selections.find(v => !v.isCorrect); const s = selections.find(v => !v.isCorrect);
// skip if there are no lines left or the mouse is moving but not selecting // skip if there are no lines left or the mouse is moving but not selecting
@ -80,26 +86,37 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
const isValidMove = x === 0 || y === 0 || x === y; const isValidMove = x === 0 || y === 0 || x === y;
const isMouseDown = isSelecting && !this.state.wasSelecting; const isMouseDown = isSelecting && !this.state.wasSelecting;
const isMouseUp = !isSelecting && this.state.wasSelecting && isValidMove; const isMouseUp = !isSelecting && this.state.wasSelecting && isValidMove;
const isValidSolution = this.solutions.some(v => str(v.bar) === str(s.bar));
const wasAlreadySelected = this.state.selections.some(v => str(v.bar) === str(s.bar));
const isValid = isValidSolution && !wasAlreadySelected;
const start: Point = isMouseDown ? pos : this.state.bar.start; const start: Point = isMouseDown ? pos : this.state.bar.start;
const bar: Bar = {start, end: pos}; const bar: Bar = {start, end: pos};
const str = JSON.stringify;
if (isValidMove) if (isValidMove)
s.bar = bar; s.bar = bar;
if (isMouseUp && this.solutions.some(v => str(v.bar) === str(bar))) if (isMouseUp && this.state.wasValid)
[s.isCorrect, score] = [true, score + 1]; [s.isCorrect, score] = [true, score + 1];
this.setState({...this.state, score, bar, selections, wasSelecting: isSelecting}); this.setState({
...this.state,
score, bar, selections,
wasValid: isValid,
wasSelecting: isSelecting
});
if (score === this.solutions.length) if (score === this.solutions.length)
this.gameOver(); this.gameOver();
} }
renderCell(s: string, pos: Point): JSX.Element { renderCell(s: string, pos: Point): JSX.Element {
const size = `${this.cellSize}px`;
const padding = `${this.cellSize / 4}px`;
return ( return (
<button <button
className="Cell" className="Cell"
style={{width: size, height: size, padding}}
key={`Cell${pos.x}${pos.y}`} key={`Cell${pos.x}${pos.y}`}
onMouseUp={() => this.updateSelection(pos, false)} onMouseUp={() => this.updateSelection(pos, false)}
onMouseDown={() => this.updateSelection(pos, true)} onMouseDown={() => this.updateSelection(pos, true)}
@ -117,7 +134,7 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
bar={s.bar} bar={s.bar}
isVisible={s.isVisible} isVisible={s.isVisible}
isCorrect={s.isCorrect} isCorrect={s.isCorrect}
cellSize={60} cellSize={this.cellSize}
/> />
); );
} }
@ -131,12 +148,14 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
let lines = this.state.selections.map((s, n) => let lines = this.state.selections.map((s, n) =>
this.renderLine(s, n)); this.renderLine(s, n));
const gridTemplateColumns = `repeat(${this.cells.length}, ${this.cellSize}px)`;
return ( return (
<div className="Container"> <div className="Container">
<div className="Content"> <div className="Content">
<div <div
className="Board" className="Board"
style={{gridTemplateColumns: `repeat(${this.cells.length}, 60px)`}} style={{gridTemplateColumns}}
> >
{cells} {cells}
</div> </div>