2017-01-14 1 views
1

У меня есть проект sml-nj, в котором я хочу работать со структурой «списка списков», которая имеет «квадраты». Я пытаюсь вставить значения в список списков рекурсивно, но я до сих пор не понял, как вставлять элементы в список 2d. Примечание - Я НЕ МОГУ ИСПОЛЬЗОВАТЬ 'REF', ТОЛЬКО http://smlfamily.org/Basis/list.html#SIG:LIST.app:VAL эти функции.2d matrix sml inserting to list - simple code

datatype SquareContent = Mine | Digit of int | Blank; 
datatype Square = Revealed of SquareContent | Concealed of SquareContent; 
fun createMineSweeperGrid (n:int) 
:(Square list list)= 
let 
fun createMines (rowCounter:int, colCounter:int 
, retGame:Square list list):(Square list list) = 
if rowCounter=n then 
retGame   (* finished all rows, should be n lists of size n*) 
else 
if colCounter=n then (*finished current row, move on*) 
createMines (rowCounter+1, 0, mines,retGame) 
else 

let 
val squareToInsert = Concealed(Mine) (* I wish to insert 'squareToInsert'   
to retGame[rowCounter][colCounter], it's done dynamically, but I don't know 
how to do that *) 
in 
createMines (rowCounter, colCounter+1, retGame) 
end 

in 
createMines (0,0,[]) 
end 

я мог вставить какой-либо площади, он решил динамически, и здесь я дал пример только скрывала Mine, так что вы можете мне помочь .. HELP ..?

ответ

2

Существенным признаком является то, что в стандартном ML вы не мутируете существующие структуры; скорее, вы создаете новые. (Standard ML делает поддержки изменяемые структуры, через ref и его друзей, но это не то, чтобы сделать легко, и я вижу, что вы уже — правильно — правили его.)

В общем, поэтому вставка что-то в середине связанного списка довольно дорого: для этого требуется «раскрутить» список до точки, в которую вы хотите вставить, затем вставить значение и, наконец, создать копию всего, что вы размотали. Например, вот функция, которая будет вставить значение x по индексу i списка:

fun insert (x, 0, L) = x :: L 
    | insert (x, i, h :: t) = h :: insert (x, i - 1, t) 
    | insert (_, _, nil) = raise Subscript 

К счастью, ваша функция написана так, чтобы не вставить что-нибудь в середину уже построенный связанный список ; скорее, если я правильно понимаю, что он пытается сделать, он всегда ставит новый квадрат на , начиная, начиная с. Итак:

let 
    val squareToInsert = Concealed(Mine) 
    val topRow :: rest = retGame 
in 
    createMines (rowCounter, colCounter+1, (squareToInsert::topRow)::rest) 
end 

Обратите внимание, что вам также необходимо исправить еще одну ошибку, которая является то, что вы никогда не создавать новые строки: у вас есть комментарий о «готовой текущей строке, двигаться дальше», но тогда он просто переходит точно так же, как если бы он все еще находился в одной строке (просто сбросив цифры, как если бы он переместился в новую строку). Чтобы исправить это, используйте [] :: retGame, если вы хотите добавить новую строку вверху, и используйте [[]] вместо [] для начальной платы (чтобы она начиналась с пустой строки).

+0

Я решил это, указав аргумент «temp: Square list», добавив, используя тот факт, что списки добавляются с помощью @ и retGame и squareToInsert, используя «[[]]», как вы уже упоминали – mooly