Пуснато на: Thu Aug 21, 2008 3:12 pm Заглавие: Tic Tac Toe
Беше им скучно и за това си начатках една дървена версия на морски шах. Кодът е 79 реда с коментарите и празните редове и има някой много красиви и някой много грозни части в него. това е още версия 1, така че не се смейте на грозните части, а на коментарите им Коментирал съм кода, така че трябва да разберете лесно как бачка, ако имате въпроси питайте.
Код:
from itertools import cycle
#matricata v koqto shte se vodi igrata, spisuk s 3 spisuka, s po 3 elementa
matrix=[[[], [], []], [[], [], []], [[], [], []]]
#vseki red e suotveten element ot matrix
row1=matrix[0]
row2=matrix[1]
row3=matrix[2]
#vsqka kolona e spisuk sus suotvetnite elementi ot suotvetnite redove
col1=[x[0] for x in matrix]
col2=[x[1] for x in matrix]
col3=[x[2] for x in matrix]
#diagonalite sa suotvetno purvia, vtoria i tretia elementi
#ot purvia, vtoria i tretia red i obratno za vtoria diagonal
diag1=[matrix[0][0],matrix[1][1],matrix[2][2]]
diag2=[matrix[2][0],matrix[1][1],matrix[0][2]]
#spisuk s vsichki vuzmozhni pechelivshi troiki, rcd=redici,colono,diagonali
rcd=(row1,row2,row3,col1,col2,col3,diag1,diag2)
#syzdavame dva iteratora, koito shte vurtqt stoinostite suoyvetno
#na player-ite i symbolite im, za tova importnahme cycle()
playerr=cycle(('player 1','player 2'))
symbb = cycle(('X','O'))
counter=0
#proverqva dali elementite sa pechelivshi
def good(x):
if x[0]==x[1]==x[2]:
return True
else:
return False
#proverqva dali v spisukut ima pechelivshi elementi
def win(x):
for i in x:
if good(i):
return True
else:
return False
#priema za vhod coordinati i vkarva v matricata suotvetnia symbol X ili O
def turn(player,symb):
#Sledvashtia red cod trqbva da napravi spisuk sus coordinatite
#No vhodut e string, za tova purvo se razdelq i se premahva ','
#posle seprevrushtat s int i tova e tsqloto list comprehention za da stane spisuk
#s map() nqmashe da e mnogo po krasivo
#Fucking Ugly VVVV
vhod=[int(x) for x in tuple(raw_input("%s coordinati? " % player).split(','))]
if matrix[vhod[0]][vhod[1]] == []:
matrix[vhod[0]][vhod[1]]=symb
else:
print"error"
inp(symb)
#printira matritsata v user friendly format :D
def printmatrix(matrix):
for x in matrix:
print x
#main-a
def mainloop(playerr,symbb,counter):
while counter < 9:
#player i symb se smenqt s vseki tsikul, zashtoto playerr i symbb sa iteratori
#i se reduvat stoinostite im s vseki .next() metod
player=playerr.next()
symb = symbb.next()
turn(player,symb)
printmatrix(matrix)
if win(rcd) == True:
print '%s wins' % player
break
counter+=1
if __name__=='__main__':
mainloop(playerr,symbb,counter)
играта се играе със следните координати за полетата:
Хаха, моя е по-къс (кода, де). Всъщност самия той е по-дълъг (кода, бе), все пак е писан на C++, без помощни библиотеки (освен iostream). Естествено без коментари, без проверка за координати, така че бъдете възпитани, моля.
Доколкото ти разбирам кода, използвам същия алгоритъм.
Имаше един руби код за морски шах. Можеше да играеш с-у машината, на няколко трудности. Ще се опитам да го потърся, за да го ползвате, ако искате да си добавите "изкуствен интелект".
При морския шах самата реализация не е нищо особено. По-интересно за мен е да си направиш генетичен алгоритъм, който се учи сам и колкото повече играе, толкова по-добър става...
При морския шах самата реализация не е нищо особено. По-интересно за мен е да си направиш генетичен алгоритъм, който се учи сам и колкото повече играе, толкова по-добър става...
Генетичен алгоритъм за морски шах не ти трябва. То има само 3^9 ситуации. Да ги сметнеш и да напишеш непобедим алгоритъм не е особено трудно.
Генетичен алгоритъм за морски шах не ти трябва. То има само 3^9 ситуации. Да ги сметнеш и да напишеш непобедим алгоритъм не е особено трудно.
То тва е ясно... Ама с генетичен алгоритъм е по-интересно Пък и все от някъде тряа се почне, ако почнеш с шахмат, сигурно направо ще ти идва да си теглиш ножа...
В горния код има един много сериозен бъг. Основната идея в него е да се създаде един глобален обект matrix(в случая е списък, но имах същия успех и със хеш таблица), чието състояние да се променя, и при всяка промяна, да се проверява, дали състоянието отговаря на определени изисквания, за да се прекрати играта(печеливш или равен). На идея това е супер, дори си мислех че работи. Горния код НЕ работи, проблемът се крие в списакът с елементите(редове, колони, диагонали). Проблемът е че редовете(row1,row2,row3) са просто указатели към списъци, докато другите(col1,col2,col3,diag1,diag2) са копия на обектите в тези списъци, т.е. те представляват нещо като снимки на състоянието на матрицата от определен момент(момента на създаването им) от там на татък не се променят, а матрицата се променя, а точно промените ни интересуват. Като резултат, програмата работи привидно, но може да победите само със 3-ка по хоризонталните редове. Ето версия 2, със един доста грозен хак, който решава проблема, просто при всяка промяна на матрицата, ще се правят копия на елементите, за да имаме моментна снимка на състоянието. Все още мисля върху алтернативи. Написал съм къде има промени. Ето кода:
Код:
from itertools import cycle
matrix=[[[], [], []], [[], [], []], [[], [], []]]
def printmatrix(matrix):
for x in matrix:
print x
#hack, vremenno reshenie
def refresh():
row1=matrix[0]
row2=matrix[1]
row3=matrix[2]
col1=[x[0] for x in matrix]
col2=[x[1] for x in matrix]
col3=[x[2] for x in matrix]
diag1=[matrix[i][i] for i in xrange(3)]
diag2=[matrix[i][m] for (i,m) in zip((2,1,0),xrange(3))]
#nai groznata chast:
global rcd
rcd=(col1,col2,col3,row1,row2,row3,diag1,diag2)
#preimenuvano ot good na same
def same(lst):
if lst[0]==lst[1]==lst[2]:
return True
else:
return False
def win(x):
for i in x:
if same(i):
#maluk hack, koito propusnah predi, []=[]=[],
#sledovatelno pecheliat, no ne biva da stava taka
if [] not in i:
return True
return False
Дълго мислих как да пренапиша играта, така че да е малко по функционална, след като я преправих във стила на функционалното програмиране определено я опростих до някъде, спестих 10-тина реда, и мисля че се получи сравнително добре. Използвах няколко прости трика, за да опростя кода на места, например използвах речник вместо списък, за да не ми се налага да използвам после и друг речник за помощ при интерфейса, което определено опрости кода, тази функция good(), която преименувах на same(), сега изчезна, задачанта и се поема от win(), mainloop(), е пренаписана в рекурсивен вариант, защото исках да премахна нуждата от глобални променливи, които да не са функции, за целта и rcd, от списък е направен на функция която връща редица(това премахва нуждата от функцията refresh(), също така премахнах нуждата от импортирането на cycle() функцията, с която да сменям стойностите на player и symb, вместо това използвам проста редица, и в зависимост дали counter%2 връща 0 или 1, имамесъответно player1,X и player2,O. това също опростява нещата малко. Лично съм доста горд от това, от грозна процедурна програма, с императивни примеси, стана красива функционална програма. Без коментарите е само 45 реда, докато преди беше около 60(първата е 58, втората версия е 61 мисля). Можех да спестя и още редове, но за четимост съм ги разделил на няколко реда. Рамносметката е 4 прости функции, и една средно сложна. Ето кода:
Код:
#poneje matricata e hash, printiraneto i e malko po osobeno
def printmatrix(matrix):
for x in [['1','2','3'],['4','5','6'],['7','8','9']]:
print matrix[x[0]],matrix[x[1]],matrix[x[2]]
#vrushta redica s redovete, kolonite i diagonalite
def rcd_gen(matrix):
return ((matrix['1'],matrix['2'],matrix['3']),
(matrix['4'],matrix['5'],matrix['6']),
(matrix['7'],matrix['8'],matrix['9']),
(matrix['1'],matrix['4'],matrix['7']),
(matrix['2'],matrix['5'],matrix['8']),
(matrix['3'],matrix['6'],matrix['9']),
(matrix['1'],matrix['5'],matrix['9']),
(matrix['7'],matrix['5'],matrix['3']))
def win(rcd):
for i in rcd:
if i[0]==i[1]==i[2]:
if [] not in i:
return True
return False
#recursvna funkcia, funky nomer
def mainloop(player,symb,matrix,counter):
if counter < 9:
#vika turn() sus suotvetnite stoinosti na player i symb,
#ako counter e 0 ili chetno tova sa suotvetno player1 i X,
#za necetni stoinosti no counter, tova sa player2 i O
turn(player[counter%2],symb[counter%2],matrix)
printmatrix(matrix)
#na win se podava kato argument rcd, generiran ot rcd_gen()
if win(rcd_gen(matrix)) == True:
print '%s wins' % player[counter%2]
else:
#recursivno povicvane, voodoo...
mainloop(player,symb,matrix,counter+1)
else: print 'raven'
if __name__=='__main__':
#vmesto da syzdavame globalni imena za argumentite, napravo gi podavame, FP rules!!!
mainloop(('player1','player2'),
(' X',' O'),
{'1':[],'2':[],'3':[],
'4':[],'5':[],'6':[],
'7':[],'8':[],'9':[]},
0)
Не Можете да пускате нови теми Не Можете да отговаряте на темите Не Можете да променяте съобщенията си Не Можете да изтривате съобщенията си Не Можете да гласувате в анкети You cannot attach files in this forum Може да сваляте файлове от този форум