Advertisement
wwwRong

ox_game3

Dec 9th, 2019
481
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2.   แปลงมาจาก OX.py ในหนังสือ Artificial Intelligence
  3.   with Machine Learning ของ รศ.ดร.ปริญญา สงวนสัตย์
  4. ]]
  5. --version 3 ใช้ penlight module ช่วยจัดการเรื่อง list และ list comprehension
  6. --ทำให้เขียนโค้ดสั้นลงใกล้เคียง python ต้้นฉบับมากขึ้น แต่ประสิทธิภาพยังไม่ได้ตรวจ
  7. -- #1.1 แก้ไขเปลี่ยนส่วนของ ai() และการตรวจสอบตอนผู้เล่นพิมพ์ตำแหน่ง
  8. local comp = require("pl.comprehension").new()
  9. local ls = require("pl.List")
  10. local O, X = ls{}, ls{}
  11. local win = {{1,2,3},
  12.             {4,5,6},
  13.             {7,8,9},
  14.             {1,4,7},
  15.             {2,5,8},
  16.             {3,6,9},
  17.             {1,5,9},
  18.             {3,5,7}}
  19. local rnd = math.random
  20. local max = math.max
  21. local floor = math.floor
  22. local concat = table.concat
  23. local unpack = table.unpack
  24.  
  25. --function all(t1, t2)
  26.   --local t = true
  27.     --for _, v in pairs(t2) do
  28.       --t = t and t1:contains(v)
  29.     --end
  30.   --return t
  31. --end
  32.  
  33. --function any(t1, t2)
  34.   --local t = 0
  35.   --for _, v in pairs(t2) do
  36.     --if t1:contains(v) then
  37.       --t = t + 1
  38.     --end
  39.   --end
  40.   --return t
  41. --end
  42.  
  43. function randomChoice(args)
  44.   return args[rnd(#args)]
  45. end
  46.  
  47. function checkWin(P)
  48.   for _, w in pairs(win) do
  49.     --if all(P, w) then
  50.       --return true
  51.     --end
  52.     local all = ls(comp "(_1):contains(v) for _,v in pairs(_2)" (P,w)):reduce(function(x,y) return x and y end)
  53.     if all then
  54.       return true
  55.     end
  56.   end
  57.   return false
  58. end
  59.  
  60. function displayOX()
  61.   local newMap = {}
  62.   for i = 1, 9, 3 do
  63.     newMap[i] = O:contains(i) and "[O]" or (X:contains(i) and "[X]" or "[_]")
  64.     newMap[i+1] = O:contains(i+1) and "[O]" or (X:contains(i+1) and "[X]" or "[_]")
  65.     newMap[i+2] = O:contains(i+2) and "[O]" or (X:contains(i+2) and "[X]" or "[_]")
  66.     print(newMap[i]..newMap[i+1]..newMap[i+2])
  67.   end
  68. end
  69.  
  70. function ai()
  71.   local validMove = ls.range(1,9)
  72.   local moved = O:clone():extend(X)
  73.   for _, v in pairs(moved) do
  74.     validMove:remove_value(v)
  75.   end
  76.   -- #1.1 แก้ไขตรวจหาแถวที่มี X สองตำแหน่งและไม่มี O ให้เลือกตำแหน่งที่ว่างในแถวนั้น
  77.   for _, w in pairs(win) do
  78.     local xl = ls(comp "(_1):contains(v) for _,v in pairs(_2)" (X,w))
  79.     local vl = ls(comp "(_1):contains(v) for _,v in pairs(_2)" (validMove,w))
  80.     if xl:count(true)==2 and vl:reduce(function(x,y) return x or y end) then
  81.       return comp "v for _,v in pairs(_1) if (_2):contains(v)"(w,validMove)[1]
  82.     end
  83.   end
  84.   --##########
  85.   local V = {-100,-100,-100,-100,-100,-100,-100,-100,-100}
  86.   for _, v in pairs(validMove) do
  87.     local tempX, criticalMove = X:clone(), {}
  88.     tempX:append(v)
  89.     V[v], criticalMove = evalOX(O,tempX)
  90.     if #criticalMove > 0 then
  91.       -- #1.1 เอาออก
  92.       --if checkWin(tempX) then
  93.         --return v
  94.       --end
  95.       --##########
  96.       -- #1.1 เปลี่ยนจากใช้ลูปเป็น list comprehention แทนและ return ค่าเดียวไม่ต้องใส่ table แล้วสุ่มเลือก
  97.       --local move = ls{}
  98.       --for _, i in pairs(criticalMove) do
  99.         --if validMove:contains(i) then
  100.           --move:append(i)
  101.         --end
  102.       --end
  103.       --return randomChoice(move)
  104.       --##########
  105.       return comp "v for _,v in pairs(_1) if (_2):contains(v)" (criticalMove,validMove)[1]
  106.     end
  107.   end
  108.   local maxV = max(unpack(V))
  109.   --local imaxV = ls{}
  110.   --for i, v in pairs(V) do
  111.     --if v == maxV then
  112.       --imaxV:append(i)
  113.     --end
  114.   --end
  115.   local imaxV = comp "i for i,v in pairs(_1) if v == (_2)" (V,maxV)
  116.   return randomChoice(imaxV)
  117. end
  118.  
  119. function evalOX(o,x)
  120.   local SO, SX, criticalMove = calSOX(o,x)
  121.   return (1 + SX - SO), criticalMove
  122. end
  123.  
  124. function calSOX(o,x)
  125.   local SO, SX = 0, 0
  126.   local criticalMove = {}
  127.   for _, w in pairs(win) do
  128.     --local cO = any(o,w)
  129.     --local cX = any(x,w)
  130.     local cO = ls(comp "(_1):contains(v) for _,v in pairs(_2)" (o,w))
  131.     local cX = ls(comp "(_1):contains(v) for _,v in pairs(_2)" (x,w))
  132.     if not cX:reduce(function(x,y) return x or y end) then
  133.       local nO = cO:count(true)
  134.       SO = SO + nO
  135.       if nO == 2 then
  136.         print("critical", "{".. concat(w,",").."}")
  137.         criticalMove = w
  138.       end
  139.     end
  140.     if not cO:reduce(function(x,y) return x or y end) then
  141.       SX = SX + cX:count(true)
  142.     end
  143.   end
  144.   return SO, SX, criticalMove
  145. end
  146.  
  147. while true do
  148.   io.write("Choose position [1-9]: ")
  149.   local move = tonumber(io.read())
  150.   print("")
  151.   goto checkMove
  152.   ::chooseAgain::
  153.   io.write("Bad move: choose position [1-9]: ")
  154.   move = tonumber(io.read())
  155.   print("")
  156.   ::checkMove::
  157.   if not move then
  158.     goto chooseAgain
  159.   -- #1.1 เอาออก
  160.   --elseif move > 9 or move < 1 then
  161.     --goto chooseAgain
  162.   --##########
  163.   else
  164.     move = floor(move)
  165.     -- #1.1 ย้ายมาตรวจหลังจากปัดเศษแล้ว
  166.     if move > 9 or move < 1 then
  167.       goto chooseAgain
  168.     end
  169.     --##########
  170.   end
  171.   if O:contains(move) or X:contains(move) then
  172.     goto chooseAgain
  173.   end
  174.   O:append(move)
  175.   displayOX()
  176.   if checkWin(O) then
  177.     print("O win")
  178.     break
  179.   end
  180.   if #O + #X == 9 then
  181.     print("Draw")
  182.     break
  183.   end
  184.   X:append(ai())
  185.   displayOX()
  186.   if checkWin(X) then
  187.     print("X win")
  188.     break
  189.   end
  190. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement