Skip to content

Commit

Permalink
Added two player version for lua
Browse files Browse the repository at this point in the history
  • Loading branch information
JanEricNitschke committed Jul 23, 2023
1 parent 38bc9f2 commit 98048a1
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 0 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/lua.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This workflow will run the tests on the lua version of tictactoe

name: lua

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./tictactoe_lua
steps:
- name: Checkout repo
uses: actions/checkout@v3
- uses: actions/checkout@v3
with:
repository: bluebird75/luaunit
path: luaunit
clean: false
sparse-checkout: |
luaunit.lua
sparse-checkout-cone-mode: false
- uses: leafo/gh-actions-lua@v10
with:
luaVersion: "5.4"
- name: Test
run: |
mv ../luaunit/luaunit.lua .
lua tests/test_tictactoe.lua
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ tictactoe_ruby/*.gem
*.class

/fibonacci
luaunit.lua

tictactoe_java/*.jar

Expand Down
3 changes: 3 additions & 0 deletions tictactoe_lua/main.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require("tictactoe_lua")

TicTacToe.play()
61 changes: 61 additions & 0 deletions tictactoe_lua/tests/test_tictactoe.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package.path = package.path .. ";../?.lua"
require("tictactoe_lua")

Lu = require('luaunit')

TestGeneral = {}

function TestGeneral:setUp()
TicTacToe.board = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }
end

function TestGeneral:test_swap_player()
Lu.assertEquals(TicTacToe.swap_player("X"), "O")
Lu.assertEquals(TicTacToe.swap_player("O"), "X")
end

function TestGeneral:test_is_board_filled()
Lu.assertFalse(TicTacToe.is_board_filled())
TicTacToe.board = { "X", "X", "X", "O", "O", "O", "O", "X", "X" }
Lu.assertTrue(TicTacToe.is_board_filled())
end

function TestGeneral:test_check_win_condition()
TicTacToe.board = { "X", "X", "3", "4", "5", "6", "7", "8", "X" }
Lu.assertEquals(TicTacToe.check_win_condition({ 1, 2, 3 }, "X"), { spots_open = { 3 }, spots_done = 2 })
Lu.assertEquals(TicTacToe.check_win_condition({ 1, 2, 9 }, "X"), { spots_open = {}, spots_done = 3 })
Lu.assertEquals(TicTacToe.check_win_condition({ 1, 2, 9 }, "O"), { spots_open = {}, spots_done = 0 })
end

function TestGeneral:Test_isplayer_win_row()
TicTacToe.board = {"X", "X", "X", "4", "5", "6", "7", "8", "X"}
Lu.assertFalse(TicTacToe.is_player_win("O"))
Lu.assertTrue(TicTacToe.is_player_win("X"))
end

function TestGeneral:Test_isplayer_win_col()
TicTacToe.board = {"1", "O", "X", "4", "O", "6", "7", "O", "X"}
Lu.assertFalse(TicTacToe.is_player_win("X"))
Lu.assertTrue(TicTacToe.is_player_win("O"))
end

function TestGeneral:Test_isplayer_win_diag()
TicTacToe.board = {"1", "2", "X", "4", "X", "6", "X", "O", "O"}
Lu.assertFalse(TicTacToe.is_player_win("O"))
Lu.assertTrue(TicTacToe.is_player_win("X"))
end

function TestGeneral:test_fix_spot()
TicTacToe.board = {"1", "2", "X", "4", "X", "6", "X", "O", "O"}
Lu.assertTrue(TicTacToe.fix_spot(1, "X"))
-- Now occupied
Lu.assertFalse(TicTacToe.fix_spot(1, "X"))
-- Too small
Lu.assertFalse(TicTacToe.fix_spot(-3, "O"))
-- Too big
Lu.assertFalse(TicTacToe.fix_spot(13, "O"))
end



os.exit(Lu.LuaUnit.run())
112 changes: 112 additions & 0 deletions tictactoe_lua/tictactoe_lua.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
TicTacToe = {
board = { "1", "2", "3", "4", "5", "6", "7", "8", "9" },
win_conditions = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, -- Rows
{ 1, 4, 7 }, { 2, 5, 8 }, { 3, 5, 9 }, -- Cols
{ 1, 5, 9 }, { 3, 5, 7 } -- Diags
},
player_markers = { X = true, O = true },
ai_opponent = false,
ai_marker = "X",
ai_strength = 0,
}

function TicTacToe.swap_player(current_player)
if current_player == "X" then
return "O"
end
return "X"
end

function TicTacToe.show_board()
local line_separator = "---------------"
local side_length = 3
print(line_separator)
for row = 1, side_length do
for col = 1, side_length do
io.write("| " .. TicTacToe.board[(row - 1) * side_length + col] .. " |")
end
print ""
print(line_separator)
end
end

function TicTacToe.is_board_filled()
for _, value in ipairs(TicTacToe.board) do
if TicTacToe.player_markers[value] == nil then
return false
end
end
return true
end

function TicTacToe.check_win_condition(win_condition, current_player)
local result = { spots_open = {}, spots_done = 0 }
for _, spot in ipairs(win_condition) do
if TicTacToe.board[spot] == current_player then
result.spots_done = result.spots_done + 1
-- If it is not the current player and it is not the other one
-- Then it is open
elseif TicTacToe.board[spot] ~= TicTacToe.swap_player(current_player) then
table.insert(result.spots_open, spot)
end
end
return result
end

function TicTacToe.is_player_win(current_player)
for _, win_condition in pairs(TicTacToe.win_conditions) do
local result = TicTacToe.check_win_condition(win_condition, current_player)
if result.spots_done == 3 then
return true
end
end
return false
end

function TicTacToe.fix_spot(spot, current_player)
if TicTacToe.board[spot] == nil then
print("ERROR: Spot has to be in range [1-9]!")
return false
end
if TicTacToe.player_markers[TicTacToe.board[spot]] ~= nil then
print("ERROR: Spot " .. spot .. " is already occupied!")
return false
end
TicTacToe.board[spot] = current_player
return true
end

function TicTacToe.player_turn(current_player)
while true do
print("Player " .. current_player .. " turn.")
TicTacToe.show_board()
local result = io.read("n")
if result == nil then
print("ERROR: Input must be a valid integer!")
io.read("l")
goto continue
end
if TicTacToe.fix_spot(result, current_player) then
break
end
::continue::
end
end

function TicTacToe.play()
local player = "X"

while true do
TicTacToe.player_turn(player)
if TicTacToe.is_player_win(player) then
print("Player " .. player .. " wins the game!")
break
end
if TicTacToe.is_board_filled() then
print("Draw!")
break
end
player = TicTacToe.swap_player(player)
end
TicTacToe.show_board()
end

0 comments on commit 98048a1

Please sign in to comment.