Skip to content

Commit a7b7a97

Browse files
dzianis-sudkoudzianis-sudkou
authored andcommitted
Almost fully implemented Computer play. Now I should go eat. Next step is to handle computer's moves
1 parent b2c370d commit a7b7a97

File tree

3 files changed

+157
-74
lines changed

3 files changed

+157
-74
lines changed

src/Generate.effekt

Lines changed: 99 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,18 @@ def generateNewBigBoard(): BigBoards = {
1616
BigBoards(bigBoard, smallBoard)
1717
}
1818

19-
def newActiveSmallBoard(bigBoards: BigBoards, number: Int): BigBoards = {
19+
20+
// Makes a new Small Board Active()
21+
def newActiveSmallBoard(gameBoard: BigBoards, smallBoardNumber: Int): BigBoards = {
2022
with on[OutOfBounds].panic
2123

22-
var newBigBoard: BigBoard = bigBoards.bigBoard
23-
var newBigBoardSmallCopy: SmallBoard = bigBoards.smallCopy
24-
var newSmallBoard: SmallBoard = newBigBoard.get(number - 1)
24+
var newBigBoard: BigBoard = gameBoard.bigBoard
25+
var newGameBoardSmallCopy: SmallBoard = gameBoard.smallCopy
26+
var newSmallBoard: SmallBoard = newBigBoard.get(smallBoardNumber )
2527

2628

2729
// Making Active Cell in the Small Copy of the Big Board
28-
newBigBoardSmallCopy = newBigBoardSmallCopy.replace(number - 1, Active())
30+
newGameBoardSmallCopy = newGameBoardSmallCopy.replace(smallBoardNumber, Active())
2931

3032
// Replacing all the Empty() cells with Active()
3133
var counter: Int = 0
@@ -38,17 +40,17 @@ def newActiveSmallBoard(bigBoards: BigBoards, number: Int): BigBoards = {
3840
()
3941
}
4042

41-
newBigBoard = newBigBoard.replace(number - 1, newSmallBoard)
42-
BigBoards(newBigBoard, newBigBoardSmallCopy)
43+
newBigBoard = newBigBoard.replace(smallBoardNumber, newSmallBoard)
44+
BigBoards(newBigBoard, newGameBoardSmallCopy)
4345
}
4446

45-
def deactivateSmallBoard(bigBoards: BigBoards, number: Int): BigBoards = {
47+
def deactivateSmallBoard(gameBoard: BigBoards, smallBoardNumber: Int): BigBoards = {
4648
with on[OutOfBounds].panic
4749

48-
var newBigBoard: BigBoard = bigBoards.bigBoard
49-
var newBigBoardSmallCopy: SmallBoard = bigBoards.smallCopy
50+
var newBigBoard: BigBoard = gameBoard.bigBoard
51+
var newGameBoardSmallCopy: SmallBoard = gameBoard.smallCopy
5052

51-
var newSmallBoard: SmallBoard = newBigBoard.get(number - 1)
53+
var newSmallBoard: SmallBoard = newBigBoard.get(smallBoardNumber)
5254
var counter: Int = 0
5355

5456

@@ -60,56 +62,37 @@ def deactivateSmallBoard(bigBoards: BigBoards, number: Int): BigBoards = {
6062
counter = counter + 1
6163
()
6264
}
63-
newBigBoard = newBigBoard.replace(number - 1, newSmallBoard)
64-
BigBoards(newBigBoard, newBigBoardSmallCopy)
65+
newBigBoard = newBigBoard.replace(smallBoardNumber, newSmallBoard)
66+
BigBoards(newBigBoard, newGameBoardSmallCopy)
6567
}
6668

67-
def checkNewCell(bigBoards: BigBoards, smallBoardNumber: Int, cellNumber: Int, player: Cell): BigBoards = {
69+
def checkNewCell(gameBoard: BigBoards, smallBoardNumber: Int, cellNumber: Int, player: Cell): BigBoards = {
6870
with on[OutOfBounds].panic
6971

70-
var newBigBoard: BigBoard = bigBoards.bigBoard
71-
var newSmallBoard: SmallBoard = newBigBoard.get(smallBoardNumber - 1)
72-
newSmallBoard = newSmallBoard.replace(cellNumber - 1, player)
73-
newBigBoard = newBigBoard.replace(smallBoardNumber - 1, newSmallBoard)
74-
BigBoards(newBigBoard, bigBoards.smallCopy)
72+
var newBigBoard: BigBoard = gameBoard.bigBoard
73+
var newSmallBoard: SmallBoard = newBigBoard.get(smallBoardNumber)
74+
newSmallBoard = newSmallBoard.replace(cellNumber, player)
75+
newBigBoard = newBigBoard.replace(smallBoardNumber, newSmallBoard)
76+
BigBoards(newBigBoard, gameBoard.smallCopy)
7577
}
7678

7779
/*
78-
* Returns true if the Small Board is free.
80+
* Returns true if the cell is free.
7981
* False Otherwise
8082
* Input : BigBoards, SmallBoardNumber, Cell Number
8183
* Output : Boolean
8284
*/
83-
def checkAvailableSmallBoard(bigBoards: BigBoards, cellNumber: Int): Bool = {
84-
with console
85+
def checkAvailableCell(smallBoard: SmallBoard, cellNumber: Int): Bool = {
8586
with on[OutOfBounds].panic
8687

87-
val cellType: Cell = bigBoards.smallCopy.get(cellNumber - 1)
88-
89-
cellType match {
88+
val cellType: Cell = smallBoard.get(cellNumber)
89+
cellType match {
9090
case Empty() => true
9191
case Active() => true
9292
case _ => false
9393
}
9494
}
9595

96-
97-
/*
98-
* Returns true if the cell is free.
99-
* False Otherwise
100-
* Input : BigBoards, SmallBoardNumber, Cell Number
101-
* Output : Boolean
102-
*/
103-
def checkAvailableCell(bigBoards: BigBoards, smallBoardNumber: Int, cellNumber: Int): Bool = {
104-
with on[OutOfBounds].panic
105-
106-
var newBigBoard: BigBoard = bigBoards.bigBoard
107-
var newSmallBoard: SmallBoard = newBigBoard.get(smallBoardNumber - 1)
108-
val cellType: Cell = newSmallBoard.get(cellNumber - 1)
109-
if (cellType is Active()) true
110-
else false
111-
}
112-
11396
/*
11497
* Returns true if Current Player has won in this Small Board.
11598
* False Otherwise
@@ -159,11 +142,79 @@ def checkWinSituation(smallBoard: SmallBoard, player: Cell): WinBoard = {
159142
win
160143
}
161144

162-
def fillWinningGameBoard(bigBoards: BigBoards, smallBoardNumber: Int, player: Cell): BigBoards = {
163-
var newBigBoard: BigBoard = bigBoards.bigBoard
164-
var newBigBoardSmallCopy: SmallBoard = bigBoards.smallCopy
145+
def fillWinningGameBoard(gameBoard: BigBoards, smallBoardNumber: Int, player: Cell): BigBoards = {
146+
var newBigBoard: BigBoard = gameBoard.bigBoard
147+
var newGameBoardSmallCopy: SmallBoard = gameBoard.smallCopy
148+
149+
newBigBoard = newBigBoard.replace(smallBoardNumber, fill(9, player))
150+
newGameBoardSmallCopy = newGameBoardSmallCopy.replace(smallBoardNumber, player)
151+
BigBoards(newBigBoard, newGameBoardSmallCopy)
152+
}
153+
154+
def computerPlay(smallBoard: SmallBoard, computer: Cell): Int = {
155+
with on[OutOfBounds].panic
156+
157+
var newSmallBoard: SmallBoard = smallBoard
158+
var player: Cell = Cross()
159+
if (computer is Cross()) player = Nought()
160+
var counter: Int = 0
161+
var resultCell: Int = 10
162+
163+
// Check for a winning move
164+
while (counter < 9 && resultCell == 10){
165+
if (checkAvailableCell(newSmallBoard, counter)){
166+
newSmallBoard = newSmallBoard.replace(counter, computer) // Simulate Computer's move
167+
if (checkWinSituation(newSmallBoard, computer) is Win()){
168+
resultCell = counter
169+
}else{
170+
newSmallBoard = newSmallBoard.replace(counter, Active())
171+
}
172+
}
173+
counter = counter + 1
174+
}
175+
176+
counter = 0
177+
// Check for a blocking move
178+
while (counter < 9 && resultCell == 10){
179+
if (checkAvailableCell(newSmallBoard, counter)){
180+
newSmallBoard = newSmallBoard.replace(counter, player) // // Simulate Player's move
181+
if (checkWinSituation(newSmallBoard, player) is Win()){
182+
resultCell = counter
183+
}else{
184+
newSmallBoard = newSmallBoard.replace(counter, Active())
185+
}
186+
}
187+
counter = counter + 1
188+
}
189+
190+
counter = 0
191+
// Choose center if available (strong strategically)
192+
if ((checkAvailableCell(newSmallBoard, 4)) && resultCell == 10){
193+
resultCell = 4
194+
}
195+
196+
counter = 0
197+
// Choose a corner if available
198+
[0,2,6,8].foreach { cellPos =>
199+
if ((checkAvailableCell(newSmallBoard, cellPos)) && resultCell == 10){
200+
resultCell = cellPos
201+
}
202+
}
203+
204+
// Choose any available side
205+
[1, 3, 5, 7].foreach { cellPos =>
206+
if ((checkAvailableCell(newSmallBoard, cellPos)) && resultCell == 10){
207+
resultCell = cellPos
208+
}
209+
}
210+
resultCell
211+
}
165212

166-
newBigBoard = newBigBoard.replace(smallBoardNumber - 1, fill(9, player))
167-
newBigBoardSmallCopy = newBigBoardSmallCopy.replace(smallBoardNumber - 1, player)
168-
BigBoards(newBigBoard, newBigBoardSmallCopy)
213+
def isComputerTurn(currentPlayer: Cell, computer: Cell): Bool = {
214+
var pcCross: Bool = false
215+
var returnValue: Bool = false
216+
if (computer is Cross()) pcCross = true
217+
if (currentPlayer is Cross()) if (pcCross) returnValue = true
218+
if (currentPlayer is Nought()) if (not(pcCross)) returnValue = true
219+
false
169220
}

src/Stupid.effekt

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,20 @@ import src/Generate
1111

1212
def playGame(): Unit = {
1313

14+
// Returns the chosen Game Mode
15+
def chooseGameMode(): GameMode / {WrongInput} = {
16+
println("Choose the Game Mode:\n[1 - 2 Players, 2 - vs Computer]:")
17+
val side = consoleInput()
18+
side match {
19+
case "1" => Local()
20+
case "2" => Computer()
21+
case _ =>
22+
do WrongInput("Invalid Game Mode. Please type '1' or '2'!")
23+
chooseGameMode()
24+
}
25+
}
26+
27+
// Returns the Cell type for the side
1428
def chooseSide(): Cell / {WrongInput} = {
1529
println("Choose the side[X, O]:")
1630
val side = consoleInput()
@@ -23,69 +37,86 @@ def playGame(): Unit = {
2337
}
2438
}
2539

26-
def chooseSmallBoard(bigBoards: BigBoards): Int / {WrongInput} = {
40+
41+
// Returns the Small Board Number [0 - 8]
42+
def chooseSmallBoard(gameBoard: BigBoards): Int / {WrongInput} = {
2743
println("Choose the Small Board[1 - 9]:")
2844
val smallBoardNumber: String = consoleInput()
2945

3046
if (not(any(Numbers) {s => s == smallBoardNumber})) {
3147
do WrongInput("Invalid input. Please type a number from 1 to 9.")
32-
chooseSmallBoard(bigBoards)
48+
chooseSmallBoard(gameBoard)
3349
}
3450
else {
3551
with on[WrongFormat].panic
3652
val smallBoardNumber: Int = toInt(smallBoardNumber)
37-
if (checkAvailableSmallBoard(bigBoards, smallBoardNumber)){
38-
smallBoardNumber
53+
if (checkAvailableCell(gameBoard.smallCopy, smallBoardNumber - 1)){
54+
smallBoardNumber - 1
3955
}else {
4056
do WrongInput("This Small Board is Already occupied. Please type a number for a valid Small Board.")
41-
chooseSmallBoard(bigBoards)
57+
chooseSmallBoard(gameBoard)
4258
}
4359
}
4460
}
4561

46-
def chooseCell(bigBoards: BigBoards, smallBoardNumber: Int): Int / {WrongInput} = {
62+
// Returns the chosen Cell inside the board [0 - 8]
63+
def chooseCell(gameBoard: BigBoards, smallBoardNumber: Int): Int / {WrongInput} = {
64+
with on[OutOfBounds].panic
65+
4766
println("Choose the cell inside your Small Board")
4867
val cellNumber: String = consoleInput()
4968
if (not(any(Numbers) {s => s == cellNumber})) {
5069
do WrongInput("Invalid input. Please type a number from 1 to 9.")
51-
chooseCell(bigBoards, smallBoardNumber)
70+
chooseCell(gameBoard, smallBoardNumber)
5271
}else {
5372
with on[WrongFormat].panic
5473
val cellNumberInt = toInt(cellNumber)
5574

56-
if(checkAvailableCell(bigBoards, smallBoardNumber, cellNumberInt)){
57-
cellNumberInt
75+
if(checkAvailableCell(gameBoard.bigBoard.get(smallBoardNumber), cellNumberInt - 1)){
76+
cellNumberInt - 1
5877
}else{
5978
do WrongInput("This Cell is Already occupied. Please type a number for a valid cell.")
60-
chooseCell(bigBoards, smallBoardNumber)
79+
chooseCell(gameBoard, smallBoardNumber)
6180
}
6281
}
6382
}
6483

65-
def gameLoop(player: Cell): Unit / {WrongInput} = {
84+
def gameLoop(player: Cell, gameMode: GameMode): Unit / {WrongInput} = {
6685
var endGame: Bool = false
6786

6887
var gameBoard: BigBoards = generateNewBigBoard()
6988
var currentSmallBoard: Int = 10
7089
var currentCell: Int = 10
90+
91+
var computer: Cell = Cross()
92+
if (player is Cross()) computer = Nought()
7193

72-
var currentPlayer: Cell = player
94+
var currentPlayer: Cell = Cross()
7395

7496
printGameScreen(gameBoard, player)
7597

76-
if (currentPlayer is Cross()) {
98+
if (player is Cross()) {
7799
println("You're starting the game!\nChoose the starting Small Board.")
78100
currentSmallBoard = chooseSmallBoard(gameBoard)
79101
gameBoard = newActiveSmallBoard(gameBoard, currentSmallBoard)
80102
} else {
81-
println("You're starting the game!\nChoose the starting Small Board.")
82-
currentSmallBoard = chooseSmallBoard(gameBoard)
83-
gameBoard = newActiveSmallBoard(gameBoard, currentSmallBoard)
103+
println("Opponent is starting the game!\nChoose the starting Small Board.")
104+
if (gameMode is Computer()){
105+
currentSmallBoard = computerPlay(gameBoard.smallCopy, computer)
106+
gameBoard = newActiveSmallBoard(gameBoard, currentSmallBoard)
107+
}else{
108+
currentSmallBoard = chooseSmallBoard(gameBoard)
109+
gameBoard = newActiveSmallBoard(gameBoard, currentSmallBoard)
110+
}
84111
}
85112

86113
// INNER GAME LOOP OF ONE GAME
87114
while (not(endGame)){
88115
if (currentSmallBoard == 10) {
116+
if (isComputerTurn(currentPlayer, computer)){
117+
currentSmallBoard = computerPlay(gameBoard.smallCopy, computer)
118+
gameBoard = newActiveSmallBoard(gameBoard, currentSmallBoard)
119+
}
89120
printGameScreen(gameBoard, currentPlayer)
90121
currentSmallBoard = chooseSmallBoard(gameBoard)
91122
gameBoard = newActiveSmallBoard(gameBoard, currentSmallBoard)
@@ -111,11 +142,6 @@ def playGame(): Unit = {
111142
}
112143
case _ => ()
113144
}
114-
// if (checkWinSituation(gameBoard.bigBoard.get(currentSmallBoard - 1), currentPlayer) is Win()){
115-
// println("\nYou won the Small Board!")
116-
// consoleInput()
117-
// gameBoard = fillWinningGameBoard(gameBoard, currentSmallBoard, currentPlayer)
118-
// }
119145

120146
// After The Player's Move
121147
printGameScreen(gameBoard, currentPlayer)
@@ -124,7 +150,7 @@ def playGame(): Unit = {
124150
consoleInput()
125151

126152
// Change the Current Small Board
127-
if (checkAvailableSmallBoard(gameBoard, currentCell)){
153+
if (checkAvailableCell(gameBoard.smallCopy, currentCell)){
128154
gameBoard = deactivateSmallBoard(gameBoard, currentSmallBoard)
129155
currentSmallBoard = currentCell
130156
gameBoard = newActiveSmallBoard(gameBoard, currentSmallBoard)
@@ -174,14 +200,19 @@ def playGame(): Unit = {
174200
var play: Bool = true
175201

176202
var player: Cell = Nought()
203+
204+
var gameMode: GameMode = Local()
177205
while (play) {
178206

179207
try{
208+
// Choosing a Game Mode
209+
gameMode = chooseGameMode()
210+
180211
// Choosing a player side
181212
player = chooseSide()
182213

183214
// Starting the game
184-
gameLoop(player)
215+
gameLoop(player, gameMode)
185216

186217
} with WrongInput { msg =>
187218
println(msg)

src/lib.effekt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ import io/console
44

55
effect WrongInput(msg: String): Unit
66

7+
type GameMode {
8+
Local()
9+
Computer()
10+
}
711

812
type Cell {
913
Empty()
1014
Active()
11-
1215
Nought()
1316
Cross()
14-
1517
Draw()
16-
1718
NewLine()
1819
Separator()
1920
}

0 commit comments

Comments
 (0)