Skip to content

Commit ed27606

Browse files
authored
Patched Issue #11 + Some Other Improvements (#21)
The commit improves a few things within the twenty48 game. - Fixes the "edge case" mentioned on line 60~71. The game no longer ends when the board is full, but a move is still possible. - Issue #11 (#11) has been patched. Tiles no longer spawn in when a player moves without any tiles actually moving. - Any other *.go files included are due to the formatting command per the contributing guide.
1 parent 8cf0469 commit ed27606

File tree

3 files changed

+60
-26
lines changed

3 files changed

+60
-26
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
*.out
88
go.work
99
/gg
10+
.DS_Store

internal/app/tetris/line_animation.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,3 @@ func (gs *gameState) handleLineAnimationTick(animationTick lineAnimationTick) te
7474
}
7575
})
7676
}
77-

internal/app/twenty48/twenty48.go

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -56,58 +56,48 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
5656
case "ctrl+c", "q":
5757
return m, tea.Quit
5858
case "left", "h":
59+
beforeMerge := m.grid
5960
m.MergeTilesLeft()
60-
/* NOTE: There is an edge case here. This code requires
61-
* that every move the user makes must free up a tile.
62-
* This means that even if the board looks like this:
63-
* 2 | 4 | 8 | 16
64-
* 2 | 4 | 8 | 16
65-
* 2 | 4 | 8 | 16
66-
* 2 | 4 | 8 | 16
67-
* and there is still technically a possible move, if
68-
* the player does not open up new space, the game is
69-
* over.
70-
*/
71-
// TODO: Fix above.
72-
if !m.AddTile() {
73-
return m, tea.Quit
74-
}
61+
m.ValidateTile(beforeMerge)
7562
case "down", "j":
7663
/* Instead of creating a separate method to merge down,
7764
* we rotate the grid. This is because the
7865
* m.MergeTilesLeft() method is *much* more complex
7966
* than m.Rotate90(), so it's simpler to rotate, merge,
8067
* then rotate back than to create a separate function.
8168
*/
69+
beforeMerge := m.grid
8270
m.Rotate90(false)
8371
m.MergeTilesLeft()
8472
m.Rotate90(true)
85-
if !m.AddTile() {
86-
return m, tea.Quit
87-
}
73+
74+
m.ValidateTile(beforeMerge)
8875
case "up", "k":
76+
beforeMerge := m.grid
8977
m.Rotate90(true)
9078
m.MergeTilesLeft()
9179
m.Rotate90(false)
92-
if !m.AddTile() {
93-
return m, tea.Quit
94-
}
80+
m.ValidateTile(beforeMerge)
9581
case "right", "l":
82+
beforeMerge := m.grid
9683
m.Rotate90(false)
9784
m.Rotate90(false)
9885
m.MergeTilesLeft()
9986
m.Rotate90(true)
10087
m.Rotate90(true)
101-
if !m.AddTile() {
102-
return m, tea.Quit
103-
}
88+
m.ValidateTile(beforeMerge)
10489
}
10590
}
10691

10792
if m.CheckForWin() {
10893
return m, tea.Quit
10994
}
11095

96+
// The game is over when there are no possible merges.
97+
if !m.CanMove() {
98+
return m, tea.Quit
99+
}
100+
111101
return m, nil
112102
}
113103

@@ -116,7 +106,7 @@ func (m model) View() string {
116106

117107
for y := 0; y < 4; y++ {
118108
for x := 0; x < 4; x++ {
119-
/* The tiles don't look like this: | 256 |, they llok
109+
/* The tiles don't look like this: | 256 |, they look
120110
* like this: --------
121111
* | |
122112
* | 256 |
@@ -236,6 +226,50 @@ func (m model) CheckForWin() bool {
236226
return false
237227
}
238228

229+
func (m *model) ValidateTile(beforeMerge [4][4]int) (tea.Model, tea.Cmd) {
230+
// Check if the grid has changed after handling the merge logic.
231+
if m.grid != beforeMerge {
232+
// If unable to add a tile, quit.
233+
if !m.AddTile() {
234+
return m, tea.Quit
235+
}
236+
}
237+
238+
return m, nil
239+
}
240+
241+
// Validates that movement is possible. Returns true only if there is at least one empty tile or any adjacent equal pairs present.
242+
func (m model) CanMove() bool {
243+
// Checks for empty tiles.
244+
for y := 0; y < 4; y++ {
245+
for x := 0; x < 4; x++ {
246+
if m.grid[y][x] == 0 {
247+
return true
248+
}
249+
}
250+
}
251+
252+
// Checks if there are any horizontal merges within the grid.
253+
for y := 0; y < 4; y++ {
254+
for x := 0; x < 3; x++ {
255+
if m.grid[y][x] == m.grid[y][x+1] {
256+
return true
257+
}
258+
}
259+
}
260+
261+
// Checks if there are any vertical merges within the grid.
262+
for x := 0; x < 4; x++ {
263+
for y := 0; y < 3; y++ {
264+
if m.grid[y][x] == m.grid[y+1][x] {
265+
return true
266+
}
267+
}
268+
}
269+
270+
return false
271+
}
272+
239273
func Run() {
240274
p := tea.NewProgram(initialModel())
241275

0 commit comments

Comments
 (0)