Introduction: Making Guesses Smarter

Welcome to the first lesson of our course, “Enhancing the Word Play Game with New Functionalities”. In this lesson, we will make our word prediction game more interactive and fair by adding a way to score player guesses. Instead of only rewarding exact matches, we want to give points for guesses that are close in meaning to the correct answer. This will make the game more fun and challenging, and it will feel more like how people actually use language.

By the end of this lesson, you’ll know how to compare two words for similarity and assign a score based on how close they are in meaning. This is a key step in building a smarter, more engaging game.

What Is Semantic Similarity?

Semantic similarity is a way to measure how close two words are in meaning. For example, car and automobile mean almost the same thing, so they are semantically similar. On the other hand, car and banana are not similar at all.

Here’s a simple table to show some examples:

Word 1Word 2Are they similar?
carautomobileYes
catkittenSomewhat
carbananaNo

In our game, we want to reward players for making guesses that are close in meaning, not just exact matches. This makes the game fairer and more fun.

How Computers Compare Word Meanings
Building the Guess Scorer Function

Let’s build our guess scorer step by step in JavaScript.

Step 1: Import the OpenAI Library and Initialize the Client

First, we need to import the OpenAI library and create a client using your API key. This will let us request word embeddings from the OpenAI API.

const OpenAI = require('openai');
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
  • require('openai') imports the OpenAI library.
  • new OpenAI({ apiKey: ... }) creates a client that can talk to the OpenAI API.
Step 2: Prepare the Words for the API

Next, we need to prepare the user’s guess and the correct word as an array of lowercase strings. This array will be sent to the API to get their embeddings.

const input = [userGuess.toLowerCase(), correctWord.toLowerCase()];
  • We use .toLowerCase() to make sure the comparison is case-insensitive.
  • Both words are put into an array, which the API will process together.
Step 3: Get Embeddings and Calculate the Similarity

Now, we can use the OpenAI API to get the embeddings for both words, and then calculate the cosine similarity between them.

const res = await client.embeddings.create({
  model: 'text-embedding-3-small',
  input
});
const [v1, v2] = res.data.map(d => d.embedding);
  • client.embeddings.create sends the words to the API and gets their embeddings.
  • res.data.map(d => d.embedding) extracts the embedding vectors for each word.

To calculate the cosine similarity, we use a helper function:

function cosineSimilarity(a, b) {
  if (!a?.length || !b?.length || a.length !== b.length) return 0;
  let dot = 0, na = 0, nb = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    na += a[i] * a[i];
    nb += b[i] * b[i];
  }
  if (!na || !nb) return 0;
  return dot / (Math.sqrt(na) * Math.sqrt(nb));
}
  • This function takes two vectors and returns a similarity score between -1 and 1.
Step 4: Convert the Score to a Percentage

To make the score easier to understand, we multiply it by 100 to get a value between 0 and 100.

const sim = cosineSimilarity(v1, v2);
return sim * 100;
Step 5: Put It All Together

Here is the complete function:

const OpenAI = require('openai');
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

function cosineSimilarity(a, b) {
  if (!a?.length || !b?.length || a.length !== b.length) return 0;
  let dot = 0, na = 0, nb = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    na += a[i] * a[i];
    nb += b[i] * b[i];
  }
  if (!na || !nb) return 0;
  return dot / (Math.sqrt(na) * Math.sqrt(nb));
}

async function scoreGuess(userGuess, correctWord) {
  try {
    const input = [userGuess.toLowerCase(), correctWord.toLowerCase()];
    const res = await client.embeddings.create({
      model: 'text-embedding-3-small',
      input
    });
    const [v1, v2] = res.data.map(d => d.embedding);
    const sim = cosineSimilarity(v1, v2);
    return sim * 100; // Scale to 0–100
  } catch (e) {
    console.error('❌ Embedding similarity failed:', e);
    return 0;
  }
}

Let’s see an example of how to use this function:

(async () => {
  console.log(await scoreGuess("cat", "kitten"));        // Output: e.g. 74.2
  console.log(await scoreGuess("car", "automobile"));    // Output: e.g. 87.5
  console.log(await scoreGuess("car", "banana"));        // Output: e.g. 12.3
})();
  • The function gives a higher score for words that are close in meaning.
  • The output values are just examples; your results may be slightly different depending on the API and model.
Summary and Practice Preview

In this lesson, you learned how to make your word prediction game smarter by scoring guesses based on their meaning, not just their spelling. We talked about semantic similarity, word vectors (embeddings), and how to use the OpenAI API in JavaScript to compare words. You also saw how to build a function that gives a score from 0 to 100 for any two words.

This new scoring system will make your game more fun and fair, rewarding players for close guesses. In the next practice exercises, you’ll get hands-on experience using and testing this function. Get ready to see how your game can understand language just a little bit more like a human!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal