Создадим игру, в которой нужно угадать число от 0 до 100, "загаданное" программой.

Игра будет состоять из трёх логических блоков: "загадывание", "отгадывание" и хранение числа.

Если необходимо иметь доступ к переменной из любой функции, то её нужно объявить во внешней области. В программировании это называется глобальной областью видимости. В нашем случае "загаданное" число должно быть видно в двух оставшихся блоках — при "загадывании" и "отгадывании".

Для этого создадим переменную, которая будет хранить "загаданное" число:
let number = -1;
Изначально присвоим переменной значение -1. Это будет означать, что число ещё не "загадано" или, другими словами, игра ещё не началась.

Напишем функцию, которая будет "загадывать" число:
function newGame() {
number = Math.ceil(Math.random() * Math.floor(100));
return "Новая игра. Угадайте число от 0 до 100.";
}
Эта функция генерирует случайное число от 0 до 100 и выводит сообщение, что можно начинать играть.

В данном курсе мы ещё не изучали генерацию случайных чисел и другие сложные математические операции. Поэтому не будем подробно разбирать, как работает функция, а просто в точности перепишем.

Если тебе интересно, как же всё-таки работает генерация случайного числа, можешь почитать про конструкции Math.random(), Math.floor() и Math.ceil() на MDN: Math.random, Math.floor, Math.ceil.

Теперь напишем функцию, которая будет сверять предположение игрока с "загаданным" числом:
function check(guess) {
if (number == -1) {
return "Чтобы начать новую игру, вызовите newGame()";
}
if (guess == number) {
let message = "Поздравляем! Вы угадали число " + number;
number = -1;
return message;
} else if (number > guess) {
return "Больше!";
} else if (number < guess) {
return "Меньше!";
}
}
  • Сначала мы проверяем, было ли "загадано" число. Если оно не было "загадано" (значение равно -1), то возвращает соответствующую строчку и завершаем функцию.
  • Далее проверяем версию игрока. Если она равна "загаданному" числу, то выводим строчку, что игрок угадал. И присваиваем переменной number значение -1, обозначая тем самым, что игра окончена.
  • Если "загаданное" число больше или меньше версии игрока, выводим соответствующую подсказку.
Вот и всё, игра готова. Давай попробуем поиграть.

Вызови check(10).

Результат: "Чтобы начать новую игру, вызовите newGame()". Всё верно, число ещё не "загадано".

Теперь необходимо начать игру newGame().

Результат: "Новая игра. Угадайте число от 0 до 100.". Всё верно.

Начнём угадывать число check(50). Алгоритм будет подсказывать нам ответами "Больше!" или "Меньше!".

Поиграй дальше и попробуй угадать число.

Маленькая хитрость, чтобы быстрее угадать: дели интервал, в котором находится число, пополам и вызывай функцию со средним значением.

Например, загадано число 68.

Искомый интервал от 0 до 100. Середина этого интервала — 50. Значит, сначала проверь check(50). Результат будет "Больше!".

Значит, новый интервал для поиска сократился вдвое и стал от 51 до 100.

Его середина равна 75. Проверяем check(75). Результат будет "Меньше!".

И снова интервал сократился вдвое: от 51 до 74. Середина примерно 62.
Проверяем check(62). Результат будет "Больше!".

Далее интервал от 63 до 74. Середина 68. Проверяем check(68). Результат будет "Поздравляем! Вы угадали число 68".

Сокращение интервала поиска вдвое — это самый быстрый способ угадать число, если подсказками могут быть либо "больше", либо "меньше".
База студентов
Давай создадим приложение, имитирующее работу с базой данных студентов.
Из каких блоков будет состоять наша программа?

  • Сама база данных. В её роли будет глобальная переменная, хранящая массив студентов.
  • Блок получения всех студентов из базы. Тут мы просто будем обращаться к переменной. В реальном проекте мы бы подключались к базе и выполняли запрос.
  • Блок получения конкретного студента по идентификатору.
  • Блок получения нескольких студентов, удовлетворяющих условию.
  • Блок изменения данных о студенте.

Обычно для работы с базой пишутся специальные функции, которые выполняют подключение, обрабатывают результат и выдают его в уже готовом виде. Так как мы этого всего пока делать не умеем, просто создадим тестовую переменную, в которую запишем несколько объектов.

Все операции будут совершаться внутри функций, которые будут работать с заданной переменной. Таким образом у нас получится имитация работы с базой данных.

В этом задании нам понадобятся знания о функциях, массивах, условиях, циклах и объектах.

Какую информацию о студентах мы хотим хранить?

  • id — уникальный идентификатор, то есть номер, по которому мы сможем найти конкретного студента. Например, если у части студентов будут одинаковые имена, то как же нам их различить? Мы должны присвоить каждому человеку уникальный номер — id;
  • name — имя студента;
  • age — возраст;
  • gender — пол;
  • beginnerCourse — прошёл ли данный студент начальный курс JS.

Итак, создадим переменную, которая будет хранить в себе массив студентов:
let students = [
{
id: 0,
name: "Николай",
age: 20,
gender: "м",
beginnerCourse: false
},
{
id: 1,
name: "Анастасия",
age: 21,
gender: "ж",
beginnerCourse: true
},
{
id: 2,
name: "Павел",
age: 28,
gender: "м",
beginnerCourse: false
},
{
id: 3,
name: "Мария",
age: 24,
gender: "ж",
beginnerCourse: true
},
{
id: 4,
name: "Николай",
age: 21,
gender: "м",
beginnerCourse: true
}
];
Так как переменная students служит для имитации базы данных, то напрямую с ней мы работать не будем, а напишем отдельную функцию. Эта функция будет возвращать "из базы" информацию о студентах:
function getStudents() {
return students;
}
Теперь напишем функцию, которая будет искать студента по его идентификатору id:
function findById(id) {
let studentsDatabase = getStudents();
for (let i = 0; i < studentsDatabase.length; i = i + 1) {
if (studentsDatabase[i].id == id) {
return studentsDatabase[i];
}
}
}
Эта функция получает всех студентов "из базы". Затем перебирает их и сравнивает свойство id с заданным.

Как только найдёт, сразу вернёт данного студента.

Если не найдёт, то ничего не вернёт. А если точнее, вернёт неопределённое значение undefined.

Напишем ещё одну функцию, с помощью которой мы сможем отфильтровать студентов по имени и возрасту:
function filter(name, ageMin, ageMax) {
let studentsFiltered = [];
let studentsDatabase = getStudents();
for (let i = 0; i < studentsDatabase.length; i = i + 1) {
if (studentsDatabase[i].name == name &&
studentsDatabase[i].age >= ageMin &&
studentsDatabase[i].age <= ageMax)
{
studentsFiltered.push( students[i]);
}
}
return studentsFiltered;
}
  • Функция принимает имя, минимальный и максимальный возраст.
  • В функции мы создаём пустой массив, в который мы будем сохранять студентов, попавших в фильтр.
  • Получаем данные всех студентов "из базы".
  • Далее перебираем данные с помощью цикла for, проверяя на совпадение с аргументами функции.
  • Если имя студента совпадает с заданным, а также возраст больше либо равен минимальному, а также меньше либо равен максимальному возрасту, то этого студента записываем в массив studentsFiltered.
  • Когда все студенты будут проверены, возвращаем результат.

Напишем функцию, с помощью которой будем конкретному студенту выставлять отметку за экзамен:
function setMark(id, mark) {
let student = findById(id);
if (student == undefined) {
return "Ошибка. Студент не найден.";
}
student.mark = mark;
}
Функция принимает уникальный идентификатор, поскольку мы хотим выставить отметку конкретному студенту. Искать по имени будет неправильно, иначе мы можем поставить отметку другому студенту с таким же именем.

Сначала с помощью функции findById() мы находим студента.

Если студента с таким идентификатором не существует, findById ничего не вернёт. Вернее, JS отдаст нам undefined.

Поэтому проверяем значение переменной student. Если оно равно undefined, возвращаем ошибку с текстом, что студент не найден.

Если же студент был найден, выставляем ему отметку. Если свойства mark в объекте не было, оно будет добавлено.

Давай протестируем наше приложение.

Для начала получим всех студентов:
getStudents();
Вернётся массив из пяти объектов.

Отлично! Предположим, студент по имени Николай получил за экзамен 5, и мы хотим проставить эту отметку в базе.

Мы точно не знаем его возраст, но знаем, что он проходил курс по JS.

Отфильтруем студентов по имени "Николай" и возрасту от 20 до 30 лет:
filter("Николай", 20, 30);
Вернётся массив из двух объектов.

Если мы их проглядим, то увидим, что студент с id == 4 проходил начальный курс beginnerCourse == true.

Тогда этому студенту и выставим отметку:
setMark(4, 5);
Посмотрим, записалась ли отметка "в базу". Для этого воспользуемся функцией поиска:
findById(4);
Результат:
{
id: 4,
name: "Николай",
age: 21,
gender: "м",
beginnerCourse: true,
mark: 5
}
Отметка сохранилась mark: 5
Отлично, подготовительная программа SaintCode — всё. У тебя получилось освоить теорию, решить все задачи и сделать практику?

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