Это одна из тривиальных реализаций простой игры, которую новичок может использовать для проверки своего уровня понимания языка программирования. На самом деле меня попросили реализовать это на JavaScript в интервью. Сначала я ожидал, что мне зададут вопросы о технологиях (Node.js и React.js) в отношении должности, потому что я провел первоначальную оценку алгоритма на платформе удаленной работы, но меня встретил интервьюер, который отвел меня на online IDE и попросил, чтобы я реализовал Tic Tac Toe с парой скелетных функций. Между тем, мы потратили 10 минут из 30 минут на сеанс на технические вопросы, переход от увеличения к Google Meet, проблемы со звуком и потраченное время не были компенсированы. Интервьюер опередил меня на 6 часов в часовом поясе. Я не масштабировался. Раздражающий. Фух!
Хотя крестики-нолики могут быть банальными, но я не уверен, что 30 минут достаточно, вероятно, час будет хорошо. После этой неприятной встречи я решил реализовать Tic Tac Toe, не обращаясь за помощью в Google (в интервью мне была предоставлена возможность поиска в Google).
Единственная часть, которую я получил от Google для этой реализации, это то, как читать ввод из командной строки в Node.js, с которым я был не очень знаком, но реализация этого помогла мне понять, как заставить объект readline принимать входные данные от команды. строка в Node.js
Крестики-нолики
По данным Википедии (см. Изображение в заголовке). Крестики-нолики, крестики и нолики или крестики и крестики - это игра в карандаш и бумагу для двух игроков, X и O, которые по очереди отмечают пробелы в сетке 3 × 3. Игрок, которому удастся разместить три своих метки в горизонтальном, вертикальном или диагональном ряду, становится победителем.
Реализация
Итак, первая часть Tic Tac Toe - это представление игры. И используется массив. Одномерный массив. Мы также можем использовать 2D или двумерный массив 3x3 (это изменит реализацию) и упростить вычисление победителя (если вы новичок, попробуйте). И массив инициализирован пустыми строками, чтобы иметь пустую доску. Мы дадим игрокам возможность сменить стартового игрока. Доска известна игрокам как 1–9.
let player = ‘X’; let ticktacktoe = [ ’ ', ’ ', ‘ ', ’ ’, ’ ’, ‘ ’, ’ ’, ’ ’, ‘ ’ ];
И при каждой игре нам нужно распечатать доску, показывающую состояние игры. Итак, мы кодируем printboard()
. Прокрутите массив (игровую доску) с помощью цикла for. Мы также можем использовать map()
. Мы использовали оператор модуля, чтобы вызвать печать новой строки.
const printBoard = () => { let line = “”; for (let i = 1; i < 10; i++) { line += ticktacktoe[i-1] + ‘ | ‘; if (i % 3 === 0) { console.log(line); console.log(‘____________’) line = “”; } } }
Мы должны дать игрокам возможность установить первого игрока . defaultPlayer()
функция проверяет, должны ли игроки продолжать с X. Сначала мы объявляем объект readline rl
для чтения из стандартного ввода. Он полагается на объект global process
. Если мы получаем «Да», мы вызываем setPlayer()
, который вызывает changePlayer().
. Если нет, мы printBoard() playTickTacToe()
и начинаем игру.
const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const defaultPlayer = () => { rl.question(“Default player is X, Do you want to change it, y or n “, function (defaultOrChoose) { let choice = defaultOrChoose.toLowerCase(); if (choice == ‘y’) { setPlayer(); } else if (choice === ’n’) { console.log(`Starting player is X`); printBoard(); playTickTacToe(); } else { defaultPlayer(); } }); } const setPlayer = () => { rl.question(“Default player is X, Do you want to change it, enter O? “, function (whichPlayer) { changePlayer(whichPlayer); }); } const changePlayer = (playerChange) => { let mov = playerChange.toUpperCase(); if (mov === ‘O’ || mov === ‘X’) { console.log(`Starting player is ${mov}`) player = mov; printBoard(); playTickTacToe(); } else { setPlayer(); } }
Следующим шагом будет кодирование пьесы. playTickTacToe()
инициализирует флаг continuePlay
, чтобы проверить, есть ли оставшиеся игровые слоты, и попросить игрока сделать ход.
const playTickTacToe = () => { let continePlay = false; for (i = 0; i < ticktacktoe.length; i++) { if (ticktacktoe[i] === ‘ ‘) { continePlay = true; } } if (continePlay === true) { rl.question(“Play Game ? “, function (movve) { gameplayer(movve) }); } };
playTickTacToe()
callsgameplayer(movve)
, который является движком, игровой логикой. Игроки играют с 1 по 9. 1–3 = первый ряд, 4–6 = второй ряд и 7–9 = третий ряд. Внутренние индексы представительства в наших советах директоров от 0 до 8. Итак, сначала мы выравниваем движение in let moveToCheck
, анализируя строку, которую мы получаем из командной строки. Затем мы переходим к обходу или итерации по массиву (игровому полю). Когда мы находим индекс, соответствующий ходу игрока, мы проверяем, является ли это пустым слотом moveToCheck == i && ticktacktoe[i] === ‘ ‘
. Если это так, мы устанавливаем слот на плеер. Иначе мы ничего не делаем и просим игрока сделать еще один ход. Если ход допустим, мы устанавливаем ход игрока. Повторить!
const gameplayer = (move) => { let moveToCheck = parseInt(move) — 1; let i; for (i = 0; i < ticktacktoe.length; i++) { if (moveToCheck == i && ticktacktoe[i] === ‘ ‘) { ticktacktoe[i] = player; if (player === ‘X’) { player = ‘O’; } else if (player === ‘O’) { player = ‘X’ } }else{ playTickTacToe(); } } console.log(‘\n’); printBoard(); const winner = calculateWinner(); if (winner != ‘ ‘) { console.log(`Winner is ${winner}`) process.exit(0); } playTickTacToe(); }
Затем мы приступаем к печати доски. И вычислите победителя. Мы опишем calculateWinner()
дальше. Это делается на каждом шагу. Мы можем по-разному подсчитывать победителя, по крайней мере, до 3 ходов. Это оптимизация. Для учащегося в центре внимания должна быть грубая сила. Сначала получите рабочее решение. В Принципах разработки программного обеспечения это называется преждевременной оптимизацией. Известный компьютерный ученый Дональд Кнут отметил это в одном из своих сочинений.
«Преждевременная оптимизация - это корень всего зла (или, по крайней мере, большей его части) в программировании» - Дональд Кнут
Функция calculateWinner()
проверяет, выпала ли одна из 8 возможных выигрышных ситуаций. Возможности выигрыша от индексов массива:
По горизонтали = ›0,1,2; 3,4,5; 6,7,8
Вертикально = ›0,3,6; 1,4,7; 2,5,8
По диагонали = ›0,4,8; 2,4,6
const calculateWinner = () => { // We can improve this to make it less verbose by declaring the // slots as const like const zero = ticktacktoe[0]; // and replace all occurances if (ticktacktoe[0] == ticktacktoe[1] && ticktacktoe[0] == ticktacktoe[2]) { return ticktacktoe[0]; } else if (ticktacktoe[3] == ticktacktoe[4] && ticktacktoe[3] == ticktacktoe[5]) { return ticktacktoe[3]; } else if (ticktacktoe[6] == ticktacktoe[7] && ticktacktoe[6] == ticktacktoe[8]) { return ticktacktoe[6]; } else if (ticktacktoe[0] == ticktacktoe[3] && ticktacktoe[0] == ticktacktoe[6]) { return ticktacktoe[0]; } else if (ticktacktoe[1] == ticktacktoe[4] && ticktacktoe[1] == ticktacktoe[7]) { return ticktacktoe[1]; } else if (ticktacktoe[2] == ticktacktoe[5] && ticktacktoe[2] == ticktacktoe[8]) { return winner = ticktacktoe[2]; } else if (ticktacktoe[0] == ticktacktoe[4] && ticktacktoe[0] == ticktacktoe[8]) { return ticktacktoe[0]; }else if (ticktacktoe[2] == ticktacktoe[4] && ticktacktoe[2] == ticktacktoe[6]) { return ticktacktoe[2]; } return ‘ ‘; }
На этом мы подошли к концу простого упражнения. Все, что мы делаем, это вызываем наши printboard()
и defaultPlayer()
, чтобы начать игру. Установив Node.js, вы можете запустить его в командной строке как node ticktacktoe.js
, и мы играем. Вот полная версия игры на github gist.
Тот интервьюер / компания, которая думала, что я не смогу реализовать крестики-нолики, упустила грамотного программиста.
Примечание на простом английском
Вы знали, что у нас четыре публикации и канал на YouTube? Вы можете найти все это на нашей домашней странице plainenglish.io - проявите немного любви, подписавшись на наши публикации и подписавшись на наш канал YouTube!