-
Create and navigate to project directory using following commands
mkdir wmd-ts-number-game cd wmd-ts-number-game
-
Intilize a node project in the newly created directory using following command, this will create a
package.json
file.npm init -y
-
Create a
tsconfig.json
file to define typescript configration using following commandtsc --init
-
Create two more directories to be used as root and out directory using
mkdir src mkdir dist
-
Update
tsconfig.json
to include above directories and also change module and moduleResolution"target": "ES2022", "module": "NodeNext", "rootDir": "./src", "moduleResolution": "NodeNext", "outDir": "./dist",
-
Update
package.json
and add following content to it"main": "./dist/index.js", "type": "module", "scripts": { "start": "node ." }, "bin": "./dist/index.js",
-
Multiple third-party packages to be used in this project so install different dependacies using following commands
npm install inquirer npm install chalk npm install chalk-animation npm install ora npm install random-int
-
Install types for the installed dependancies for the development using following set of commands
npm install --save-dev @types/inquirer npm install --save-dev @types/chalk npm install --save-dev @types/chalk-animation npm install --save-dev @types/ora npm install --save-dev @types/random-int
-
After installation
package.json
file will be updated andpackage-lock.json
file along withnode_modules
folder will be created. We don't need git to track newly created files and folders so create a.gitignore
file with the following contentnode_modules package-lock.json
-
To check if everything is setup properly first create a hello world. All the typescript files should be created in
./src
directory. Create aindex.ts
file with the following contentconsole.log('Hello World!');
-
To transpile our code to javascript we can use any of the following command, one thing to rember we need to use first command every time we make a change and the second one automatically create js files on every change. So we are going to use the latter one. All the js files will be stored in the
./dist
folder as we declared in ourtsconfig.json
file earlier.tsc tsc -w
-
to run the js file we can use any of the following commands
node .\dist\index.js node . npm start
-
If everything is right we will have a console output.
-
Create
welcomeMessage.ts
will the following content to display welcome message to the userimport chalkAnimation from 'chalk-animation'; import chalk from 'chalk'; let t1: string = chalk.inverse.bold('\n****************************\n'); let t2: string = chalk.inverse.bold('***'); let t3: string = chalk.greenBright.italic(' Number Guessing Game '); async function msg1Promise( t1: string, t2: string, t3: string ): Promise<boolean> { console.clear(); console.log(`${t1 + t2 + t3 + t2 + t1}`); return new Promise<boolean>((resolve) => { setTimeout(() => { resolve(true); }, 700); }); } async function msg2Promise(): Promise<boolean> { console.clear(); let radar = chalkAnimation.radar( '\n****************************\n*** Number Guessing Game ***\n****************************\n', 0.6 ); return new Promise<boolean>((resolve) => { setTimeout(() => { radar.stop(); resolve(true); }, 3200); }); } async function wellcomeMessage(): Promise<void> { await msg1Promise(t1, t2, t3); await msg2Promise(); await msg1Promise(t1, t2, t3); } async function wellcomeMessageStatic(): Promise<void> { await msg1Promise(t1, t2, t3); } export { wellcomeMessage, wellcomeMessageStatic };
-
All the functions are called through
index.ts
so update it with the following content#!/usr/bin/env node import { wellcomeMessage } from './welcomeMessage.js'; (async (): Promise<void> => { await wellcomeMessage(); })();
-
Create
instructions.ts
will the following content to display instructions on how to play the gameimport chalk from 'chalk'; async function instructions(): Promise<boolean> { return await new Promise<boolean>((resolve) => { console.log(chalk.cyan('How to play : ')); console.log('\tA randowm number between 1 to 20 will be generated'); console.log('\tTo win, guess the number'); console.log('\tYou can play in any of the following mode\n'); setTimeout(() => { resolve(true); }, 1500); }); } export { instructions };
-
Update
index.ts
to call instructions functionimport { instructions } from './instructions.js'; await instructions();
-
Create
modes.ts
will the following content to display different modes available in the gameimport chalk from 'chalk'; async function modesOfGame(mode: string): Promise<boolean> { function newbie() { console.log(chalk.yellow('\tNewbie : ')); console.log('\t\tUnlimited number of tries'); console.log('\t\tA hint on each wrong guess'); console.log('\t\tNumber to guess remains the same on wrong guess'); } function beginner() { console.log(chalk.yellow('\tBeginner : ')); console.log('\t\tLimited (10) number of tries'); console.log('\t\tA hint on each wrong guess'); console.log('\t\tNumber to guess remains the same on wrong guess'); } function proficient() { console.log(chalk.yellow('\tProficient : ')); console.log('\t\tLimited (8) number of tries'); console.log('\t\tNo hint after wrong guess'); console.log('\t\tNumber to guess remains the same on wrong guess'); } function expert() { console.log(chalk.yellow('\tExpert : ')); console.log('\t\tLimited (5) number of tries'); console.log('\t\tNo hint after wrong guess'); console.log('\t\tNumber to guess changes on wrong guess'); } return await new Promise<boolean>((resolve) => { switch (mode) { case 'Newbie': console.log(chalk.cyan('\nSelected Mode : ')); newbie(); console.log('\t\tTo quit app at any time enter 4815162342\n'); break; case 'Beginner': console.log(chalk.cyan('\nSelected Mode : ')); beginner(); console.log('\t\tTo quit app at any time enter 4815162342\n'); break; case 'Proficient': console.log(chalk.cyan('\nSelected Mode : ')); proficient(); console.log('\t\tTo quit app at any time enter 4815162342\n'); break; case 'Expert': console.log(chalk.cyan('\nSelected Mode : ')); expert(); console.log('\t\tTo quit app at any time enter 4815162342\n'); break; default: console.log(chalk.cyan('Modes : ')); newbie(); beginner(); proficient(); expert(); console.log('\n'); break; } setTimeout(() => { resolve(true); }, 1500); }); } export { modesOfGame };
-
Update
index.ts
to call modes functionimport { modesOfGame } from './modes.js'; await modesOfGame('all');
-
create
askToPlay.ts
to define a function which asks the user to play game or quit the appimport inquirer from 'inquirer'; async function askToPlay(): Promise<any> { enum Commands { Use = 'Play Game', Quit = 'Quit App', } const startAppC = await inquirer.prompt([ { message: 'Do you wan to continue ? ', name: 'startApp', type: 'list', choices: Object.values(Commands), }, ]); return startAppC['startApp']; } export { askToPlay };
-
Update
index.ts
to call above functionimport { askToPlay } from './askToPlay.js'; let askToPlayChoice = await askToPlay();
-
create
startApp.ts
to define a function which displays some animaton before opeing the appimport ora, { Ora } from 'ora'; import chalk from 'chalk'; function startApp(): Promise<boolean> { return new Promise<boolean>((resolve) => { console.log(''); const spinner: Ora = ora(chalk.green(' Starting App ')); spinner.color = 'yellow'; spinner.start(); setTimeout(() => { spinner.stop(); console.clear(); resolve(true); }, 1500); }); } export { startApp };
-
create
quitApp.ts
to define a function which quits the app after displaying some animationimport ora, { Ora } from 'ora'; import chalk from 'chalk'; function quitApp(): Promise<boolean> { return new Promise<boolean>((resolve) => { console.log(''); const spinner: Ora = ora(chalk.magenta(' See You Again ')); spinner.spinner = 'material'; spinner.color = 'magenta'; spinner.start(); setTimeout(() => { spinner.color = 'red'; spinner.text = chalk.bgRed(' Closing App ! '); }, 1500); setTimeout(() => { spinner.stop(); console.clear(); resolve(true); }, 3000); }); } export { quitApp };
-
update
index.ts
to call startapp or quit app based on user choice and displays a message when app starts upimport { wellcomeMessageStatic } from './welcomeMessage.js'; import { quitApp } from './quitApp.js'; import { startApp } from './startApp.js'; if (askToPlayChoice === 'Play Game') { await startApp(); let playAgainCheck = true; while (playAgainCheck) { await wellcomeMessageStatic(); } } else { await quitApp(); }
-
create
askForMode.ts
to ask user to select mode to play inimport inquirer from 'inquirer'; async function askForMode(): Promise<any> { enum Commands { Newbie = 'Newbie', Beginner = 'Beginner', Proficient = 'Proficient', Expert = 'Expert', } const selectModeC = await inquirer.prompt([ { message: 'Select Mode ? ', name: 'selectMode', type: 'list', choices: Object.values(Commands), }, ]); return selectModeC['selectMode']; } export { askForMode };
-
update
index.ts
to call above function and based on user choise displays instructionimport { askForMode } from './askForMode.js'; let selectedMode = await askForMode(); await modesOfGame(selectedMode);
-
Create
askNumber.ts
to ask user to guess the number// Ask user to guess the number import inquirer from 'inquirer'; async function askNumber(guessNumber: number): Promise<number> { let number = await inquirer.prompt([ { message: `Guess the number (try no. ${guessNumber}) : `, type: 'number', name: 'guessedNumber', }, ]); return number.guessedNumber; } export { askNumber };
-
Create
hint.ts
to display a message to be displayed based on miltiple casesimport chalk from 'chalk'; function hint( guessedNumber: number, generatedNumber: number, selectedMode: string, guessNumber: number ) { if (selectedMode === 'Expert') { return `, Number of ${chalk.red( `tries left : ${5 - guessNumber}` )} \n new Number Generated : ${chalk.inverse(`******`)}`; } else if (selectedMode === 'Beginner') { return `, Number of ${chalk.red( `tries left : ${10 - guessNumber}` )} \n ${ guessedNumber < generatedNumber ? `Guess a ${chalk.red(`higher`)} number ` : `Guess a ${chalk.red(`lower`)} number` }`; } else if (selectedMode === 'Proficient') { return `, Number of ${chalk.red(`tries left : ${8 - guessNumber}`)} \n`; } else { if (guessedNumber < generatedNumber) { return `, Guess a ${chalk.red(`higher`)} number `; } else { return `, Guess a ${chalk.red(`lower`)} number`; } } } export { hint };
-
create
quitMidway.ts
to ask user in case he opts to quit the app any timeimport inquirer from 'inquirer'; async function quitMidway(): Promise<string> { console.log(''); type QuitMidwayResponse = { quitMidway: string }; let quitMidwayResponse: QuitMidwayResponse = await inquirer.prompt([ { message: `Do You wan't to quit the game Midway ? `, type: 'list', name: 'quitMidway', choices: ['⛔ Yes', '👍 No'], }, ]); return quitMidwayResponse.quitMidway; } export { quitMidway };
-
create
playAgain.ts
to ask user to play the game againimport inquirer from 'inquirer'; async function playAgain(): Promise<string> { console.log(''); type PlayAgainResponse = { playAgain: string }; let playAgainResponse: PlayAgainResponse = await inquirer.prompt([ { message: `Do You wan't to play again ? `, type: 'list', name: 'playAgain', choices: ['👍 Yes', '⛔ No'], }, ]); return playAgainResponse.playAgain; } export { playAgain };
-
create
game.ts
to define all features of the gameimport chalk from 'chalk'; import { hint } from './hint.js'; import randomInteger from 'random-int'; import { askNumber } from './askNumber.js'; import { playAgain } from './playAgain.js'; import { quitMidway } from './quitMidway.js'; async function game(selectedMode: string) { let guessNumber: number = 1; let startGuessing: boolean = true; let playAgainResponse: string = '⛔ No'; let quitMidwayResponse: string = '👍 No'; let generatedNumber = randomInteger(1, 20); console.log(`Random Number Generated : ${chalk.inverse(`******`)}\n`); while (startGuessing) { if ( selectedMode === 'Newbie' || (selectedMode === 'Beginner' && guessNumber <= 10) || (selectedMode === 'Proficient' && guessNumber <= 8) || (selectedMode === 'Expert' && guessNumber <= 5) ) { let guessedNumber = await askNumber(guessNumber); if (guessedNumber === generatedNumber) { console.log( `\n🎆 🏅 🎆 ${chalk.bgGreen.bold( ' Congratulation ' )}: You guessed the number in ${chalk.magenta( guessNumber )} tries.\n` ); startGuessing = false; playAgainResponse = await playAgain(); } else if (guessedNumber === 4815162342) { quitMidwayResponse = await quitMidway(); if (quitMidwayResponse === '👍 No') { guessNumber > 1 ? (guessNumber -= 1) : guessNumber; console.log(''); } else { startGuessing = false; playAgainResponse = await playAgain(); } } else { if (selectedMode === 'Expert') { generatedNumber = randomInteger(1, 20); } console.log( `\n❌ Wrong Answer${hint( guessedNumber, generatedNumber, selectedMode, guessNumber )}\n` ); guessNumber += 1; } } else { console.log(`\n☠️☠️☠️ ${chalk.bgRed('You lost the game.')} ☠️☠️☠️\n`); startGuessing = false; playAgainResponse = await playAgain(); } } return playAgainResponse; } export { game };
-
update
index.ts
to use game function and quit or continue playing based on result from the gameimport { game } from './game.js'; let resultPlayAgain = await game(selectedMode); if (resultPlayAgain === '👍 Yes') { continue; } else { playAgainCheck = false; await quitApp(); }
-
login to npm
npm login
-
publish app
npm publish
-
to update
npm version <type>
-
version types
patch minor major