Ich habe eine Othello-App mit kivy erstellt, einer Open-Source-Bibliothek für die Entwicklung von Multi-Tap-Apps in Python. Schließlich habe ich es mit (xcode) im iOS Simulator erstellt.
python: 3.7.7 kivy: 1.11.1 xcode: 11.7
Vollständiges Formular
Ich werde erklären, während ich der Reihenfolge folge, in der die Othello-App entwickelt wurde, die dieses Mal erstellt wurde.
Erstellen Sie bis zum folgenden Status
class OthelloApp(App):
title = 'Othello'
def build(self):
return OthelloGrid()
OthelloApp().run()
Rückgabe der OthelloGrid-Klasse in der APP-Klasse. Die Verarbeitung dieser Anwendung erfolgt in dieser OthelloGrid-Klasse.
class OthelloGrid(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.num = 8
self.tile = [[' ' for x in range(self.num)] for x in range(self.num)]
self.turn = 'W'
self.grid = GridLayout(cols=self.num, spacing=[3,3], size=(Window.width, Window.height))
for x in range(self.num):
for y in range(self.num):
if x == 3 and y == 3 or x == 4 and y == 4:
self.grid.add_widget(WhiteStone())
self.tile[x][y] = 'W'
elif x == 4 and y == 3 or x == 3 and y == 4:
self.grid.add_widget(BlackStone())
self.tile[x][y] = 'B'
else:
self.grid.add_widget(PutButton(background_color=(0.451,0.3059,0.1882,1), background_normal='', tile_id=[x, y]))
self.add_widget(self.grid)
self.num
ist die Anzahl der vertikalen und horizontalen Quadrate auf dem Othello-Brett.
self.tile
ist eine Liste zum Speichern des Status der Tafel. Wenn Weiß platziert wird'W'
, wenn Schwarz platziert wird
B', wird nichts platziert. Nimmt den Wert von wann '' ''.
self.turnmerkt sich, ob die aktuelle Kurve schwarz oder weiß ist, und beginnt zunächst mit einer weißen Kurve. Die Tafel, die tatsächlich auf dem Bildschirm gezeichnet wird, wird durch "self.grid (GridLayout)" definiert. Für die Quadrate, auf denen bereits Steine platziert sind, die "WhiteStone-Klasse" für weiße Steine und die "BlackStone-Klasse" für schwarze Steine. Wir add_widget
und add_widget PutButton class
zu den Quadraten, auf denen noch keine Steine platziert wurden.
class WhiteStone(Label):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(pos=self.update)
self.bind(size=self.update)
self.update()
def update(self, *args):
self.canvas.clear()
self.canvas.add(Color(0.451,0.3059,0.1882,1))
self.canvas.add(Rectangle(pos=self.pos, size=self.size))
self.canvas.add(Color(1,1,1,1))
self.canvas.add(Ellipse(pos=self.pos, size=self.size))
class BlackStone(Label):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(pos=self.update)
self.bind(size=self.update)
self.update()
def update(self, *args):
self.canvas.clear()
self.canvas.add(Color(0.451,0.3059,0.1882,1))
self.canvas.add(Rectangle(pos=self.pos, size=self.size))
self.canvas.add(Color(0,0,0,1))
self.canvas.add(Ellipse(pos=self.pos, size=self.size))
class PutButton(Button):
def __init__(self, tile_id, **kwargs):
super().__init__(**kwargs)
self.tile_id = tile_id
Die Klassen WhiteStone
und BlackStone
erben von der Label-Klasse und haben einfach eine elliptische Stein-Ellipse (pos = self.pos) über dem Massen-Rechteck (pos = self.pos, size = self.size). , size = self.size)
wird gerade gezeichnet.
Die PutButton-Klasse erbt von der Button-Klasse, und es erfolgt noch keine Verarbeitung, wenn sie gedrückt wird.
Als tile_id
kann sich die Instanz selbst merken, welche Position auf dem Gitter
liegt.
Erstellen Sie bis zum folgenden Status
Erstellen Sie eine "on_press" -Funktion in der "PutButton" -Klasse, wie unten gezeigt, und fügen Sie die Verarbeitung hinzu, wenn auf eine Zelle getippt wird.
PutButton-Klasse
def on_press(self):
put_x = self.tile_id[0]
put_y = self.tile_id[1]
turn = self.parent.parent.turn
self.parent.parent.tile[put_x][put_y] = turn
self.parent.parent.put_stone()
Ersetzen Sie "get_x" und "put_y" durch die abgegriffene Zellennummer und ersetzen Sie "turn" durch die aktuelle Runde.
Rufen Sie die Funktion "put_stone" auf, indem Sie den Wert von "turn" der Position der abgegriffenen Zelle von "tile" in der übergeordneten Klasse ("OthelloGrid") zuweisen.
put_stone
ist eine Funktion, die in OthelloGrid
wie unten gezeigt erstellt wurde und eine Funktion zum Neuerstellen des Boards aus dem Inhalt von tile
.
OthelloGrid-Klasse
def put_stone(self):
self.clear_widgets()
self.grid = GridLayout(cols=self.num, spacing=[3,3], size=(Window.width, Window.height))
next_turn = 'W' if self.turn == 'B' else 'B'
for x in range(self.num):
for y in range(self.num):
if self.tile[x][y] == 'W':
self.grid.add_widget(WhiteStone())
elif self.tile[x][y] == 'B':
self.grid.add_widget(BlackStone())
else:
self.grid.add_widget(PutButton(background_color=(0.451,0.3059,0.1882,1), background_normal='', tile_id=[x, y]))
Erstellen Sie bis zum folgenden Status
Fügen Sie der Klasse "OthelloGrid" die Funktionen "can_reverse_check" und "reverse_list" hinzu, um zu überprüfen, ob Steine vorhanden sind, die von den Koordinaten der Masse und der aktuellen Kurve umgedreht werden können, wie unten gezeigt.
OthelloGrid-Klasse
def can_reverse_check(self, check_x, check_y, turn):
check =[]
#Bestätigung oben links
check += self.reverse_list(check_x, check_y, -1, -1, turn)
#Oben bestätigt
check += self.reverse_list(check_x, check_y, -1, 0, turn)
#Bestätigung oben rechts
check += self.reverse_list(check_x, check_y, -1, 1, turn)
#Richtige Bestätigung
check += self.reverse_list(check_x, check_y, 0, 1, turn)
#Bestätigung unten rechts
check += self.reverse_list(check_x, check_y, 1, 1, turn)
#Überprüfen Sie unten
check += self.reverse_list(check_x, check_y, 1, 0, turn)
#Bestätigung unten links
check += self.reverse_list(check_x, check_y, 1, -1, turn)
#Linke Bestätigung
check += self.reverse_list(check_x, check_y, 0, -1, turn)
return check
def reverse_list(self, check_x, check_y, dx, dy, turn):
tmp = []
while True:
check_x += dx
check_y += dy
if check_x < 0 or check_x > 7:
tmp = []
break
if check_y < 0 or check_y > 7:
tmp = []
break
if self.tile[check_x][check_y] == turn:
break
elif self.tile[check_x][check_y] == ' ':
tmp = []
break
else:
tmp.append((check_x, check_y))
return tmp
can_reverse_check
ruft reverse_list
auf, eine Funktion, mit der überprüft wird, ob es einen Stein gibt, der von dem Quadrat, auf dem der Stein platziert werden soll, in jede Richtung gedreht werden kann.
Als Rückgabewert wird eine Liste der Koordinaten von Steinen zurückgegeben, die umgedreht werden können.
Rufen Sie diesen "can_reverse_check" (in "on_press") auf, wenn die "PutButton" -Klasse getippt wird, und aktualisieren Sie den Wert von "tile", wenn eine Liste von Rückgabewerten vorhanden ist, wie unten gezeigt. Neu erstellen (put_stone
aufrufen).
Wenn die Liste leer ist, tun Sie nichts.
PutButton-Klasse
def on_press(self):
put_x = self.tile_id[0]
put_y = self.tile_id[1]
check =[]
turn = self.parent.parent.turn
check += self.parent.parent.can_reverse_check(self.tile_id[0], self.tile_id[1], turn)
if check:
self.parent.parent.tile[put_x][put_y] = turn
for x, y in check:
self.parent.parent.tile[x][y] = turn
self.parent.parent.put_stone()
Pass-Funktion, wenn kein Platz zum Ablegen von Steinen vorhanden ist
Gewinn / Verlust-Urteil am Ende des Spiels
Erweitern Sie put_stone der Klasse OthelloGrid wie folgt
OthelloGrid-Klasse
def put_stone(self):
pass_flag = True
finish_flag = True
check = []
self.clear_widgets()
self.grid = GridLayout(cols=self.num, spacing=[3,3], size=(Window.width, Window.height))
next_turn = 'W' if self.turn == 'B' else 'B'
for x in range(self.num):
for y in range(self.num):
if self.tile[x][y] == 'W':
self.grid.add_widget(WhiteStone())
elif self.tile[x][y] == 'B':
self.grid.add_widget(BlackStone())
else:
self.grid.add_widget(PutButton(background_color=(0.451,0.3059,0.1882,1), background_normal='', tile_id=[x, y]))
for x in range(self.num):
for y in range(self.num):
if self.tile[x][y] == ' ':
finish_flag = False
check += self.can_reverse_check(x, y, next_turn)
if check:
pass_flag = False
break
if finish_flag:
content = Button(text=self.judge_winner())
popup = Popup(title='Game set!', content=content, auto_dismiss=False, size_hint=(None, None), size=(Window.width, Window.height/3))
content.bind(on_press=popup.dismiss)
popup.open()
else:
if pass_flag:
skip_turn_text = 'White Turn' if self.turn == 'B' else 'Black Turn'
content = Button(text='OK')
popup = Popup(title=skip_turn_text+' Skip!', content=content, auto_dismiss=False, size_hint=(None, None), size=(Window.width, Window.height/3))
content.bind(on_press=popup.dismiss)
popup.open()
else:
self.turn = next_turn
self.add_widget(self.grid)
Bereiten Sie "pass_flag" und "finish_flag" vor und beurteilen Sie anhand dieser Punkte, ob Sie das Spiel bestehen oder beenden möchten. Überprüfen Sie für alle leeren Felder in "Plättchen" (Felder mit dem Wert ""), ob ein Stein umgedreht werden muss, wenn der Spieler in der nächsten Runde einen Stein auf dieses Feld legt. Wenn nicht, überspringen Sie die nächste Runde. Zeigen Sie zu diesem Zeitpunkt auf dem Bildschirm an, den Sie mit Popup übersprungen haben.
Wenn in tile
kein Leerzeichen vorhanden ist, wird davon ausgegangen, dass das Spiel beendet ist, und die folgende Funktion Judge_winner
bestimmt, welches Spiel gewinnt, und zeigt es mit Popup auf dem Bildschirm an.
OthelloGrid-Klasse
def judge_winner(self):
white = 0
black = 0
for x in range(self.num):
for y in range(self.num):
if self.tile[x][y] == 'W':
white += 1
elif self.tile[x][y] == 'B':
black += 1
print(white)
print(black)
return 'White Win!' if white >= black else 'Black Win!'
Dies ist das Ende der Verarbeitung von Othello.
Wir haben auch ResetButton und eine Beschriftung hinzugefügt, die die Abbiegung anzeigt. Bitte überprüfen Sie den gesamten Quellcode unten für diesen Bereich. (Ich gebe es auch git. Https://github.com/fu-yuta/kivy-project/tree/master/Othello)
main.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.graphics import Color, Ellipse, Rectangle
class OthelloGrid(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.num = 8
self.tile = [[' ' for x in range(self.num)] for x in range(self.num)]
self.turn = 'W'
self.grid = GridLayout(cols=self.num, spacing=[3,3], size_hint_y=7)
for x in range(self.num):
for y in range(self.num):
if x == 3 and y == 3 or x == 4 and y == 4:
self.grid.add_widget(WhiteStone())
self.tile[x][y] = 'W'
elif x == 4 and y == 3 or x == 3 and y == 4:
self.grid.add_widget(BlackStone())
self.tile[x][y] = 'B'
else:
self.grid.add_widget(PutButton(background_color=(0.451,0.3059,0.1882,1), background_normal='', tile_id=[x, y]))
self.creat_view('White Turn')
def put_stone(self):
self.grid = GridLayout(cols=self.num, spacing=[3,3], size_hint_y=7)
pass_flag = True
finish_flag = True
check = []
next_turn = 'W' if self.turn == 'B' else 'B'
for x in range(self.num):
for y in range(self.num):
if self.tile[x][y] == 'W':
self.grid.add_widget(WhiteStone())
elif self.tile[x][y] == 'B':
self.grid.add_widget(BlackStone())
else:
self.grid.add_widget(PutButton(background_color=(0.451,0.3059,0.1882,1), background_normal='', tile_id=[x, y]))
for x in range(self.num):
for y in range(self.num):
if self.tile[x][y] == ' ':
finish_flag = False
check += self.can_reverse_check(x, y, next_turn)
if check:
pass_flag = False
break
if finish_flag:
content = Button(text=self.judge_winner())
popup = Popup(title='Game set!', content=content, auto_dismiss=False, size_hint=(None, None), size=(Window.width, Window.height/3))
content.bind(on_press=popup.dismiss)
popup.open()
self.restart_game()
else:
if pass_flag:
skip_turn_text = 'White Turn' if self.turn == 'B' else 'Black Turn'
content = Button(text='OK')
popup = Popup(title=skip_turn_text+' Skip!', content=content, auto_dismiss=False, size_hint=(None, None), size=(Window.width, Window.height/3))
content.bind(on_press=popup.dismiss)
popup.open()
else:
self.turn = next_turn
turn_text = 'Black Turn' if self.turn == 'B' else 'White Turn'
self.creat_view(turn_text)
def can_reverse_check(self, check_x, check_y, turn):
check =[]
#Bestätigung oben links
check += self.reverse_list(check_x, check_y, -1, -1, turn)
#Oben bestätigt
check += self.reverse_list(check_x, check_y, -1, 0, turn)
#Bestätigung oben rechts
check += self.reverse_list(check_x, check_y, -1, 1, turn)
#Richtige Bestätigung
check += self.reverse_list(check_x, check_y, 0, 1, turn)
#Bestätigung unten rechts
check += self.reverse_list(check_x, check_y, 1, 1, turn)
#Überprüfen Sie unten
check += self.reverse_list(check_x, check_y, 1, 0, turn)
#Bestätigung unten links
check += self.reverse_list(check_x, check_y, 1, -1, turn)
#Linke Bestätigung
check += self.reverse_list(check_x, check_y, 0, -1, turn)
return check
def reverse_list(self, check_x, check_y, dx, dy, turn):
tmp = []
while True:
check_x += dx
check_y += dy
if check_x < 0 or check_x > 7:
tmp = []
break
if check_y < 0 or check_y > 7:
tmp = []
break
if self.tile[check_x][check_y] == turn:
break
elif self.tile[check_x][check_y] == ' ':
tmp = []
break
else:
tmp.append((check_x, check_y))
return tmp
def judge_winner(self):
white = 0
black = 0
for x in range(self.num):
for y in range(self.num):
if self.tile[x][y] == 'W':
white += 1
elif self.tile[x][y] == 'B':
black += 1
print(white)
print(black)
return 'White Win!' if white >= black else 'Black Win!'
def restart_game(self):
print("restart game")
self.tile = [[' ' for x in range(self.num)] for x in range(self.num)]
self.turn = 'W'
self.grid = GridLayout(cols=self.num, spacing=[3,3], size_hint_y=7)
for x in range(self.num):
for y in range(self.num):
if x == 3 and y == 3 or x == 4 and y == 4:
self.grid.add_widget(WhiteStone())
self.tile[x][y] = 'W'
elif x == 4 and y == 3 or x == 3 and y == 4:
self.grid.add_widget(BlackStone())
self.tile[x][y] = 'B'
else:
self.grid.add_widget(PutButton(background_color=(0.451,0.3059,0.1882,1), background_normal='', tile_id=[x, y]))
self.creat_view('White Turn')
def creat_view(self, turn_text):
self.clear_widgets()
self.turn_label = Label(text=turn_text, width=Window.width , size_hint_y=1, font_size='30sp')
self.restart_button = RestartButton(text='Restart')
self.layout = BoxLayout(orientation='vertical', spacing=10, size=(Window.width, Window.height))
self.layout.add_widget(self.turn_label)
self.layout.add_widget(self.grid)
self.layout.add_widget(self.restart_button)
self.add_widget(self.layout)
class WhiteStone(Label):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(pos=self.update)
self.bind(size=self.update)
self.update()
def update(self, *args):
self.canvas.clear()
self.canvas.add(Color(0.451,0.3059,0.1882,1))
self.canvas.add(Rectangle(pos=self.pos, size=self.size))
self.canvas.add(Color(1,1,1,1))
self.canvas.add(Ellipse(pos=self.pos, size=self.size))
class BlackStone(Label):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(pos=self.update)
self.bind(size=self.update)
self.update()
def update(self, *args):
self.canvas.clear()
self.canvas.add(Color(0.451,0.3059,0.1882,1))
self.canvas.add(Rectangle(pos=self.pos, size=self.size))
self.canvas.add(Color(0,0,0,1))
self.canvas.add(Ellipse(pos=self.pos, size=self.size))
class PutButton(Button):
def __init__(self, tile_id, **kwargs):
super().__init__(**kwargs)
self.tile_id = tile_id
def on_press(self):
print(self.tile_id)
put_x = self.tile_id[0]
put_y = self.tile_id[1]
check =[]
turn = self.parent.parent.parent.turn
check += self.parent.parent.parent.can_reverse_check(self.tile_id[0], self.tile_id[1], turn)
if check:
self.parent.parent.parent.tile[put_x][put_y] = turn
for x, y in check:
self.parent.parent.parent.tile[x][y] = turn
self.parent.parent.parent.put_stone()
class RestartButton(Button):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def on_press(self):
content = Button(text='OK')
popup = Popup(title='Restart Game!', content=content, auto_dismiss=False, size_hint=(None, None), size=(Window.width, Window.height/3))
content.bind(on_press=popup.dismiss)
popup.open()
self.parent.parent.restart_game()
class OthelloApp(App):
title = 'Othello'
def build(self):
return OthelloGrid()
OthelloApp().run()
Ich habe auf den folgenden Artikel verwiesen. https://qiita.com/sobassy/items/b06e76cf23046a78ba05
Wenn das Xcode-Befehlszeilentool nicht enthalten ist, führen Sie den folgenden Befehl aus.
xcode-select --install
Abhängigkeiten installieren
brew install autoconf automake libtool pkg-config
brew link libtool
Installieren Sie Cython
pip install cython
Git-Klon kivy-ios.
git clone https://github.com/kivy/kivy-ios.git
cd kivy-ios
Führen Sie den folgenden Befehl aus, um kivy für iOS zu erstellen (der Vorgang kann mehrere zehn Minuten dauern).
python toolchain.py build kivy
Sobald dies abgeschlossen ist, erstellen Sie das Kivy-Programm für Xcode.
python toolchain.py create [Xcode-Projektname (beliebiger Name)] [Kivy-Programmordnername]
Zu diesem Zeitpunkt muss der Name der Kivy-Programmdatei "main.py" sein. Wenn der Xcode-Projektname "App" lautet, wird ein Verzeichnis mit dem Namen "App-ios" erstellt und darin "App.xcodeproj" erstellt. Öffnen Sie dieses Projekt in Xcode.
open App.xcodeproj
Wenn Sie Simulator in Xcode angeben und erstellen, wird die App gestartet. Wenn Sie das Kivy-Programm aktualisieren, müssen Sie auch das Xcode-Projekt mit dem folgenden Befehl aktualisieren.
python toolchain.py update App
Ich habe eine Othello-App mit kivy, einer der Python-Bibliotheken, erstellt und mit Simulater unter iOS erstellt. Dieses Mal habe ich die gesamte Verarbeitung in main.py geschrieben, aber kivy ist eine kv-Sprache, und wighet usw. kann separat geschrieben werden. Daher möchte ich eine Portierung in Betracht ziehen. Darüber hinaus möchten wir die KI von Othello integrieren und in Zukunft eine Kampffunktion zwischen Spieler und CPU hinzufügen.
https://qiita.com/sobassy/items/b06e76cf23046a78ba05 https://github.com/PrestaMath/reverse_tile
Recommended Posts