-1
\$\begingroup\$

I've created a simple node modules that allows displaying a matrix of characters in the terminal, as well as capturing keypresses.

The purpose of the tool is to make simple games like snake, space invaders, within the context of teaching people to code.

Here's an example application, I hope it's easy to understand:

import {startMatrixApplication, clearMatrix, setCell} from "node-cli-character-matrix";

const N_ROWS = 5; 
const N_COLUMNS=5;
const INTERVAL_MS=100; 

let currentX = 0; 
let currentY = 0; 

startMatrixApplication(N_ROWS, N_COLUMNS, INTERVAL_MS, (matrix, tickCount, exit, keyPress) => {
    
    const clearedMatrix =  clearMatrix(matrix); 

    if (keyPress) {

        switch (keyPress.name) {
            case "down": {
                currentY = (currentY + 1 + N_ROWS) % N_ROWS; 
                break;
            }
            //Snip for brevity
        }
    }

    const newMatrix = setCell(clearedMatrix, currentY, currentX, 'X');

    if (tickCount > 100) {
        exit("Thank you for playing!");
    }
    return newMatrix; 
});

This application will move an X around on the display, when the user presses the arrow keys. The application terminates after 100 ticks.

Now the core logic is implemented in the callback function of signature:

(
    oldMatrix: Matrix,
    tickCount: number,
    exit: (message: string) => void,
    keyPress : KeyPress | null
) => Matrix

That is, at a regular interval this function will be called, it passes you the state of current displaying matrix, gives you the tick count number, as well as the last key pressed, if any, as well as a callback to terminate the program.

Whatever is returned from this function will be displayed.

The application I've got here works fine.

However, any game state, other than the display matrix itself needs to be stored at a module scope. You can see I've done that with my currentX and currentY variables, and I reassign the variables each call of the function.

It occurs to me, that I could extend the startMatrixApplication tool, to also pass back an arbitrary game state on each call of the callback.

ie. the code would look like this:

import {startMatrixApplication, clearMatrix, setCell} from "node-cli-character-matrix";

const N_ROWS = 5; 
const N_COLUMNS=5;
const INTERVAL_MS=100; 

startMatrixApplication(N_ROWS, N_COLUMNS, INTERVAL_MS, (matrix, tickCount, exit, keyPress, state) => { // old state is passed into the callback

    const clearedMatrix =  clearMatrix(matrix); 

    let newState = {...state}; 
    if (keyPress) {

        switch (keyPress.name) {
            case "down": {
                newState.y = (currentY + 1 + N_ROWS) % N_ROWS; 
                break;
            }
            //Snip for brevity
        }
    }

    const newMatrix = setCell(clearedMatrix, newState.y, newState.x, 'X');

    if (tickCount > 100) {
        exit("Thank you for playing!");
    }

    //return both the new matrix, as well as new state. 
    return {
         newMatrix: newMatrix, 
         newState: newState, 
    }; 
}, 
{x: 0, y: 0}); // Adding initial state here

This would be a 'more functional' style of coding. Deterministic, and no side effects.

But then I think 'Am I over cooking things here?'.

What is it that I'd actually be solving by adopting this more functional style?

Is there a drawback from passing state back from the callback (eg. memory consumption?)?

\$\endgroup\$
4
  • \$\begingroup\$ Second snippet You still have currentY, and currentX should that not be newState.y and newState.x \$\endgroup\$ – Blindman67 2 days ago
  • \$\begingroup\$ @Blindman67 Thanks. \$\endgroup\$ – dwjohnston 2 days ago
  • \$\begingroup\$ This is a fairly ill-fitting question for code review, since you seem to be primarily interested in a review of the API of your library. The code of that library is not included in the question and therefore not reviewable. While I can understand the desire to create a nice and idiomatic API, Code Review really wants to be much more than just API review... \$\endgroup\$ – Vogel612 yesterday
  • \$\begingroup\$ @Vogel612 - Have you got a suggestion for a more appropriate place to post it? It wasn't well received on software engineering. \$\endgroup\$ – dwjohnston yesterday

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.