2
\$\begingroup\$

I've created a chessboard model in JavaScript that will eventually iterate through some moves of a championship game.

I've created a board object and a piece constructor. I've also created all the pieces with their correct position on a typical chessboard by rank and file. I don't think I've created my move method correctly in the piece constructor though, which would just move the pieces on the board. Is this the best way to simulate moving pieces you think? I want the move method to push the moves onto my empty game array and eventually I want to be able to move back and forth on the array.

This is going to be hooked up to the chessboard I've already made with the HTML and CSS code below if you care to look at it. (Some of the boilerplate CSS has been omitted.)

(function(window) {

    var board = {
      file: ["a", "b", "c", "d", "e", "f", "g", "h"],
      rank: [1, 2, 3, 4, 5, 6, 7, 8]
    };
    var piece = function (filePlace, rankPlace) {
      this.file = board.file[filePlace - 1];
      this.rank = board.rank[rankPlace - 1];
      this.move = function (a, b) {
        this.file = board.file[a - 1];
        this.rank = board.rank[b - 1];
      };
    };

    var whiteRook1 = new piece(1, 1);
    var whiteRook2 = new piece(8, 1);
    var whiteKnight1 = new piece(2, 1);
    var whiteKnight2 = new piece(7, 1);
    var whiteBishop1 = new piece(3, 1);
    var whiteBishop2 = new piece(6, 1);
    var whiteQueen = new piece(4, 1);
    var whiteKing = new piece(5, 1);
    var whitePawn1 = new piece(1, 2);
    var whitePawn2 = new piece(2, 2);
    var whitePawn3 = new piece(3, 2);
    var whitePawn4 = new piece(4, 2);
    var whitePawn5 = new piece(5, 2);
    var whitePawn6 = new piece(6, 2);
    var whitePawn7 = new piece(7, 2);
    var whitePawn8 = new piece(8, 2);

    var blackRook1 = new piece(1, 8);
    var blackRook2 = new piece(8, 8);
    var blackKnight1 = new piece(2, 8);
    var blackKnight2 = new piece(7, 8);
    var blackBishop1 = new piece(3, 8);
    var blackBishop2 = new piece(6, 8);
    var blackQueen = new piece(4, 8);
    var blackKing = new piece(5, 8);
    var blackPawn1 = new piece(1, 7);
    var blackPawn2 = new piece(2, 7);
    var blackPawn3 = new piece(3, 7);
    var blackPawn4 = new piece(4, 7);
    var blackPawn5 = new piece(5, 7);
    var blackPawn6 = new piece(6, 7);
    var blackPawn7 = new piece(7, 7);
    var blackPawn8 = new piece(8, 7);

    var game = [];

    window.chess = {

    };

})(window);
   body {
     background-color: darkgrey;
   }

   .container {
       width: 80%;
       margin: 3em auto 3em auto;
       min-width: 1in;
       max-width: 6in;
   }

   .chessboard .row {
     margin: 0; padding: 0;
     position: relative;
     clear: both;
   }

   .chessboard .row::before,
   .chessboard .row::after {
     font-size: 300%;
     position: absolute;
   }

   .chessboard .row::after {
     left: 103%;
   }

   .chessboard .row::before {
     right: 103%;
   }

   .chessboard .rank-8::before, .chessboard .rank-8::after {
     content: '8';
   }

   .chessboard .rank-7::before, .chessboard .rank-7::after {
     content: '7';
   }

   .chessboard .rank-6::before, .chessboard .rank-6::after {
     content: '6';
   }

   .chessboard .rank-5::before, .chessboard .rank-5::after {
     content: '5';
   }

   .chessboard .rank-4::before, .chessboard .rank-4::after {
     content: '4';
   }

   .chessboard .rank-3::before, .chessboard .rank-3::after {
     content: '3';
   }

   .chessboard .rank-2::before, .chessboard .rank-2::after {
     content: '2';
   }

   .chessboard .rank-1::before, .chessboard .rank-1::after {
     content: '1';
   }

   .chessboard .square {
       background-color: red;
       width: 12.5%;
       padding-bottom: 12.5%;
       display: inline-block;
       float: left;
   }

   .chessboard .row:nth-child(even) .square:nth-child(even) {
       background-color: red;
   }

   .chessboard .row:nth-child(even) .square:nth-child(odd) {
       background-color: lightgray;
   }

   .chessboard .square:nth-child(even) {
       background-color: lightgrey;
   }

   .chessboard .legend {
     display: inline-block;
     width: 12.5%;
     text-align: center;
     float: left;
     margin: 0;
     padding: 0;
     font-size: 300%;
   }

   nav {
     text-align: center;
   }

   nav button {
     font-size: 5ex;
     background-color: red;
     padding: 0 0.5em 0 0.5em;
     border-radius: 20%;
   }

   .chessboard .row .white::before, .chessboard .row .black::before {
     font-size: 300%;
     text-align: center;
     position: absolute;
     width: 12.5%;
     line-height: 1.2;
   }

   .chessboard .row .black.pawn::before, .white.pawn::before {
     content: '\265f';
   }

   .chessboard .row .black.knight::before, .white.knight::before {
     content: '\265e';
   }

   .chessboard .row .black.rook::before, .white.rook::before {
     content: '\265c';
   }

   .chessboard .row .black.queen::before, .white.queen::before {
     content: '\265b';
   }

   .chessboard .row .black.king::before, .white.king::before {
     content: '\265a';
   }

   .chessboard .row .black.bishop::before, .white.bishop::before {
     content: '\265d';
   }

   .chessboard .row .white {
     color: white;
   }
<!doctype html>
<html class="no-js" lang="">

<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>TIY Chessboard: Kasparov v Karpov (1984)</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Place favicon.ico in the root directory -->

    <link rel="stylesheet" href="css/normalize.css">
    <link rel="stylesheet" href="css/main.css">
    <script src="js/vendor/modernizr-2.8.3.min.js"></script>
</head>

<body>
    <!--[if lt IE 8]>
            <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->

    <style>

    </style>

    <main class="container">
        <div class="chessboard">
            <section class="rowFileLegend">
                <p class="legend">A</p>
                <p class="legend">B</p>
                <p class="legend">C</p>
                <p class="legend">D</p>
                <p class="legend">E</p>
                <p class="legend">F</p>
                <p class="legend">G</p>
                <p class="legend">H</p>
            </section>
            <section class="row rank-8">
                <div class="square file-a black rook"></div>
                <div class="square file-b black knight"></div>
                <div class="square file-c black bishop"></div>
                <div class="square file-d black queen"></div>
                <div class="square file-e black king"></div>
                <div class="square file-f black bishop"></div>
                <div class="square file-g black knight"></div>
                <div class="square file-h black rook"></div>
            </section>
            <section class="row rank-7">
                <div class="square file-a black pawn"></div>
                <div class="square file-b black pawn"></div>
                <div class="square file-c black pawn"></div>
                <div class="square file-d black pawn"></div>
                <div class="square file-e black pawn"></div>
                <div class="square file-f black pawn"></div>
                <div class="square file-g black pawn"></div>
                <div class="square file-h black pawn"></div>
            </section>
            <section class="row rank-6">
                <div class="square file-a"></div>
                <div class="square file-b"></div>
                <div class="square file-c"></div>
                <div class="square file-d"></div>
                <div class="square file-e"></div>
                <div class="square file-f"></div>
                <div class="square file-g"></div>
                <div class="square file-h"></div>
            </section>
            <section class="row rank-5">
                <div class="square file-a"></div>
                <div class="square file-b"></div>
                <div class="square file-c"></div>
                <div class="square file-d"></div>
                <div class="square file-e"></div>
                <div class="square file-f"></div>
                <div class="square file-g"></div>
                <div class="square file-h"></div>
            </section>
            <section class="row rank-4">
                <div class="square file-a"></div>
                <div class="square file-b"></div>
                <div class="square file-c"></div>
                <div class="square file-d"></div>
                <div class="square file-e"></div>
                <div class="square file-f"></div>
                <div class="square file-g"></div>
                <div class="square file-h"></div>
            </section>
            <section class="row rank-3">
                <div class="square file-a"></div>
                <div class="square file-b"></div>
                <div class="square file-c"></div>
                <div class="square file-d"></div>
                <div class="square file-e"></div>
                <div class="square file-f"></div>
                <div class="square file-g"></div>
                <div class="square file-h"></div>
            </section>
            <section class="row rank-2">
                <div class="square file-a white pawn"></div>
                <div class="square file-b white pawn"></div>
                <div class="square file-c white pawn"></div>
                <div class="square file-d white pawn"></div>
                <div class="square file-e white pawn"></div>
                <div class="square file-f white pawn"></div>
                <div class="square file-g white pawn"></div>
                <div class="square file-h white pawn"></div>
            </section>
            <section class="row rank-1">
                <div class="square file-a white rook"></div>
                <div class="square file-b white knight"></div>
                <div class="square file-c white bishop"></div>
                <div class="square file-d white queen"></div>
                <div class="square file-e white king"></div>
                <div class="square file-f white bishop"></div>
                <div class="square file-g white knight"></div>
                <div class="square file-h white rook"></div>
            </section>
            <section class="rowFileLegend">
                <p class="legend">A</p>
                <p class="legend">B</p>
                <p class="legend">C</p>
                <p class="legend">D</p>
                <p class="legend">E</p>
                <p class="legend">F</p>
                <p class="legend">G</p>
                <p class="legend">H</p>
            </section>
            <nav>
              <button class="buttons">&#9654;</button>
              <button class="buttons">| <</button>
              <button class="buttons"><</button>
              <button class="buttons">></button>
              <button class="buttons">> |</button>
            </nav>
        </div>
    </main>

</body>

</html>

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Semantic markup

This is a clear misuse of the p and section elements. Sections are for outlining purposes, and single letters don't make for a paragraph.

Game boards like this are tabular data, making tables the best element to use. The "labels" A-H and 1-8 should be marked up using the th element.

Classitis

There's nothing efficient about adding a class to every single element on the page:

<div class="square file-a"></div>

This sort of repetition is precisely why we have the descendant selector, element selector, and the wildcard selector. Element selector will fit best when the markup is switched to a table.

td, th {
  width: 12.5%;
  padding-bottom: 12.5%;
}

Class names for storing metadata

Using the class attribute to store information about your tiles is a poor choice and it makes moving your pieces more annoying (because now you have to modify your list of classes to remove/change what piece resides there). In some instances, using the custom data-* attributes will make things easier to work with.

Your chess pieces are content. The information for them should be in the markup, not your CSS.

<tr>
<th>1</th>
<td>&#9814;</td><!-- white rook -->
<td></td><!-- the white knight used to be here -->
<td>&#9815;</td><!-- white bishop -->
<!-- etc -->
</tr>

This way, moving the pieces is just a matter of removing/appending the text nodes to the cell element. Using an extra element such as a span to contain each chess piece might make it easier to write your click event handler(s) if you want to make this a playable chess game. You might also prefer it for readability purposes (<td>&#9815;</td> vs <td><span data-color="white" data-piece="bishop">&#9815;</span></td>).

Upgrade your browser notifications

This sort of warning is pretty tacky. On top of that, the number of features you're using that would prevent an IE8 user from enjoying your content is pretty much nil (nth-child is the only thing I see that I'm certain won't work, and that's purely decorative) or requires an extremely tiny shim (section and main, and we've already established that you shouldn't be using section for this).

\$\endgroup\$
2
\$\begingroup\$

Unfortunately I believe your JavaScript model is quite useless. All you have is a bunch of variable names which store a pair of coordinates. The piece class doesn't even contain the color or the type of the piece.

When executing a move in chess you'll usually get (in the most simple case) two sets of coordinates like b2-b4. Now how do you find the piece at b2? In your case you'd need to loop over a list of all pieces (which you don't have) to find the right one.

You need to turn the logic around. Instead of modelling the pieces and storing where each of them is, you need to model the board and store which piece is on which square.


You HTML is far too complicated. First off: A chess board is a prime example of a table.

Also you have far too many classes. Rule of thumb: If all (child) elements have the same class, you are doing something wrong. Classes are used to mark that element that is different from the others.

You also don't need a class for each separate rank/file (rank-1, rank-2, file-a , file-b). Another rule of thumb in programming: Anytime you start numbering something manually, you are doing something wrong.

Finally your HTML doesn't contain any content. The pieces are all "hidden" in the class names. A non-visual visitor (search engine, blind human) won't "see" anything.

Here's a code review from a few years ago with a similar topic where I posted an example how to model a chess board in HTML:

Can someone have a look to my Chess Project?

http://jsfiddle.net/xL9B8/4/

Edit: Here is an updated version of my chessboard with coordinates: http://jsfiddle.net/snatmdeh/2/

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.