4

I am trying to randomize the order of my array in my Angular6 project. I have no idea how to do it and ended up trying to sort the array with the Math.random() function... (didn't work XD)

This is my code so far:

HTML

    <div style="background: darkcyan; width: 600px; height: 600px; margin: auto">
  <table>
    <tr *ngFor="let card of cards">
      <div id="{{card.id}}" [ngStyle]="{'background-color': card.color}" style=" width: 100px; height: 125px; margin: 5px"></div>
    </tr>
  </table>
</div>
<button (click)="shuffle()">Shuffle Cards</button>

TypeScript

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-memory-game',
  templateUrl: './memory-game.component.html',
  styleUrls: ['./memory-game.component.css']
})
export class MemoryGameComponent implements OnInit {
  cards = [];
  constructor() { }

  ngOnInit() {
    this.cards = [
        {
          'id': 1,
          'color': 'red'
        },
        {
            'id': 2,
            'color': 'green'
        },
        {
            'id': 3,
            'color': 'blue'
        },
        {
            'id': 4,
            'color': 'yellow'
        }
    ];
      this.shuffle();
  }

  public shuffle() {
      this.cards.sort(Math.random);
  }
}

I don't know if there is an easy solution, but I really hope someone is able to help me out..

Thanks

Jerry Stratton
  • 3,287
  • 1
  • 22
  • 30
Marcus Scharf
  • 55
  • 1
  • 1
  • 5
  • `Math.random` always returns a positive number, so the result will not be random. Refer to @Shan-Desai's answer to solve the issue (by substraction 0.5 from `Math.random` https://stackoverflow.com/a/53066842/1423259 – tommueller Oct 30 '18 at 15:01

3 Answers3

11

I think the problem is that you need to do something like:

this.cards.sort((a,b) => 0.5 - Math.random());

based on some previous answers on SE

Or do something like this:

 this.cards.sort(() => Math.random() - 0.5);

Based on this SE Query

codeepic
  • 3,723
  • 7
  • 36
  • 57
Shan-Desai
  • 3,101
  • 3
  • 46
  • 89
2

One potential solution you could take would be to create a function to generate a random int and use it in your Array.prototype.sort function callback:

var cards = [{
    'id': 1,
    'color': 'red'
  },
  {
    'id': 2,
    'color': 'green'
  },
  {
    'id': 3,
    'color': 'blue'
  },
  {
    'id': 4,
    'color': 'yellow'
  }
];

function getRandomInt(max) {
  return Math.floor(Math.random() * Math.floor(max));
}

cards.sort(function(a, b) {
  return getRandomInt(cards.length) - getRandomInt(cards.length);
});

console.log(cards);
Tom O.
  • 5,730
  • 2
  • 21
  • 35
0

Try this shuffle function.

function shuffle(arrParam: any[]): any[]{
    let arr = arrParam.slice(),
        length = arr.length,
        temp,
        i;

    while(length){
        i = Math.floor(Math.random() * length--);

        temp = arr[length];
        arr[length] = arr[i];
        arr[i] = temp;
    }

    return arr;
}

It is a pure function and can be used on any array. It will create a new shuffled array preserving the original one.

If you want to make it work in your template so it sorts this.cards, you can make the component method shuffle() that mutate this.cards:

public shuffle(): any[]{
    let arr = this.cards.slice(),
        length = arr.length,
        temp,
        i;

    while(length){
        i = Math.floor(Math.random() * length--);

        temp = arr[length];
        arr[length] = arr[i];
        arr[i] = temp;
    }

    this.cards = arr;
}

EDIT: I checked @wannadream link he provided in a comment and it looks like my shuffle function above is "The de-facto unbiased shuffle algorithm is the Fisher-Yates (aka Knuth) Shuffle". I must have written it using Fisher-Yates shuffling algorithm as a reference.

codeepic
  • 3,723
  • 7
  • 36
  • 57