Mastermind is a simple code-breaking game that’s educational and fun. I grew up playing the Hasbro game, where one person configures the code and the other tries to solve it. The tight logic and scoring algorithms make it a good fit for programming projects.

For this version, I wanted the design to scale to both a desktop and a mobile device. An old program I had written put the output in a table, but as I played with dynamic scaling, it dawned on me that the table structure wasn’t adding much value. Design purists famously hate tables used to control layout. I’m no purist, but this seemed a good time to dive into using CSS and JavaScript to manage the output.

Each element in the game exists in a div tag with an ID. There are two CSS properties I set universally in the internal style sheet:

div {
  position: absolute;
  text-align: center;
  }

Absolute positioning allows you to locate an element via the top and left properties, effectively the x and y coordinates of the element’s upper-left-hand corner. (You can also access the bottom and right properties.)

I use JavaScript to effect translation and scale transformations on each element, based on the window’s display size. The DOM window object includes properties innerWidth and innerHeight, letting me calculate the scaling factors. (The properties outerWidth and outerHeight include space used for the browser’s controls.)

My scaleToGrid function below lets me use a layout grid based on the game’s rows and columns rather than worrying about pixel specifications. It makes it easy to locate and stretch elements to take up the right amount of space on the screen, regardless of its dimensions.

function scaleToGrid(objID, x, y, horScale, verScale) {
  obj = document.getElementById(objID); 
  obj.style.left = x*gridWidth;
  obj.style.top = y*gridHeight; 
  obj.style.width = gridWidth*horScale + "px";
  obj.style.height = gridHeight*verScale + "px";
  obj.style.fontSize = gridHeight*verScale + "px";
  obj.style.lineHeight = gridHeight*verScale + "px";
  }

Because scaling fonts is more elegant than scaling bitmap images, I use graphical unicode characters in place of img tags. For the default six-character set, I use the chess symbols in unicode (♚ ♛ ♜ ♝ ♞ ♟, which look unrecognizable when the size is too small). By using a font size measured in pixels (rather than points or ems), I can ensure it fits the row’s height, though each browser renders them a little differently.

I have two global variables, gridWidth and gridHeight, which have the pixel measurements for each square on the virtual grid. The drawGame function assigns them their values, then runs though all the elements, assigning them to their positions. It’s called from the onload and onresize events, from the body tag.

function drawGame() {
  gridWidth = window.innerWidth/6;
  gridHeight = window.innerHeight/13;
  scaleToGrid("title", 0, 0, 6, 1); 
  scaleToGrid("matches", 4, 1, 2, 0.45); 
  for (c = 0; c < 4; c++) {
    scaleToGrid("solution" + c, c, 1, 1, 1); 
    scaleToGrid("button" + c, c, 10, 1, 1); 
    }
  scaleToGrid("exact", 4, 1.5, 1, 0.45); 
  scaleToGrid("near", 5, 1.5, 1, 0.45); 
  scaleToGrid("buttonGo", 4.5, 10, 1, 1); 
  ...and so on...
  }

I tested the app with testiphone.com and ipadpeek.com.

You can play the game at mvjantzen.com/games/mastermind.php.

Building Mastermind for All Screen Sizes

Leave a Reply