{"id":22551318,"url":"https://github.com/joelumbley/tic-tac-toe","last_synced_at":"2026-01-07T21:06:15.698Z","repository":{"id":169390617,"uuid":"645006173","full_name":"JoeLumbley/Tic-Tac-Toe","owner":"JoeLumbley","description":"Three in a row game.","archived":false,"fork":false,"pushed_at":"2023-07-30T22:03:31.000Z","size":119,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-02T10:36:00.850Z","etag":null,"topics":["game","noughts-and-crosses","three-in-a-row","tic-tac-toe","vb","vb-net","xogame"],"latest_commit_sha":null,"homepage":"","language":"Visual Basic .NET","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JoeLumbley.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-24T18:02:45.000Z","updated_at":"2023-07-30T22:02:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"fc4ae09c-b8e8-4afb-bf93-d7a71c59833e","html_url":"https://github.com/JoeLumbley/Tic-Tac-Toe","commit_stats":null,"previous_names":["joelumbley/tic-tac-toe"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoeLumbley%2FTic-Tac-Toe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoeLumbley%2FTic-Tac-Toe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoeLumbley%2FTic-Tac-Toe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoeLumbley%2FTic-Tac-Toe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JoeLumbley","download_url":"https://codeload.github.com/JoeLumbley/Tic-Tac-Toe/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246009076,"owners_count":20708881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["game","noughts-and-crosses","three-in-a-row","tic-tac-toe","vb","vb-net","xogame"],"created_at":"2024-12-07T17:12:12.044Z","updated_at":"2026-01-07T21:06:15.693Z","avatar_url":"https://github.com/JoeLumbley.png","language":"Visual Basic .NET","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tic-Tac-Toe\nThree in a row game, also known as Noughts and Crosses or X's and O's.\n\nThis app is resizable, supports mouse input and has a computer player. Works with Windows 10 and 11.\n\n\n![001](https://github.com/JoeLumbley/Tic-Tac-Toe/assets/77564255/2d3e72ac-cee3-4715-857a-6fe81cdc20f6)\n\n\n## Set Up Board\n\nThe Board is a 3x3 grid of cells where players place their mark to try to get three in a row. We represent The Board as a two-dimensional array of cells, where each cell can be empty or occupied by a player's mark.\n\nWe define the Board as a two-dimensional array that holds the state of each cell.\n\n```\n\nPrivate ReadOnly Board(2, 2) As Cell\n\n```\n\nWe use the Cell enumeration to represent the possible states of each cell.\n\n```\n\nEnum Cell\n        Empty\n        X\n        O\nEnd Enum\n\n```\n\nThe possible states of each cell on the Board being: Empty, X, or O.\n\n\n![002](https://github.com/JoeLumbley/Tic-Tac-Toe/assets/77564255/4dea998f-d56c-427f-8d2f-abc3718af36d)\n\nWe initialize the Board to all Empty cells using a loop:\n\n\n```\n\nPrivate Sub InitializeBoard()\n\n        For X = 0 To 2\n\n            For Y = 0 To 2\n\n                Board(X, Y) = Cell.Empty\n\n            Next\n\n        Next\n\nEnd Sub\n\n```\n\n\nThis will set every cell on the Board to Cell.Empty.\n\nNow we're ready to play.\n\n## Making Moves\n\nFor the human player we handle mouse clicks on the form to update the state of the Board.\n\n\n```\n\nPrivate Sub Form1_MouseClick(sender As Object, e As MouseEventArgs) Handles MyBase.MouseClick\n\n        UpdateMouse(e)\n\nEnd Sub\n\n```\n\n\nWe handle clicks on a square by converting form coordinates to \nboard coordinates.\n\nIf the square is empty we mark the square with the player's mark.\n\nWe then check for a win or draw using the CheckForWin and\nCheckForDraw methods.\n\n\n```\n\n\nPrivate Sub UpdateMouse(e As MouseEventArgs)\n\n        Select Case GameState\n\n            Case GameStateEnum.Playing\n\n                Dim X As Integer = MouseToBoardX(e)\n\n                Dim Y As Integer = MouseToBoardY(e)\n\n                If Board(X, Y) = Cell.Empty Then\n\n                    If CurrentPlayer = Cell.X Then\n\n                        'Human move.\n                        Board(X, Y) = Cell.X\n\n                        If CheckForWin(Cell.X) Then\n\n                            Winner = Win.Human\n\n                            GameState = GameStateEnum.EndScreen\n\n                        ElseIf CheckForDraw() Then\n\n                            Winner = Win.Draw\n\n                            GameState = GameStateEnum.EndScreen\n\n                        Else\n\n                            'We switch to the computer player's turn.\n                            CurrentPlayer = Cell.O\n\n                        End If\n\n                        My.Computer.Audio.Play(My.Resources.tone700freq,\n                                               AudioPlayMode.Background)\n\n                    End If\n\n                End If\n\n            Case GameStateEnum.EndScreen\n\n                ResetGame()\n\n                GameState = GameStateEnum.Playing\n\n        End Select\n\nEnd Sub\n\n    \n```\n\n\nIf the human player didn't win and the game isn't a draw we switch to the computer player's turn.\n\n\n```\n\n\nPrivate Sub UpdatePlaying()\n\n        If CurrentPlayer = Cell.O Then\n            'Computer player's turn\n\n            ComputerMove()\n\n            If CheckForWin(Cell.O) Then\n\n                Winner = Win.Computer\n\n                GameState = GameStateEnum.EndScreen\n\n            ElseIf CheckForDraw() Then\n\n                Winner = Win.Draw\n\n                GameState = GameStateEnum.EndScreen\n\n            Else\n\n                'We switch to the human player's turn.\n                CurrentPlayer = Cell.X\n\n            End If\n\n        End If\n\nEnd Sub\n\n\n```\n\n\n## Draw Board\n\n\n\n\nWe draw the game board by first clearing the background to black. \n\n\n\n```\n\nPrivate Sub DrawGame()\n\n        Buffer.Graphics.Clear(Color.Black)\n\n        Select Case GameState\n\n            Case GameStateEnum.StartScreen\n\n                'DrawStartScreen()\n\n            Case GameStateEnum.Instructions\n\n                'DrawInstructions()\n\n            Case GameStateEnum.Playing\n\n                DrawPlaying()\n\n            Case GameStateEnum.EndScreen\n\n                DrawEndScreen()\n\n        End Select\n\nEnd Sub\n\n\nPrivate Sub DrawPlaying()\n\n        DrawBoardLines()\n\n        DrawXsAndOs()\n\n        DrawCoordinates()\n\nEnd Sub\n    \n    \n```\n    \n    \n\nWe draw the board lines using a white pen. \n\n\n\n```\n\n\nPrivate Sub DrawBoardLines()\n\n        Dim LinePen As New Pen(Color.White, LinePenWidth)\n\n        'Draw vertical board lines\n        Buffer.Graphics.DrawLine(LinePen,\n                                 CellWidth,\n                                 0,\n                                 CellWidth,\n                                 ClientSize.Height)\n\n        Buffer.Graphics.DrawLine(LinePen,\n                                 ClientSize.Width * 2 \\ 3,\n                                 0,\n                                 ClientSize.Width * 2 \\ 3,\n                                 ClientSize.Height)\n\n        'Draw horizontal board lines\n        Buffer.Graphics.DrawLine(LinePen,\n                                 0,\n                                 CellHeight,\n                                 ClientSize.Width,\n                                 ClientSize.Height \\ 3)\n\n        Buffer.Graphics.DrawLine(LinePen,\n                                 0,\n                                 ClientSize.Height * 2 \\ 3,\n                                 ClientSize.Width,\n                                 ClientSize.Height * 2 \\ 3)\n\n        LinePen.Dispose()\n\nEnd Sub\n\n\n```\n\n\nWe then loop through the game board array.\n\nWe draw X's and O's on the cells based on their state in the board array.\n\n\n```\n\n\nPrivate Sub DrawXsAndOs()\n\n        For X = 0 To 2\n\n            For Y = 0 To 2\n\n                'Does the cell contain an x?\n                If Board(X, Y) = Cell.X Then\n                    'Yes, the cell contains an x.\n\n                    DrawX(X, Y)\n\n                    'Does the cell contain an o?\n                ElseIf Board(X, Y) = Cell.O Then\n                    'Yes, the cell contains an o.\n\n                    DrawO(X, Y)\n\n                End If\n\n            Next\n\n        Next\n\nEnd Sub\n    \n    \n```\n\n\nWe draw the X's using a blue pen. \n\n\n\n```\n\n\nPrivate Sub DrawX(X As Integer, Y As Integer)\n        'To draw the letter X, we start by drawing two diagonal lines that\n        'cross in the middle.\n\n        Dim XPen As New Pen(Color.Blue, XPenWidth)\n\n        'We begin by drawing a diagonal line\n        'from the top left corner to the bottom right corner.\n        Buffer.Graphics.DrawLine(XPen,\n        X * CellWidth + CellPaddingWidth,\n                                 Y * CellHeight + CellPaddingHeight,\n                                 (X + 1) * CellWidth - CellPaddingWidth,\n                                 (Y + 1) * CellHeight - CellPaddingHeight)\n\n        'Then we draw a second diagonal line this time\n        'from the top right corner to the bottom left corner.\n        Buffer.Graphics.DrawLine(XPen,\n                                 X * CellWidth + CellPaddingWidth,\n                                 (Y + 1) * CellHeight - CellPaddingHeight,\n                                 (X + 1) * CellWidth - CellPaddingWidth,\n                                 Y * CellHeight + CellPaddingHeight)\n\n        'The two lines intersect in the middle to form an X shape.\n\n        XPen.Dispose()\n\nEnd Sub\n\n\n```\n\n\nWe draw the O's using a red pen.\n\n\n```\n\n\nPrivate Sub DrawO(X As Integer, Y As Integer)\n\n        Dim OPen As New Pen(Color.Red, OPenWidth)\n\n        Buffer.Graphics.DrawEllipse(OPen,\n                                    X * CellWidth + CellPaddingWidth,\n                                    Y * CellHeight + CellPaddingHeight,\n                                    CellWidth - 2 * CellPaddingWidth,\n                                    CellHeight - 2 * CellPaddingHeight)\n\n        OPen.Dispose()\n\nEnd Sub\n\n\n```\n\n\n\n\nWe draw the buffer to the form in the Paint event handler.\n\n\n\n\n```\n\n\nProtected Overrides Sub OnPaint(ByVal e As PaintEventArgs)\n\n        DrawGame()\n\n        DrawFPS()\n\n        'Show buffer on form.\n        Buffer.Render(e.Graphics)\n\n        'Release memory used by buffer.\n        Buffer.Dispose()\n        Buffer = Nothing\n\n        'Create new buffer.\n        Buffer = Context.Allocate(CreateGraphics(), ClientRectangle)\n\n        'Use these settings when drawing to the backbuffer.\n        With Buffer.Graphics\n\n            'Bug Fix: Don't Change.\n            'To fix draw string error with anti aliasing: \"Parameters not valid.\"\n            'I set the compositing mode to: SourceOver.\n            .CompositingMode = CompositingMode.SourceOver\n\n            .TextRenderingHint = TextRenderingHint.AntiAliasGridFit\n            .SmoothingMode = SmoothingMode.AntiAlias\n            .CompositingQuality = CompositingQuality.HighQuality\n            .InterpolationMode = InterpolationMode.HighQualityBicubic\n            .PixelOffsetMode = PixelOffsetMode.HighQuality\n            .TextContrast = 6 'a value between 0 and 12\n        End With\n\n        UpdateFrameCounter()\n\nEnd Sub\n\n\n```\n\n\n\n\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoelumbley%2Ftic-tac-toe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoelumbley%2Ftic-tac-toe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoelumbley%2Ftic-tac-toe/lists"}