data: added python sample project
This commit is contained in:
@@ -1,18 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<config>
|
||||
<application>
|
||||
<application>
|
||||
<window_base_width>500</window_base_width>
|
||||
<window_base_height>500</window_base_height>
|
||||
</application>
|
||||
<indexing>
|
||||
<indexer_thread_count>0</indexer_thread_count>
|
||||
</indexing>
|
||||
<indexing>
|
||||
<indexer_thread_count>0</indexer_thread_count>
|
||||
</indexing>
|
||||
<user>
|
||||
<recent_projects>
|
||||
<recent_project>./projects/tutorial/tutorial.srctrlprj</recent_project>
|
||||
<recent_project>./projects/tictactoe/tictactoe.srctrlprj</recent_project>
|
||||
<recent_project>./projects/tictactoe_cpp/tictactoe_cpp.srctrlprj</recent_project>
|
||||
<recent_project>./projects/tictactoe_py/tictactoe_py.srctrlprj</recent_project>
|
||||
<recent_project>./projects/javaparser/javaparser.srctrlprj</recent_project>
|
||||
</recent_projects>
|
||||
</user>
|
||||
<version>6</version>
|
||||
<version>7</version>
|
||||
</config>
|
||||
|
||||
+5
-3
@@ -81,14 +81,16 @@ int Field::SameInRow( Token token, int amount ) const {
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
if ( grid_[i][0] + grid_[i][1] + grid_[i][2] == sum ) {
|
||||
count++;
|
||||
} else if ( grid_[0][i] + grid_[1][i] + grid_[2][i] == sum ) {
|
||||
}
|
||||
if ( grid_[0][i] + grid_[1][i] + grid_[2][i] == sum ) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( grid_[0][0] + grid_[1][1] + grid_[2][2] == sum ) {
|
||||
count++;
|
||||
} else if ( grid_[2][0] + grid_[1][1] + grid_[0][2] == sum ) {
|
||||
}
|
||||
if ( grid_[2][0] + grid_[1][1] + grid_[0][2] == sum ) {
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -117,7 +119,7 @@ void Field::MakeMove( const Move& move, Token token ) {
|
||||
}
|
||||
|
||||
void Field::ClearMove( const Move& move ) {
|
||||
if ( !InRange( move ) || !IsEmpty( move ) || left_ == 9 ) {
|
||||
if ( !InRange( move ) || IsEmpty( move ) || left_ == 9 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
from enum import Enum
|
||||
from random import randint
|
||||
|
||||
|
||||
def numberIn():
|
||||
return int(input())
|
||||
|
||||
|
||||
def numberOut(num):
|
||||
print(str(num), end="")
|
||||
|
||||
|
||||
def stringOut(str):
|
||||
print(str, end="")
|
||||
|
||||
|
||||
class GameObject:
|
||||
pass
|
||||
|
||||
|
||||
class Field(GameObject):
|
||||
class Token(Enum):
|
||||
TOKEN_NONE = 0
|
||||
TOKEN_PLAYER_A = 1
|
||||
TOKEN_PLAYER_B = 4
|
||||
|
||||
|
||||
def opponent(self, token):
|
||||
if token == Field.Token.TOKEN_PLAYER_A:
|
||||
return Field.Token.TOKEN_PLAYER_B
|
||||
elif token == Field.Token.TOKEN_PLAYER_B:
|
||||
return Field.Token.TOKEN_PLAYER_A
|
||||
return Field.Token.TOKEN_NONE
|
||||
|
||||
|
||||
class Move:
|
||||
def __init__(self):
|
||||
self.row = None
|
||||
self.col = None
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self._grid = []
|
||||
for j in range(0, 3):
|
||||
row = []
|
||||
for i in range(0, 3):
|
||||
row.append(Field.Token.TOKEN_NONE)
|
||||
self._grid.append(row)
|
||||
self._left = 9
|
||||
|
||||
|
||||
def clone(self):
|
||||
field = Field()
|
||||
for j in range(0, 3):
|
||||
for i in range(0, 3):
|
||||
field._grid[i][j] = self._grid[i][j]
|
||||
field._left = self._left
|
||||
return field
|
||||
|
||||
|
||||
def clear(self):
|
||||
for j in range(0, 3):
|
||||
for i in range(0, 3):
|
||||
self._grid[i][j] = Field.Token.TOKEN_NONE
|
||||
self._left = 9
|
||||
|
||||
|
||||
def show(self):
|
||||
stringOut(" 1 2 3\n")
|
||||
for row in range(0, 3):
|
||||
numberOut(row + 1)
|
||||
stringOut(" ")
|
||||
for col in range(0, 3):
|
||||
if self._grid[row][col] == Field.Token.TOKEN_PLAYER_A:
|
||||
stringOut(" X ")
|
||||
elif self._grid[row][col] == Field.Token.TOKEN_PLAYER_B:
|
||||
stringOut(" O ")
|
||||
else:
|
||||
stringOut(" ")
|
||||
if col < 2:
|
||||
stringOut("|")
|
||||
if row < 2:
|
||||
stringOut("\n -----------\n")
|
||||
stringOut("\n\n")
|
||||
|
||||
|
||||
def sameInRow(self, token, amount):
|
||||
total = amount * token.value
|
||||
count = 0
|
||||
for i in range(0, 3):
|
||||
if self._grid[i][0].value + self._grid[i][1].value + self._grid[i][2].value == sum:
|
||||
count += 1
|
||||
if self._grid[0][i].value + self._grid[1][i].value + self._grid[2][i].value == sum:
|
||||
count += 1
|
||||
if self._grid[0][0].value + self._grid[1][1].value + self._grid[2][2].value == sum:
|
||||
count += 1
|
||||
if self._grid[2][0].value + self._grid[1][1].value + self._grid[0][2].value == sum:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
|
||||
def inRange(self, move):
|
||||
return move.row >= 0 and move.row < 3 and move.col >= 0 and move.col < 3
|
||||
|
||||
|
||||
def isEmpty(self, move):
|
||||
return self._grid[move.row][move.col] == Field.Token.TOKEN_NONE
|
||||
|
||||
|
||||
def isFull(self):
|
||||
return self._left == 0
|
||||
|
||||
|
||||
def makeMove(self, move, token):
|
||||
if not self.inRange(move):
|
||||
return
|
||||
if not self.isEmpty(move):
|
||||
return
|
||||
if token is Field.Token.TOKEN_NONE:
|
||||
return
|
||||
if self.isFull():
|
||||
return
|
||||
self._grid[move.row][move.col] = token
|
||||
self._left -= 1
|
||||
|
||||
|
||||
def clearMove(self, move):
|
||||
if not self.inRange(move):
|
||||
return
|
||||
if self.isEmpty(move):
|
||||
return
|
||||
if self._left == 9:
|
||||
return
|
||||
self._grid[move.row][move.col] = Field.Token.TOKEN_NONE
|
||||
self._left += 1
|
||||
|
||||
|
||||
class Player(GameObject):
|
||||
def __init__(self, token, name):
|
||||
self.token = token
|
||||
self.name = name
|
||||
|
||||
|
||||
def turn(field):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class HumanPlayer(Player):
|
||||
def __init__(self, token, name):
|
||||
Player.__init__(self, token, name)
|
||||
|
||||
|
||||
def turn(self, field):
|
||||
stringOut(self.name)
|
||||
stringOut("\n")
|
||||
while True:
|
||||
move = self._input()
|
||||
if self._check(field, move):
|
||||
break
|
||||
return move
|
||||
|
||||
|
||||
def _input(self):
|
||||
move = Field.Move()
|
||||
stringOut("Insert row: ")
|
||||
move.row = numberIn() - 1
|
||||
stringOut("Insert col: ")
|
||||
move.col = numberIn() - 1
|
||||
stringOut("\n")
|
||||
return move
|
||||
|
||||
|
||||
def _check(self, field, move):
|
||||
if not field.inRange(move):
|
||||
stringOut("Wrong inpot!\n")
|
||||
return False
|
||||
elif not field.isEmpty(move):
|
||||
stringOut("Is occupied!\n")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class ArtificialPlayer(Player):
|
||||
class Node:
|
||||
def __init__(self):
|
||||
self.move = None
|
||||
self.value = 0
|
||||
|
||||
|
||||
def __init__(self, token, name):
|
||||
Player.__init__(self, token, name)
|
||||
|
||||
|
||||
def turn(self, field):
|
||||
tempField = field.clone()
|
||||
node = self._minMax(tempField, self.token)
|
||||
return node.move
|
||||
|
||||
|
||||
def _minMax(self, field, token, prefix = ""):
|
||||
node = ArtificialPlayer.Node()
|
||||
node.value = -10000
|
||||
|
||||
move = Field.Move()
|
||||
sameMove = 0
|
||||
|
||||
for j in range(0, 3):
|
||||
move.row = j
|
||||
for i in range(0, 3):
|
||||
move.col = i
|
||||
|
||||
if not field.isEmpty(move):
|
||||
continue
|
||||
|
||||
field.makeMove(move, token)
|
||||
|
||||
turnValue = self._evaluate(field, token)
|
||||
if turnValue == 0 and not field.isFull():
|
||||
turnValue = -self._minMax(field, field.opponent(token), prefix + " ").value
|
||||
|
||||
field.clearMove(move)
|
||||
|
||||
if turnValue > node.value:
|
||||
node.move = move
|
||||
node.value = turnValue
|
||||
sameMove = 1
|
||||
elif turnValue == node.value:
|
||||
sameMove += 1
|
||||
if randint(0, sameMove - 1) == 0:
|
||||
node.move = move
|
||||
return node
|
||||
|
||||
|
||||
def _evaluate(self, field, token):
|
||||
if field.sameInRow(token, 3):
|
||||
return 2
|
||||
elif field.sameInRow(field.opponent(token), 2):
|
||||
return -1
|
||||
elif field.sameInRow(token, 2) > 1:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
class TicTacToe:
|
||||
def __init__(self):
|
||||
self._field = Field()
|
||||
self._players = [None, None]
|
||||
|
||||
|
||||
def start(self):
|
||||
self._reset()
|
||||
stringOut("Tic Tac Toe\n\n[1] Human\n[2] Computer\n[3] Quit\n\n")
|
||||
|
||||
self._players[0] = self._selectPlayer(Field.Token.TOKEN_PLAYER_A, "Player A")
|
||||
if self._players[0] is None:
|
||||
return False
|
||||
|
||||
self._players[1] = self._selectPlayer(Field.Token.TOKEN_PLAYER_B, "Player B")
|
||||
if self._players[1] is None:
|
||||
return False
|
||||
|
||||
stringOut("\n")
|
||||
return True
|
||||
|
||||
|
||||
def run(self):
|
||||
self._field.show()
|
||||
playerIndex = 0
|
||||
for i in range(0, 9):
|
||||
player = self._players[playerIndex]
|
||||
self._field.makeMove(player.turn(self._field), player.token)
|
||||
self._field.show()
|
||||
if self._field.sameInRow(player.token, 3):
|
||||
stringOut(player.name)
|
||||
stringOut(" won!\n\n")
|
||||
return
|
||||
playerIndex = (playerIndex + 1) % 2
|
||||
stringOut("Game ends in draw!\n\n")
|
||||
|
||||
|
||||
def _reset(self):
|
||||
for i in range(0, 2):
|
||||
self._players[i] = None
|
||||
self._field.clear()
|
||||
|
||||
|
||||
def _selectPlayer(self, token, name):
|
||||
while (True):
|
||||
stringOut("Choose ")
|
||||
stringOut(name)
|
||||
stringOut(": ")
|
||||
selection = numberIn()
|
||||
if selection == 1:
|
||||
return HumanPlayer(token, name)
|
||||
elif selection == 2:
|
||||
return ArtificialPlayer(token, name)
|
||||
elif selection == 3:
|
||||
return None
|
||||
stringOut("Wrong input!\n")
|
||||
|
||||
|
||||
def main():
|
||||
tictactoe = TicTacToe()
|
||||
while tictactoe.start():
|
||||
tictactoe.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<config>
|
||||
<source_groups>
|
||||
<source_group_b7e201f1-a5d5-4578-9629-b14152507962>
|
||||
<name>TicTacToe Source Group</name>
|
||||
<source_extensions>
|
||||
<source_extension>.py</source_extension>
|
||||
</source_extensions>
|
||||
<source_paths>
|
||||
<source_path>src</source_path>
|
||||
</source_paths>
|
||||
<status>enabled</status>
|
||||
<type>Python Source Group</type>
|
||||
</source_group_b7e201f1-a5d5-4578-9629-b14152507962>
|
||||
</source_groups>
|
||||
<version>7</version>
|
||||
</config>
|
||||
Reference in New Issue
Block a user