diff --git a/.eslintrc.js b/.eslintrc.js index f44c7a1d..1a606478 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,10 +1,10 @@ module.exports = { extends: '@mate-academy/eslint-config', env: { - jest: true + jest: true, }, rules: { - 'no-proto': 0 + 'no-proto': 'warn', }, - plugins: ['jest'] + plugins: ['jest'], }; diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bb13dfc4..7baa33b4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,11 +2,10 @@ name: Test on: pull_request: - branches: [ master ] + branches: [master] jobs: build: - runs-on: ubuntu-latest strategy: @@ -14,10 +13,10 @@ jobs: node-version: [20.x] steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: npm install - - run: npm test + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm test diff --git a/.github/workflows/test.yml-template b/.github/workflows/test.yml-template new file mode 100644 index 00000000..bb13dfc4 --- /dev/null +++ b/.github/workflows/test.yml-template @@ -0,0 +1,23 @@ +name: Test + +on: + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm test diff --git a/package-lock.json b/package-lock.json index 185b2268..631641b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "license": "GPL-3.0", "devDependencies": { "@mate-academy/eslint-config": "latest", - "@mate-academy/scripts": "^1.8.6", + "@mate-academy/scripts": "^1.9.12", "eslint": "^8.57.0", "eslint-plugin-jest": "^28.6.0", "eslint-plugin-node": "^11.1.0", @@ -1467,10 +1467,11 @@ } }, "node_modules/@mate-academy/scripts": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.8.6.tgz", - "integrity": "sha512-b4om/whj4G9emyi84ORE3FRZzCRwRIesr8tJHXa8EvJdOaAPDpzcJ8A0sFfMsWH9NUOVmOwkBtOXDu5eZZ00Ig==", + "version": "1.9.12", + "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.9.12.tgz", + "integrity": "sha512-/OcmxMa34lYLFlGx7Ig926W1U1qjrnXbjFJ2TzUcDaLmED+A5se652NcWwGOidXRuMAOYLPU2jNYBEkKyXrFJA==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/rest": "^17.11.2", "@types/get-port": "^4.2.0", diff --git a/package.json b/package.json index 216da526..5847534c 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "license": "GPL-3.0", "devDependencies": { "@mate-academy/eslint-config": "latest", - "@mate-academy/scripts": "^1.8.6", + "@mate-academy/scripts": "^1.9.12", "eslint": "^8.57.0", "eslint-plugin-jest": "^28.6.0", "eslint-plugin-node": "^11.1.0", diff --git a/readme.md b/readme.md index b0d82156..4b146c9f 100644 --- a/readme.md +++ b/readme.md @@ -13,11 +13,12 @@ Implement `Bulls and cows` game so the user can run and play it using command li - `cow` - guessed digit exists in the number but the place (index) is wrong - the game ends when the numbers is found - write a solution using separate modules for generating a number, calculating bulls and cows, validate user input, input/output operations -**(corresponding files are already created)** + **(corresponding files are already created)** - use `npm run test` command to test your modules - use `npm run play` to run the game ## Example + Computer makes `1234`, user prints `1345`. The result is one `bull` (guessed digit `1` is on it's place) and 2 `cows` (digits `3` and `4` are present but on wrong places). diff --git a/src/app.js b/src/app.js index e89a2d97..24c4b85c 100644 --- a/src/app.js +++ b/src/app.js @@ -1,3 +1,37 @@ 'use strict'; +import readline from 'node:readline'; +import { generateRandomNumber } from './modules/generateRandomNumber.js'; +import { checkIsValidUserInput } from './modules/checkIsValidUserInput.js'; +import { getBullsAndCows } from './modules/getBullsAndCows.js'; -// Write your code here +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); +const hiddenNumber = generateRandomNumber(); + +const requestANumber = () => { + // console.log(hiddenNumber); + + rl.question('Write your number? ', (userValue) => { + const isValidUserInput = checkIsValidUserInput(userValue); + + if (!isValidUserInput) { + requestANumber(); + + return; + } + + const bullsAndCows = getBullsAndCows(userValue, hiddenNumber); + + if (bullsAndCows.bulls === 4) { + rl.close(); + + return; + } + + requestANumber(); + }); +}; + +requestANumber(); diff --git a/src/modules/checkIsValidUserInput.js b/src/modules/checkIsValidUserInput.js index 40979664..74c5f018 100644 --- a/src/modules/checkIsValidUserInput.js +++ b/src/modules/checkIsValidUserInput.js @@ -8,8 +8,63 @@ * @param {string} userInput - The user input * @return {boolean} - True if the user input is valid, false otherwise */ +const checkIsUniqueNumbers = (value) => { + const arrayValue = `${value}`.split(''); + // console.log(arrayValue.length); + + if (arrayValue.length !== 4) { + // console.log('(arrayValue.length !== 4)'); + + return false; + } + + if (typeof +value !== 'number') { + // console.log(`(typeof value !== 'number')`); + + return false; + } + + if (arrayValue[0] === '0') { + // console.log(`(arrayValue[0] === '0')`); + + return false; + } + + const arrayValueToCheck = [...arrayValue]; + + for (let i = 0; i < arrayValue.length; i++) { + const numberToCheck = arrayValue[i]; + + arrayValueToCheck.splice(i, 1); + + if (arrayValueToCheck.includes(numberToCheck)) { + // console.log(`arrayValueToCheck.includes(numberToCheck)`); + + return false; + } + + return true; + } +}; + function checkIsValidUserInput(userInput) { /* Write your code here */ + + const numberedUserInput = +userInput; + + if (userInput.length !== 4) { + return false; + } + + if (typeof numberedUserInput !== 'number' || isNaN(numberedUserInput)) { + return false; + } + + if (+userInput[0] === 0) { + return false; + } + + return checkIsUniqueNumbers(userInput); } module.exports = { diff --git a/src/modules/generateRandomNumber.js b/src/modules/generateRandomNumber.js index 14ad1e2b..ad707248 100644 --- a/src/modules/generateRandomNumber.js +++ b/src/modules/generateRandomNumber.js @@ -7,7 +7,18 @@ * @return {number} A random 4-digit number */ function generateRandomNumber() { + const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + const generatedNumsArr = []; + + for (let i = 0; i < 4; i++) { + const pickingNumberIndex = Math.floor(Math.random() * nums.length); + + generatedNumsArr.push(nums[pickingNumberIndex]); + nums.splice(pickingNumberIndex, 1); + } /* Write your code here */ + + return +generatedNumsArr.join(''); } module.exports = { diff --git a/src/modules/getBullsAndCows.js b/src/modules/getBullsAndCows.js index 3f0b39a6..4439a56b 100644 --- a/src/modules/getBullsAndCows.js +++ b/src/modules/getBullsAndCows.js @@ -14,6 +14,29 @@ */ function getBullsAndCows(userInput, numberToGuess) { /* Write your code here */ + const userInputArr = userInput.toString().split(''); + const numberToGuessArr = numberToGuess.toString().split(''); + const result = { bulls: 0, cows: 0 }; + + for (let i = 0; i < userInputArr.length; i++) { + if (userInputArr[i] === numberToGuessArr[i]) { + result.bulls += 1; + + continue; + } + + if (numberToGuessArr.includes(userInputArr[i])) { + result.cows += 1; + } + } + + // if (result.bulls === 4) { + // console.log('you won!'); + + // return; + // } + + return result; } module.exports = {