5
\$\begingroup\$

This is a game about matching the right colour. In the first level you start with 3 cubes that each have a different colour. After 2 seconds the colours of the cubes disappear and the cubes become white, so you need to remember the colours of the cubes. Above the cubes you have coloured circles of the previous colours you just saw in different colour orders. You need to click on the white cube in the right order the colour circle above is showing you. If you click at the wrong colour cube (so the wrong colour order) all the cubes will turn white again until all the colour cubes are selected in the right order.

So if you got a cube colour in the right order the cube will turn into colour again, if it's wrong the cube will stay white when you press the second cube wrong. The higher your level is the more cubes there will be to memorise. You have a 1-minute time limit to achieve your high score before the game ends.

How can I make the script shorter and easier? The script is working but in my opinion the script can be shorter and better.

This is my script but I want to delete this script because it isn't good in my opinion.

    var AllColors = ['yellow', 'gray', 'blue', 'green', 'pink', 'orange'];
    var RandomColors = [];
    var ChosenColors = [];
    var UsedColors = [];
    var Time = 100;
    var Score = 0;
    var Round = 3;

    function Randomize(Subject) {
      let counter = Subject.length;
      while (counter > 0) {
        let index = Math.floor(Math.random() * counter);
        counter--;

        let temp = Subject[counter];
        Subject[counter] = Subject[index];
        Subject[index] = temp;
      }
      return Subject;
    }


    function ClearArrays() {
      RandomColors.splice(0, RandomColors.length);
      ChosenColors.splice(0, ChosenColors.length);
      UsedColors.splice(0, UsedColors.length);
    }

    function arraysEqual(a, b) {
      if (a === b) return true;
      if (a == null || b == null) return false;
      if (a.length != b.length) return false;

      for (var i = 0; i < a.length; ++i) {
        if (a[i] !== b[i]) return false;
      }
      return true;
    }

    function Counter() {
      var Countdown = Time;
      $('.counter').text(Countdown);

      count = setInterval(function() {
        Countdown--;
        if (Countdown >= 0) {
          $('.counter').text(Countdown);
        }
        if (Countdown == 0) {
          clearInterval(count);
          ClearGame();
        }
      }, 1000);

    }

    function RandomArray(Subject) {
      var index = Math.floor(Math.random() * Subject.length);
      var val = Subject[index];
      return val;
    }


    function setColorToGrey() {
      $.each(UsedColors, function(index, value) {
        $("." + value + "").css('background-color', '');
      });
    }

    function CreateObjTop() {
      randomcolors = Randomize(UsedColors);

      $(this).delay(2000).queue(function() {
        $(this).hide();

        setColorToGrey();

        i = 0;
        $.each(randomcolors, function(index, value) {

          $('<div class="' + value + '" style="background-color:' + value + '; width: 25px; height: 25px; float: left; margin-left:20px; border-radius: 100%; border: 2px solid #ACACAC;"></div>').appendTo("#top").hide().fadeIn(2000);
          RandomColors.push(value);

          $("#" + [i] + "").click(function() {
            $("#" + $(this).attr('id') + "").css('background-color', $(this).attr('class'));
            ChosenColors.push($(this).attr('class'));

            CheckStatus();

          });
          i++;
        });
        $(this).dequeue();
      });
    }

    function LoadGame() {

      for (i = 0; i < Round; i++) {
        var color = RandomArray(AllColors);
        $('<div id="' + [i] + '" class="' + color + '"  data-color="' + color + '" style="background: ' + color + ';  width: 40px;height: 40px; border-radius: 25px 25px 25px 25px; -moz-border-radius: 25px 25px 25px 25px; -webkit-border-radius: 4px 4px 4px 4px; border: 1px solid #5e5e5e; margin: 10px;float:left; "></div>').appendTo("#mid").hide().fadeIn(2000);
        UsedColors.push(color);
      }

      CreateObjTop();

    }

    function CheckStatus() {
      if (ChosenColors.length === Round) {
        if (arraysEqual(UsedColors, ChosenColors)) {
          if (Score === 4 || Score == 9 || Score == 14) {
            Round++;
          }

          $.each(RandomColors, function(index, value) {
            $("." + value + "").remove();
          });

          ClearArrays();
          LoadGame(Round);
          Score++;
          $('.score').text(Score);
        } else {
          ChosenColors.splice(0, ChosenColors.length);

          $.each(UsedColors, function(index, value) {
            $('[data-color="' + value + '"]').css('background-color', 'white');
          });
        }
      }
    }

    function ClearGame() {

      $('.counter').text('Game over');
      $('.score').text(Score);

      $.each(AllColors, function(index, value) {
        $('.' + value + '').remove();
        ClearArrays();
      });

      $('.sitename').show();
      $('.navbar').show();
      $('.endgame').show();

      $('.statics-time').hide();
      $('.statics-score').hide();

      Score = 0;
      Round = 3;

      $(this).delay(2000).queue(function() {
        $("#bt-ready").delay(2000).show();
        $(this).dequeue();
      });
    }

    function StartGame() {
      Counter();
      LoadGame();
    }

    StartGame();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="top">

</div>
<br />
<br />
<div id="mid">

</div>

\$\endgroup\$
1
\$\begingroup\$

The code works pretty well. There are a few techniques that can be used to shorten the code. I notice that features like let are used but not many others. See the list below:

Global variables

All the variables declared with var are put into the global window namespace. It is wise to wrap those in an IIFE or better yet, since it is wise to wait for the DOM to be ready before querying it, use the jQuery DOM ready syntax:

$(function() { /* function to execute once DOM has finished loading */});

Also, use let for local variables and const for anything that doesn't get re-assigned (including arrays).

Swapping Array Elements

let temp = Subject[counter];
Subject[counter] = Subject[index];
Subject[index] = temp;

This can be shortened using destructuring assignment:

[Subject[index], Subject[counter]] = [Subject[counter], Subject[index]];

Array truncation

The three lines inside ClearArrays() can be simplified to simply set the length of each array to 0 because "You can set the length property to truncate an array at any time"1.

RandomColors.length = 0;
ChosenColors.length = 0;
UsedColors.length = 0;

Cache DOM references

Querying the DOM isn't exactly cheap so it is wise to look up elements once and store them in a variable (and use const since those shouldn't be re-assigned). References to elements like #top and #mid can be stored in a constant instead of looked up each time (especially when iteratively adding elements like the cubes and circles).

Put styles in CSS instead of inline in each cube and circle

Don't repeat the styles for each circle and cube. See the rewrite below where the styles for the circles and cubes are moved out to the cubes. Also, instead of updating the background colors using inline styles, I updated the code to add and remove a class obscure that sets the background color to white when appropriate. While it meant adding a CSS ruleset for each color (which could have been done programmatically), it allows for simple code when clearing and re-adding colors.

Use single click handler

Instead of adding a click handler to each cube, which eventually gets removed from the DOM, use a single click handler on the mid element. Then check if the element clicked was a cube. In the rewrite below, I moved the styles to a new class (i.e. cube) mentioned in the previous section.

Rewrite

The code below is simplified a bit using the suggestions above. Some elements referenced in the original code didn't appear to exist so those have been removed.

$(function() {
  const AllColors = ['yellow', 'gray', 'blue', 'green', 'pink', 'orange'];
  const RandomColors = [];
  const ChosenColors = [];
  const UsedColors = [];
  const Time = 100;
  let Score = 0;
  let Round = 3;
  //cache DOM references
  const counterElement = $('.counter');
  const topElement = $("#top");
  const midElement = $("#mid");
  const scoreElement = $('.score');

  function Randomize(Subject) {
    let counter = Subject.length;
    while (counter > 0) {
      let index = Math.floor(Math.random() * counter);
      counter--;
      [Subject[index], Subject[counter]] = [Subject[counter], Subject[index]];
    }
    return Subject;
  }


  function ClearArrays() {
    RandomColors.length = 0;
    ChosenColors.length = 0;
    UsedColors.length = 0;
  }

  function arraysEqual(a, b) {
    if (a === b) return true;
    if (a == null || b == null) return false;
    if (a.length != b.length) return false;

    for (var i = 0; i < a.length; ++i) {
      if (a[i] !== b[i]) return false;
    }
    return true;
  }

  function Counter() {
    let Countdown = Time;
    counterElement.text(Countdown);

    count = setInterval(function() {
      Countdown--;
      if (Countdown >= 0) {
        counterElement.text(Countdown);
      }
      if (Countdown == 0) {
        clearInterval(count);
        ClearGame();
      }
    }, 1000);

  }

  function RandomArray(Subject) {
    const index = Math.floor(Math.random() * Subject.length);
    return Subject[index];
  }


  function setColorToGrey() {
    $(".cube").addClass('obscured');
  }

  function CreateObjTop() {
    randomcolors = Randomize(UsedColors);

    $(this).delay(2000).queue(function() {
      $(this).hide();
      setColorToGrey();
      $.each(randomcolors, function(index, value) {
        $('<div class="circle ' + value + '"></div>').appendTo(topElement).hide().fadeIn(2000);
        RandomColors.push(value);
      });
      $(this).dequeue();
    });
  }

  function LoadGame() {

    for (i = 0; i < Round; i++) {
      var color = RandomArray(AllColors);
      $('<div id="' + [i] + '" class="cube ' + color + '"  data-color="' + color + '" ></div>').appendTo(midElement).hide().fadeIn(2000);
      UsedColors.push(color);
    }

    CreateObjTop();

  }
  $(midElement).click(function(event) {
    const target = $(event.target);
    if (target.hasClass("cube")) {
      target.removeClass('obscured');
      ChosenColors.push(target.data('color'));
      CheckStatus();
    }
  });

  function CheckStatus() {
    if (ChosenColors.length === Round) {
      if (arraysEqual(UsedColors, ChosenColors)) {
        if (Score === 4 || Score == 9 || Score == 14) {
          Round++;
        }
        $(".cube, .circle").remove();

        ClearArrays();
        LoadGame(Round);
        Score++;
        scoreElement.text(Score);
      } else {
        ChosenColors.length = 0;
        setColorToGrey();
      }
    }
  }

  function ClearGame() {

    counterElement.text('Game over');
    scoreElement.text(Score);

    $(".cube, .circle").remove();

    Score = 0;
    Round = 3;

    $(this).delay(2000).queue(function() {
      $("#bt-ready").delay(2000).show();
      $(this).dequeue();
    });
  }

  function StartGame() {
    Counter();
    LoadGame();
  }

  StartGame();
});
.circle {
  width: 25px;
  height: 25px;
  float: left;
  margin-left: 20px;
  border-radius: 100%;
  border: 2px solid #ACACAC;
}

.cube {
  width: 40px;
  height: 40px;
  border-radius: 25px 25px 25px 25px;
  -moz-border-radius: 25px 25px 25px 25px;
  -webkit-border-radius: 4px 4px 4px 4px;
  border: 1px solid #5e5e5e;
  margin: 10px;
  float: left;
}

.blue {
  background-color: blue;
}

.gray {
  background-color: gray;
}

.green {
  background-color: green;
}

.orange {
  background-color: orange;
}

.pink {
  background-color: pink;
}

.yellow {
  background-color: yellow;
}

.cube.obscured {
  background-color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="top">

</div>
<br />
<br />
<div id="mid">

</div>
<div class="score"></div>
<div class="counter"></div>

1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length#Description

\$\endgroup\$

Your Answer

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

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