solution is no longer available by inspection

This commit is contained in:
quentin 2025-04-22 16:27:52 +02:00
parent d85687b956
commit f4e92f039c
6 changed files with 69 additions and 48 deletions

View File

@ -31,23 +31,12 @@ function App() {
const nColors = 7; const nColors = 7;
const nLines = 7; const nLines = 7;
if (!isPlaying) {
return ( return (
<> <>
<div className="root"> <div className="root">
<h1>Mastermind</h1> <h1>Mastermind</h1>
<button id={"play-button"} onClick={() => setIsPlaying(true)}><b>Play</b></button> <button id={"play-button"} onClick={() => setIsPlaying(true)} hidden={!isPlaying}><b>Play</b></button>
</div> <div hidden={isPlaying}><Game combination={generateCombination(nColors)} nColors={nColors} nLines={nLines}></Game></div>
<Footer />
</>
)
}
return (
<>
<div className="root">
<h1>Mastermind</h1>
<Game combination={generateCombination(nColors)} nColors={nColors} nLines={nLines}></Game>
</div> </div>
<Footer /> <Footer />
</> </>

View File

@ -49,8 +49,7 @@ button {
overflow: hidden; overflow: hidden;
} }
button:focus, button:hover:enabled {
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color; outline: 4px auto -webkit-focus-ring-color;
} }

View File

@ -28,17 +28,7 @@
background-color: lightgray; background-color: lightgray;
} }
#lose-header {
display: flex;
width: 100%;
align-items: center;
justify-content: center;
gap: 2em;
}
#lose-header .scroll-arrow {
font-size: 3em;
}
@media (max-width: 720px) { @media (max-width: 720px) {
#game { #game {
@ -56,8 +46,4 @@
width: 100%; width: 100%;
flex-direction: row; flex-direction: row;
} }
#lose-header .scroll-arrow {
width: calc(3em / 1.5);
}
} }

View File

@ -5,6 +5,7 @@ import DroppablePin from "../DroppablePin/DroppablePin.tsx";
import Color, {colors} from "../Color.ts"; import Color, {colors} from "../Color.ts";
import Line from "../Line/Line.tsx"; import Line from "../Line/Line.tsx";
import {CaseInfo} from "../Case/Case.tsx"; import {CaseInfo} from "../Case/Case.tsx";
import GameState from "../GameState/GameState.tsx";
interface GameProps { interface GameProps {
combination: string[]; combination: string[];
@ -18,6 +19,7 @@ function Game(props: GameProps) {
const [activeLine, setActiveLine] = useState<number>(0) const [activeLine, setActiveLine] = useState<number>(0)
// eslint-disable-next-line react-hooks/rules-of-hooks // eslint-disable-next-line react-hooks/rules-of-hooks
const [valid, setValid] = useState<boolean>(false) const [valid, setValid] = useState<boolean>(false)
const [isPlaying, setIsPlaying] = useState<boolean>(true)
const initCases: CaseInfo[][] = [] const initCases: CaseInfo[][] = []
for(let li = 0; li < props.nLines; li++) { for(let li = 0; li < props.nLines; li++) {
@ -42,8 +44,13 @@ function Game(props: GameProps) {
const checkLine: (combination: Color[]) => boolean = (combination) => { const checkLine: (combination: Color[]) => boolean = (combination) => {
if (combination.every((elem, idx) => elem.name === props.combination[idx]) ){ if (combination.every((elem, idx) => elem.name === props.combination[idx]) ){
setValid(true); setValid(true);
setIsPlaying(false);
return true return true
} }
if (activeLine === props.nLines-1) {
setIsPlaying(false);
}
return false; return false;
} }
@ -78,25 +85,7 @@ function Game(props: GameProps) {
} }
</div> </div>
</div> </div>
<GameState isPlaying={isPlaying} hasWon={valid} activeLine={activeLine} combination={props.combination}></GameState>
<div hidden={(valid || activeLine >= props.nLines)}><h1>Trys : {activeLine}</h1></div>
<div hidden={!valid}><h1>Congratulations ! you won in {activeLine+1} try(s) !</h1></div>
<div className={"lose"} hidden={!(!valid && activeLine >= props.nLines)}>
<div id={"lose-header"}><h1>You lost !</h1><div className={"fa fa-arrow-alt-circle-down scroll-arrow"}
onClick={() => {
console.log("clicked");
document.getElementById("bottom")!.scrollIntoView({behavior: "smooth"});
}}></div>
</div>
<h2>Combination was :</h2>
<div className={"line"}>
{props.combination.map(
(color, idx) => <DroppablePin key={'result-'+idx} color={color} id={'result-'+idx} className={'circle'} />)
}
</div>
</div>
<span id="bottom"></span> <span id="bottom"></span>
</> </>
) )

View File

@ -0,0 +1,17 @@
#lose-header {
display: flex;
width: 100%;
align-items: center;
justify-content: center;
gap: 2em;
}
#lose-header .scroll-arrow {
font-size: 3em;
}
@media (max-width: 720px) {
#lose-header .scroll-arrow {
width: calc(3em / 1.5);
}
}

View File

@ -0,0 +1,41 @@
import DroppablePin from "../DroppablePin/DroppablePin.tsx";
interface GameStateProps {
isPlaying: boolean;
hasWon: boolean;
activeLine: number;
combination: Array<string>;
}
function GameState(props: GameStateProps) {
const tries = props.isPlaying ? <div><h1>Tries : {props.activeLine}</h1></div> : null;
const win = (!props.isPlaying && props.hasWon) ? <div><h1>Congratulations ! you won in {props.activeLine+1} tries !</h1></div> : null;
const lose = (!props.isPlaying && !props.hasWon) ? <div className={"lose"}>
<div id={"lose-header"}><h1>You lost !</h1><div className={"fa fa-arrow-alt-circle-down scroll-arrow"}
onClick={() => {
console.log("clicked");
document.getElementById("bottom")!.scrollIntoView({behavior: "smooth"});
}}></div>
</div>
<h2>Combination was :</h2>
<div className={"line"}>
{props.combination!.map(
(color, idx) => <DroppablePin key={'result-'+idx} color={color} id={'result-'+idx} className={'circle'} />)
}
</div>
</div> : null;
return (
<>
{tries}
{win}
{lose}
</>
);
}
export default GameState;