11import React from "react" ;
22
3- const MOVES = [ "rock" , "paper" , "scissors" ] as const ;
4- type Move = ( typeof MOVES ) [ number ] ;
3+ const MOVES_CONFIG = {
4+ rock : {
5+ scissors : "crushes" ,
6+ lizard : "crushes" ,
7+ } ,
8+ paper : {
9+ rock : "covers" ,
10+ spock : "disproves" ,
11+ } ,
12+ scissors : {
13+ paper : "cuts" ,
14+ lizard : "decapitates" ,
15+ } ,
16+ lizard : {
17+ paper : "eats" ,
18+ Spock : "poisons" ,
19+ } ,
20+ Spock : {
21+ scissors : "smashes" ,
22+ rock : "vaporizes" ,
23+ } ,
24+ } as const ;
25+
26+ type Move = keyof typeof MOVES_CONFIG ;
27+
28+ function objectKeys < T extends Record < PropertyKey , unknown > > (
29+ obj : T ,
30+ ) : ( keyof T ) [ ] {
31+ return Object . keys ( obj ) ;
32+ }
33+
34+ const MOVES : readonly Move [ ] = objectKeys ( MOVES_CONFIG ) ;
535
636function getRandomMove ( ) : Move {
7- const index = Math . floor ( Math . random ( ) * 3 ) ;
37+ const index = Math . floor ( Math . random ( ) * MOVES . length ) ;
838 return MOVES [ index ] ;
939}
1040
@@ -13,9 +43,7 @@ function getWinner(moveA: Move, moveB: Move): "a" | "b" | "tie" {
1343 return "tie" ;
1444 }
1545
16- const indexA = MOVES . indexOf ( moveA ) ;
17- const indexB = MOVES . indexOf ( moveB ) ;
18- return ( indexA + 1 ) % MOVES . length === indexB ? "b" : "a" ;
46+ return Object . hasOwn ( MOVES_CONFIG [ moveA ] , moveB ) ? "a" : "b" ;
1947}
2048
2149type GameResults = { wins : number ; losses : number ; draws : number } ;
@@ -68,6 +96,8 @@ function App() {
6896 < button onClick = { ( ) => handleMove ( "rock" ) } > 🪨</ button >
6997 < button onClick = { ( ) => handleMove ( "paper" ) } > 📄</ button >
7098 < button onClick = { ( ) => handleMove ( "scissors" ) } > ✂️</ button >
99+ < button onClick = { ( ) => handleMove ( "lizard" ) } > 🦎</ button >
100+ < button onClick = { ( ) => handleMove ( "Spock" ) } > 🖖</ button >
71101 </ div >
72102 </ div >
73103 ) ;
0 commit comments