React Native Word Search: Locking Used Letters & Highlighting Found Words

0
51

React Native Word Search: Locking Used Letters & Highlighting Found Words

๐Ÿš€ Tutorial #13 โ€“ Applying Colors to Guessed Words & Locking Used Cells


๐Ÿ“Œ SEO Optimization

SEO Title:

โ€œReact Native Word Search: Lock Used Letters & Highlight Found Wordsโ€

Short Meta Description (Max 60 characters):

โ€œLock guessed words and highlight found letters in Word Search.โ€

Full Meta Description:

โ€œLearn how to visually lock used letters, prevent reselection, and highlight found words in a React Native Word Search game. This tutorial covers UI improvements and game logic.โ€

Keywords:

React Native Word Search, Track guessed words, Highlight found words, Prevent duplicate word selection, Lock letters in Word Search, TypeScript word search improvements


๐Ÿ“Œ Introduction

In this tutorial, we will:
โœ… Ensure that once a word is correctly guessed, the letters cannot be selected again.
โœ… Apply a grey color (foundLetter style) to guessed letters to visually lock them.
โœ… Update the FlatList to track found words and highlight them in green.
โœ… Modify handleSubmit to update found definitions and prevent duplicate submissions.
โœ… Ensure users cannot select letters that are already locked.
โœ… Fully test the solution on both iOS and Android to confirm correct behavior.

By the end of this tutorial, your Word Search game will track guessed words visually, preventing re-selection while enhancing UI feedback. ๐Ÿš€


๐Ÿ“Œ Step 1: Locking Used Letters in the Grid

Currently, after guessing a word, letters remain selectable. We need to lock them visually and prevent further selection.

1๏ธโƒฃ Tracking Used Letters

We add a state to track used letters separately from selectedCells:

const [usedCells, setUsedCells] = useState<{ row: number; col: number }[]>([]);

โœ… Now, we can track individual letters that belong to correctly guessed words.


2๏ธโƒฃ Applying the foundLetter Style

Modify the handleSubmit function to add guessed word letters to usedCells, ensuring they are greyed out and locked.

const handleSubmit = () => {
  const lowerCaseSelectedWord = selectedWord.toLowerCase();
  const lowerCaseDefinitions = definitions.map((definition) => definition.toLowerCase());

  if (foundDefinitions.includes(lowerCaseSelectedWord)) {
    alert(`โŒ "${selectedWord}" has already been found.`);
    return;
  }

  if (lowerCaseDefinitions.includes(lowerCaseSelectedWord)) {
    setGuessedWords([...guessedWords, selectedWord]); // Add word to guessed list
    setUsedLetters([...usedLetters, ...selectedCells]); // Lock letters in grey
    setUsedCells([...usedCells, ...selectedCells]); // Lock cells in place
    setFoundDefinitions([...foundDefinitions, lowerCaseSelectedWord]); // Add definition to found list
    setSelectedWord(""); // Clear text box
    setSelectedCells([]); // Reset selected cells
    alert(`โœ… Correct! "${selectedWord}" is a valid word.`);
  } else {
    alert(`โŒ Incorrect. Try again.`);
  }
};

โœ… Now, guessed word letters cannot be selected again and remain grey.


3๏ธโƒฃ Preventing Selection of Locked Letters

Modify handleTouch to prevent selecting letters that are in usedCells.

const handleTouch = (event: GestureResponderEvent) => {
  const { pageX, pageY } = event.nativeEvent;

  const row = Math.floor((pageY - gridLayout.y) / CELL_SIZE);
  const col = Math.floor((pageX - gridLayout.x) / CELL_SIZE);

  // Ensure the touch is within a valid grid cell and hasn't been used already
  if (
    row >= 0 &&
    row < GRID_SIZE &&
    col >= 0 &&
    col < GRID_SIZE &&
    !usedCells.some((cell) => cell.row === row && cell.col === col)
  ) {
    const selectedLetter = grid[row][col].letter;

    if (!selectedCells.some((cell) => cell.row === row && cell.col === col)) {
      setSelectedCells([...selectedCells, { row, col }]);
      setSelectedWord((prevWord) => prevWord + selectedLetter);
    }
  }
};

โœ… Now, users cannot select letters that are already locked from previous guesses.


๐Ÿ“Œ Step 2: Highlighting Found Words in FlatList

1๏ธโƒฃ Tracking Found Words

We modify FlatList rendering logic to highlight words that have been found.

<FlatList
  data={words}
  keyExtractor={(item) => item}
  numColumns={4}
  renderItem={({ item, index }) => (
    <View style={[
      globalStyles.wordBox,
      foundDefinitions.includes(definitions[index].toLowerCase()) && globalStyles.wordFound
    ]}>
      <Text style={globalStyles.wordBoxText}>{item}</Text>
    </View>
  )}
/>

โœ… Now, guessed words are marked in green in the word list.


๐Ÿ“Œ Step 3: Updating UI Styles

๐Ÿ“ We modify globalStyles.ts to:
โœ… Apply grey (foundLetter) to locked letters.
โœ… Apply green (wordFound) to found words.

foundLetter: {
  backgroundColor: "#B0B0B0", // Grey for found letters
},

wordFound: {
  backgroundColor: "#A1F3A1", // Light green for found words
},

โœ… Now, locked letters are grey, and guessed words are green.


๐Ÿ“Œ Step 4: The Final wordSearch.tsx Code

๐Ÿ“ Location: app/wordSearch.tsx

<View
  ref={gridRef}
  style={globalStyles.gridBackground}
  {...panResponder.panHandlers}
  onLayout={() => {
    if (gridRef.current) {
      gridRef.current.measure((x, y, width, height, pageX, pageY) => {
        setGridLayout({ x: pageX, y: pageY, width, height });
      });
    }
  }}
>
  {grid.map((row, rowIndex) => (
    <View key={rowIndex} style={globalStyles.wordSearchRow}>
      {row.map((cell) => (
        <TouchableOpacity
          key={`${cell.row}-${cell.col}`}
          style={[
            globalStyles.wordSearchCell,
            { width: CELL_SIZE, height: CELL_SIZE }, // Fixed size cells
            selectedCells.some((c) => c.row === cell.row && c.col === cell.col) && globalStyles.foundWord,
            usedCells.some((c) => c.row === cell.row && c.col === cell.col) && globalStyles.foundLetter, // Apply foundLetter style to used cells
          ]}
          onPress={(event) => handleTouch({
            ...event,
            nativeEvent: {
              ...event.nativeEvent,
              pageX: cell.col * CELL_SIZE + gridLayout.x,
              pageY: cell.row * CELL_SIZE + gridLayout.y,
            }
          })}
        >
          <Text style={globalStyles.wordSearchLetter}>{cell.letter}</Text>
        </TouchableOpacity>
      ))}
    </View>
  ))}
</View>

โœ… Now, the grid correctly updates, preventing re-selection of locked letters.


๐Ÿ“Œ Step 5: Restart & Test the Fix

1๏ธโƒฃ Restart the app:

npx expo start

2๏ธโƒฃ Test the following:

  • Grid correctly places definition characters first.
  • Words remain selected until manually cleared.
  • Once a word is guessed, its letters remain grey and cannot be reselected.
  • FlatList changes guessed words to green.
  • Other instances of the same letter remain selectable.
    3๏ธโƒฃ Check the console logs for correct letter selection.
Touched Cell: Row 3, Col 5, Letter: "B"

๐Ÿ“Œ Conclusion

๐ŸŽฏ Now, your Word Search game is fully interactive!
โœ… The grid places all definition characters, including spaces and punctuation.
โœ… Words remain selected until manually cleared.
โœ… Letters used in guessed words turn grey and cannot be reselected.
โœ… FlatList highlights guessed words in green.
โœ… Other occurrences of the same letter remain selectable.

๐Ÿš€ Now, the Word Search game has fully dynamic grid generation and proper word tracking! ๐ŸŽฎ๐Ÿ”ฅ

Try it out and let me know if the tutorial is clear! ๐Ÿš€