Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- แปลงมาจาก OX.py ในหนังสือ Artificial Intelligence
- with Machine Learning ของ รศ.ดร.ปริญญา สงวนสัตย์
- ]]
- --version 3 ใช้ penlight module ช่วยจัดการเรื่อง list และ list comprehension
- --ทำให้เขียนโค้ดสั้นลงใกล้เคียง python ต้้นฉบับมากขึ้น แต่ประสิทธิภาพยังไม่ได้ตรวจ
- -- #1.1 แก้ไขเปลี่ยนส่วนของ ai() และการตรวจสอบตอนผู้เล่นพิมพ์ตำแหน่ง
- local comp = require("pl.comprehension").new()
- local ls = require("pl.List")
- local O, X = ls{}, ls{}
- local win = {{1,2,3},
- {4,5,6},
- {7,8,9},
- {1,4,7},
- {2,5,8},
- {3,6,9},
- {1,5,9},
- {3,5,7}}
- local rnd = math.random
- local max = math.max
- local floor = math.floor
- local concat = table.concat
- local unpack = table.unpack
- --function all(t1, t2)
- --local t = true
- --for _, v in pairs(t2) do
- --t = t and t1:contains(v)
- --end
- --return t
- --end
- --function any(t1, t2)
- --local t = 0
- --for _, v in pairs(t2) do
- --if t1:contains(v) then
- --t = t + 1
- --end
- --end
- --return t
- --end
- function randomChoice(args)
- return args[rnd(#args)]
- end
- function checkWin(P)
- for _, w in pairs(win) do
- --if all(P, w) then
- --return true
- --end
- local all = ls(comp "(_1):contains(v) for _,v in pairs(_2)" (P,w)):reduce(function(x,y) return x and y end)
- if all then
- return true
- end
- end
- return false
- end
- function displayOX()
- local newMap = {}
- for i = 1, 9, 3 do
- newMap[i] = O:contains(i) and "[O]" or (X:contains(i) and "[X]" or "[_]")
- newMap[i+1] = O:contains(i+1) and "[O]" or (X:contains(i+1) and "[X]" or "[_]")
- newMap[i+2] = O:contains(i+2) and "[O]" or (X:contains(i+2) and "[X]" or "[_]")
- print(newMap[i]..newMap[i+1]..newMap[i+2])
- end
- end
- function ai()
- local validMove = ls.range(1,9)
- local moved = O:clone():extend(X)
- for _, v in pairs(moved) do
- validMove:remove_value(v)
- end
- -- #1.1 แก้ไขตรวจหาแถวที่มี X สองตำแหน่งและไม่มี O ให้เลือกตำแหน่งที่ว่างในแถวนั้น
- for _, w in pairs(win) do
- local xl = ls(comp "(_1):contains(v) for _,v in pairs(_2)" (X,w))
- local vl = ls(comp "(_1):contains(v) for _,v in pairs(_2)" (validMove,w))
- if xl:count(true)==2 and vl:reduce(function(x,y) return x or y end) then
- return comp "v for _,v in pairs(_1) if (_2):contains(v)"(w,validMove)[1]
- end
- end
- --##########
- local V = {-100,-100,-100,-100,-100,-100,-100,-100,-100}
- for _, v in pairs(validMove) do
- local tempX, criticalMove = X:clone(), {}
- tempX:append(v)
- V[v], criticalMove = evalOX(O,tempX)
- if #criticalMove > 0 then
- -- #1.1 เอาออก
- --if checkWin(tempX) then
- --return v
- --end
- --##########
- -- #1.1 เปลี่ยนจากใช้ลูปเป็น list comprehention แทนและ return ค่าเดียวไม่ต้องใส่ table แล้วสุ่มเลือก
- --local move = ls{}
- --for _, i in pairs(criticalMove) do
- --if validMove:contains(i) then
- --move:append(i)
- --end
- --end
- --return randomChoice(move)
- --##########
- return comp "v for _,v in pairs(_1) if (_2):contains(v)" (criticalMove,validMove)[1]
- end
- end
- local maxV = max(unpack(V))
- --local imaxV = ls{}
- --for i, v in pairs(V) do
- --if v == maxV then
- --imaxV:append(i)
- --end
- --end
- local imaxV = comp "i for i,v in pairs(_1) if v == (_2)" (V,maxV)
- return randomChoice(imaxV)
- end
- function evalOX(o,x)
- local SO, SX, criticalMove = calSOX(o,x)
- return (1 + SX - SO), criticalMove
- end
- function calSOX(o,x)
- local SO, SX = 0, 0
- local criticalMove = {}
- for _, w in pairs(win) do
- --local cO = any(o,w)
- --local cX = any(x,w)
- local cO = ls(comp "(_1):contains(v) for _,v in pairs(_2)" (o,w))
- local cX = ls(comp "(_1):contains(v) for _,v in pairs(_2)" (x,w))
- if not cX:reduce(function(x,y) return x or y end) then
- local nO = cO:count(true)
- SO = SO + nO
- if nO == 2 then
- print("critical", "{".. concat(w,",").."}")
- criticalMove = w
- end
- end
- if not cO:reduce(function(x,y) return x or y end) then
- SX = SX + cX:count(true)
- end
- end
- return SO, SX, criticalMove
- end
- while true do
- io.write("Choose position [1-9]: ")
- local move = tonumber(io.read())
- print("")
- goto checkMove
- ::chooseAgain::
- io.write("Bad move: choose position [1-9]: ")
- move = tonumber(io.read())
- print("")
- ::checkMove::
- if not move then
- goto chooseAgain
- -- #1.1 เอาออก
- --elseif move > 9 or move < 1 then
- --goto chooseAgain
- --##########
- else
- move = floor(move)
- -- #1.1 ย้ายมาตรวจหลังจากปัดเศษแล้ว
- if move > 9 or move < 1 then
- goto chooseAgain
- end
- --##########
- end
- if O:contains(move) or X:contains(move) then
- goto chooseAgain
- end
- O:append(move)
- displayOX()
- if checkWin(O) then
- print("O win")
- break
- end
- if #O + #X == 9 then
- print("Draw")
- break
- end
- X:append(ai())
- displayOX()
- if checkWin(X) then
- print("X win")
- break
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement