iT邦幫忙

2025 iThome 鐵人賽

DAY 28
2

前言

昨天我們完成了 輸入違規提示與剩餘格數、錯誤格數的顯示,今天要進一步設計遊戲的 勝利檢查與結束畫面。這是數獨遊戲的最後一步之一,能讓玩家有完整的挑戰與回饋體驗。

🎯 本日主題

  • 當 剩餘格數 = 0 且錯誤格數 = 0 時 → 判定玩家完成遊戲,顯示「恭喜完成!」。
  • 設計簡單的 遊戲結束畫面,包含重新開始選項。
  • 在遊戲狀態結束後,禁止再輸入數字,直到重新開始。

📦 資料結構延伸

我們在原本的 Game 結構中,加上遊戲狀態判斷:

type GameLayout struct {
	gameInstance *game.Game
	difficulty   game.Difficulty
	isPlayerWin  bool
}
// checkIfPlayerWin - 檢查勝利狀態
func (gameLayout *GameLayout) checkIfPlayerWin() bool {
	board := gameLayout.gameInstance.Board
	remainingCount := board.TargetSolvedCount - board.FilledCount
	conflictCount := board.ConflictCount
	return remainingCount == 0 && conflictCount == 0
}

📝 勝利檢查邏輯

當玩家每次輸入數字時,重新計算 Remaining 與 Errors,並在 Update 時進行判斷:

func (gameLayout *GameLayout) Update() error {
	gameLayout.handleRestartButton()
	if gameLayout.isPlayerWin {
		return nil
	}
	gameLayout.DetectCursor()
	gameLayout.DetectInput()
	// 檢查狀態
	gameLayout.isPlayerWin = gameLayout.checkIfPlayerWin()
	return nil
}

🖥️ 畫面顯示設計

在 Ebiten 繪製畫面時,依照 IsPlayerWin 狀態繪製不同提示:

// drawBoardStatus - 根據是否勝利來畫出不同的提示詞
func (gameLayout *GameLayout) drawBoardStatus(screen *ebiten.Image) {
	emojiValue := "⏳"
	message := "Keep going"
	iconColor := getIconColor(Playing)
	if gameLayout.isPlayerWin {
		emojiValue = "🏆"
		message = "You Win!"
		iconColor = getIconColor(Win)
	}
	emojiXPos := len(emojiValue)
	emojiYPos := cellSize + cellSize/2
	emojiOpts := &text.DrawOptions{}
	emojiOpts.ColorScale.ScaleWithColor(iconColor)
	emojiOpts.PrimaryAlign = text.AlignStart
	emojiOpts.SecondaryAlign = text.AlignCenter
	emojiOpts.GeoM.Translate(float64(emojiXPos), float64(emojiYPos))
	text.Draw(screen, emojiValue, &text.GoTextFace{
		Source: emojiFaceSource,
		Size:   30,
	}, emojiOpts)
	textValue := message
	textXPos := cellSize
	textYPos := cellSize + cellSize/2
	textOpts := &text.DrawOptions{}
	textOpts.ColorScale.ScaleWithColor(color.Black)
	textOpts.PrimaryAlign = text.AlignStart
	textOpts.SecondaryAlign = text.AlignCenter
	textOpts.GeoM.Translate(float64(textXPos), float64(textYPos))
	text.Draw(screen, textValue, &text.GoTextFace{
		Source: mplusFaceSource,
		Size:   25,
	}, textOpts)
}

🎮 重新開始功能

繪製重新開始的 Button

// drawRestartButton - 繪製重新開始的 Button
func (gameLayout *GameLayout) drawRestartButton(screen *ebiten.Image) {
	vector.DrawFilledCircle(screen, float32(8*cellSize+cellSize/2), cellSize+cellSize/2, 25,
		getIconColor(Button),
		true,
	)
	emojiValue := "🔃"
	emojiXPos := 8*cellSize + len(emojiValue)
	emojiYPos := cellSize + cellSize/2
	emojiOpts := &text.DrawOptions{}
	emojiOpts.ColorScale.ScaleWithColor(getIconColor(Restart))
	emojiOpts.PrimaryAlign = text.AlignStart
	emojiOpts.SecondaryAlign = text.AlignCenter
	emojiOpts.GeoM.Translate(float64(emojiXPos), float64(emojiYPos))
	text.Draw(screen, emojiValue, &text.GoTextFace{
		Source: emojiFaceSource,
		Size:   30,
	}, emojiOpts)
}

實做重新開始功能

// ResetBoardToDefault - 重開始功能
func (board *Board) ResetBoardToDefault() {
	for row := 0; row < BoardSize; row++ {
		for col := 0; col < BoardSize; col++ {
			if board.Cells[row][col].Type != Preset {
				board.Cells[row][col].Type = Empty
				board.Cells[row][col].Value = 0
			}
		}
	}
	board.FilledCount = 0
	board.ConflictCount = 0
}

綁定 button 與功能

// handleRestartButton
func (gameLayout *GameLayout) handleRestartButton() {
	if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
		xPos, yPos := ebiten.CursorPosition()
		if (xPos >= 8*cellSize && xPos <= 9*cellSize) &&
			(yPos >= cellSize && yPos <= 2*cellSize) {
			gameLayout.gameInstance.Board.ResetBoardToDefault()
		}
	}
	gameLayout.isPlayerWin = gameLayout.checkIfPlayerWin()
}

執行畫面

勝利畫面

https://ithelp.ithome.com.tw/upload/images/20250910/20111580QAQS1z7sFs.png

重新開始功能

https://ithelp.ithome.com.tw/upload/images/20250910/20111580iSwK0t6QfR.png

github action 測試

https://github.com/leetcode-golang-classroom/sudoku-game/actions/runs/17590954625/job/49971332265

✅ 驗收條件

  • 當剩餘格數 = 0 且錯誤格數 = 0 → 出現「🏆 You Win!」提示。
  • 結束畫面出現後,不能再輸入數字。
  • 按下 restart button → 重新開始新遊戲。

📌 本日收穫

  • 完成數獨遊戲的 勝利檢查邏輯。
  • 設計了 結束畫面,提供玩家清楚的回饋。
  • 增加了 重新開始機制,提升遊戲循環體驗

🔮 明日預告

明日將會加入關卡難度選擇與顯示執行時間


上一篇
Sudoku遊戲:輸入違規時給予錯誤提示或標記
下一篇
Sudoku 遊戲:關卡難度選擇與顯示執行時間
系列文
在 ai 時代 gopher 遊戲開發者的 30 天自我養成30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言