package main import ( "image" "os" "strconv" _ "image/png" "github.com/faiface/pixel" "github.com/faiface/pixel/imdraw" "github.com/faiface/pixel/pixelgl" "github.com/faiface/pixel/text" "github.com/golang/freetype/truetype" "golang.org/x/image/colornames" "golang.org/x/image/font/gofont/goregular" ) const ( width = 900 ) var input bool var x, y int var board = [9][9]int{} var puzzle = [9][9]int{ {6, 7, 2, 3, 4, 1, 5, 8, 9}, {5, 3, 4, 9, 6, 8, 1, 2, 7}, {8, 9, 1, 7, 5, 2, 6, 3, 4}, {3, 5, 6, 8, 2, 9, 4, 7, 1}, {7, 2, 8, 4, 1, 5, 3, 9, 6}, {4, 1, 9, 6, 7, 3, 8, 5, 2}, {1, 8, 3, 2, 9, 6, 7, 4, 5}, {9, 6, 7, 5, 3, 4, 2, 1, 8}, {2, 4, 5, 1, 8, 7, 9, 6, 3}, } var mask = [9][9]bool{ {false, false, true, false, false, true, true, true, false}, {false, false, true, true, true, false, false, false, true}, {true, false, false, false, false, false, true, true, false}, {false, true, true, false, true, false, true, true, false}, {false, true, false, false, false, true, false, true, false}, {false, true, true, false, true, false, true, true, false}, {false, true, true, false, false, false, false, false, true}, {true, false, false, false, true, true, true, false, false}, {false, true, true, true, false, false, true, false, false}, } func loadPicture(path string) (pixel.Picture, error) { file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() img, _, err := image.Decode(file) if err != nil { return nil, err } return pixel.PictureDataFromImage(img), nil } func updateBoard(value int, imd *imdraw.IMDraw) { board[x][y] = value imd.Clear() input = false } func run() { // initialize window cfg := pixelgl.WindowConfig{ Title: "Sudoku", Bounds: pixel.R(0, 0, width, width), VSync: true, } win, err := pixelgl.NewWindow(cfg) if err != nil { panic(err) } // initialize imdraw imd := imdraw.New(nil) // initialize font ttf, err := truetype.Parse(goregular.TTF) if err != nil { panic(err) } face := truetype.NewFace(ttf, &truetype.Options{ Size: 64 * width / 900, }) atlas := text.NewAtlas(face, text.ASCII) // initialize batch batch := pixel.NewBatch(&pixel.TrianglesData{}, atlas.Picture()) // initialize text placeholder num := text.New(pixel.ZV, atlas) // setup game for i := 0; i < 9; i++ { for j := 0; j < 9; j++ { if mask[i][j] { board[i][j] = puzzle[i][j] } } } for !win.Closed() { // win condition if board == puzzle { win.SetClosed(true) } // select a box if win.JustPressed(pixelgl.MouseButtonLeft) { if input { imd.Clear() } pos := win.MousePosition() x = int(pos.X) / (width / 9) y = int(pos.Y) / (width / 9) if !mask[x][y] { imd.Color = colornames.Paleturquoise imd.Push(pixel.V(float64(x*width/9)+1, float64(y*width/9)+1), pixel.V(float64((x+1)*width/9)-1, float64((y+1)*width/9)-1)) imd.Rectangle(0) input = true } } // act on user input if input && !mask[x][y] { if win.JustPressed(pixelgl.Key1) || win.JustPressed(pixelgl.KeyKP1) { updateBoard(1, imd) } if win.JustPressed(pixelgl.Key2) || win.JustPressed(pixelgl.KeyKP2) { updateBoard(2, imd) } if win.JustPressed(pixelgl.Key3) || win.JustPressed(pixelgl.KeyKP3) { updateBoard(3, imd) } if win.JustPressed(pixelgl.Key4) || win.JustPressed(pixelgl.KeyKP4) { updateBoard(4, imd) } if win.JustPressed(pixelgl.Key5) || win.JustPressed(pixelgl.KeyKP5) { updateBoard(5, imd) } if win.JustPressed(pixelgl.Key6) || win.JustPressed(pixelgl.KeyKP6) { updateBoard(6, imd) } if win.JustPressed(pixelgl.Key7) || win.JustPressed(pixelgl.KeyKP7) { updateBoard(7, imd) } if win.JustPressed(pixelgl.Key8) || win.JustPressed(pixelgl.KeyKP8) { updateBoard(8, imd) } if win.JustPressed(pixelgl.Key9) || win.JustPressed(pixelgl.KeyKP9) { updateBoard(9, imd) } if win.JustPressed(pixelgl.Key0) || win.JustPressed(pixelgl.KeyKP0) || win.JustPressed(pixelgl.KeyBackspace) || win.JustPressed(pixelgl.KeySpace) { updateBoard(0, imd) } } // set up lines for drawing for i := 1; i < 9; i++ { imd.Color = colornames.Black if i%3 == 0 { imd.Push(pixel.V(float64(i*width/9), 0), pixel.V(float64(i*width/9), width)) imd.Line(6) imd.Push(pixel.V(0, float64(i*width/9)), pixel.V(width, float64(i*width/9))) imd.Line(6) } else { imd.Push(pixel.V(float64(i*width/9), 0), pixel.V(float64(i*width/9), width)) imd.Line(3) imd.Push(pixel.V(0, float64(i*width/9)), pixel.V(width, float64(i*width/9))) imd.Line(3) } } // set up numbers for drawing batch.Clear() for a, sa := range board { for b, sb := range sa { if sb != 0 { num.Clear() num.WriteString(strconv.Itoa(sb)) num.DrawColorMask(batch, pixel.IM. Scaled( pixel.ZV, float64(width)/900). Moved( pixel.V((float64(a)+0.3)*width/9, (float64(b)+0.25)*width/9)), colornames.Black) } } } // draw the scene to the window win.Clear(colornames.Snow) batch.Draw(win) imd.Draw(win) // update the window win.Update() } } func main() { pixelgl.Run(run) }