初始化项目文件

This commit is contained in:
2025-07-11 16:54:11 +08:00
parent 6bffd582a0
commit 39fedaac16
213 changed files with 16944 additions and 0 deletions

View File

@ -0,0 +1,614 @@
package api
import (
"errors"
"fmt"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"io"
"main/database"
"main/model"
"main/utils"
"math/rand"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
)
var initChessPawns = model.ChessStatus{
Current: "",
IsEnd: false,
Status: "0,1,2,3,4,5,6,7,8;-1,-1,-1,-1,-1,-1,-1,-1,-1;-1,9,-1,-1,-1,-1,-1,10,-1;11,-1,12,-1,13,-1,14,-1,15;-1,-1,-1,-1,-1,-1,-1,-1,-1;-1,-1,-1,-1,-1,-1,-1,-1,-1;31,-1,30,-1,29,-1,28,-1,27;-1,26,-1,-1,-1,-1,-1,25,-1;-1,-1,-1,-1,-1,-1,-1,-1,-1;24,23,22,21,20,19,18,17,16",
Winner: "",
ChessId: "",
}
func addAiChessPlayer(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if username.Username == "" {
return
}
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if status.Players != username.Username {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房主方可添加机器人"))
return
}
status.Players += ",ai--" + id
status.Status = initChessPawns.Status
status.Current = username.Username
status.IsEnd = initChessPawns.IsEnd
status.Winner = initChessPawns.Winner
status.ChessId = initChessPawns.ChessId
db := database.GetInstance().GetMysqlDb()
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
func updateChessAiStep(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if username.Username == "" {
return
}
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if players := strings.Split(status.Players, ","); players[0] != username.Username || players[1] != "ai--"+id {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间人员配置错误"))
return
}
if status.Current != "ai--"+id {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("当前非ai回合"))
return
}
stepList := strings.Split(getAiChessStep(chessPawnStatusToFen(chessPawnStrToSlice(status.Status)), "queryall", "b"), "|")
var tmpNum int
if strings.Index(stepList[0], "score:??") != -1 {
rand.NewSource(time.Now().Unix())
tmpNum = rand.Intn(len(stepList))
} else {
tmpNum = 0
}
stepTmp := strings.Split(stepList[tmpNum], ",")[0]
//fmt.Println(stepTmp, chessPawnStatusToFen(chessPawnStrToSlice(status.Status)))
if strings.Index(stepTmp, "move:") == -1 {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(errors.New("机器人无合适步骤,对局结束"))
return
}
step := strings.Split(stepTmp, "move:")[1]
tmp := "abcdefghi0123456789"
statusList := chessPawnStrToSlice(status.Status)
start0 := 8 - strings.IndexByte(tmp, step[0])
end0 := 8 - strings.IndexByte(tmp, step[2])
start1 := strings.IndexByte(tmp, step[1]) - 9
end1 := strings.IndexByte(tmp, step[3]) - 9
statusList[end1][end0] = statusList[start1][start0]
statusList[start1][start0] = "-1"
status.Status = chessPawnSliceToStr(statusList)
status.ChessId = statusList[end1][end0]
status.Current = username.Username
db := database.GetInstance().GetMysqlDb()
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(200, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
func testChess(ctx iris.Context) {
var res [][]string
db := database.GetInstance().GetMysqlDb()
var status []model.ChessStatus
if err := db.Find(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
for _, s := range status {
stepTmp := getAiChessStep(chessPawnStatusToFen(chessPawnStrToSlice(s.Status)), "queryall", "b")
//fmt.Println(s.Status, chessPawnStatusToFen(chessPawnStrToSlice(s.Status)))
step := strings.Split(stepTmp, "move:")[1]
tmp := "abcdefghi0123456789"
//statusList := chessPawnStrToSlice(status.Status)
start0 := strings.IndexByte(tmp, step[0])
end0 := strings.IndexByte(tmp, step[2])
start1 := strings.IndexByte(tmp, step[1]) - 9
end1 := strings.IndexByte(tmp, step[3]) - 9
statusTmp := chessPawnStrToSlice(s.Status)
start := statusTmp[start1][start0]
end := statusTmp[end1][end0]
res = append(res, []string{start, end})
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", res))
if utils.ErrHandle(ctx, err) {
return
}
}
func resetRoom(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if username.Username == "" {
return
}
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if utils.DataIsNil(status) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间号不存在"))
return
}
if strings.Split(status.Players, ",")[0] != username.Username {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房主方可重置房间"))
return
}
db := database.GetInstance().GetMysqlDb()
status.Status = initChessPawns.Status
status.Current = username.Username
status.IsEnd = initChessPawns.IsEnd
status.Winner = initChessPawns.Winner
status.ChessId = initChessPawns.ChessId
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
// 新建房间
func newChessRoom(ctx iris.Context) {
creator := utils.GetLoginUser(ctx)
if creator.Username == "" {
return
}
db := database.GetInstance().GetMysqlDb()
status := model.ChessStatus{
Players: creator.Username,
Current: creator.Username,
IsEnd: initChessPawns.IsEnd,
Status: initChessPawns.Status,
Winner: initChessPawns.Winner,
ChessId: initChessPawns.ChessId,
}
if err := db.Create(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status.ID))
if utils.ErrHandle(ctx, err) {
return
}
}
// 获取所有房间
func getChessRooms(ctx iris.Context) {
db := database.GetInstance().GetMysqlDb()
var rooms []model.ChessStatus
if err := db.Find(&rooms).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", rooms))
if utils.ErrHandle(ctx, err) {
return
}
}
// 加入房间
func joinChessRoom(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if utils.DataIsNil(status) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间号不存在"))
return
}
if len(strings.Split(status.Players, ",")) >= 2 {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间人数已满"))
return
}
if utils.CheckListItem(strings.Split(status.Players, ","), username.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("不可重复加入房间"))
return
}
status.Players += fmt.Sprintf(",%s", username.Username)
db := database.GetInstance().GetMysqlDb()
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if err := db.Create(&model.ChessStatusLog{
RoomId: status.ID,
Players: status.Players,
Current: status.Current,
IsEnd: status.IsEnd,
Status: status.Status,
Winner: status.Winner,
ChessId: status.ChessId,
Time: status.CreatedAt,
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
// 离开房间
func leaveChessRoom(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if utils.DataIsNil(status) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间号不存在"))
return
}
if !utils.CheckListItem(strings.Split(status.Players, ","), username.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("未加入该房间"))
return
}
for _, v := range strings.Split(status.Players, ",") {
if v != username.Username {
status.Players = v
}
}
db := database.GetInstance().GetMysqlDb()
if status.Players == username.Username || status.Players == "ai--"+id {
if err := db.Delete(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
} else {
status.Current = status.Players
status.ChessId = initChessPawns.ChessId
status.IsEnd = initChessPawns.IsEnd
status.Winner = initChessPawns.Winner
status.Status = initChessPawns.Status
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
// 获取房间状态接口
func getChessRoom(ctx iris.Context) {
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if utils.DataIsNil(status) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间号不存在"))
return
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
// 更新棋盘状态
func updateChessStatus(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
id := ctx.Params().Get("id")
pawn := ctx.URLParam("pawn")
des := ctx.URLParam("des")
status := getChessRoomStatus(id)
if utils.DataIsNil(status) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间号不存在"))
return
}
if len(strings.Split(status.Players, ",")) < 2 {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间人数不足"))
return
}
pawnNum, _ := strconv.Atoi(pawn)
if (strings.Split(status.Players, ",")[0] == username.Username && pawnNum > 15) || (strings.Split(status.Players, ",")[1] == username.Username && pawnNum < 16) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("只能移动自己的棋子"))
return
}
if status.Current != username.Username {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("当前不是你的回合"))
return
}
if checkChessStep(pawn, status.Status, des) {
tmpStatus := chessPawnStrToSlice(status.Status)
locTmp := getPawnLoc(status.Status, pawn)
toTmp0, _ := strconv.Atoi(strings.Split(des, ",")[0])
toTmp1, _ := strconv.Atoi(strings.Split(des, ",")[1])
tmpStatus[locTmp[0]][locTmp[1]] = "-1"
tmpStatus[toTmp0][toTmp1] = pawn
status.Status = chessPawnSliceToStr(tmpStatus)
status.ChessId = pawn
for _, v := range strings.Split(status.Players, ",") {
if v != username.Username {
status.Current = v
}
}
if checkWinner(status.Status) == 1 {
status.Winner = username.Username
status.IsEnd = true
status.Current = ""
}
} else {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("当前无法移到该位置"))
return
}
db := database.GetInstance().GetMysqlDb()
if checkWinner(status.Status) == 2 {
for _, v := range strings.Split(status.Players, ",") {
if v != username.Username {
status.Winner = v
status.IsEnd = true
}
}
}
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if err := db.Create(&model.ChessStatusLog{
RoomId: status.ID,
Current: status.Current,
Players: status.Players,
IsEnd: status.IsEnd,
Status: status.Status,
Winner: status.Winner,
ChessId: status.ChessId,
Time: status.CreatedAt,
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
// 获取房间状态方法
func getChessRoomStatus(id string) model.ChessStatus {
db := database.GetInstance().GetMysqlDb()
var status model.ChessStatus
if err := db.Where("id = ?", id).First(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
return status
}
func checkWinner(status string) int {
if utils.DataIsNil(getPawnLoc(status, "4")) || utils.DataIsNil(getPawnLoc(status, "20")) {
return 1
}
if checkNullPath(chessPawnStrToSlice(status), getPawnLoc(status, "4"), getPawnLoc(status, "20")) {
return 2
}
return 0
}
// 获取棋子位置
func getPawnLoc(statusStr string, pawn string) [2]int {
var res [2]int
status := chessPawnStrToSlice(statusStr)
for row, i := range status {
for col, j := range i {
if j == pawn {
res[0] = row
res[1] = col
}
}
}
return res
}
// 判断棋子是否可移动
func checkChessStep(pawn string, statusStr string, to string) bool {
locList := getPawnLoc(statusStr, pawn)
status := chessPawnStrToSlice(statusStr)
locTmp0 := locList[0]
locTmp1 := locList[1]
toTmp := strings.Split(to, ",")
toTmp0, _ := strconv.Atoi(toTmp[0])
toTmp1, _ := strconv.Atoi(toTmp[1])
//目标位置超出棋盘
if toTmp0 < 0 || toTmp1 < 0 || toTmp0 > 10 || toTmp1 > 8 {
return false
}
pawnNum, _ := strconv.Atoi(pawn)
toPawnNum, _ := strconv.Atoi(status[toTmp0][toTmp1])
if (pawnNum < 16 && toPawnNum < 16 && toPawnNum >= 0) || (pawnNum > 15 && toPawnNum > 15) {
return false
}
switch pawn {
case "0", "8", "16", "24": //车:同行列,路径为空
if (toTmp0 == locTmp0 && toTmp1 != locTmp1) || (toTmp1 == locTmp1 && toTmp0 != locTmp0) && checkNullPath(status, [2]int{locTmp0, locTmp1}, [2]int{toTmp0, toTmp1}) {
return true
}
case "1", "7", "17", "23": //马:日字,前后左右无子
if (utils.IntAbs(toTmp0-locTmp0) == 1 && utils.IntAbs(toTmp1-locTmp1) == 2 && status[locTmp0][(locTmp1+toTmp1)/2] == "-1") || (utils.IntAbs(toTmp0-locTmp0) == 2 && utils.IntAbs(toTmp1-locTmp1) == 1 && status[(locTmp0+toTmp0)/2][locTmp1] == "-1") {
return true
}
case "2", "6", "18", "22": //象:田字,不过河,中间格子为空
if utils.IntAbs(toTmp0-locTmp0) == 2 && utils.IntAbs(toTmp1-locTmp1) == 2 && ((locTmp0 < 5 && toTmp0 < 5) || (locTmp0 > 4 && toTmp0 > 4)) && status[(locTmp0+toTmp0)/2][(locTmp1+toTmp1)/2] == "-1" {
return true
}
case "3", "5", "19", "21": //士:斜着走,不超出方格
if toTmp1 < 3 || toTmp1 > 5 || (locTmp0 < 5 && toTmp0 > 2) || (locTmp0 > 4 && toTmp0 < 7) {
return false
}
if utils.IntAbs(toTmp0-locTmp0) == 1 && utils.IntAbs(toTmp1-locTmp1) == 1 {
return true
}
case "4", "20": //将:走一步,不超出方格
if toTmp1 < 3 || toTmp1 > 5 || (locTmp0 < 5 && toTmp0 > 2) || (locTmp0 > 4 && toTmp0 < 7) {
return false
}
if utils.IntAbs(toTmp0-locTmp0)+utils.IntAbs(toTmp1-locTmp1) == 1 {
return true
}
case "9", "10", "25", "26": //炮:同行列,路径不为空,目标位置不为空
if ((toTmp0 == locTmp0 && toTmp1 != locTmp1) || (toTmp1 == locTmp1 && toTmp0 != locTmp0)) && ((!checkNullPath(status, [2]int{locTmp0, locTmp1}, [2]int{toTmp0, toTmp1}) && status[toTmp0][toTmp1] != "-1") || (checkNullPath(status, [2]int{locTmp0, locTmp1}, [2]int{toTmp0, toTmp1}) && status[toTmp0][toTmp1] == "-1")) {
return true
}
case "11", "12", "13", "14", "15": //兵:走一步,过河后可横移
if (toTmp0 < 5 && toTmp1 == locTmp1 && toTmp0-locTmp0 == 1) || (toTmp0 > 4 && utils.IntAbs(toTmp0-locTmp0+toTmp1-locTmp1) == 1) {
return true
}
case "27", "28", "29", "30", "31": //兵:走一步,过河后可横移
if (toTmp0 > 4 && toTmp1 == locTmp1 && toTmp0-locTmp0 == -1) || (toTmp0 < 5 && utils.IntAbs(toTmp0-locTmp0+toTmp1-locTmp1) == 1) {
return true
}
default:
return false
}
return false
}
// 棋盘状态字符串转数组
func chessPawnStrToSlice(status string) [][]string {
var res [][]string
for _, i := range strings.Split(status, ";") {
var colList []string
for _, j := range strings.Split(i, ",") {
colList = append(colList, j)
}
res = append(res, colList)
}
return res
}
// 棋盘状态数组转字符串
func chessPawnSliceToStr(status [][]string) string {
var resList []string
for _, i := range status {
resList = append(resList, strings.Join(i, ","))
}
res := strings.Join(resList, ";")
return res
}
func chessPawnStatusToFen(status [][]string) string {
var res []string
for _, i := range status {
resTmp := ""
count := 0
for col, j := range i {
if j == "-1" && col == len(i)-1 {
resTmp += strconv.Itoa(count + 1)
} else if j == "-1" {
count += 1
} else {
if count != 0 {
resTmp += strconv.Itoa(count)
count = 0
}
switch j {
case "0", "8":
resTmp += "R"
case "1", "7":
resTmp += "N"
case "2", "6":
resTmp += "B"
case "3", "5":
resTmp += "A"
case "4":
resTmp += "K"
case "9", "10":
resTmp += "C"
case "11", "12", "13", "14", "15":
resTmp += "P"
case "16", "24":
resTmp += "r"
case "17", "23":
resTmp += "n"
case "18", "22":
resTmp += "b"
case "19", "21":
resTmp += "a"
case "20":
resTmp += "k"
case "25", "26":
resTmp += "c"
case "27", "28", "29", "30", "31":
resTmp += "p"
}
}
}
res = append(res, resTmp)
}
return utils.Reverse(strings.Join(res, "/"))
}
// 判断路径是否为空
func checkNullPath(status [][]string, start [2]int, end [2]int) bool {
if start[0] == end[0] {
path := []int{start[1], end[1]}
sort.Ints(path)
for i := path[0] + 1; i < path[1]; i++ {
if status[start[0]][i] != "-1" {
return false
}
}
return true
}
if start[1] == end[1] {
path := []int{start[0], end[0]}
sort.Ints(path)
for i := path[0] + 1; i < path[1]; i++ {
if status[i][start[1]] != "-1" {
return false
}
}
return true
}
return false
}
func getAiChessStep(fenStatus string, t string, p string) string {
urlPath, err := url.Parse("http://www.chessdb.cn/chessdb.php")
params := url.Values{}
params.Set("action", t)
params.Set("board", fmt.Sprintf("%s %s", fenStatus, p))
params.Set("showall", "1")
urlPath.RawQuery = params.Encode()
res, err := http.Get(urlPath.String())
if err != nil {
return err.Error()
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
}
}(res.Body)
body, _ := io.ReadAll(res.Body)
return string(body)
}