Tic Tac Toe game, trying to use more than 9 choices.

Been working on a bingo game.  Used the tutorial for “Building your first game in Corona” was able to make the game.  Started changing things like the grid from 9 spots to 25. I am stuck because the numbers and background colors do not conform with the new 25 space grid.  It still shows 3 numbers across but does give 25 colored squares.  How do I get this to match up with the grid. 

This is the code I used.

– main.lua


– Your code here

local widget = require( “widget” )

local winningLine

local winningText

local resetButton

local allowMoves = true

local leftVerticalLine = display.newRoundedRect( display.contentCenterX - 90, display.contentCenterY, 5, 300 , 3)

local leftVerticalLine = display.newRoundedRect( display.contentCenterX - 30, display.contentCenterY, 5, 300 , 3)

local rightVerticalLine = display.newRoundedRect( display.contentCenterX + 30, display.contentCenterY, 5, 300, 3 )

local rightVerticalLine = display.newRoundedRect( display.contentCenterX + 90, display.contentCenterY, 5, 300, 3 )

local topHorzontalLine = display.newRoundedRect( display.contentCenterX, display.contentCenterY - 30, 300, 5, 3 )

local topHorzontalLine = display.newRoundedRect( display.contentCenterX, display.contentCenterY - 90, 300, 5, 3 )

local bottomHorizontalLine = display.newRoundedRect( display.contentCenterX, display.contentCenterY + 30, 300, 5, 3 )

local bottomHorizontalLine = display.newRoundedRect( display.contentCenterX, display.contentCenterY + 90, 300, 5, 3 )

local spots = {}

local player = “X” – Player X goes first in Tic Tac Toe

local winPatterns = {}

winPatterns[1] = { 1, 2, 3 } – top horizontal row

winPatterns[2] = { 4, 5, 6 } – middle horizontal row

winPatterns[3] = { 7, 8, 9 } – bottom horizontal row

winPatterns[4] = { 1, 4, 7 } – left vertical column

winPatterns[5] = { 2, 5, 8 } – middle vertical column

winPatterns[6] = { 3, 6, 9 } – right vertical column

winPatterns[7] = { 1, 5, 9 } – top left to bottom right diagonal

winPatterns[8] = { 7, 5, 3 } – bottom left to top right diagonal

local function resetGame()

    for i = 1, #spots do

        spots[i].moveText.text = " "

        spots[i].moveType = nil

    end

    display.remove( winningLine )

    winningLine = nil

    display.remove( winningText )

    winningText = nil

    display.remove( resetButton )

    resetButton = nil

    player = “X”

    allowMoves = true

end

local function gameOver( winningMove, currentPlayer )

    – lets draw a line thru the winning numbers

    allowMoves = false

    if winningMove then

        local startX = spots[winPatterns[ winningMove][1] ].x

        local startY = spots[winPatterns[ winningMove][1] ].y

        local endX = spots[winPatterns[ winningMove][3] ].x

        local endY = spots[winPatterns[ winningMove][3] ].y

        winningLine = display.newLine( startX, startY, endX, endY )

        winningLine:setStrokeColor( 1, 0, 0 )

        winningLine.strokeWidth = 5

        winningText = display.newText( “Player " … currentPlayer … " won!”, display.contentCenterX, display.contentHeight - 60, native.systemFontBold, 40 )

    else

        winningText = display.newText( “Stalemate”,  display.contentCenterX, display.contentHeight - 60, native.systemFontBold, 40  )

    end

    resetButton = widget.newButton({

        label = “Reset”,

        x = display.contentCenterX,

        y = display.contentHeight - 20,

        font = native.systemFontBold,

        fontSize = 20,

        labelColor = { default = { 0.75, 0.75, 1}, over = { 1, 1, 1 } },

        onPress = resetGame

    })

end

local function checkForStalemate()

    for i = 1, #spots do

        if spots[i].moveType == nil then

            return

        end

    end

    – if we get here, the board is full

    gameOver( nil, nil )

end

local function isGameOver( currentPlayer )

    local isWinner = false

    for i = 1, #winPatterns do

        if  spots[winPatterns[i][1]].moveType == currentPlayer and

                 spots[winPatterns[i][2]].moveType == currentPlayer and

               spots[winPatterns[i][3]].moveType == currentPlayer then

            – we have a winner!

             isWinner = true

            gameOver( i, currentPlayer )

            break

        end

    end

    if not isWinner then

        checkForStalemate()

    end

    if currentPlayer == “O” then

        player = “X”

    else

        player = “O”

    end

end

local function handleMove( event )

    if event.phase == “began” then

        if event.target.moveType == nil and allowMoves then

            event.target.moveText.text = player

            event.target.moveType = player

            isGameOver( player )

        end

    end

    return true

end

for i = 1, 25 do

    spots[i] = display.newRect( 0, 0, 60, 60)

    spots[i]:setFillColor( 1, 0, 0,0.4 )

    spots[i].x = ( i - 1 ) % 5* 100+ 60

    spots[i].y = math.floor( ( i - 1 ) / 5 ) * 100 + 140

    spots[i].moveText = display.newText( " ", spots[i].x, spots[i].y, native.systemFontBold, 80)

    spots[i].moveType = nil

    spots[i]:addEventListener( “touch”, handleMove )

end

Thanks again, 

Mark. 

I took a glimpse at your code, which, btw, you should post to the forums by using the code insert button <>.

It seemed that you had only changed the way that you create those “spots”. The rest of it seems to simply be lifted off the tic-tac-toe, including the game logic itself. This means that the game is trying to determine the winner in a 3x3 grid, even though you’ve given it a 5x5 grid.

As for the reason why they don’t line up, it’s most likely due to your math being incorrect. I just did this in my head, so it might not be correct, but try changing the x and y value generation to:

 

 spots[i].x = ( i - 1 ) % 5\* 60 + 120 spots[i].y = math.floor( ( i - 1 ) / 5 ) \* 60 + 40

Finally, you have numerous variables with duplicate names, e.g. leftVerticalLine. You don’t want to do that, because the moment that you create a new variable with the same name, you can no longer control the previously created variable and it’ll just stay there until the app closes.

Tutorials are a great place to get started and to pick some new tricks, but I wouldn’t recommend starting to build a game that relies on entirely different logic upon a tutorial, like you now have. You’ll just end up with messy code and problems that should have never existed.

Agree with @XeduR. By all means it’s a good idea to mess around with the tutorial code to get it to do slightly different things, so you understand better how it works. I started with Corona by reversing an angry birds tutorial so that you designed the tower and the AI fired the birds.

However once you’ve learned all you can, it’s best to start fresh. I get the impression you don’t yet fully understand how the tic-tac-toe code is working, which makes it difficult to build something more complex with it.

The only reference to the logic I have is the code supplied in the tutorial.  I am new.  I don’t know the logic of the math or what I am manipulating. My point is I am trying to make this work on a grid that is 5x5 rather than 3x3.  I can build the grid.  I have changed the names of the lines to make each unique.  I have changed the number in the [i] sections.  It still gives me the 5x5 grid with background colors 3 across.  I can change the size of the background square but I don’t see where to change the grid to 5x5.  There is nothing in the tutorial.  I have watched both segments of it several times.  The math on how to move the square doesn’t give any logic on how and what the numbers represent.  The narrator simply says that he already calculated the math and we might want to play around with it.  I did this and it moves the squares and numbers in illogical areas.  Sometimes changing the order.  I have no reference point.  All I can do is guess.  I have been working on this for over a week.  Could someone help me.  All I get is so far is to watch the tutorials. This isn’t helping. I can completely make the tic tac toe game.  But this isn’t my end goal. 

This is the code I am using.

<-----------------------------------------------------------------------------------------

– main.lua


– Your code here

local firstVerticalLine = display.newRect( display.contentCenterX - 90, display.contentCenterY, 5, 300 )

local secondVerticalLine = display.newRect( display.contentCenterX - 30, display.contentCenterY, 5, 300 )

local thirdVerticalLine = display.newRect( display.contentCenterX + 30, display.contentCenterY, 5, 300 )

local forthVerticalLine = display.newRect( display.contentCenterX + 90, display.contentCenterY, 5, 300 )

local firstHorzontalLine = display.newRect( display.contentCenterX, display.contentCenterY - 90, 300, 5 )

local secondHorzontalLine = display.newRect( display.contentCenterX, display.contentCenterY - 30, 300, 5 )

local thirdHorizontalLine = display.newRect( display.contentCenterX, display.contentCenterY + 30, 300, 5 )

local forthHorizontalLine = display.newRect( display.contentCenterX, display.contentCenterY + 90, 300, 5 )

local spots = {}

for i = 1, 25 do

    spots[i] = display.newRect( 0, 0, 60, 60)

    spots[i]:setFillColor( 0.2, 0.2, 0.2 )

    spots[i].x = ( i - 1 ) % 3 * 100 + 60

    spots[i].moveType = nil

end>

The source initially is from the source code for the tic tac toe game.  I didn’t see in it or on the tutorial where and how it was set to 3x3.  This is where I am stuck. I have started over again in a new project typing the code in line by line.  It still doesn’t give a 5x5 grid.

Well, it seems you are trying to run before you can walk. There’s not much point in a tutorial if you don’t understand every bit of code, what it’s doing and why. 

I’d advise you to continue learning the basics (perhaps with tutorials that actually explain the code) before trying to make something fairly complex like a bingo game. Hacking it together with guesswork won’t do you any good in the long run.

Do I need to watch every tutorial that there is on LUA  before I can get the answer to a simple question like how to convert a 3x3 grid to a 5x5?  I don’t think this is the most difficult question.  But it is like a combination to a safe.  If you don’t know the answer just simply guessing isn’t going to help.  If you don’t know I understand.  If someone out there knows where I can find the information needed to solve this please tell me.  If it is in another tutorial, that is fine.  I have no reference point and telling me to look to the tutorial.  I can’t find it in the tutorial.  I have watched it several times.  It does not explain where to set the grid to 3x3.  

Of course it’s not a difficult question, but you’re asking someone to read through 200 lines of unformatted code they haven’t seen before, work out what it’s doing (there are a hundred ways you could implement tic-tac-toe) then work out exactly what you actually want it to do, which isn’t at all clear from the original post. 

It is unfortunate the tutorial seems to be poorly done, simply skipping over key lines of code. Pretty amazed that’s an official Corona video really…

Here’s what that bit of code does:

[lua]

for i = 1, 9 do   – loop through the nine squares

    spots[i] = display.newRect( 0, 0, 90, 90)   – create a new 90 x 90 square and add it to the spots table

    spots[i]:setFillColor( 0.2, 0.2, 0.2 )    – set the colour to grey

    

    spots[i].x = ( i - 1 ) % 3 * 100 + 60   – calculate the X position of the square (see below)

        

        – i - 1    – if we are doing square one, use 0. if we are doing square 6, use 5.

        – % 3      – get the remainder of (i-1) when divided by 3. This gives us our ‘column ID’

                    – 0 % 3 = 0. 1 % 3 = 1. 2 % 3 = 2. 3 % 3 = 0. 4 % 3 = 1. etc.

        – * 100    – multiply the column ID by 100. So the first column will be 0, the last column 200.  

        – + 60     – finally add 60 to the calculation. Column 0 = 60. Column 1 = 160. Column 2 = 260

        

    spots[i].y = math.floor( ( i - 1 ) / 3 ) * 100 + 140 – calculate the Y position of the square (see below)

    

        – i - 1      – if we are doing square one, use 0. if we are doing square 6, use 5.

        – / 3        – divide this number by 3. 1 / 3 = 0.333. 4 / 3 = 1.333.

        – math.floor – round this number down to the nearest whole number.

                      – therefore, 0.333 = 0, 1.333 = 1

                      – this gives us our ‘row ID’

      – * 100        – multiply the row ID by 100. Row 0 = 0. Row 2 = 200.

      – + 140        – add 140 to the calculation. Row 0 = 140. Row 1 = 240. Row 2 = 340

      

    spots[i].moveText = display.newText( i, spots[i].x, spots[i].y, native.systemFontBold, 80)

                – create a text object in the same place as our square

    spots[i].moveType = nil   – pointless line…already nil

    spots[i]:addEventListener( “touch”, handleMove )    – add a touch listener to this square, which will call handleMove function.

    

end

[/lua]

Important to note this code is completely independent from the grid lines drawn individually near the top. I’d get rid of those lines, and just add a stroke (border) to the grid rectangles. A good example of a tutorial trying to make things easier to understand but teaching bad coding practices…

I appreciate this and it is helpful to know some of the math.  I still don’t see anywhere how to change the grid from a 3x3 to a 5x5.  I have searched through everything I can find.  What am I missing?

The 3x3 grid is created in that code (apart from the fairly pointless grid lines created near the top - they are just cosmetic).

The math explains how the 9 squares are allocated to either column 0, 1 or 2, and row 0, 1 or 2. So you need to adjust the math so that they are allocated to a column between 0-4 and row 0-4, and adjust the x/y positioning to take into account a bigger number of smaller squares.

XeduR gave you a clue on that in his post.

I agree with nick’s point in that you should perhaps go through a few general lua tutorials to get a bit more familiar with the language itself. You could also have a look at these tutorials: https://docs.coronalabs.com/tutorial/ to better understand some basic things in Corona.

The most important thing about tutorials is to understand what is actually being done and why. After you’ve practiced a bit, you should be able to solve your problem with relative ease.

 

You don’t need to read and watch every tutorial, but no one tutorial can teach you everything.

As mentioned above the grid lines were done specifically to create a 3x3 style tic-tac-toe board. If you’re making BINGO, you probably wouldn’t use this kind of UI design, but likely have some background graphic designed in a tool like Photoshop that you load on the screen.

Next, for positioning the numbers, there is a key line that got pointed out earlier that you mentioned:

spots[i].x = ( i - 1 ) % 3 \* 100 + 60

You are going to loop over 25 spots in your 5x5 grid. That line of code positions on a 3x3 grid. The loop uses “i” as an index variable of the for loop to count from 1 to 25.  It then takes ( i - 1 ) and does a modulus operator (gets the remainder of a divide).  So basically if i = 1, then 0 % 3 will be 0. Multiply that by 100 and you get 0. Then add 60 and you get 60. The first spot will be drawn at X = 60.

Now the next time through the loop, i is 2.  ( i - 1 ) % 3 which will produce a value of 1. Now 1 * 100 + 60 will make X = 160. The third time through ( 3 - 1 ) % 3 = 2, 2 * 100 + 60 will make X = 260.  The results are three spots at 60, 160 and 260, evenly spacing them across the screen.

As the loop continues, the results of using “% 3” will result in values of either 0, 1 or 2 so for each future row (there was something that adds a value to the Y calculation to move the next row of numbers down the screen.  If you change the (% 3) to (% 5), then you will get 5 numbers across, but they will be X values of 60, 160, 260, 360 and 460, with the last two being off screen since your config.lua is likely creating a content area that’s 320 points wide. You would need to change the value for how much to move based on 5 wide. Perhaps 

spots[i].x = ( i - 1 ) % 3 \* 65 + 35

That would give you 35, 100, 165, 230, 295

But this is all a moot point because that’s not how BINGO works. If you number the spots, you would end up with:

&nbsp;1&nbsp; 2&nbsp; 3&nbsp; 4&nbsp; 5 &nbsp;6&nbsp; 7&nbsp; 9&nbsp; 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

BINGO numbers are more like:

 1 16 31 46 66 3 17 32 48 68 &nbsp;7 20 FS 42 70 10 24 40 60 71 15 30 45 65 75

So numbers count up and down a column before moving to the next column over. Compounding matters is that the numbers are not computed in order, but are random numbers. Column 1 being 1 - 15, column 2 being 16 to 30, column 3 being 31 to 45, etc. So the positioning logic of simply counting from 1 to 25 isn’t really going to work for you anyway.

The logic for a BINGO board is something more like:

local B = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } local I = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 } local N = { 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45 } local G = { 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58 ,59, 60 } local O = { 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75 } math.randomseed( os.time() )&nbsp; -- Seed the pseudo-random number generator local function shuffleTable( t ) &nbsp;&nbsp;&nbsp;&nbsp;if ( type(t) ~= "table" ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print( "WARNING: shuffleTable() function expects a table" ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false &nbsp;&nbsp;&nbsp;&nbsp;end &nbsp;&nbsp;&nbsp;&nbsp;local j &nbsp;&nbsp;&nbsp;&nbsp;for i = #t, 2, -1 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = math.random( i ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t[i], t[j] = t[j], t[i] &nbsp;&nbsp;&nbsp;&nbsp;end &nbsp;&nbsp;&nbsp;&nbsp;return t end shuffleTable( B ) shuffleTable( I ) shuffleTable( N ) shuffleTable( G ) shuffleTable( O )

Now you have 5 tables that have been randomly sorted. Now to draw, those numbers on the screen:

local B\_spots = {} local I\_spots = {} local N\_spots = {} local G\_spots = {} local O\_spots = {}

for i = 1, 5 do &nbsp; &nbsp; B\_spots[i] = display.newText( B[i], 35, i \* 35, native.systemFontBold, 28 ) &nbsp; &nbsp; I\_spots[i] = display.newText( I[i], 100, i \* 35, native.systemFontBold, 28 ) &nbsp; &nbsp; N\_spots[i] = display.newText( N[i], 165, i \* 35, native.systemFontBold, 28 ) &nbsp; &nbsp; G\_spots[i] = display.newText( G[i], 230, i \* 35, native.systemFontBold, 28 ) &nbsp; &nbsp; O\_spots[i] = display.newText( O[i], 295, i \* 35, native.systemFontBold, 28 ) end N\_spots[3].text = "Free"

So just because Tic-Tac-Toe is a grid game, doesn’t mean that code is useful for other grid games.

And of course, the rest of the Tic-Tac-Toe game logic isn’t practical at all for BINGO. Finally, there are many different ways to accomplish this. I’m sure other developers would come up with a different way of managing displaying a BINGO board. 

Rob

Thank you so much.  Your help is very much appreciated.  I will play with this and learn.  Thanks again

Thanks again for your help.  I am taking this one step at a time.  My first step is to get a grid of squares on the screen (without the grid).  I have played around with the code, 

<

local spots = {}

for i = 1, 25 do

    spots[i] = display.newRect( 0, 0, 50, 50)

    spots[i]:setFillColor( 1, 1, 1, 0.2)

    spots[i].x = ( i - 1 ) % 5 * 60 + 40

    spots[i].moveType = nil

end

>

I get a single row at the top of the app of 5 squares across.  I don’t know how to get all 25 to appear.  I have changed the 60+40 to many different things but that only moves the squares horizontally, not vertically.  How do I get this to move down the screen.  

Sorry for the annoyance. I am trying everything I know before I write. 

You are missing the line that sets the ‘y’ position, i.e. where the square is positioned from top to bottom.

This is still screaming ‘go back to basics’. Then you would easily spot that you never set a ‘y’ position and therefore they all stack on top of each other at the default y position of 0.

I had never “set”  a “Y” position.  I am using the code you provided with your tutorials and in this forum. I am not inventing my own. I obviously don’t know the code for this.  I can’t find it on any of your help pages. I understand that I am trying to move this down the “y” position.  I have gone through your pages for Corona and I can’t find any code that makes sense to move this.  Each time I send a message you are very happy to tell me that I have no clue as to what I am doing.  I already understand that.  I am looking for where I can find this or how to do this.  Simply telling me that I don’t know the answer once again isn’t helping.  Is there some reason that you do not want to help?  I don’t mean to be bothering you.  I am just looking for guidance. If there is a tutorial that you know of, please which is it?  I have gone through the basics.  I have built the balloon, the tic tac toe.   If in this and others I have searched for I am missing it.  Could you please give me a clue.  And better yet, if you are trying to help could you give me an answer?  You are under no obligation to help me.  I apologize for the intrusion. I thought that is what forums were for. 

Mate, the code is on this thread about 3 or 4 times, including my post where I explained each line in detail. You’ve removed it from your code for some reason.

I could just point you at the exact line, but if you read through this thread again you should be able to figure it out. Not through any coding knowledge at all, just literally playing ‘spot the difference’.

You’ve had valuable advice from various professionals who remember what it was like to know nothing, and that is to build towards a game like this, not leap right in.

I’m currently learning .NET for work, and I’ve had to go right back to basics. How to set up Visual Studio & SQL server, how to download plugins, how to print text to the screen. I’m not trying to build Facebook, or even a calculator app, on day one. I might be able to learn faster through my knowledge of C# and game development, but I still have to start from scratch.

When I was learning Unity I coded along with a tutorial series for over 75 hours, making sure I understood every single line of code and editor function used, re-watching several times if necessary. It made absolutely no sense at first coming from Corona, but it eventually clicked and now is second nature.

Hi @mark036, the thing is you had this code in your original post at the top:

for i = 1, 25 do

    spots[i] = display.newRect( 0, 0, 60, 60)

    spots[i]:setFillColor( 1, 0, 0,0.4 )

    spots[i].x = ( i - 1 ) % 5* 100+ 60

    spots[i].y = math.floor( ( i - 1 ) / 5 ) * 100 + 140

    spots[i].moveText = display.newText( " ", spots[i].x, spots[i].y, native.systemFontBold, 80)

    spots[i].moveType = nil

 

    spots[i]:addEventListener( “touch”, handleMove )

end

 

I’m not going to format the code because I want to really highlight the one line of the code.

 

One thing I did not cover well in the original tic-tac-toe tutorial or in my response last night is where do these numbers come from. Let’s start with the width.

 

Assuming you have a content area of 320 points wide (which the Tic-Tac-Toe tutorial uses) and you want three equal spaces across the screen, you would divide 320 / 3 and come up with 106.66667 points per spot available.  But you want some padding between spots, There are four areas of padding in a 3 wide grid (left, right and in between the three spots) 20 points / 4 would be 5 points of padding for each spot. That’s a convenient amount and it leaves 300 points for three spots, which is 100 points each. This is where the 100 came from.

 

Then the height of the text filling the spots was set to 80. That leaves 10 points of padding above and below (and around) each number so the number doesn’t fully fill each square. Since a Tic-Tac-Toe board’s spots are square, then the height of each row would need to be 100 also. Each new row needs to be 100 + padding + an offset to account for UI chrome like the title of the game and move each row lower on the screen.

 

If you’re going to use 5 instead of 3, you have to change the assumptions for everything. 

 

320 / 5 = 64

 

But that would pack each spot exactly beside each other. You may want some padding, so making each spot 60x60 with 4 points of padding should work for you. But your “bingo background” may end up with more padding needed between spaces. This would change your computations for the Y axis too.

 

spots[i].y = math.floor( ( i - 1 ) / 5 ) * 60 + ( i - 1 ) * 4 + 140

I tweaked this a bit more, so now you’re using 60 points for the size of the spot, applying 4 points of padding and offsetting it 140 points from the top.

Rob

Thank you for your help.  I do appreciate it.  I am sorry for getting frustrated.  I looked into your help pages on how to change the color of the text.  I found, <

local myText = display.newText( “hello”, 0, 0, native.systemFontBold, 12 )

 

myText:setFillColor( 1, 0.2, 0.2 )>

 

I tried to put the <

myText:setFillColor( 1, 0.2, 0.2 )> In several spots to make the B,I,N,G,O black instead of white. It keeps giving me an error that I can’t set it to “nil”

The issue there is that your code doesn’t contain a myText variable.

That is the variable used in the example, but you need to adapt it to work with the spots[i].moveText variable.

Again, this is basic stuff that there is no shame in not knowing, but it’s stuff you would have learnt if you followed all the introductory tutorials posted by others above. You can’t build a table without knowing how to cut wood, and you can’t build a game without knowing what variables are.