@@ -45,39 +45,89 @@ function initWhackaMole() {
4545 let timeLeft = 30 ;
4646 let gameActive = false ;
4747 let activeIndex = - 1 ;
48+ let lastActiveIndex = - 1 ;
49+ let lastActiveTime = 0 ;
4850 let timerId = null ;
4951 let moleId = null ;
5052
5153 const holes = Array . from ( { length : 9 } , ( _ , index ) => {
5254 const button = document . createElement ( 'button' ) ;
5355 button . type = 'button' ;
5456 button . className = 'whack-hole' ;
57+ button . textContent = '🕳️' ;
5558 button . setAttribute ( 'aria-label' , `Hole ${ index + 1 } ` ) ;
56- button . addEventListener ( 'click' , ( ) => {
57- if ( ! gameActive || index !== activeIndex ) return ;
59+
60+ const handleHit = ( e ) => {
61+ if ( e ) e . preventDefault ( ) ;
62+ if ( ! gameActive ) return ;
63+
64+ const isDirectHit = ( index === activeIndex ) ;
65+ const isGraceHit = ( index === lastActiveIndex && ( Date . now ( ) - lastActiveTime ) < 150 ) ;
66+
67+ if ( ! isDirectHit && ! isGraceHit ) return ;
68+
5869 score += 1 ;
5970 scoreEl . textContent = String ( score ) ;
60- messageEl . textContent = 'Hit!' ;
71+ messageEl . textContent = 'Hit! 🔨' ;
72+ button . textContent = '💥' ;
73+ button . classList . remove ( 'active' ) ;
74+
75+ // Set to -1 immediately to prevent double hits
76+ activeIndex = - 1 ;
77+ lastActiveIndex = - 1 ;
78+
6179 clearTimeout ( moleId ) ;
62- showMole ( ) ;
63- } ) ;
80+ moleId = setTimeout ( showMole , 250 ) ;
81+ } ;
82+
83+ button . addEventListener ( 'pointerdown' , handleHit ) ;
84+ button . addEventListener ( 'click' , handleHit ) ;
85+
6486 board . appendChild ( button ) ;
6587 return button ;
6688 } ) ;
6789
6890 function showMole ( ) {
69- holes . forEach ( hole => hole . classList . remove ( 'active' ) ) ;
70- activeIndex = Math . floor ( Math . random ( ) * holes . length ) ;
91+ if ( ! gameActive ) return ;
92+
93+ // Save previous active mole state for grace period
94+ if ( activeIndex !== - 1 ) {
95+ lastActiveIndex = activeIndex ;
96+ lastActiveTime = Date . now ( ) ;
97+ }
98+
99+ holes . forEach ( hole => {
100+ hole . classList . remove ( 'active' ) ;
101+ hole . textContent = '🕳️' ;
102+ } ) ;
103+
104+ // Choose a new hole, ensuring it is different from the current one
105+ let newIndex ;
106+ do {
107+ newIndex = Math . floor ( Math . random ( ) * holes . length ) ;
108+ } while ( newIndex === activeIndex && holes . length > 1 ) ;
109+
110+ activeIndex = newIndex ;
71111 holes [ activeIndex ] . classList . add ( 'active' ) ;
112+ holes [ activeIndex ] . textContent = '🐭' ;
113+
72114 moleId = setTimeout ( showMole , 850 ) ;
73115 }
74116
75117 function stopGame ( finalMessage ) {
76118 gameActive = false ;
77119 clearInterval ( timerId ) ;
120+ timerId = null ;
78121 clearTimeout ( moleId ) ;
79- holes . forEach ( hole => hole . classList . remove ( 'active' ) ) ;
122+ moleId = null ;
123+ activeIndex = - 1 ;
124+ lastActiveIndex = - 1 ;
125+ holes . forEach ( hole => {
126+ hole . classList . remove ( 'active' ) ;
127+ hole . textContent = '🕳️' ;
128+ } ) ;
80129 messageEl . textContent = finalMessage ;
130+ startBtn . disabled = false ;
81131 }
82132
83133 function startGame ( ) {
@@ -87,29 +137,37 @@ function initWhackaMole() {
87137 scoreEl . textContent = '0' ;
88138 timeEl . textContent = '30' ;
89139 messageEl . textContent = 'Go!' ;
140+ startBtn . disabled = true ;
90141 clearInterval ( timerId ) ;
91142 clearTimeout ( moleId ) ;
92- showMole ( ) ;
93143 timerId = setInterval ( ( ) => {
94144 timeLeft -= 1 ;
95145 timeEl . textContent = String ( timeLeft ) ;
96146 if ( timeLeft <= 0 ) {
97147 stopGame ( `Time! Final score: ${ score } ` ) ;
98148 }
99149 } , 1000 ) ;
150+ showMole ( ) ;
100151 }
101152
102153 startBtn . addEventListener ( 'click' , startGame ) ;
103154 resetBtn . addEventListener ( 'click' , ( ) => {
104155 clearInterval ( timerId ) ;
156+ timerId = null ;
105157 clearTimeout ( moleId ) ;
158+ moleId = null ;
106159 score = 0 ;
107160 timeLeft = 30 ;
108161 gameActive = false ;
109162 activeIndex = - 1 ;
110- holes . forEach ( hole => hole . classList . remove ( 'active' ) ) ;
163+ lastActiveIndex = - 1 ;
164+ holes . forEach ( hole => {
165+ hole . classList . remove ( 'active' ) ;
166+ hole . textContent = '🕳️' ;
167+ } ) ;
111168 scoreEl . textContent = '0' ;
112169 timeEl . textContent = '30' ;
113170 messageEl . textContent = 'Hit the mole when it appears.' ;
171+ startBtn . disabled = false ;
114172 } ) ;
115173}
0 commit comments