完善十子棋功能
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"work_cation/views"
|
||||
)
|
||||
|
||||
func TestP1(t *testing.T) {
|
||||
r := views.IsArithmeticSequence2([]int{0, 4, 8}, 8, 3, 3, 3)
|
||||
fmt.Println(r)
|
||||
}
|
||||
+6
-2
@@ -3,7 +3,11 @@ package global
|
||||
import "work_cation/models"
|
||||
|
||||
type SendGlobal struct {
|
||||
SendChan chan *models.Message
|
||||
SendChan chan *models.Message
|
||||
Game1Chan chan *models.GameMessage
|
||||
}
|
||||
|
||||
var Send = &SendGlobal{SendChan: make(chan *models.Message, 1000)}
|
||||
var Send = &SendGlobal{
|
||||
SendChan: make(chan *models.Message, 1000),
|
||||
Game1Chan: make(chan *models.GameMessage, 1000),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package models
|
||||
|
||||
type GameMessage struct {
|
||||
UserID string `json:"user_id"`
|
||||
Pos int `json:"pos"`
|
||||
}
|
||||
@@ -105,6 +105,28 @@ func (s *serverService) StartListenServer() error {
|
||||
c.JSON(200, gin.H{"message": "ok"})
|
||||
})
|
||||
|
||||
// 游戏接口
|
||||
router.POST("/game", func(c *gin.Context) {
|
||||
uuid := c.GetHeader("User-UserID")
|
||||
user := repo.UserFollow.GetUser(global.DB, uuid)
|
||||
if user.Ip != c.ClientIP() {
|
||||
c.JSON(200, gin.H{"message": "对方未关注你"})
|
||||
return
|
||||
}
|
||||
var msg = make(map[string]interface{})
|
||||
if err := c.ShouldBind(&msg); err != nil {
|
||||
c.JSON(200, gin.H{"message": "输入异常"})
|
||||
return
|
||||
}
|
||||
|
||||
message := &models.GameMessage{
|
||||
UserID: user.ID,
|
||||
Pos: msg["text"].(int),
|
||||
}
|
||||
global.Send.Game1Chan <- message
|
||||
c.JSON(200, gin.H{"message": "ok"})
|
||||
})
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: cfg.T.ServerAddr,
|
||||
Handler: router,
|
||||
|
||||
+138
-47
@@ -1,6 +1,9 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
@@ -13,18 +16,29 @@ import (
|
||||
|
||||
func TenChinaGameView() {
|
||||
game := NewTenGame(nil)
|
||||
//go func() {
|
||||
// for {
|
||||
// select {
|
||||
// case <-game.Ctx.Done():
|
||||
// return
|
||||
// case msg := <-global.Send.Game1Chan:
|
||||
// game.play()
|
||||
// }
|
||||
// }
|
||||
//}()
|
||||
game.StartShow()
|
||||
}
|
||||
|
||||
type TenGame struct {
|
||||
lock sync.Mutex
|
||||
lock sync.Mutex // 玩家操作锁
|
||||
|
||||
playerMax int // 玩家总人数
|
||||
playerID2Image map[int]fyne.Resource // 各个玩家对应的图标
|
||||
defaultImage fyne.Resource
|
||||
defaultImage fyne.Resource // 默认图标
|
||||
|
||||
CurrentRoundPlayer int // 当前行动的玩家
|
||||
currentRoundPlayer int // 当前行动的玩家
|
||||
players [][]int // 各个玩家已完成下棋数据
|
||||
allMaps []int // 所有下棋数据
|
||||
|
||||
winCallback func(int) // 胜利返回
|
||||
|
||||
@@ -34,38 +48,52 @@ type TenGame struct {
|
||||
itemSize fyne.Size //单个格子大小
|
||||
itemX float32 // 格子总数x
|
||||
itemY float32 // 格子总数y
|
||||
|
||||
winSum int // 胜利连线数
|
||||
|
||||
Ctx context.Context
|
||||
Cancel func()
|
||||
}
|
||||
|
||||
func NewTenGame(winCallback func(int)) *TenGame {
|
||||
game := &TenGame{
|
||||
playerID2Image: map[int]fyne.Resource{
|
||||
0: theme.RadioButtonIcon(),
|
||||
1: theme.CancelIcon(),
|
||||
},
|
||||
defaultImage: theme.CheckButtonIcon(),
|
||||
playerImageMap := map[int]fyne.Resource{
|
||||
0: theme.RadioButtonIcon(),
|
||||
1: theme.CancelIcon(),
|
||||
//2: theme.DownloadIcon(),
|
||||
}
|
||||
|
||||
CurrentRoundPlayer: 0,
|
||||
players: make([][]int, 2),
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
game := &TenGame{
|
||||
playerID2Image: playerImageMap,
|
||||
defaultImage: theme.CheckButtonIcon(),
|
||||
|
||||
currentRoundPlayer: 0,
|
||||
players: make([][]int, len(playerImageMap)),
|
||||
winCallback: winCallback,
|
||||
itemSize: fyne.NewSize(100, 100),
|
||||
itemSize: fyne.NewSize(25, 25),
|
||||
itemX: 3,
|
||||
itemY: 3,
|
||||
winSum: 3,
|
||||
Ctx: ctx,
|
||||
Cancel: cancel,
|
||||
}
|
||||
return game
|
||||
}
|
||||
|
||||
func (t *TenGame) StartShow() {
|
||||
myApp := fyne.CurrentApp()
|
||||
myWindow := myApp.NewWindow("Game")
|
||||
myWindow := myApp.NewWindow(fmt.Sprintf("Game %0.f*%0.f win:%d", t.itemX, t.itemY, t.winSum))
|
||||
t.w = myWindow
|
||||
myWindow.SetContent(t.CanvasObject())
|
||||
myWindow.Resize(fyne.NewSize(t.itemX*t.itemSize.Width+20, t.itemY*t.itemSize.Height+20))
|
||||
myWindow.Resize(fyne.NewSize(t.itemX*(t.itemSize.Width+8), t.itemY*(t.itemSize.Height+8)))
|
||||
myWindow.CenterOnScreen()
|
||||
t.w.SetOnClosed(func() { t.Cancel() })
|
||||
myWindow.Show()
|
||||
}
|
||||
|
||||
func (t *TenGame) CanvasObject() fyne.CanvasObject {
|
||||
gridWrap := container.NewGridWrap(t.itemSize)
|
||||
var items []fyne.CanvasObject
|
||||
|
||||
for i := 0; i < int(t.itemX*t.itemY); i++ {
|
||||
var itemIndex = i
|
||||
|
||||
@@ -75,28 +103,34 @@ func (t *TenGame) CanvasObject() fyne.CanvasObject {
|
||||
t.Items = append(t.Items, image)
|
||||
|
||||
toggle := widget.NewButton("", func() {
|
||||
t.Play(0, itemIndex)
|
||||
_ = t.Play(0, itemIndex)
|
||||
})
|
||||
toggle.Resize(t.itemSize)
|
||||
//toggle.Alignment = 3
|
||||
|
||||
gridWrap.Add(container.NewBorder(nil, nil, nil, nil, container.NewWithoutLayout(image, toggle)))
|
||||
iViews := container.NewBorder(nil, nil, nil, nil, container.NewWithoutLayout(image, toggle))
|
||||
//gridWrap.Add()
|
||||
items = append(items, iViews)
|
||||
}
|
||||
gridWrap := container.NewGridWithRows(int(t.itemX), items...)
|
||||
return container.NewScroll(gridWrap)
|
||||
}
|
||||
|
||||
func (t *TenGame) Play(userIndex int, pos int) error {
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
//if t.CurrentRoundPlayer != userIndex {
|
||||
// return errors.New("not your turn")
|
||||
//if t.currentRoundPlayer != userIndex {
|
||||
// return errors.New("你急个der")
|
||||
//}
|
||||
if slices.Contains(t.allMaps, pos) {
|
||||
return errors.New("已经下过了")
|
||||
}
|
||||
// 下棋
|
||||
t.allMaps = append(t.allMaps, pos)
|
||||
t.play(pos)
|
||||
|
||||
// 推进
|
||||
t.CurrentRoundPlayer++
|
||||
if t.CurrentRoundPlayer+1 > len(t.playerID2Image) {
|
||||
t.CurrentRoundPlayer = 0
|
||||
t.currentRoundPlayer++
|
||||
if t.currentRoundPlayer+1 > len(t.playerID2Image) {
|
||||
t.currentRoundPlayer = 0
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -108,53 +142,110 @@ func (t *TenGame) Play(userIndex int, pos int) error {
|
||||
*/
|
||||
func (t *TenGame) play(pos int) {
|
||||
// 更新玩家数据
|
||||
playerIntList := t.players[t.CurrentRoundPlayer]
|
||||
playerIntList := t.players[t.currentRoundPlayer]
|
||||
playerIntList = append(playerIntList, pos)
|
||||
t.players[t.CurrentRoundPlayer] = playerIntList
|
||||
t.players[t.currentRoundPlayer] = playerIntList
|
||||
|
||||
// 刷新展示
|
||||
t.Items[pos].Resource = t.playerID2Image[t.CurrentRoundPlayer]
|
||||
t.Items[pos].Resource = t.playerID2Image[t.currentRoundPlayer]
|
||||
t.Items[pos].Refresh()
|
||||
|
||||
// check 胜利 判断
|
||||
if t.winCheck(playerIntList) {
|
||||
if t.winCheck(playerIntList, pos) {
|
||||
endView := widget.NewButton("关闭", func() {
|
||||
t.w.Close()
|
||||
})
|
||||
|
||||
img := canvas.NewImageFromResource(t.playerID2Image[t.CurrentRoundPlayer])
|
||||
img := canvas.NewImageFromResource(t.playerID2Image[t.currentRoundPlayer])
|
||||
img.FillMode = canvas.ImageFillOriginal
|
||||
|
||||
v := container.NewBorder(nil, endView, nil, nil,
|
||||
container.NewBorder(nil, nil, img, nil, widget.NewLabel("胜利")))
|
||||
dialog.NewCustomWithoutButtons("游戏结束", v, t.w).Show()
|
||||
if t.winCallback != nil {
|
||||
t.winCallback(t.CurrentRoundPlayer)
|
||||
t.winCallback(t.currentRoundPlayer)
|
||||
}
|
||||
} else if len(t.allMaps) == int(t.itemX*t.itemY) {
|
||||
endView := widget.NewButton("关闭", t.w.Close)
|
||||
|
||||
img := canvas.NewImageFromResource(t.playerID2Image[t.currentRoundPlayer])
|
||||
img.FillMode = canvas.ImageFillOriginal
|
||||
|
||||
v := container.NewBorder(nil, endView, nil, nil,
|
||||
container.NewBorder(nil, nil, img, nil, widget.NewLabel("平局")))
|
||||
dialog.NewCustomWithoutButtons("游戏结束", v, t.w).Show()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TenGame) winCheck(playerIntList []int) bool {
|
||||
slices.Sort(playerIntList)
|
||||
if isArithmeticSequence(playerIntList, 1) ||
|
||||
isArithmeticSequence(playerIntList, 2) ||
|
||||
isArithmeticSequence(playerIntList, 3) ||
|
||||
isArithmeticSequence(playerIntList, 4) {
|
||||
return true
|
||||
func (t *TenGame) winCheck(playerIntList []int, pos int) bool {
|
||||
//slices.Sort(playerIntList)
|
||||
|
||||
return IsArithmeticSequence2(playerIntList, pos, t.winSum, int(t.itemX), int(t.itemY))
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
0, 1, 2
|
||||
3, 4, 5
|
||||
6, 7, 8
|
||||
*/
|
||||
|
||||
type pos struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
/*
|
||||
{0, 0}, {1, 0}, {2, 0}
|
||||
{0, 1}, {1, 1}, {2, 1}
|
||||
{0, 2}, {1, 2}, {2, 2}
|
||||
|
||||
0 1 2
|
||||
3 4 5
|
||||
6 7 8
|
||||
*/
|
||||
func int3pos(maxX, i int) pos {
|
||||
return pos{x: i % maxX, y: i / maxX}
|
||||
}
|
||||
|
||||
func pos2int(maxX int, pos pos) int {
|
||||
return pos.x + pos.y*maxX
|
||||
}
|
||||
|
||||
var lineDirection = [][]pos{
|
||||
{{1, 1}, {-1, -1}},
|
||||
{{1, -1}, {-1, 1}},
|
||||
{{1, 0}, {-1, 0}},
|
||||
{{0, 1}, {0, -1}},
|
||||
}
|
||||
|
||||
func IsArithmeticSequence2(numbers []int, in int, diff int, mapX, mapY int) bool {
|
||||
if len(numbers) <= diff-1 {
|
||||
return false
|
||||
}
|
||||
inPos := int3pos(mapX, in)
|
||||
for _, direction := range lineDirection {
|
||||
var sum = 0
|
||||
for _, idirec := range direction {
|
||||
sum += lineSum(inPos, mapX, mapY, numbers, idirec)
|
||||
}
|
||||
if sum >= diff-1 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isArithmeticSequence(numbers []int, diff int) bool {
|
||||
if len(numbers) <= 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 1; i < len(numbers); i++ {
|
||||
if numbers[i]-numbers[i-1] != diff {
|
||||
return false
|
||||
func lineSum(pos pos, mapX, mapY int, numbers []int, direction pos) (sum int) {
|
||||
for {
|
||||
pos.x += direction.x
|
||||
pos.y += direction.y
|
||||
if pos.x >= mapX || pos.y >= mapY || pos.x < 0 || pos.y < 0 {
|
||||
return
|
||||
}
|
||||
if !slices.Contains(numbers, pos2int(mapX, pos)) {
|
||||
return
|
||||
}
|
||||
sum++
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user