Kryziuku nuliuku pavyzdys
Jump to navigation
Jump to search
Kryžiukų-nuliukų žaidimo pavyzdys Angies platformoje. Žaisti Kryžiukus nuliukus
Kompiuterio ėjimams paskaičiuoti naudojamas rekursiškas Minimax algoritmas.
Žaidimo sudėtingumui sumažinti reikia pakeisti paieškos gylį objektui MinimaxAlgoritmas.
Kad programa veiktų, reikia failų tictactoe.jpg
, o.png
ir x.png
tavo paskyroje.
reikalinga angis
reikalingas žaidimas
"""
sutartinės reikšmės (konstantos).
Ir modelyje, ir algoritmuose laikome, kad žmogaus ėjimai žymimi -1, o kompiuterio +1
"""
ŽMOGUS = -1
KOMPIUTERIS = +1
class Modelis:
"""
Kryžiukų-nuliukų žaidimo modelis. Žino apie galimus ėjimus, moka žymėti žaidėjo ėjimą, ir nustatyti laimėtoją.
"""
VISI_LANGELIAI = [[0,0], [1,0], [2,0], [0,1], [1,1], [2,1], [0,2], [1,2], [2,2]]
komanda __init__(mano):
mano.išNaujo()
komanda išNaujo(mano):
mano.langeliai = [ [0, 0, 0],
[0, 0, 0],
[0, 0, 0] ]
komanda sukurkKloną(mano):
"""
grąžina šios lentos kloną
"""
klonas = Modelis()
klonas.langeliai = []
kiekvienam eil iš mano.langeliai:
klonas.langeliai.append(eil[:])
grąžink klonas
komanda duokTuščiusLangelius(mano):
"""
išrenka tuščius langelius iš lentos (t.y. galimus ėjimus).
"""
ats = []
kiekvienam eil iš intervalo(3):
kiekvienam st iš intervalo(3):
jei mano.langeliai[eil][st] == 0:
ats.append([eil, st])
grąžink ats
komanda duokLaiminčiusLangelius(mano, žaidėjas):
"""
grąžina laiminčių langelių sąrašą jei žaidimą laimėjo nurodytas žaidėjas
arba None, jei niekas nelaimėjo
"""
kiekvienam eil iš intervalo(0, 3):
jei mano.langeliai[eil][0] == mano.langeliai[eil][1] == mano.langeliai[eil][2] == žaidėjas:
grąžink [ [eil, 0], [eil, 1], [eil, 2] ]
kiekvienam st iš intervalo(0, 3):
jei mano.langeliai[0][st] == mano.langeliai[1][st] == mano.langeliai[2][st] == žaidėjas:
grąžink [ [0, st], [1, st], [2, st] ]
jei mano.langeliai[0][0] == mano.langeliai[1][1] == mano.langeliai[2][2] == žaidėjas:
grąžink [ [0,0], [1,1], [2,2] ]
jei mano.langeliai[0][2] == mano.langeliai[1][1] == mano.langeliai[2][0] == žaidėjas:
grąžink [ [0,2], [1,1], [2,0] ]
grąžink None
komanda yraLangelisTuščias(mano, eilutė, stulpelis):
"""
pasako, ar nurodytas langelis tuščias
"""
grąžink mano.langeliai[eilutė][stulpelis] == 0
komanda žymėkĖjimą(mano, eilutė, stulpelis, žaidėjas):
"""
pažymi nurodytą langelį žaidėjui
"""
mano.langeliai[eilutė][stulpelis] = žaidėjas
komanda yraŽaidimasBaigtas(mano):
"""
grąžina True, jei laimėjo kuris nors žaidėjas arba baigėsi langeliai
"""
langeliai = mano.duokLaiminčiusLangelius(1)
jei langeliai != None:
grąžink True
langeliai = mano.duokLaiminčiusLangelius(-1)
jei langeliai != None:
grąžink True
jei len(mano.duokTuščiusLangelius()) == 0 :
grąžink True
grąžink False
class Interfeisas:
"""
Moka vizualiai nupiešti 3x3 langelius, žymėti žaidėjų ėjimus, ir laiminčią simbolių liniją.
Taip pat moka konvertuoti tarp ekrano koordinačių X,Y ir modelio koordinačių EILUTĖ,STULPELIS
"""
komanda __init__(mano):
angis.naudosiuFailus(['pav/efektai/sprogimas.json',
'tictactoe.jpg', 'o.png', 'x.png'])
žaidimas.duokSceną().fonas('tictactoe.jpg')
mano.figūros = []
komanda išNaujo(mano):
kiekvienam f iš mano.figūros:
f.išnyk()
mano.figūros = []
komanda paskaičiuokEilStulp(mano, x, y):
eilutė = -1
stulpelis = -1
jei x > 10 ir x <= 267:
stulpelis = 0
ojei x > 267 ir x <= 524:
stulpelis = 1
ojei x > 524 ir x <=699:
stulpelis = 2
jei y > 10 ir y <= 200:
eilutė = 0
ojei y > 200 ir y <= 400:
eilutė = 1
ojei y > 400 ir y <=600:
eilutė = 2
grąžink eilutė, stulpelis
komanda paskaičiuokXY(mano, eilutė, stulpelis):
grąžink stulpelis * 240 + 80, eilutė * 200 + 40
komanda pieškFigūrą(mano, eilutė, stulpelis, žaidėjas):
x, y = mano.paskaičiuokXY(eilutė, stulpelis)
failovardas = "o.png" jei žaidėjas == KOMPIUTERIS kituatveju "x.png"
figūra = žaidimas.Daiktas(failovardas, x, y)
mano.figūros.append(figūra)
komanda sprogdink(mano, langeliai):
kiekvienam eil, stulp iš langeliai:
mano.rodykSprogimą(eil, stulp)
komanda rodykSprogimą (mano, eilutė, stulpelis):
x, y = mano.paskaičiuokXY(eilutė, stulpelis)
sprogimas = žaidimas.Animacija(failoVardas = "pav/efektai/sprogimas.json", pavadinimas="sprogimas", greitis=0.5)
sprogimas.atsirask(x, y)
sprogimas.grokFone()
class Švieslentė:
"""
Moka vizualiai ekrane parodyti žaidėjų surinktus taškus
"""
komanda __init__(mano):
mano.žmogausTaškai = 0
mano.kompiuterioTaškai = 0
mano.tekstas = žaidimas.Tekstas("kryžiukai 0 : nuliukai 0")
mano.tekstas.atsirask (10, 10)
mano.tekstas.spalva("#AAAAAA")
mano.tekstas.dydis(15)
komanda žymėkLaimėjimą(mano, laimėtojas):
jei laimėtojas == ŽMOGUS:
mano.žmogausTaškai = mano.žmogausTaškai + 1
ojei laimėtojas == KOMPIUTERIS:
mano.kompiuterioTaškai = mano.kompiuterioTaškai + 1
mano.perpiešk()
komanda perpiešk(mano):
mano.tekstas.užrašas("kryžiukai "
+ str(mano.žmogausTaškai)
+ " : nuliukai "
+ str(mano.kompiuterioTaškai) )
class MinimaxAlgoritmas:
"""
Moka rasti geriausią žaidėjo ėjimą pagal Minimax algoritmą.
"""
komanda __init__(mano, modelis, paieškosGylis):
mano.modelis = modelis
mano.gylis = paieškosGylis
komanda raskĖjimą(mano, žaidėjas):
grąžink mano.__raskĖjimąRekursiškai(mano.modelis, žaidėjas, mano.gylis)
komanda __raskĖjimąRekursiškai(mano, modelis, žaidėjas, gylis):
jei modelis.yraLangelisTuščias(1, 1):
grąžink [1, 1, žaidėjas] # centrinis langelis yra strategiškai svarbus
tuštiLangeliai = modelis.duokTuščiusLangelius()
jei len(tuštiLangeliai) == 0:
grąžink [-1, -1, 0] # taip neturi būti
jei len(tuštiLangeliai) == 8:
grąžink [0, 0, žaidėjas] # jei užimtas tik vienas langelis, ir jis centre, tai užsiimam kampą.
ats = None
kiekvienam eil, st iš tuštiLangeliai:
jei ats == None:
ats = [eil, st, -žaidėjas]
# bandom modeliuoti žaidėjo ėjimą į eil, st
modelioKopija = modelis.sukurkKloną()
modelioKopija.žymėkĖjimą(eil, st, žaidėjas)
jei modelioKopija.duokLaiminčiusLangelius(žaidėjas) != None:
grąžink [eil, st, žaidėjas] # garantuotas laimėjimas
jei gylis <= 0:
ats = [eil, st, 0] # garantuotos lygiosios, įsiminkim dėl viso pikto
tęsk
# rekursiškai modeliuojam tolimesnius žingsnius, pradedant nuo priešininko
e, s, rezultatas = mano.__raskĖjimąRekursiškai(modelioKopija, -žaidėjas, gylis-1)
jei rezultatas == žaidėjas:
grąžink [eil, st, rezultatas] # galimas laimėjimas!
jei rezultatas == 0:
ats = [eil, st, 0] # galimos lygiosios, įsiminkim dėl viso pikto
grąžink ats
class Taisyklės:
"""
Užtikrina žaidimo taisykles: ėjimų eiliškumą, komponentų tarpusavio sąveiką
"""
komanda __init__(mano, modelis, interfeisas, švieslentė, algoritmas):
mano.modelis = modelis
mano.interfeisas = interfeisas
mano.švieslentė = švieslentė
mano.algoritmas = algoritmas
mano.žmogausĖjimas = True
komanda išNaujo(mano):
mano.modelis.išNaujo()
mano.interfeisas.išNaujo()
mano.žmogausĖjimas = True
komanda žymėkŽmogausĖjimą(mano, eilutė, stulpelis):
jei mano.žmogausĖjimas == False:
grįžk
jei mano.modelis.yraLangelisTuščias(eilutė, stulpelis) == False:
grįžk
mano.žmogausĖjimas = False
mano.modelis.žymėkĖjimą(eilutė, stulpelis, ŽMOGUS)
mano.interfeisas.pieškFigūrą(eilutė, stulpelis, ŽMOGUS)
jei modelis.yraŽaidimasBaigtas():
mano.__užbaikŽaidimą()
grįžk
eil, st, rezultatas = mano.algoritmas.raskĖjimą(KOMPIUTERIS)
mano.modelis.žymėkĖjimą(eil, st, KOMPIUTERIS)
mano.interfeisas.pieškFigūrą(eil, st, KOMPIUTERIS)
jei mano.modelis.yraŽaidimasBaigtas():
mano.__užbaikŽaidimą()
grįžk
mano.žmogausĖjimas = True
komanda __užbaikŽaidimą(mano):
laimintysLangeliai, laimėtojas = mano.__duokLaimėtoją()
mano.švieslentė.žymėkLaimėjimą(laimėtojas)
mano.interfeisas.sprogdink(laimintysLangeliai)
mano.išNaujo()
komanda __duokLaimėtoją(mano):
ats = mano.modelis.duokLaiminčiusLangelius(ŽMOGUS)
jei ats != None:
grąžink ats, ŽMOGUS
ats = mano.modelis.duokLaiminčiusLangelius(KOMPIUTERIS)
jei ats != None:
grąžink ats, KOMPIUTERIS
grąžink mano.modelis.VISI_LANGELIAI, 0
modelis = Modelis()
interfeisas = Interfeisas()
švieslentė = Švieslentė()
algoritmas = MinimaxAlgoritmas(modelis, paieškosGylis = 3)
taisyklės = Taisyklės(modelis, interfeisas, švieslentė, algoritmas)
komanda pelėsPaspaudimas(pelėsX, pelėsY):
eilutė, stulpelis = interfeisas.paskaičiuokEilStulp(pelėsX, pelėsY)
jei eilutė >= 0 ir stulpelis >= 0:
taisyklės.žymėkŽmogausĖjimą(eilutė, stulpelis)
žaidimas.pelęPaspaudus(pelėsPaspaudimas)