1+ import { Block , TetriminoType , Tetriminos } from "@/components/Tetrimino" ;
2+
3+ // eslint-disable-next-line prefer-const
4+ let bag : TetriminoType [ ] = [ ] ;
5+
6+ /**
7+ * 随机选择方块类型
8+ * (Multi-bag Random Generator)
9+ */
10+ export function getRandomTetrimino ( ) : TetriminoType {
11+ const shuffleArray = ( array : TetriminoType [ ] ) : TetriminoType [ ] => {
12+ for ( let i = array . length - 1 ; i > 0 ; i -- ) {
13+ const j = Math . floor ( Math . random ( ) * ( i + 1 ) ) ;
14+ [ array [ i ] , array [ j ] ] = [ array [ j ] , array [ i ] ] ;
15+ }
16+ return array ;
17+ }
18+ const fillBag = ( ) => {
19+ const tetriminos = Object . keys ( Tetriminos ) as TetriminoType [ ] ;
20+ for ( let i = 0 ; i < 3 ; i ++ ) { // 每种方块三个
21+ bag . push ( ...tetriminos ) ;
22+ }
23+ shuffleArray ( bag ) ;
24+ }
25+
26+ if ( bag . length === 0 ) {
27+ fillBag ( ) ;
28+ }
29+
30+ return bag . pop ( ) ! ;
31+ }
32+
33+ /**
34+ * 随机旋转方块
35+ */
36+ export function rotateRandomly ( blocks : Block [ ] ) : Block [ ] {
37+ for ( let i = 0 ; i < 5 ; i ++ ) {
38+ const rotateTypes = Math . floor ( Math . random ( ) * 3 ) ;
39+ switch ( rotateTypes ) {
40+ case 0 :
41+ blocks = blocks . map ( block => ( { x : block . y , y : - block . x , z : block . z } ) ) ;
42+ break ;
43+ case 1 :
44+ blocks = blocks . map ( block => ( { x : - block . z , y : block . y , z : block . x } ) ) ;
45+ break ;
46+ default :
47+ break ;
48+ }
49+ }
50+ return blocks ;
51+ }
52+
53+ /**
54+ * 随机获取下落位置
55+ */
56+ export function getRandomPosition ( rotatedBlocks : Block [ ] ) : [ number , number , number ] {
57+ const getBounds = ( blocks : Block [ ] ) => {
58+ let minX = Infinity , maxX = - Infinity ;
59+ let minY = Infinity , maxY = - Infinity ;
60+ let minZ = Infinity , maxZ = - Infinity ;
61+
62+ blocks . forEach ( block => {
63+ minX = Math . min ( minX , block . x ) ;
64+ maxX = Math . max ( maxX , block . x ) ;
65+ minY = Math . min ( minY , block . y ) ;
66+ maxY = Math . max ( maxY , block . y ) ;
67+ minZ = Math . min ( minZ , block . z ) ;
68+ maxZ = Math . max ( maxZ , block . z ) ;
69+ } ) ;
70+
71+ return { minX, maxX, minY, maxY, minZ, maxZ } ;
72+ }
73+
74+ const bounds = getBounds ( rotatedBlocks ) ;
75+
76+ const xRange = 5 - ( bounds . maxX - bounds . minX ) ;
77+ const zRange = 5 - ( bounds . maxZ - bounds . minZ ) ;
78+
79+ const x = Math . floor ( Math . random ( ) * xRange ) - bounds . minX + 0.5 ;
80+ const y = 11.5 - bounds . maxY ;
81+ const z = Math . floor ( Math . random ( ) * zRange ) - bounds . minZ + 0.5 ;
82+
83+ return [ x , y , z ] ;
84+ }
0 commit comments