Синтаксический анализатор StringToken, который дает стиль Google Search, “Сделал Вы имеете в виду”: предложения

Вы можете .map текущие координаты змеи в массив строк currentSnakeX_Ys (x#_y#), затем сгенерировать food x и y с, а currentSnakeX_Ys.includes(`${food.x}_${food.y}`):

//create new food position
const currentSnakeX_Ys = snake.map(({ x, y }) => `${x}_${y}`);
do {
  food = {
    x: Math.floor(Math.random() * ((cvsW / unit) - 1) + 1) * unit,
    y: Math.floor(Math.random() * ((cvsH / unit) - 1) + 1) * unit
  }
} while (currentSnakeX_Ys.includes(`${food.x}_${food.y}`));

const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');

//set canvas dimension equal to css dimension
canvas.width = 768;
canvas.height = 512;

//now put those dimensions into variables
const cvsW = canvas.width;
const cvsH = canvas.height;

//create snake unit
const unit = 16;

//create snake array
let snake = [{
  x: cvsW / 2,
  y: cvsH / 2
}];

//delcare global variable to hold users direction
let direction;

//create food object
let food = {
  x: Math.floor(Math.random() * ((cvsW / unit) - 1) + 1) * unit,
  y: Math.floor(Math.random() * ((cvsH / unit) - 1) + 1) * unit
}

//read user's direction
document.addEventListener('keydown', changeDirection);

function changeDirection(e) {
  //set direction
  if (e.keyCode == 37 && direction != 'right') direction = 'left';
  else if (e.keyCode == 38 && direction != 'down') direction = 'up';
  else if (e.keyCode == 39 && direction != 'left') direction = 'right';
  else if (e.keyCode == 40 && direction != 'up') direction = 'down';
}

function draw() {
  //refresh canvas
  ctx.clearRect(0, 0, cvsW, cvsH);
  //draw snake
  for (let i = 0; i < snake.length; i++) {
    ctx.fillStyle = 'limegreen';
    ctx.fillRect(snake[i].x, snake[i].y, unit, unit);
  }

  //grab head position
  let headX = snake[0].x;
  let headY = snake[0].y;

  //posistion food on board
  ctx.fillStyle = 'red';
  ctx.fillRect(food.x, food.y, unit, unit);

  //send the snake in chosen direction
  if (direction == 'left') headX -= unit;
  else if (direction == 'up') headY -= unit;
  else if (direction == 'right') headX += unit;
  else if (direction == 'down') headY += unit;

  // //check if snake hit wall
  // if(headX < 0 || headY < 0 || headX > (cvsW-unit) || headY > (cvsH-unit)) {
  // 	clearInterval(runGame);
  // }

  if (headX < 0) headX = cvsW - unit;
  else if (headX > cvsW - unit) headX = 0;
  else if (headY < 0) headY = cvsH - unit;
  else if (headY > cvsH - unit) headY = 0;

  // check to see if snake has collided with itself
  // for(let i = 0; i < snake.length; i++) {
  // 	if(headX == snake[i].x && headY == snake[i].y) {
  // 		clearInterval(game);
  // 	}
  // }

  //create new head
  let newHead = {
    x: headX,
    y: headY
  }

  //if snake eats food -do this
  if (headX == food.x && headY == food.y) {
    //create new food position
    const currentSnakeX_Ys = snake.map(({ x, y }) => `${x}_${y}`);
    do {
      food = {
        x: Math.floor(Math.random() * ((cvsW / unit) - 1) + 1) * unit,
        y: Math.floor(Math.random() * ((cvsH / unit) - 1) + 1) * unit
      }
    } while (currentSnakeX_Ys.includes(`${food.x}_${food.y}`));

    //add 3 units to the snake
    for (let i = 30; i > 0; i--) {
      snake.unshift(newHead);
    }
  } else {
    //remove tail
    snake.pop();
  }

  //add head to snake
  snake.unshift(newHead);
}

//run game engine
let runGame = setInterval(draw, 40);
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Snake Game</title>
  <style>
    body {
      background-color: #333;
    }
    
    canvas {
      background-color: #4d4d4d;
      margin: auto;
      display: block;
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      width: 750px;
      height: 500px;
    }
  </style>
</head>

<body>
  <canvas id="canvas"></canvas>
  <script src="script.js"></script>
</body>

</html>

(вы также можете проходить итерации по snake вместо каждого поколения продуктов питания и проверять текущий x ] и y не относятся как к x, так и к y пищи, но заранее создав массив строк, все становится намного проще, потому что тогда вы можете просто использовать тест .includes)

код СУХОЙ, вместо того, чтобы вводить его каждый раз, когда вам нужно сгенерировать пищу, поместите вышеупомянутое в функцию и вызовите эту функцию:

5
задан Georg Fritzsche 22 May 2010 в 20:35
поделиться

8 ответов

В его статье How to Write a Spelling Corrector Peter Norvig обсуждает, как могла быть реализована подобная Google программа проверки правописания. Статья содержит реализацию с 20 строками в Python, а также связывается с несколькими перереализациями в C, C++, C# и Java. Вот выборка:

Полное изложение корректора написания промышленной силы как Google более сбивало бы с толку, чем просвещение, но я полагал, что на плоском полете домой, меньше чем на странице кода, мог записать игрушечный орфографический корректор, который достигает 80 или 90%-я точность в скорости обработки по крайней мере 10 слов в секунду.

С помощью кода Norvig и этого текста как обучающее множество, я получаю следующие результаты:

>>> import spellch
>>> [spellch.correct(w) for w in 'fonetic wrd nterpreterr'.split()]
['phonetic', 'word', 'interpreters']
11
ответ дан 18 December 2019 в 06:52
поделиться

Можно использовать веб-сервис Yahoo здесь: http://developer.yahoo.com/search/web/V1/spellingSuggestion.html

Однако это - только веб-сервис... (т.е. нет никаких API для другого языка и т.д.), но это производит JSON или XML, так... довольно легкий адаптироваться к любому языку...

2
ответ дан 18 December 2019 в 06:52
поделиться

Можно также использовать Google API для проверки правописания. Существует реализация ASP здесь (я не должен кредитовать за это, хотя).

2
ответ дан 18 December 2019 в 06:52
поделиться

Прежде всего:

Используйте тот по Вашему выбору. Я подозреваю, что это выполняет запрос против механизма проверки правописания с пределом слова точно один, это затем ничего не делает, если весь запрос допустим, иначе это заменяет каждое слово лучшим соответствием того слова. Другими словами, следующий алгоритм (пустая возвращаемая строка означает, что запрос не имел никаких проблем):

startup()
{
   set the spelling engines word suggestion limit to 1
}

option 1()
{
   int currentPosition = engine.NextWord(start the search at word 0, querystring);

   if(currentPosition == -1)
      return empty string; // Query is a-ok.

   while(currentPosition != -1)
   {
       queryString = engine.ReplaceWord(engine.CurrentWord, queryString, the suggestion with index 0);
       currentPosition = engine.NextWord(currentPosition, querystring);
   }

   return queryString;
}
2
ответ дан 18 December 2019 в 06:52
поделиться

Так как никто еще не упомянул это, я дам еще одну фразу для поиска: "отредактируйте расстояние" (например, текст ссылки). Это может использоваться для нахождения самых близких соответствий, предполагая, что это - опечатки, где буквы транспонированы, отсутствуя или добавлены.

Но обычно это также вместе со своего рода информацией об уместности; любой по простой популярности (для принятия обычно используемый достаточно близко соответствуют, является, скорее всего, корректным словом), или контекстной вероятностью (слова, которые следуют за предыдущим корректным словом или прибывают перед одним). Это входит в информационный поиск; один способ запуститься состоит в том, чтобы посмотреть на биграмму и триграммы (последовательности слов, замеченных вместе). Google имеет очень обширные наборы данных в свободном доступе для них.

Для простого начального решения, хотя пара словаря с находящимся в Levenshtein matchers работает удивительно хорошо.

2
ответ дан 18 December 2019 в 06:52
поделиться

Google SOAP Search APIs делает это.

1
ответ дан 18 December 2019 в 06:52
поделиться

Вы могли включить Lucene, который имеет средство словаря, реализовывая метод расстояния Левенштейна.

Вот пример от Wiki, где 2 расстояние.

String[] l=spellChecker.suggestSimilar("sevanty", 2);
//l[0] = "seventy"
2
ответ дан 18 December 2019 в 06:52
поделиться

Если Вам сохранили словарь как trie, существует довольно простой способ найти лучше всего соответствующие записи, где символы могут быть вставлены, удалены или заменены.

void match(trie t, char* w, string s, int budget){
  if (budget < 0) return;
  if (*w=='\0') print s;
  foreach (char c, subtrie t1 in t){
    /* try matching or replacing c */
    match(t1, w+1, s+c, (*w==c ? budget : budget-1));
    /* try deleting c */
    match(t1, w, s, budget-1);
  }
  /* try inserting *w */
  match(t, w+1, s + *w, budget-1);
}

Идея состоит в том, что сначала Вы называете его с бюджетом нуля и видите, распечатывает ли это что-нибудь. Затем попробуйте бюджет 1, и так далее, пока он не распечатает некоторые соответствия. Чем больше бюджет, тем дольше он берет. Вы могли бы хотеть только подойти к бюджету 2.

Добавленный: не слишком трудно расширить это для обработки общих префиксов и суффиксов. Например, английские префиксы как "ООН", "анти-" и "скидка", могут быть в словаре и могут затем связаться назад с верхней частью словаря. Для суффиксов как "изм", "", и "редактор" там может быть отдельный trie, содержащий просто суффиксы и большинство слов, может связаться с тем суффиксом trie. Затем это может обработать странные слова как "antinationalizationalization".

1
ответ дан 18 December 2019 в 06:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: