Building Jason Chess — Part 1: Rendering the Board and Pieces

cooljasonmelton

Jason Melton

Posted on October 26, 2020

Building Jason Chess — Part 1: Rendering the Board and Pieces

An ongoing series about building a React app called Jason Chess, a version of chess where if your name is Jason, you can’t lose.

What Is All This?

Over quarantine, I’ve become very addicted to chess. I like how random chance plays a small role in the game. Instead, better players manifest from hours of obsessive study. Getting better at chess has been a great distraction from the world crumbling all around me, lol.

As an engineer, it’s my job to build solutions to problems, right? Right. Well I’ll identify one problem that exists: me losing at chess. My solution: Jason Chess.

Jason Chess is a version of chess where if your name is “Jason”, you can’t lose.

This blog will follow the development of Jason Chess. It’s my goal to provide you with something instructive or, at minimum, I hope you find the some humor in the idea.

I’m a junior developer so please forgive my imprecisions. If you have any feedback, please comment or to email me at jason.melton2@gmail.com.

chessboard

jump to the GitHub

Rendering the Board and Pieces

Table of Contents

  • Preliminary Junk
  • Basic Layout and Menu
  • Rendering the Board
  • Rendering the Pieces
  • Conclusion

Preliminary Junk

To get this bad boy started, I set up a create-react-app, deleted default junk, and created a GitHub repository. Before going further, I spent some time planning. I like to write as I plan so I’ll keep some commented out notes in the readme until the project is finished.

I think of the work for this project in two parts: the logic and the render. Very similar to the divide between a front and back end. However, in this case, I won’t have a true back end.

The logic of the chess board will be an array of eight arrays. Each array will have a length of eight to represent the 64 spaces of a chess board. Pieces will be coded with two character strings.



  const boardArr = [
      ["br", "bn", "bb", "bq", "bk", "bb", "bn", "br"],
      ["bp", "bp", "bp", "bp", "bp", "bp", "bp", "bp"],
      [null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null],
      ["wp", "wp", "wp", "wp", "wp", "wp", "wp", "wp"],
      ["wr", "wn", "wb", "wq", "wk", "wb", "wn", "wr"]
    ]


Enter fullscreen mode Exit fullscreen mode

The render will consist of mapping boardArr into the corresponding components.

Basic Layout and Menu

For now, I’m going to keep the app simple. There will be two main elements: a chessboard and a menu.

chessboard

Later, I will also add a box above and below for entering the player’s name. Remember, if your name is “Jason”, then you cannot be checkmated.

I picked out some colors from Coolors.co and added height and width to the App component. I also created a class called .cfb (center flex box) that I use to center things throughout the project.

App.css



* {
    margin: 0;
    padding: 0;
}

.App {
    width: 100%;
    height: 100vh;
}

.cfb {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}


Enter fullscreen mode Exit fullscreen mode

The menu is a simple component, Navbar.js:



import React from 'react';

// styling
import './Navbar.css';

const Navbar = () => {
  return (
    <div className="Navbar">
        <h1 className="logo">Jason Chess</h1>
    </div>
  );
}

export default Navbar;


Enter fullscreen mode Exit fullscreen mode

Navbar.css



.Navbar {
    padding: 1rem;
    background-color: #0A090C;
    color: #F0EDEE;
}


Enter fullscreen mode Exit fullscreen mode

I’ll cover the chessboard in the next two sections.

Rendering the Board

My plan for the board is this: I will map my boardArr into 64 divs that will be evenly displayed using CSS grid.

board

I’ll show the whole Board component and CSS file and explain my work:

Board.js



import React from 'react';

// styling
import './Board.css';

// components
import PieceImg from './PieceImg'

const Board = props => {
    const { board, setBoard, turn, setTurn } = props
    // takes num, returns true if even
    const isEven = n => n % 2 === 0;
    // returns string of classnames for square
    const squareClass = index => {
        const classArr = ["cfb"]
        // rank even, file odd OR rank odd, file even --> dark square
        const rank = isEven(Math.floor(index/8))
        const file = isEven(index % 8)
        if ((rank && !file) || (!rank && file)) classArr.push("dark")
        return classArr.join(" ")
    };

    const renderBoard = () => {
        let startNum = 0
        const counter = () => startNum++
        return board.map(rank => rank.map(sq => {
            let sqNum = counter()
            return (
                <div key={sqNum} 
                    className={squareClass(sqNum)}>
                    <PieceImg piece={sq ? sq : false}/>
                </div>
            )
        }))
    }

    return (
        <div className="Board">
            {renderBoard()}
        </div>
    );
}

export default Board;


Enter fullscreen mode Exit fullscreen mode

Board.css



.Board {
    margin: 2rem;

    height: 35rem;
    width: 35rem;

    border: 1rem solid #0A090C;
    border-radius: 1rem;

    background-color: #F0EDEE;
    display: grid;
    grid: repeat(8, 1fr) / repeat(8, 1fr);
}

.dark{
    width: 100%;
    height: 100%;
    background-color: #90DDF0;
}

.piece-img {
    width: 100%;
    height: 100%;
}


Enter fullscreen mode Exit fullscreen mode

Board gets the boardArr as props. The function renderBoard() maps each rank of boardArr and then each square of each rank to return a div. That way I get 64 divs.

I use the function squareClass() to determine the classnames for each square. Light squares get a class of cfb and dark squares get a class of cfb dark.

As previously mentioned, cfb adds a centering flex box and dark adds a light blue background-color.

squareClass() also determines which squares are dark squares. I use the helper function isEven() to do this.

Starting from 0, even ranks and odd files are dark while on odd ranks, even files are dark. I find the rank and file of each square and add dark to the appropriate divs.

Rendering the Pieces

I render the pieces in two steps:

  1. I create a picture library that can be accessed via an object.
  2. I create a dynamic function that plugs in the correct image for the string code in the boardArr.

I found this great site for chess piece svgs. I threw the images in a folder and created a file called index.js.

In index.js, I created an object called pieceObject that accesses the image based on a key corresponding to the string codes in the array.



export const pieceObject = {
    wp: require('./wpawn.png'),
    wn: require('./wknight.png'),
    wb: require('./wbishop.png'),
    wr: require('./wrook.png'),
    wq: require('./wqueen.png'),
    wk: require('./wking.png'),
    bp: require('./bpawn.png'),
    bn: require('./bknight.png'),
    bb: require('./bbishop.png'),
    br: require('./brook.png'),
    bq: require('./bqueen.png'),
    bk: require('./bking.png')
}


Enter fullscreen mode Exit fullscreen mode

Next, I feed this object to a component called PieceImg.



import React from 'react';

// images
import { pieceObject } from '../../images/index.js'

// styling
import './Board.css';

const PieceImg = props => {
    const { piece } = props
    return (
        piece ? 
            <img className="piece-img" src={pieceObject[piece]} alt="piece"/> 
                : <div></div> 
        );
}

export default PieceImg;


Enter fullscreen mode Exit fullscreen mode

PieceImg takes props of piece that will be a code like bp for black pawn or wn for white knight. The pieceObject looks up the corresponding image. Also, if there isn’t a piece code on the square, piece will point be false and I will return an empty div.



const renderBoard = () => {
        let startNum = 0
        const counter = () => startNum++
        return board.map(rank => rank.map(sq => {
            let sqNum = counter()
            return (
                <div key={sqNum} 
                    className={squareClass(sqNum)}
                    onClick={() => clickPiece(sq, sqNum)}>
                    <PieceImg piece={sq ? sq : false}/>
                </div>
            )
        }))
    }


Enter fullscreen mode Exit fullscreen mode

Look again at the renderBoard() function in Board. Here you can see the PieceImg is being fed the props of a piece code or false.

Conclusion

Thanks a ton for reading. Again, I assume there are some great ways to make chess games. I came up with this off the top of my head, grinding out bugs along the way. I’m sure there are better ways so I’d love your feedback. Hit me with a comment or an email — jason.melton2@gmail.com.

This will be an ongoing project so I may be inconsistent with the blogs, but I appreciate you reading.

Best, Jason

💖 💪 🙅 🚩
cooljasonmelton
Jason Melton

Posted on October 26, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related