我正在开发一款记忆游戏,用户会看到一个5x5的正方形网格,其中9个突出显示。然后用户必须记住并选择那9个方格。
如何生成预期/获胜的电路板配置?
目前,我已将Board
作为List (List Bool)
在一种命令式语言中,就像JS一样,我只是在网格上迭代9次,随机选择一个列和行索引进行变异。这在榆树中是不可能的,所以我有点卡住了。
我想到了几种策略:
策略1
生成随机网格
策略2
使用Array
并随机播放所有坐标,选择前9个。
注意我还需要一种方法来选择图块,因此Board
可能List (List Tile)
Tile
{ x: Int, y: Int, selected: Bool}
为module Main exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Html.App as App
import Random
import Random.Array
import Array exposing (..)
-- model
type alias Board =
Array (Array Bool)
type alias Tile =
{ x : Int
, y : Int
, selected : Bool
}
type alias Model =
{ board : Board
, expectedBoard : Board
, gameOver : Bool
, playerWon : Bool
, turnCount : Int
}
initModel : ( Model, Cmd Msg )
initModel =
( { board = generateSquareMatrix 5 False
, expectedBoard = Array.fromList []
, gameOver = False
, playerWon = False
, turnCount = 0
}
, Cmd.none
)
generateSquareMatrix : Int -> Bool -> Array (Array Bool)
generateSquareMatrix num value =
Array.repeat num (Array.repeat num value)
-- update
type Msg
= SelectTile Bool
| RestartGame
| SuffleBoard
| NewBoard (Array (Array Bool))
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case (Debug.log "msg" msg) of
SelectTile tile ->
( { model
| turnCount = model.turnCount + 1
}
, Cmd.none
)
RestartGame ->
( { model
| turnCount = 0
}
, Cmd.none
)
SuffleBoard ->
( model, Random.generate NewBoard (Random.Array.shuffle model.board) )
NewBoard newBoard ->
( { model | board = newBoard }
, Cmd.none
)
-- view
view : Model -> Html Msg
view model =
div [ class "scoreboard" ]
[ h1 [] [ text "Recall" ]
, grid model
, button [ onClick SuffleBoard ] [ text "New Board" ]
, p [] [ text (toString model) ]
]
grid : Model -> Html Msg
grid model =
div [ class "recall-grid" ]
(List.map
(\row ->
div
[ class "recall-grid-row" ]
(List.map
(\tile ->
div [ class "recall-grid-tile", onClick (SelectTile tile) ] []
)
(Array.toList row)
)
)
(Array.toList model.board)
)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
main : Program Never
main =
App.program
{ init = initModel
, view = view
, update = update
, subscriptions = subscriptions
}
。
我已经用vanilla JS编写游戏了。你可以在这里试试:http://mruzekw.github.io/recall/
到目前为止,我编写的代码有点实施策略:
Storage::makeDirectory(public_path('img/uploads/projects' . $project->id), 0777);
答案 0 :(得分:1)
策略2工作得很好,因为它可以保证随机元素的唯一性。
在处理随机性时,最好使用生成器映射函数从简单的生成器构建复杂的生成器。这使您不必在实际生成器代码中跟踪随机种子。
我们需要的第一个生成器是构建数组索引列表的生成器,我将其描述为 0 1
0 Brand Name Emporio Armani
2 Model number AR0143
4 Part Number AR0143
6 Item Shape Rectangular
8 Dial Window Material Type Mineral
10 Display Type Analogue
12 Clasp Type Buckle
14 Case Material Stainless steel
16 Case Diameter 31 millimetres
18 Band Material Leather
20 Band Length Women's Standard
22 Band Colour Black
24 Dial Colour Black
26 Special Features second-hand
28 Movement Quartz
的元组。
(Int, Int)
现在我们可以使用indexGenerator : Int -> Int -> Random.Generator (Array (Int, Int))
indexGenerator edgeSize sampleSize =
List.map (\i -> List.map2 (,) (List.repeat edgeSize i) [0..(edgeSize-1)]) [0..(edgeSize-1)]
|> List.concat
|> Array.fromList
|> Random.Array.shuffle
|> Random.map (Array.slice 0 sampleSize)
以及您的初始Falses矩阵来构建Random.map
:
squareMatrixGenerator
上述代码还依赖于elm-community/array-extra
数组更新包。
然后,您可以在squareMatrixGenerator : Int -> Int -> Bool -> Random.Generator (Array (Array Bool))
squareMatrixGenerator edgeSize sampleSize value =
let
initialMatrix =
Array.repeat edgeSize (Array.repeat edgeSize value)
invertPoint (x, y) =
Array.Extra.update x (Array.Extra.update y not)
indexes =
indexGenerator edgeSize sampleSize
in
Random.map (Array.foldl invertPoint initialMatrix) indexes
期间将种子传递到init
,并在使用Random.step
时通过ShuffleBoard
消息传递给您。例如:
Random.generate