Example #1
0
// screenToCoord translates the provided pixel location to grid coordinates.
func screenToCoord(g *grid.Grid, x, y int) (col, row int, err error) {
	// Note: a regular grid would simplify this code a lot.

	var area = [][]image.Rectangle{
		{
			image.Rect(0, 0, 138, 119),   // 0, 0
			image.Rect(0, 133, 146, 243), // 0, 1
			image.Rect(0, 244, 157, 409), // 0, 2
		},
		{
			image.Rect(154, 0, 309, 116),   // 1, 0
			image.Rect(165, 136, 299, 245), // 1, 1
			image.Rect(158, 261, 322, 409), // 1, 2
		},
		{
			image.Rect(310, 0, 499, 128),   // 2, 0
			image.Rect(317, 129, 499, 258), // 2, 1
			image.Rect(323, 270, 499, 409), // 2, 2
		},
	}

	pt := image.Pt(x, y)
	for col = 0; col < g.Width(); col++ {
		for row = 0; row < g.Height(); row++ {
			if pt.In(area[col][row]) {
				return col, row, nil
			}
		}
	}
	return 0, 0, fmt.Errorf("screenToCoord: invalid cell (x=%d, y=%d)", x, y)
}
Example #2
0
// Render renders the grid each time a value is sent on the render channel.
func Render(win wde.Window, g *grid.Grid, render chan bool) {
	screen := win.Screen()
	bounds := screen.Bounds()
	grey := image.NewUniform(color.RGBA{R: 0xF9, G: 0xF9, B: 0xF9}) /// ### todo ### A: 0xFF?
	for {
		<-render

		// Draw grid background.
		draw.Draw(screen, bounds, grey, image.ZP, draw.Src)
		draw.Draw(screen, bounds, imgGrid, image.ZP, draw.Over)

		// Draw grid markers.
		var img image.Image
		for col := 0; col < g.Width(); col++ {
			for row := 0; row < g.Height(); row++ {
				switch g[col][row] {
				case grid.MarkO:
					img = imgO
				case grid.MarkX:
					img = imgX
				default:
					continue
				}
				pt := getCellPt(col, row, g[col][row])
				rect := image.Rect(0, 0, img.Bounds().Dx(), img.Bounds().Dy())
				draw.Draw(screen, rect.Add(pt), img, image.ZP, draw.Over)
			}
		}

		// Flush screen updates.
		win.FlushImage(bounds)
	}
}
Example #3
0
// Input handles user input.
func Input(win wde.Window, g *grid.Grid, render chan bool) {
	// turnB keeps track of whose turn it is. When true, it's player B's turn.
	var turnB bool

	// When end is true the game has ended.
	var end bool

	// mde handles mouse down events.
	mde := func(e wde.MouseDownEvent) {
		if e.Which == wde.LeftButton {
			// Left click places a marker.

			if end {
				// Game has already ended.
				return
			}

			// Translate pixel location to grid coordinate.
			col, row, err := screenToCoord(g, e.Where.X, e.Where.Y)
			if err != nil {
				///log.Println(err)
				return
			}

			// Place marker.
			player := markA
			if turnB {
				player = markB
			}
			err = g.Place(col, row, player)
			if err != nil {
				///log.Println(err)
				return
			}
			turnB = !turnB
			render <- true

			// Check if the game has ended.
			end = true
			markWin := g.Check()
			if markWin != grid.MarkNone {
				fmt.Printf("===> %q wins :)\n", markWin)
				return
			}

		loop:
			for col := 0; col < g.Width(); col++ {
				for row := 0; row < g.Height(); row++ {
					if g[col][row] == grid.MarkNone {
						end = false
						break loop
					}
				}
			}
			if end {
				fmt.Println("===> no winner :(")
			}

		} else if e.Which == wde.MiddleButton {
			// Middle click clears the grid.
			g.Clear()
			turnB = false
			end = false
			render <- true
		}
	}

	for e := range win.EventChan() {
		switch v := e.(type) {
		case wde.CloseEvent:
			return
		case wde.MouseDownEvent:
			mde(v)
		}
	}
}