I am attempting to write a horse race simulator with multiple rows.
Each row will represent one horse location calculated by a goroutine.
For some reason the code, when run on the Go Playground, does not output the numbers randomly as happens on my machine.
package main
import (
"math/rand"
"os"
"strconv"
"time"
)
var counter = 0
func main() {
i := 1
horses := 9
for i <= horses {
go run(i)
i++
}
time.Sleep(5000 * time.Millisecond)
print("\ncounter: " + strconv.Itoa(counter))
print("\nEnd of main()")
}
func run(number int) {
var i = 1
var steps = 5
for i <= steps {
print("[" + strconv.Itoa(number) + "]")
rand.Seed(time.Now().UnixNano())
sleep := rand.Intn(10)
time.Sleep(time.Duration(sleep) * time.Millisecond)
i++
counter++
}
if i == steps {
println(strconv.Itoa(number) + " wins")
os.Exit(1)
}
}
Playground: https://play.golang.org/p/pycZ4EdH7SQ
My output unordered is:
[1][5][8][2][3][4][7][9][6][7][9][9][4][3]...
But my question is how would I go about to print the numbers like:
[1][1]
[2][2][2][2][2][2][2][2]
[3][3][3]
...
[N][N][N][N][N]
you may want to check out this stackoverflow answer which uses goterm to move the terminal cursor and allow you to overwrite part of it.
The idea is that once you get to the terminal bit you want to be "dynamic" (much like a videogame screen clear+redraw), you always reposition the cursor and "draw" your "horses" position.
Note that with this you will need to store their positions somewhere, to then "draw" their positions at each "frame".
With this exercise you are getting close to how video games work, and for this you may want to set up a goroutine with a given refresh rate to clear your terminal and render what you want.
Related
I'm trying to make a channel with never ending ticker, but it works only 2 times.
Could you help me to understand where is the problem?
Code:
package main
import (
"fmt"
"time"
)
var mark = [2]float64{8.9876, 762.098568}
func tick(out chan <- [2]float64){
c := time.NewTicker(time.Millisecond *500)
for range c.C{
out <- mark
}
}
func main() {
fmt.Println("Start")
md := make(chan [2]float64)
go tick(md)
for range <-md{
fmt.Println(<-md)
}
}
Output:
Start
[8.9876 762.098568]
[8.9876 762.098568]
Example: https://play.golang.org/p/P2FaUwbW-3
This:
for range <-md{
is not the same as:
for range md{
The latter ranges over the channel (what you want), while the former ranges over the value received from the channel when the loop starts, which happens to be a two-element array, hence the two executions. You're also ignoring the value received from the channel in the for statement, and reading from it again in the loop body, ignoring every other message on the channel (though this makes no difference in the example, since every value is identical, it would make a significant difference in practice). What you really want is:
for foo := range md{
fmt.Println(foo)
}
Here's a working version of your playground example, slightly modified to avoid "program took too long" errors because in its current form it never stops: https://play.golang.org/p/RSUJFvluU5
I created a very small game of number guessing in Go. The thing is, it executes differently under Windows and under Linux. By executing it on Ubuntu for example, everything works just fine. But when I try to start it under Windows, it compiles just fine but during execution when I enter something (for example 5) it prints me twice "Smaller than random num"or "Bigger than random num". I have no idea why it happens.
package main
import (
"fmt"
"math/rand"
"time"
)
func main () {
var number int //declaration
var tries int = 0
random_number := random(1, 9) //gets random number
for ; ;tries++ {
//fmt.Printf("Enter your prediction: ")
fmt.Scanf("%v",&number)
if number == random_number {
break;
} else if number<random_number{
fmt.Printf("Smaller than random num\n")
} else {
fmt.Printf("Bigger than random num\n")
}
}
fmt.Printf("You guessed correctly in %v tries",tries)
}
func random(min, max int) int {
rand.Seed(time.Now().Unix())
return rand.Intn(max - min) + min
}
Newlines are different in Linux and Windows, and thus your program behaves differently.
See this issue: https://github.com/golang/go/issues/5391
To fix this, you can replace your Scanf with this (note the "\n" at the end):
fmt.Scanf("%v\n",&number)
I just started using go and wrote my first program but the output is not as expected. I have writtern a async routine addUrl which adds url to channel 5000 times and consumeUrl removes from the channel and prints it.
The routine runs only 9 time. Why is it? Below is the code and output
package main
import "fmt"
import "time"
var urlCount = 0
func main(){
urlHolder := make(chan string,5000)
fmt.Printf("Starting program")
go addUrls(urlHolder)
time.Sleep(time.Millisecond * 100)
go consumeUrls(urlHolder)
fmt.Printf("Done")
}
func addUrls(urlHolder chan string){
var myurl string = "https://example.com/"
for i:=0; i<5000 ; i++ {
urlHolder<-myurl
fmt.Printf(" %d url added \n",i)
time.Sleep(time.Millisecond * 10)
}
}
func consumeUrls(urlHolder chan string) {
urlCount++
urlsConsumed := <- urlHolder
fmt.Printf("Pulled url %d",urlCount," ",urlsConsumed,"\n")
time.Sleep(time.Millisecond * 20)
}
The output is
Starting program
0 url added
1 url added
2 url added
3 url added
4 url added
5 url added
6 url added
7 url added
8 url added
Done
Why is it terminating at 8 when loop is 5000?
You are using time.Sleep to wait for main to finish but you really should be using WaitGroups.
That way you don't have to try to pick some arbitrary time and hope it's enough for your program to finish, or worry about setting too much time and your program sits around doing nothing.
I've added the implementation of WaitGroups to your code here:
https://play.golang.org/p/1zn2JYefaA
Also, the way your consumeUrls function is written is not looping properly and you won't get everything in your channel printed. But since that wasn't your specific question I won't address it here.
Actually The problem was like Nipun said, the main got terminated early.
I need to wait until x.Addr is being updated but it seems the for loop is not run. I suspect this is due the go scheduler and I'm wondering why it works this way or if there is any way I can fix it(without channels).
package main
import "fmt"
import "time"
type T struct {
Addr *string
}
func main() {
x := &T{}
go update(x)
for x.Addr == nil {
if x.Addr != nil {
break
}
}
fmt.Println("Hello, playground")
}
func update(x *T) {
time.Sleep(2 * time.Second)
y := ""
x.Addr = &y
}
There are two (three) problems with your code.
First, you are right that there is no point in the loop at which you give control to the scheduler and such it can't execute the update goroutine. To fix this you can set GOMAXPROCS to something bigger than one and then multiple goroutines can run in parallel.
(However, as it is this won't help as you pass x by value to the update function which means that the main goroutine will never see the update on x. To fix this problem you have to pass x by pointer. Now obsolete as OP fixed the code.)
Finally, note that you have a data race on Addr as you are not using atomic loads and stores.
Given a QR Code of dimensions 100 x 100, I need to make a 2D bit array (array[100][100] that will hold 1 or 0). To get a better idea of the array I am trying to make, look at the array given in this Stack Overflow question.
After hours of searching, I found a function on Google Code that would appear to get the job done. The problem is that the code is given in a .go file, which my computer cannot open.
The ideal solution would either offer a solution in another language, or suggest the way I should go about using the code I found on Google Code.
Thank you in advance for your help!
If you are looking for encoding an url (or other text) to a QR code array and show a textual presentation of the 2D array, you can rather easily make a command line tool to do this in Go.
Below is a fully working example of such a tool using the go package you mentioned.
In order to compile it and run it, go to http://golang.org where you can find instructions on how to install Go, install external libraries, and compile the tool:
package main
import (
"flag"
"fmt"
"os"
"code.google.com/p/go-qrcode"
)
var (
url = flag.String("url", "", "Url to encode")
level = flag.Int("level", 0, "Recovery level. 0 is lowest, 3 is highest")
)
func main() {
flag.Parse()
if *level < 0 || *level > 3 {
fmt.Println("Level must be between 0 and 3")
os.Exit(1)
}
qr, err := qrcode.New(*url, qrcode.RecoveryLevel(*level))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
printArray(qr.Bitmap())
}
func printArray(a [][]bool) {
fmt.Println("{")
for _, x := range a {
fmt.Print(" {")
out := ""
for _, y := range x {
if y {
out += "1"
} else {
out += "0"
}
fmt.Print(out)
out = ","
}
fmt.Println("}")
}
fmt.Println("}")
}
Usage:
Usage of qrarray.exe:
-level=0: Recovery level. 0 is lowest, 3 is highest
-url="": Url to encode