Go Ebiten小游戏开发:井字棋

image-20250113024452832

今天我将分享如何使用 Go 语言和 Ebiten 游戏库开发一个简单的井字棋游戏。Ebiten 是一个轻量级的 2D 游戏库,非常适合用来开发小型游戏。通过这个项目,我们可以学习到如何使用 Ebiten 处理输入、渲染图形以及管理游戏状态。

项目概述

井字棋是一个经典的两人对战游戏,玩家轮流在 3x3 的棋盘上放置自己的标记(通常是“圈”和“叉”),先连成一条线的玩家获胜。我们的目标是实现一个简单的井字棋游戏,支持以下功能:

  • 玩家轮流下棋
  • 检测游戏是否结束(胜利或平局)
  • 游戏结束后的重新开始功能
  • 简单的动画效果

代码结构

我们的代码主要分为以下几个部分:

  1. 游戏状态管理:包括棋盘状态、当前玩家回合、游戏是否结束等。
  2. 输入处理:处理鼠标点击和键盘输入。
  3. 渲染逻辑:绘制棋盘、棋子和游戏结束动画。
  4. 游戏逻辑:检查胜利条件、平局条件等。

1. 游戏状态管理

我们使用一个 Game 结构体来管理游戏的状态:

type Game struct {
   
	Turn       bool      // 当前玩家回合(true: 玩家1,false: 玩家2)
	Board      [3][3]int // 3x3 的棋盘,0: 空,1: 玩家1,2: 玩家2
	IsGameOver bool      // 游戏是否结束
}

2. 输入处理

我们通过 HandleInput 函数来处理玩家的输入。玩家可以通过鼠标点击来下棋,按下 R 键重新开始游戏,按下 ESC 键退出游戏。

func (game *Game) HandleInput() {
   
	if ebiten.IsKeyPressed(ebiten.KeyEscape) {
   
		game.Exit() // 按下 ESC 键退出游戏
	}
	if !game.IsGameOver && ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
   
		game.HandleMouseClick() // 如果游戏未结束且按下鼠标左键,处理点击
	}
	if game.IsGameOver && ebiten.IsKeyPressed(ebiten.KeyR) {
   
		game.Restart() // 如果游戏结束且按下 R 键,重新开始游戏
	}
}

3. 渲染逻辑

我们使用 DrawBoard 函数来绘制棋盘和棋子。棋盘由两条垂直线和两条水平线组成,棋子则根据棋盘状态绘制“圈”或“叉”。

func DrawBoard(screen *ebiten.Image, game *Game) {
   
	// 绘制棋盘线条
	for i := 1; i <= 2; i++ {
   
		vector.DrawFilledRect(screen, float32(i)*BlockSize, 0, LineWidth, 3*BlockSize+LineWidth, WHITE, true)
		vector.DrawFilledRect(screen, 0, float32(i)*BlockSize, 3*BlockSize+LineWidth, LineWidth, WHITE, true)
	}
	// 绘制棋子的圈和叉
	for i := 0; i < 3; i++ {
   
		for j := 0; j < 3; j++ {
   
			if game.Board[i][j] == 1 {
   
				DrawCircle(screen, i, j) // 画圈
			} else if game.Board[i][j] == 2 {
   
				DrawCross(screen, i, j) // 画叉
			}
		}
	}
}

4. 游戏逻辑

我们通过 CheckGameOver 函数来检查游戏是否结束。如果棋盘已满且没有玩家获胜,则为平局;否则,检查是否有玩家连成一条线。

func (game *Game) CheckGameOver() {
   
	if IsBoardFull(game.Board) {
    // 检查是否平局
		game.IsGameOver = true
		GameOverText = "It's a Draw!"
	} else if CheckWin(game.Board) {
    // 检查是否有玩家获胜
		game.IsGameOver = true
		if game.Turn {
    // 当前回合是 O,说明 X 赢了
			GameOverText = "Player X Wins!"
		} else {
    // 当前回合是 X,说明 O 赢了
			GameOverText = "Player O Wins!"
		}
	}
}

完整代码

package main

import (
	"image"
	"image/color"
	"log"
	"math"
	"os"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/vector"
	"golang.org/x/image/font"
	"golang.org/x/image/font/basicfont"
	"golang.org/x/image/math/fixed"
)

const (
	BlockSize       float32 = 200                               // 每个格子的大小
	WindowWidth     int     = 3*int(BlockSize) + 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值