fix: bouncing ball exercises
This commit is contained in:
		
							
								
								
									
										119
									
								
								18-project-bouncing-ball/exercises/01-find-the-bug/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								18-project-bouncing-ball/exercises/01-find-the-bug/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/inancgumus/screen" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // --------------------------------------------------------- | ||||||
|  | // EXERCISE: Find the Bug | ||||||
|  | // | ||||||
|  | //  As I've annotated in the lectures, there is a bug | ||||||
|  | //  in this code. Please find the bug and fix it. | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // HINT #1 | ||||||
|  | // | ||||||
|  | //  💀 Read this only if you get stuck. | ||||||
|  | // | ||||||
|  | //  Print the width*height and the capacity of the drawing buffer | ||||||
|  | //  after a single drawing loop ends. You might be surprised. | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // HINT #2 | ||||||
|  | // | ||||||
|  | //  💀 Read this only if you get stuck. | ||||||
|  | // | ||||||
|  | //  The bug is in the drawing buffer. It doesn't include the | ||||||
|  | //  newline and space characters when creating the buffer. So | ||||||
|  | //  the buffer is not large enough to hold all the characters. | ||||||
|  | //  So new backing arrays are getting allocated. | ||||||
|  | // | ||||||
|  | // --------------------------------------------------------- | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	const ( | ||||||
|  | 		width  = 50 | ||||||
|  | 		height = 10 | ||||||
|  |  | ||||||
|  | 		cellEmpty = ' ' | ||||||
|  | 		cellBall  = '⚾' | ||||||
|  |  | ||||||
|  | 		maxFrames = 1200 | ||||||
|  | 		speed     = time.Second / 20 | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	var ( | ||||||
|  | 		px, py int    // ball position | ||||||
|  | 		vx, vy = 1, 1 // velocities | ||||||
|  |  | ||||||
|  | 		cell rune // current cell (for caching) | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	// create the board | ||||||
|  | 	board := make([][]bool, width) | ||||||
|  | 	for column := range board { | ||||||
|  | 		board[column] = make([]bool, height) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// create a drawing buffer | ||||||
|  | 	buf := make([]rune, 0, width*height) | ||||||
|  |  | ||||||
|  | 	// clear the screen once | ||||||
|  | 	screen.Clear() | ||||||
|  |  | ||||||
|  | 	for i := 0; i < maxFrames; i++ { | ||||||
|  | 		// calculate the next ball position | ||||||
|  | 		px += vx | ||||||
|  | 		py += vy | ||||||
|  |  | ||||||
|  | 		// when the ball hits a border reverse its direction | ||||||
|  | 		if px <= 0 || px >= width-1 { | ||||||
|  | 			vx *= -1 | ||||||
|  | 		} | ||||||
|  | 		if py <= 0 || py >= height-1 { | ||||||
|  | 			vy *= -1 | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// remove the previous ball | ||||||
|  | 		for y := range board[0] { | ||||||
|  | 			for x := range board { | ||||||
|  | 				board[x][y] = false | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// put the new ball | ||||||
|  | 		board[px][py] = true | ||||||
|  |  | ||||||
|  | 		// rewind the buffer (allow appending from the beginning) | ||||||
|  | 		buf = buf[:0] | ||||||
|  |  | ||||||
|  | 		// draw the board into the buffer | ||||||
|  | 		for y := range board[0] { | ||||||
|  | 			for x := range board { | ||||||
|  | 				cell = cellEmpty | ||||||
|  | 				if board[x][y] { | ||||||
|  | 					cell = cellBall | ||||||
|  | 				} | ||||||
|  | 				buf = append(buf, cell, ' ') | ||||||
|  | 			} | ||||||
|  | 			buf = append(buf, '\n') | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// print the buffer | ||||||
|  | 		screen.MoveTopLeft() | ||||||
|  | 		fmt.Print(string(buf)) | ||||||
|  |  | ||||||
|  | 		// slow down the animation | ||||||
|  | 		time.Sleep(speed) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -0,0 +1,99 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/inancgumus/screen" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	const ( | ||||||
|  | 		width  = 50 | ||||||
|  | 		height = 10 | ||||||
|  |  | ||||||
|  | 		cellEmpty = ' ' | ||||||
|  | 		cellBall  = '⚾' | ||||||
|  |  | ||||||
|  | 		maxFrames = 1200 | ||||||
|  | 		speed     = time.Second / 20 | ||||||
|  |  | ||||||
|  | 		// drawing buffer length | ||||||
|  | 		// *2 for extra spaces | ||||||
|  | 		// +1 for newlines | ||||||
|  | 		bufLen = (width*2 + 1) * height | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	var ( | ||||||
|  | 		px, py int    // ball position | ||||||
|  | 		vx, vy = 1, 1 // velocities | ||||||
|  |  | ||||||
|  | 		cell rune // current cell (for caching) | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	// create the board | ||||||
|  | 	board := make([][]bool, width) | ||||||
|  | 	for column := range board { | ||||||
|  | 		board[column] = make([]bool, height) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// create a drawing buffer | ||||||
|  | 	// BUG FIXED! | ||||||
|  | 	buf := make([]rune, 0, bufLen) | ||||||
|  |  | ||||||
|  | 	// clear the screen once | ||||||
|  | 	screen.Clear() | ||||||
|  |  | ||||||
|  | 	for i := 0; i < maxFrames; i++ { | ||||||
|  | 		// calculate the next ball position | ||||||
|  | 		px += vx | ||||||
|  | 		py += vy | ||||||
|  |  | ||||||
|  | 		// when the ball hits a border reverse its direction | ||||||
|  | 		if px <= 0 || px >= width-1 { | ||||||
|  | 			vx *= -1 | ||||||
|  | 		} | ||||||
|  | 		if py <= 0 || py >= height-1 { | ||||||
|  | 			vy *= -1 | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// remove the previous ball | ||||||
|  | 		for y := range board[0] { | ||||||
|  | 			for x := range board { | ||||||
|  | 				board[x][y] = false | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// put the new ball | ||||||
|  | 		board[px][py] = true | ||||||
|  |  | ||||||
|  | 		// rewind the buffer (allow appending from the beginning) | ||||||
|  | 		buf = buf[:0] | ||||||
|  |  | ||||||
|  | 		// draw the board into the buffer | ||||||
|  | 		for y := range board[0] { | ||||||
|  | 			for x := range board { | ||||||
|  | 				cell = cellEmpty | ||||||
|  | 				if board[x][y] { | ||||||
|  | 					cell = cellBall | ||||||
|  | 				} | ||||||
|  | 				buf = append(buf, cell, ' ') | ||||||
|  | 			} | ||||||
|  | 			buf = append(buf, '\n') | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// print the buffer | ||||||
|  | 		screen.MoveTopLeft() | ||||||
|  | 		fmt.Print(string(buf)) | ||||||
|  |  | ||||||
|  | 		// slow down the animation | ||||||
|  | 		time.Sleep(speed) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -5,6 +5,15 @@ | |||||||
| // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"github.com/inancgumus/screen" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
| // --------------------------------------------------------- | // --------------------------------------------------------- | ||||||
| // EXERCISE: Adjust the width and height automatically | // EXERCISE: Adjust the width and height automatically | ||||||
| // | // | ||||||
| @@ -88,15 +97,6 @@ | |||||||
| // | // | ||||||
| // --------------------------------------------------------- | // --------------------------------------------------------- | ||||||
| 
 | 
 | ||||||
| package main |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 	"time" |  | ||||||
| 
 |  | ||||||
| 	"github.com/inancgumus/screen" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func main() { | func main() { | ||||||
| 	const ( | 	const ( | ||||||
| 		width  = 50 | 		width  = 50 | ||||||
| @@ -107,6 +107,12 @@ func main() { | |||||||
| 
 | 
 | ||||||
| 		maxFrames = 1200 | 		maxFrames = 1200 | ||||||
| 		speed     = time.Second / 20 | 		speed     = time.Second / 20 | ||||||
|  | 
 | ||||||
|  | 		// drawing buffer length | ||||||
|  | 		// | ||||||
|  | 		// *2 for extra spaces | ||||||
|  | 		// +1 for newlines | ||||||
|  | 		bufLen = (width*2 + 1) * height | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 	var ( | 	var ( | ||||||
| @@ -123,7 +129,7 @@ func main() { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// create a drawing buffer | 	// create a drawing buffer | ||||||
| 	buf := make([]rune, 0, width*height) | 	buf := make([]rune, 0, bufLen) | ||||||
| 
 | 
 | ||||||
| 	// clear the screen once | 	// clear the screen once | ||||||
| 	screen.Clear() | 	screen.Clear() | ||||||
| @@ -57,8 +57,13 @@ func main() { | |||||||
| 		board[column] = make([]bool, height) | 		board[column] = make([]bool, height) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// drawing buffer length | ||||||
|  | 	// *2 for extra spaces | ||||||
|  | 	// +1 for newlines | ||||||
|  | 	bufLen := (width*2 + 1) * height | ||||||
|  | 
 | ||||||
| 	// create a drawing buffer | 	// create a drawing buffer | ||||||
| 	buf := make([]rune, 0, width*height) | 	buf := make([]rune, 0, bufLen) | ||||||
| 
 | 
 | ||||||
| 	// clear the screen once | 	// clear the screen once | ||||||
| 	screen.Clear() | 	screen.Clear() | ||||||
| @@ -72,8 +72,13 @@ func main() { | |||||||
| 		board[column] = make([]bool, height) | 		board[column] = make([]bool, height) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// drawing buffer length | ||||||
|  | 	// *2 for extra spaces | ||||||
|  | 	// +1 for newlines | ||||||
|  | 	bufLen := (width*2 + 1) * height | ||||||
|  | 
 | ||||||
| 	// create a drawing buffer | 	// create a drawing buffer | ||||||
| 	buf := make([]rune, 0, width*height) | 	buf := make([]rune, 0, bufLen) | ||||||
| 
 | 
 | ||||||
| 	// clear the screen once | 	// clear the screen once | ||||||
| 	screen.Clear() | 	screen.Clear() | ||||||
| @@ -23,13 +23,14 @@ func main() { | |||||||
| 		maxFrames = 1200 | 		maxFrames = 1200 | ||||||
| 		speed     = time.Second / 20 | 		speed     = time.Second / 20 | ||||||
| 
 | 
 | ||||||
| 		initVx, initVy = 5, 2 | 		// initial velocities | ||||||
|  | 		ivx, ivy = 5, 2 | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 	var ( | 	var ( | ||||||
| 		px, py   int              // ball position | 		px, py   int        // ball position | ||||||
| 		ppx, ppy int              // previous ball position | 		ppx, ppy int        // previous ball position | ||||||
| 		vx, vy   = initVx, initVy // velocities | 		vx, vy   = ivx, ivx // velocities | ||||||
| 
 | 
 | ||||||
| 		cell rune // current cell (for caching) | 		cell rune // current cell (for caching) | ||||||
| 	) | 	) | ||||||
| @@ -50,8 +51,13 @@ func main() { | |||||||
| 		board[column] = make([]bool, height) | 		board[column] = make([]bool, height) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// drawing buffer length | ||||||
|  | 	// *2 for extra spaces | ||||||
|  | 	// +1 for newlines | ||||||
|  | 	bufLen := (width*2 + 1) * height | ||||||
|  | 
 | ||||||
| 	// create a drawing buffer | 	// create a drawing buffer | ||||||
| 	buf := make([]rune, 0, width*height) | 	buf := make([]rune, 0, bufLen) | ||||||
| 
 | 
 | ||||||
| 	// clear the screen once | 	// clear the screen once | ||||||
| 	screen.Clear() | 	screen.Clear() | ||||||
| @@ -62,10 +68,10 @@ func main() { | |||||||
| 		py += vy | 		py += vy | ||||||
| 
 | 
 | ||||||
| 		// when the ball hits a border reverse its direction | 		// when the ball hits a border reverse its direction | ||||||
| 		if px <= 0 || px >= width-initVx { | 		if px <= 0 || px >= width-ivx { | ||||||
| 			vx *= -1 | 			vx *= -1 | ||||||
| 		} | 		} | ||||||
| 		if py <= 0 || py >= height-initVy { | 		if py <= 0 || py >= height-ivx { | ||||||
| 			vy *= -1 | 			vy *= -1 | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @@ -43,13 +43,14 @@ func main() { | |||||||
| 		maxFrames = 1200 | 		maxFrames = 1200 | ||||||
| 		speed     = time.Second / 20 | 		speed     = time.Second / 20 | ||||||
| 
 | 
 | ||||||
| 		initVx, initVy = 5, 2 | 		// initial velocities | ||||||
|  | 		ivx, ivy = 5, 2 | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 	var ( | 	var ( | ||||||
| 		px, py   int              // ball position | 		px, py   int        // ball position | ||||||
| 		ppx, ppy int              // previous ball position | 		ppx, ppy int        // previous ball position | ||||||
| 		vx, vy   = initVx, initVy // velocities | 		vx, vy   = ivx, ivy // velocities | ||||||
| 
 | 
 | ||||||
| 		cell rune // current cell (for caching) | 		cell rune // current cell (for caching) | ||||||
| 	) | 	) | ||||||
| @@ -70,8 +71,13 @@ func main() { | |||||||
| 		board[column] = make([]bool, height) | 		board[column] = make([]bool, height) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// drawing buffer length | ||||||
|  | 	// *2 for extra spaces | ||||||
|  | 	// +1 for newlines | ||||||
|  | 	bufLen := (width*2 + 1) * height | ||||||
|  | 
 | ||||||
| 	// create a drawing buffer | 	// create a drawing buffer | ||||||
| 	buf := make([]rune, 0, width*height) | 	buf := make([]rune, 0, bufLen) | ||||||
| 
 | 
 | ||||||
| 	// clear the screen once | 	// clear the screen once | ||||||
| 	screen.Clear() | 	screen.Clear() | ||||||
| @@ -82,10 +88,10 @@ func main() { | |||||||
| 		py += vy | 		py += vy | ||||||
| 
 | 
 | ||||||
| 		// when the ball hits a border reverse its direction | 		// when the ball hits a border reverse its direction | ||||||
| 		if px <= 0 || px >= width-initVx { | 		if px <= 0 || px >= width-ivx { | ||||||
| 			vx *= -1 | 			vx *= -1 | ||||||
| 		} | 		} | ||||||
| 		if py <= 0 || py >= height-initVy { | 		if py <= 0 || py >= height-ivy { | ||||||
| 			vy *= -1 | 			vy *= -1 | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @@ -23,13 +23,14 @@ func main() { | |||||||
| 		maxFrames = 1200 | 		maxFrames = 1200 | ||||||
| 		speed     = time.Second / 20 | 		speed     = time.Second / 20 | ||||||
| 
 | 
 | ||||||
| 		initVx, initVy = 5, 2 | 		// initial velocities | ||||||
|  | 		ivx, ivy = 5, 2 | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 	var ( | 	var ( | ||||||
| 		px, py   int              // ball position | 		px, py   int        // ball position | ||||||
| 		ppx, ppy int              // previous ball position | 		ppx, ppy int        // previous ball position | ||||||
| 		vx, vy   = initVx, initVy // velocities | 		vx, vy   = ivx, ivy // velocities | ||||||
| 
 | 
 | ||||||
| 		cell rune // current cell (for caching) | 		cell rune // current cell (for caching) | ||||||
| 	) | 	) | ||||||
| @@ -47,8 +48,13 @@ func main() { | |||||||
| 	// create a single-dimensional board | 	// create a single-dimensional board | ||||||
| 	board := make([]bool, width*height) | 	board := make([]bool, width*height) | ||||||
| 
 | 
 | ||||||
|  | 	// drawing buffer length | ||||||
|  | 	// *2 for extra spaces | ||||||
|  | 	// +1 for newlines | ||||||
|  | 	bufLen := (width*2 + 1) * height | ||||||
|  | 
 | ||||||
| 	// create a drawing buffer | 	// create a drawing buffer | ||||||
| 	buf := make([]rune, 0, width*height) | 	buf := make([]rune, 0, bufLen) | ||||||
| 
 | 
 | ||||||
| 	// clear the screen once | 	// clear the screen once | ||||||
| 	screen.Clear() | 	screen.Clear() | ||||||
| @@ -59,25 +65,22 @@ func main() { | |||||||
| 		py += vy | 		py += vy | ||||||
| 
 | 
 | ||||||
| 		// when the ball hits a border reverse its direction | 		// when the ball hits a border reverse its direction | ||||||
| 		if px <= 0 || px >= width-initVx { | 		if px <= 0 || px >= width-ivx { | ||||||
| 			vx *= -1 | 			vx *= -1 | ||||||
| 		} | 		} | ||||||
| 		if py <= 0 || py >= height-initVy { | 		if py <= 0 || py >= height-ivy { | ||||||
| 			vy *= -1 | 			vy *= -1 | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// check whether the ball goes beyond the borders | 		// calculate the new and the previous ball positions | ||||||
| 		if px < width && py < height { | 		pos := py*width + px | ||||||
| 			// calculate the new and the previous ball positions | 		ppos := ppy*width + ppx | ||||||
| 			pos := py*width + px |  | ||||||
| 			ppos := ppy*width + ppx |  | ||||||
| 
 | 
 | ||||||
| 			// remove the previous ball and put the new ball | 		// remove the previous ball and put the new ball | ||||||
| 			board[pos], board[ppos] = true, false | 		board[pos], board[ppos] = true, false | ||||||
| 
 | 
 | ||||||
| 			// save the previous positions | 		// save the previous positions | ||||||
| 			ppx, ppy = px, py | 		ppx, ppy = px, py | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		// rewind the buffer (allow appending from the beginning) | 		// rewind the buffer (allow appending from the beginning) | ||||||
| 		buf = buf[:0] | 		buf = buf[:0] | ||||||
		Reference in New Issue
	
	Block a user