Permainan Boggle adalah permianan papan yang terdpaat huruf - huruf. Kita diperintahkan untuk mencari kata apa saja terdapat pada papan tersebut, dengan menghubung huruf satu dengan yang lainnya.
Tutorial kali ini kita akan membuat boggle solver, dimana game ini akan men-solve kata - kata apa saja yang ada di papan tersebut. Saat ini kita buat untuk kata - kata yang ada di dalam KBBI saja yaa, untuk bahasa lain seperti bahasa inggris, german, dll bisa ditambahkan dengan ubah sedikit kode & menambahkan bahasa dalam bentuk file json saja.
Mari mulai dari membuat psudo-code, implementasi pseudo-code ke dalam bahasa pemrograman, kemudian membuat tampilan. Hasilnya nanti kurang lebih seperti ini yaa demo
Caranya hanya membuat method solve() saja, berikut struktur modular function-nya
solve(){
...
checkWord(){
...
getNextLetter()
getMove()
}
}
METHOD checkWord() digunakan untuk mengecek kata apa yang ada di dalam papan.
METHOD getNextLetter() untuk mendapatkan huruf selanjutnya pada suatu kata
METHOD getMove() untuk mengetahui arah urutan huruf & menentukan apakah suatu kata
dapat dibentuk dalam papan tersebut
Format kamus KBBI-nya seperti ini yaa ind.json
{
A: ["ABAD","ABADI","ABAH","ABAI","ABAL", ...],
B: ["BABA","BABAD","BABAH","BABAK", ...],
...
}
// SET GLOBALLY
import IND from "../static/ind.json";
import ENG from "../static/eng.json";
SET DIC = {
IND, ENG, ...
}
SET ROW = LENGTH OF boards ROW
SET COL = LENGTH OF boards COLUMN
SET language = "IND"
// EXAMPLE BOARDS
SET BOARDS = [
['A', 'H', 'O', 'R', 'J'],
['Q', 'Q', 'U', 'O', 'I'],
['S', 'S', 'C', 'P', 'D'],
['M', 'U', 'P', 'S', 'M'],
['A', 'U', 'U', 'L', 'I'],
]
RESULT
AH
AHO
HUS
M E T H O D solve()
Pastikan tidak ada kotak yang kosong,
untuk mengeceknya bisa buat method checkBoard() dulu yaa
// UNTUK OPTIMASI (LEBIH BAIK LOOPING HURUF YANG ADA DI BOARDS-NYA)
SET keyOfBoard = {}
FOREACH boards => (rows)
FOREACH rows => (key)
SET keyOfBoad[e] = null
END FOREACH
END FOREACH
FOR key IN keyOfBoards
SET words = DIC[language][key]
FOR w = 0 UNTIL w < LENGTH OF words AND w++
CALL checkWord()
END FOR
END FOR
M E T H O D checkWord()
FOR i = 0 UNTIL i < ROW AND i++
FOR j = 0 UNTIL j < COL AND j++
SET histories = []
SET w = 0
SET boards = CLONE BOARDS ORIGINAL
IF boards[i][j] !== null && boards[i][j] !== true
| IF boards[i][j] === word[w]
| | PUSH { iH: i, jH: j, vH: boards[i][j] } TO histories
| | SET boards[i][j] = TRUE
| | SET nextLetter = getNextLetter(w, word)
| |
| | IF nextLetter
| | | w++
| | | SET x = i
| | | SET y = j
| | | SET FLAG = TRUE
| | | WHILE FLAG
| | | | SET move = getMove({ i: x, j: y, nextLetter, boards })
| | | | SET FLAG = move.flag
| | | | SET boards = move.boards
| | | |
| | | | IF FLAG
| | | | | SET x = move.x
| | | | | SET y = move.y
| | | | | PUSH { iH: x, jH: y, vH: nextLetter } TO histories
| | | | | SET nextLetter = getNextLetter(w, word)
| | | | |
| | | | | IF nextLetter
| | | | | | w++
| | | | | ELSE
| | | | | | PUSH {
| | | | | | word,
| | | | | | boards: JSON.parse(JSON.stringify(boards)),
| | | | | | }
| | | | | | SET FLAG = FALSE
| | | | | END IF
| | | | ELSE IF LENGTH OF histories > 1
| | | | | SET back = POP histories
| | | | | SET boards[back.iH][back.jH] = NULL
| | | | | SET { iH, jH, vH } = histories.pop();
| | | | | SET x = iH;
| | | | | SET y = jH;
| | | | | SET w--;
| | | | | SET nextLetter = word[w]
| | | | | SET FLAG = TRUE
| | | | END IF
| | | END WHILE
| | END IF
| END IF
END IF
IF j > 0
BREAK LOOPING
END IF
END FOR
BREAK LOOPING
END FOR
M E T H O D getNextLetter(w, word)
IF word[w + 1]
RETURN word[w + 1]
END IF
RETURN NULL
M E T H O D getMove(payload)
SET { i, j, nextLetter, boards } = payload
// 1 | 2 | 3
// 8 | X | 4
// 7 | 6 | 5
SET arrow = {
1: { i: -1, j: -1 },
2: { i: -1, j: 0 },
3: { i: -1, j: 1 },
4: { i: 0, j: 1 },
5: { i: 1, j: 1 },
6: { i: 1, j: 0 },
7: { i: 1, j: -1 },
8: { i: 0, j: -1 },
};
SET result = { x: i, y: j, nextLetter, flag: false }
FOR [key, value] OF Object.entries(arrow)
SET x = i + value.i
SET y = j + value.j
IF x >= 0 && x < ROW && y >= 0 && y < COL
| IF boards[x][y] !== null && boards[x][y] !== true
| | IF boards[x][y] === nextLetter
| | | SET boards[x][y] = TRUE
| | | SET result.x = x
| | | SET result.y = y
| | | SET result.flag = TRUE
| | | BREAK LOOPING
| | ELSE
| | | SET boards[x][y] = null
| | END IF
| END IF
END IF
END FOR
SET result.boards = boards;
RETURN result