简介:
游戏双方分别使用绵羊(S)和老虎(T)
图 1
图中6S代表当前为位置上有6只绵羊
除了如图所示为6S的点外,其他点只能同时有一个动物,6S点可容纳任意数量的动物,但必须是同一种类,两只老虎不能同时出现在同一位置上
绵羊每次可以沿着连线移动一个位置,老虎每次也可以仅移动一个位置,但如果该直线方向上相邻是绵羊,且距离为2的点为空时,老虎可以跨过绵羊跳到该位置,并吃掉绵羊
当绵羊数为0时老虎胜,老虎无法移动时绵羊胜,如图2,(3, 2)位置上的老虎跳到(5, 2)吃掉(4,2)上的一只绵羊
图 2
绵羊和老虎轮流移动一个棋子,每局开始以如图1所示开始,且老虎先走。
游戏操作:
提示:It's turn to tigger
输入:老虎所在行 (回车)老虎所在列(回车)
提示: Input move target
输入:要移动到的位置行(回车),列(回车)
完成后切换到羊
提示: It's turn to sheep
输入:羊所在行(回车),列(回车)
如果该位置有多只羊
提示Select piece,并列出该位置上羊的索引如1 2 3 4 5 6
输入:羊的索引 ,如1(回车)
提示:Input move target
输入:要移动到的位置行(回车),列(回车)
完成羊的移动,切换到老虎,交换操作直到游戏结束,如
Sheep win
源代码:
下载连接
http://download.youkuaiyun.com/detail/piaobotudou/7718661
Array类:
--class array --
Array = {
nextIdx = 1,
}
function Array:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
o.content = {}
for i=1, #o do
if o[i] then
o:push_back(o[i])
end
end
return o;
end
function Array:count()
return self.nextIdx - 1
end
function Array:toIndex(idx)
i = tonumber(idx)
if i and i>0 and i<=self:count() then
return i
end
return nil
end
function Array:push_back(a)
self.content[self.nextIdx] = a
self.nextIdx = self.nextIdx + 1
end
function Array:pop_back()
if self:count() > 0 then
self.nextIdx = self.nextIdx - 1
res = self.content[self.nextIdx]
self.content[self.nextIdx] = nil
return res
end
return nil
end
function Array:cleanup()
for i=1, #self.content do
self.content[i] = nil
end
self.nextIdx = 1
end
function Array:find(item)
for i=1, self:count() do
if self.content[i] == item then
return i
end
end
return nil
end
function Array:remove_item(item)
idx = self:find(item)
if idx then
self:remove(idx)
end
end
function Array:insert(idx, a)
idx = self:toIndex(idx)
if idx then
local cpl
local cp2
cp1 = a
for i=idx, self:count() do
cp2 = self.content[i]
self.content[i] = cp1
cp1 = cp2
end
self:push_back(cp1)
end
end
function Array:getAt(idx)
i = self:toIndex(idx)
if i then
return self.content[idx]
end
return nil
end
function Array:remove(idx)
idx = self:toIndex(idx)
if idx then
for i=idx, self:count()-1 do
self.content[i] = self.content[i+1]
end
self:pop_back()
end
end
--Insert at 1
function Array:push_front(a)
self:insert(1, a)
end
function Array:pop_front()
res = self.content[1]
self:remove(1)
return res
end
function Array:print()
local s = "";
if self:count() > 0 then
s = s..self:getAt(1)
end
for i=2, self:count() do
s = s.." ".. self:getAt(i)
end
print(s)
end
core.lua
--Chess board class---
--Include Line & Node --
PIECETYPE = {
none = 0,
tigger = 1,
sheep = 2
}
--piece define--
Piece = {}
Piece.name = "unnamed piece"
Piece.r = -1 --row
Piece.c = -1 --col
Piece.idx = -1
Piece.dead = false
Piece.type = none
function Piece:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
PieceTigger = Piece:new()
PieceTigger.name = "Tigger"
Piece.type = PIECETYPE.tigger
PieceSheep = Piece:new()
PieceSheep.name = "Sheep"
PieceSheep.type = PIECETYPE.sheep
PieceManager = {tiggers=nil,sheeps=nil}
function PieceManager:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self;
o.tiggers = {}
o.sheeps = {}
return o
end
function PieceManager:makealive()
for i=1,#self.tiggers do
self.tiggers[i].dead = false
end
for i=1,#self.sheeps do
self.sheeps[i].dead = false
end
end
function PieceManager:getpiece(idx)
if idx < 25 then
return self.sheeps[idx]
elseif idx<27 then
return self.tiggers[idx - 24]
else
return nil
end
end
function PieceManager:init(tn, sn)
for i=1, tn do
self.tiggers[i] = PieceTigger:new()
self.tiggers[i].idx = i + sn
self.tiggers[i].name = "tigger "..(i-sn)
end
for i=1,sn do
self.sheeps[i] = PieceSheep:new()
self.sheeps[i].idx = i
self.sheeps[i].name = "sheep "..i
end
end
--class Line--
Line = {}
Line.nodes = nil
function Line:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
o.nodes = {}
return o
end
function Line:append(node)
self.nodes[(#(self.nodes)) + 1] = node
end
--
--class Node--
--
dofile("array.lua")
Node = {}
Node.lines = nil
Node.pieces = nil
Node.capacity = 1
function Node:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
o.pieces = Array:new()
o.lines = {}
return o
end
function Node:canaddpiece()
return self.pieces:count() < self.capacity
end
function Node:empty()
return self.pieces:count() == 0
end
function Node:firstpiece()
if self:empty() then
return nil
else
return self.pieces:getAt(1);
end
end
function Node:add(l, i)
self.lines[#self.lines + 1] = {line = l, idx = i}
end
function Node:isonline(lidx)
for i = 1, #self.lines do
if self.lines[i].line == lidx then
return true
end
end
return false
end
function Node:getidxofline(lidx)
for i=1, #self.lines do
if self.lines[i].line == lidx then
return self.lines[i].idx
end
end
return nil
end
function Node:printlines()
print( "LinesCount: "..#self.lines)
str = ""
for i=1, #self.lines do
str = str .. self.lines[i].line.." "
end
print(str)
end
function Node:getline(otherNode)
--self:printlines()
--otherNode:printlines()
for i=1, #self.lines do
if otherNode:isonline(self.lines[i].line) then
return self.lines[i].line
end
end
return nil
end
--Board--
--[[
1 2 3 4 5
--------/-------.,------/-------. 6
|`. | ,`|` | ,`|
| `. | ,' | `. | ,' |
|', | - | ', | - |
| `|,' | `|,' |
--------|---------------|-------- 7
| ,' | `. | ,' | `. |
| ,- | `, | ,- | `, |
| / | ',| / | ',|
-`------|-------|-------|-------. 8
11 |`. | ,`|`. | ,`| 16
| `. | ,' | `. | ,' |
| ', | - | ', | - |
| `|,' | `|,' |
--------|---------------|-------- 9
| ,' | `. | ,' | `. |
| ,- | `, | ,- | `, |
| / | ',| / | ',|
-`------\-------'`------\-------' 10
12 13 14 15
----]]
Board = {}
Board.nodes = nil
Board.lines = nil
function Board:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
o.nodes = {}
o.lines = {}
return o
end
function rowcolToIndex(r, c)
return (r-1)*5 + c
end
function indexToRow(idx)
return math.ceil(idx/5)
end
function indexToCol(idx)
return idx - (indexToRow(idx) - 1)*5
end
function Board:appendNodeToLine(lidx, r, c)
self.lines[lidx]:append(rowcolToIndex(r, c))
self.nodes[r][c]:add(lidx, #self.lines[lidx].nodes)
end
function Board:Init()
for i=1, 5 do
self.nodes[i] = {}
for j=1, 5 do
self.nodes[i][j] = Node:new()
end
end
self.nodes[2][2].capacity = 100
self.nodes[4][2].capacity = 100
self.nodes[2][4].capacity = 100
self.nodes[4][4].capacity = 100
for i=1,16 do
self.lines[i] = Line:new()
end
for i=1, 5 do
for k=1,5 do
self:appendNodeToLine(i, k, i)
self:appendNodeToLine(i+5, i, k)
end
end
self:appendNodeToLine(11, 3, 1)
self:appendNodeToLine(11, 2, 2)
self:appendNodeToLine(11, 1, 3)
self:appendNodeToLine(12, 5, 1)
self:appendNodeToLine(12, 4, 2)
self:appendNodeToLine(12, 3, 3)
self:appendNodeToLine(12, 2, 4)
self:appendNodeToLine(12, 1, 5)
self:appendNodeToLine(13, 5, 3)
self:appendNodeToLine(13, 4, 4)
self:appendNodeToLine(13, 3, 5)
self:appendNodeToLine(14, 3, 1)
self:appendNodeToLine(14, 4, 2)
self:appendNodeToLine(14, 5, 3)
self:appendNodeToLine(15, 1, 1)
self:appendNodeToLine(15, 2, 2)
self:appendNodeToLine(15, 3, 3)
self:appendNodeToLine(15, 4, 4)
self:appendNodeToLine(15, 5, 5)
self:appendNodeToLine(16, 1, 3)
self:appendNodeToLine(16, 2, 4)
self:appendNodeToLine(16, 3, 5)
end
--GAME--
Game = {}
Game.board = nil
Game.pieces = nil--PieceManager:new()
Game.turn = PIECETYPE.tigger
Game.curpick = -1
function Game:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
o.board = Board:new()
o.pieces = PieceManager:new()
return o
end
function Game:AddPieceToBoard(r, c, idx, bt)
self.board.nodes[r][c].pieces:push_back(idx)
--print(r.." "..c.." "..idx)
if bt then
self.pieces.tiggers[idx-24].r = r
self.pieces.tiggers[idx-24].c = c
else
self.pieces.sheeps[idx].r = r
self.pieces.sheeps[idx].c = c
end
end
function Game:restart()
for i=1, 5 do
for j=1,5 do
self.board.nodes[i][j].pieces:cleanup()
end
end
-- for i, v in ipairs(self.board.nodes) do
-- end
self.pieces:makealive()
for i=1,6 do
self:AddPieceToBoard(2, 2, i, false)
self:AddPieceToBoard(2, 4, i+6, false)
self:AddPieceToBoard(4, 2, i+12, false)
self:AddPieceToBoard(4, 4, i+18, false)
end
--self.board.nodes[2][2].pieces:print()
--self.board.nodes[2][4].pieces:print()
--for i,v in ipairs(self.pieces.sheeps) do
-- print(v.name.." "..v.r.." "..v.c)
-- if v.r<0 then
-- break
-- end
-- end
self:AddPieceToBoard(3, 2, 25, true)
self:AddPieceToBoard(3, 4, 26, true)
self.turn = PIECETYPE.tigger
self.curpick = -1
end
function Game:init()
self.board:Init()
self.pieces:init(2, 24)
self:restart()
end
--1:25 2:26--
function Game:getsheepmoveablenodeidx(idx)
local curpiece = self.pieces:getpiece(idx)
local curnode = self.board.nodes[curpiece.r][curpiece.c]
local lidx = 0
local nidx = 0
local line = nil
local tr = 0
local tc = 0
local tn = nil
res = {}
for i=1, #curnode.lines do
lidx = curnode.lines[i].line
nidx = curnode.lines[i].idx
line = self.board.lines[lidx]
if nidx - 1 > 0 then
tr = indexToRow(line.nodes[nidx - 1])
tc = indexToCol(line.nodes[nidx - 1])
tn = self.board.nodes[tr][tc]
if tn:empty() or (tn:canaddpiece() and self.pieces:getpiece(tn:firstpiece()).type == PIECETYPE.sheep) then
res[#res + 1] = line.nodes[nidx - 1]
end
end
if nidx + 1 <= #line.nodes then
tr = indexToRow(line.nodes[nidx + 1])
tc = indexToCol(line.nodes[nidx + 1])
tn = self.board.nodes[tr][tc]
if tn:empty() or (tn:canaddpiece() and self.pieces:getpiece(tn:firstpiece()).type == PIECETYPE.sheep) then
res[#res + 1] = line.nodes[nidx + 1]
end
end
end
return res
end
function Game:gettiggermoveablenodeidx(idx)
local idx = idx + 24
local curpiece = self.pieces:getpiece(idx)
local curnode = self.board.nodes[curpiece.r][curpiece.c]
local lidx = 0
local nidx = 0
local line = nil
local tr = 0
local tc = 0
local tn = nil
res = {}
for i=1, #curnode.lines do
lidx = curnode.lines[i].line
nidx = curnode.lines[i].idx
line = self.board.lines[lidx]
--ss = "Line index: " .. lidx.."nIdx: "..curnode.lines[i].idx
--print(ss)
--ss = ""
--for i=1, #line.nodes do
-- ss = ss.." "..line.nodes[i]
--end
--print(ss)
if nidx - 1 > 0 then
tr = indexToRow(line.nodes[nidx - 1])
tc = indexToCol(line.nodes[nidx - 1])
tn = self.board.nodes[tr][tc]
if tn:empty() then
res[#res + 1] = line.nodes[nidx - 1]
elseif nidx - 2 > 0 and self.pieces:getpiece(tn:firstpiece()).type == PIECETYPE.sheep then
tr = indexToRow(line.nodes[nidx - 2])
tc = indexToCol(line.nodes[nidx - 2])
tn = self.board.nodes[tr][tc]
if tn:empty() then
res[#res + 1] = line.nodes[nidx - 2]
end
end
end
if nidx + 1 <= #line.nodes then
tr = indexToRow(line.nodes[nidx + 1])
tc = indexToCol(line.nodes[nidx + 1])
--print("tr "..tr.."tc: "..tc)
tn = self.board.nodes[tr][tc]
if tn:empty() then
res[#res + 1] = line.nodes[nidx + 1]
elseif nidx + 2 <= #line.nodes and self.pieces:getpiece(tn:firstpiece()).type == PIECETYPE.sheep then
tr = indexToRow(line.nodes[nidx + 2])
tc = indexToCol(line.nodes[nidx + 2])
tn = self.board.nodes[tr][tc]
if tn:empty() then
res[#res + 1] = line.nodes[nidx + 2]
end
end
end
end
return res
end
function Game:istiggerunmoveable(idx)
res = self:gettiggermoveablenodeidx(idx)
return #res == 0
end
function Game:pickpiece(idx)
if self.turn == PIECETYPE.tigger then
if idx< 25 or idx>26 then
self.curpick = -1;
return false
else
self.curpick = idx
return true
end
else
if idx<1 or idx>24 then
self.curpick = -1;
return false
else
self.curpick = idx
return true
end
end
end
function Game:movepieceto(r, c, pieceIdx)
curPiece = self.pieces:getpiece(pieceIdx)
self.board.nodes[curPiece.r][curPiece.c].pieces:remove_item(pieceIdx)
self.board.nodes[r][c].pieces:push_back(pieceIdx)
curPiece.r = r
curPiece.c = c
if curPiece.type == PIECETYPE.sheep then
self.turn = PIECETYPE.tigger
else
self.turn = PIECETYPE.sheep
end
--print("It's turn to "..self.turn)
end
function Game:eatsheepinnode(node)
idx = node.pieces:pop_back()
self.pieces:getpiece(idx).dead = true
end
function Game:moveto(r, c)
if self.curpick < 1 or self.curpick > 26 or r < 1 or r > 5
or c< 1 or c > 5 then
print("curpick or r, c error")
return false
end
local curPiece = self.pieces:getpiece(self.curpick)
local curNode = self.board.nodes[curPiece.r][curPiece.c]
local tarNode = self.board.nodes[r][c]
local lidx = curNode:getline(tarNode)
local midNode
--not same line
if not lidx then
print("Can't get line")
return false
end
local curidx = curNode:getidxofline(lidx)
local taridx = tarNode:getidxofline(lidx)
print("Line: "..lidx.." Move from: "..curidx.." To: "..taridx)
if curidx == taridx or not curidx or not taridx then
return false
end
local step = math.abs(curidx - taridx)
if step == 1 then
--Move one step, move if target node can hold--
if curPiece.type == PIECETYPE.tigger then
if tarNode:empty() then
print("Tigger move one step")
self:movepieceto(r, c, self.curpick)
else
print("Target node is not empty")
end
else
if tarNode:canaddpiece() and
(not tarNode:firstpiece() or self.pieces:getpiece(tarNode:firstpiece()).type == curPiece.type) then
print("Sheep move one step")
self:movepieceto(r, c, self.curpick)
else
print("Can't move to target")
end
end
elseif step == 2 and curPiece.type == PIECETYPE.tigger and tarNode:empty() then
mididx = (curidx + taridx)/2
midNode = self.board.nodes[indexToRow(self.board.lines[lidx].nodes[mididx])][indexToCol(self.board.lines[lidx].nodes[mididx])]
if midNode:firstpiece() and self.pieces:getpiece(midNode:firstpiece()).type == PIECETYPE.sheep then
print("Trigger move and eat sheep in node "..mididx)
self:movepieceto(r, c, self.curpick)
self:eatsheepinnode(midNode)
else
print("Trigger can't jump");
end
end
return false
end
function Game:getpiecesonnode(r, c)
local res = {}
--print(r.." "..c.." ")
--print(self.board.nodes[r][c])
for i=1, self.board.nodes[r][c].pieces:count() do
res[#res+1] = self.board.nodes[r][c].pieces:getAt(i)
end
return res
end
function Game:whowin()
if self.turn == PIECETYPE.tigger then
if self:istiggerunmoveable(1) and self:istiggerunmoveable(2) then
return PIECETYPE.sheep
end
else
local bres = true
for i=1,24 do
if not self.pieces.sheeps[i].dead then
bres = false
break
end
end
if bres then
return PIECETYPE.tigger
end
end
return nil
end
--no sheeps or tigger can't move
function Game:isover()
type = self:whowin()
if type then
return true
else
return false
end
end
game.lua
#!
dofile("board.lua")
function getnodestr(game, node)
if node.pieces:count() > 0 then
--print(game.pieces:getpiece(node.pieces:getAt(1)).name);
if game.pieces:getpiece(node.pieces:getAt(1)).type == PIECETYPE.sheep then
return node.pieces:count().."S"
else
return node.pieces:count().."T"
end
end
return "0 "
end
function drawnodeonline(i, game, board)
local str = ""
for j=1,4 do
str = str ..getnodestr(game, board.nodes[i][j]).." ----\t"
end
str = str .. getnodestr(game, board.nodes[i][5])
print(str)
end
function drawchessboard(game, board)
drawnodeonline(1, game, board)
print("| \\ | / | \\ | / |")
print("| \\ | / | \\ | / |")
drawnodeonline(2, game, board)
print("| / | \\ | / | \\ |")
print("| / | \\ | / | \\ |")
drawnodeonline(3, game, board)
print("| \\ | / | \\ | / |")
print("| \\ | / | \\ | / |")
drawnodeonline(4, game, board)
print("| / | \\ | / | \\ |")
print("| / | \\ | / | \\ |")
drawnodeonline(5, game, board)
end
function printturn(g)
if g.turn == 1 then
print("It's turn to Tigger")
else
print("It's turn to Sheep")
end
end
game = Game:new{}
game:init()
drawchessboard(game,game.board)
printturn(game)
winner = nil
while not winner do
row = io.read("*number")
col = io.read("*number")
pics = game:getpiecesonnode(row, col)
local str = " "
if #pics > 1 then
print("Select piece: ")
for i=1, #pics do
str = str..pics[i].." "
end
print(str)
sel = io.read("*number")
bok = false
for i=1,#pics do
if sel == pics[i] then
bok = true;
break
end
end
if bok and game:pickpiece(sel) then
print("Input move target")
row = io.read("*number")
col = io.read("*number")
game:moveto(row, col)
else
print("Wrong")
end
elseif #pics == 1 then
if game:pickpiece(pics[1]) then
print("Select piece "..pics[1])
print("Input move target")
row = io.read("*number")
col = io.read("*number")
game:moveto(row, col)
else
print("Wrong piece")
end
else
print("No piece available")
end
drawchessboard(game,game.board)
printturn(game)
winner = game:whowin()
end
if winner == PIECETYPE.tigger then
print("Tigger win")
else
print("Sheep win")
end