How to resolve the algorithm 2048 step by step in the Wren programming language
Published on 12 May 2024 09:40 PM
How to resolve the algorithm 2048 step by step in the Wren programming language
Table of Contents
Problem Statement
Implement a 2D sliding block puzzle game where blocks with numbers are combined to add their values.
The name comes from the popular open-source implementation of this game mechanic, 2048.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm 2048 step by step in the Wren programming language
Source code in the wren programming language
import "./dynamic" for Enum, Struct
import "random" for Random
import "./ioutil" for Input
import "./fmt" for Fmt
import "./str" for Str
var MoveDirection = Enum.create("MoveDirection", ["up", "down", "left", "right"])
var Tile = Struct.create("Tile", ["value", "isBlocked"])
class G2048 {
construct new() {
_isDone = false
_isWon = false
_isMoved = true
_score = 0
_board = List.filled(4, null)
for (i in 0..3) {
_board[i] = List.filled(4, null)
for (j in 0..3) _board[i][j] = Tile.new(0, false)
}
_rand = Random.new()
initializeBoard()
}
initializeBoard() {
for (y in 0..3) {
for (x in 0..3) _board[x][y] = Tile.new(0, false)
}
}
loop() {
addTile()
while (true) {
if (_isMoved) addTile()
drawBoard()
if (_isDone) break
waitKey()
}
var endMessage = _isWon ? "You've made it!" : "Game Over!"
System.print(endMessage)
}
drawBoard() {
System.print("\e[2J") // clear terminal
System.print("Score: %(_score)\n")
for (y in 0..3) {
System.print("+------+------+------+------+")
System.write("| ")
for (x in 0..3) {
if (_board[x][y].value == 0) {
System.write(" ")
} else {
Fmt.write("$-4s", _board[x][y].value)
}
System.write(" | ")
}
System.print()
}
System.print("+------+------+------+------+\n\n")
}
waitKey() {
_isMoved = false
var input = Str.upper(Input.option("(W) Up (S) Down (A) Left (D) Right: ", "WSADwsad"))
if (input == "W") {
move(MoveDirection.up)
} else if (input == "A") {
move(MoveDirection.left)
} else if (input == "S") {
move(MoveDirection.down)
} else if (input == "D") {
move(MoveDirection.right)
}
for (y in 0..3) {
for (x in 0..3) _board[x][y].isBlocked = false
}
}
addTile() {
for (y in 0..3) {
for (x in 0..3) {
if (_board[x][y].value != 0) continue
var a
var b
while (true) {
a = _rand.int(4)
b = _rand.int(4)
if (_board[a][b].value == 0) break
}
var r = _rand.float()
_board[a][b].value = (r > 0.89) ? 4 : 2
if (canMove()) return
}
}
_isDone = true
}
canMove() {
for (y in 0..3) {
for (x in 0..3) {
if (_board[x][y].value == 0) return true
}
}
for (y in 0..3) {
for (x in 0..3) {
if (testAdd(x + 1, y, _board[x][y].value) ||
testAdd(x - 1, y, _board[x][y].value) ||
testAdd(x, y + 1, _board[x][y].value) ||
testAdd(x, y - 1, _board[x][y].value)) return true
}
}
return false
}
testAdd(x, y, value) {
if (x < 0 || x > 3 || y < 0 || y > 3) return false
return _board[x][y].value == value
}
moveVertically(x, y, d) {
if (_board[x][y + d].value != 0 &&
_board[x][y + d].value == _board[x][y].value &&
!_board[x][y].isBlocked &&
!_board[x][y + d].isBlocked) {
_board[x][y].value = 0
_board[x][y + d].value = _board[x][y + d].value * 2
_score = _score + _board[x][y + d].value
_board[x][y + d].isBlocked = true
_isMoved = true
} else if (_board[x][y + d].value == 0 && _board[x][y].value != 0) {
_board[x][y + d].value = _board[x][y].value
_board[x][y].value = 0
_isMoved = true
}
if (d > 0) {
if (y + d < 3) moveVertically(x, y + d, 1)
} else {
if (y + d > 0) moveVertically(x, y + d, -1)
}
}
moveHorizontally(x, y, d) {
if (_board[x + d][y].value != 0 &&
_board[x + d][y].value == _board[x][y].value &&
!_board[x + d][y].isBlocked &&
!_board[x][y].isBlocked) {
_board[x][y].value = 0
_board[x + d][y].value = _board[x + d][y].value * 2
_score = _score + _board[x + d][y].value
_board[x + d][y].isBlocked = true
_isMoved = true
} else if (_board[x + d][y].value == 0 && _board[x][y].value != 0) {
_board[x + d][y].value = _board[x][y].value
_board[x][y].value = 0
_isMoved = true
}
if (d > 0) {
if (x + d < 3) moveHorizontally(x + d, y, 1)
} else {
if (x + d > 0) moveHorizontally(x + d, y, -1)
}
}
move(direction) {
if (direction == MoveDirection.up) {
for (x in 0..3) {
for (y in 1..3) {
if (_board[x][y].value != 0) moveVertically(x, y, -1)
}
}
} else if (direction == MoveDirection.down) {
for (x in 0..3) {
for (y in 2..0) {
if (_board[x][y].value != 0) moveVertically(x, y, 1)
}
}
} else if (direction == MoveDirection.left) {
for (y in 0..3) {
for (x in 1..3) {
if (_board[x][y].value != 0) moveHorizontally(x, y, -1)
}
}
} else if (direction == MoveDirection.right) {
for (y in 0..3) {
for (x in 2..0) {
if (_board[x][y].value != 0) moveHorizontally(x, y, 1)
}
}
}
}
}
var runGame // forward declaration
var checkRestart = Fn.new {
var input = Str.upper(Input.option("(N) New game (P) Exit: ", "NPnp"))
if (input == "N") {
runGame.call()
} else if (input == "P") return
}
runGame = Fn.new {
var game = G2048.new()
game.loop()
checkRestart.call()
}
runGame.call()
You may also check:How to resolve the algorithm Averages/Mean time of day step by step in the Tcl programming language
You may also check:How to resolve the algorithm Ludic numbers step by step in the Nim programming language
You may also check:How to resolve the algorithm Best shuffle step by step in the PL/I programming language
You may also check:How to resolve the algorithm Metronome step by step in the Go programming language
You may also check:How to resolve the algorithm Operator precedence step by step in the Raku programming language