A modern, extensible “Connect X” (generalized Connect Four) game implemented in C#/.NET with two front‑ends:
hyper-connect-x: a modular console application with reusable librarieshyper-connect-x-web: an ASP.NET Core Razor Pages web application with Identity
This README is beginner‑friendly and explains how to run both apps, what every folder does, and how the parts fit together.
- Configurable board size: any
rows×columns - Configurable win length:
WinningSequence - Optional cylindrical board (horizontal wrap)
- Human vs Human or Human vs AI (Minimax)
- Save/Load games via SQLite (Entity Framework Core)
- Two UIs: console and web (Razor Pages + Identity)
Prerequisites:
- .NET SDK 9 (or the version specified by the projects)
Clone/open the repository, then from the repository root:
-
Build everything
cd /Users/kaarel/RiderProjects/connect_x dotnet build hyper-connect-x/hyper-connect-x.sln dotnet build hyper-connect-x-web/hyper-connect-x-web.sln -
Run the console app
dotnet run --project hyper-connect-x/ConsoleApp/ConsoleApp.csproj
First run creates a local SQLite database file
hyper-connect-x/ConsoleApp/connectx.dband seeds default configurations. -
Run the web app
cd hyper-connect-x-web/WebApp dotnet runOpen the URL printed to the console (e.g.,
http://localhost:5001).Note: If you encounter build errors, ensure dependencies are built first:
cd ../../hyper-connect-x dotnet build Database/Database.csproj dotnet build GameLib/GameLib.csproj cd ../hyper-connect-x-web/WebApp dotnet build
hyper-connect-x— Console solution and reusable librariesBoardLib— board representation and rulesGameLib— core game logic, DTOs, AI, repositoriesDatabase— EF Core context, entities, migrations, seedingMenuLib— console menusPlayersLib— player modelConsoleApp— console entry point and SQLite DB fileUI— extra console UI helpers (if present)Utils— shared utilities (if present)
hyper-connect-x-web— Web solution (Razor Pages)WebApp— ASP.NET Core project with Identity, Razor Pages UI, DI wiringPages/Play.cshtml— main gameplay page with interactive boardPages/NewGame/*— game creation flow (preset/custom configurations)Pages/LoadGame/Index.cshtml— saved game browserwwwroot/— static assets (CSS, JS)
How the solutions relate:
- Both reuse the same domain logic from
hyper-connect-x/GameLiband the same database model fromhyper-connect-x/Database. - The web app points to the console app’s SQLite game DB by default, so you can inspect or share saves easily.
- Build:
dotnet build hyper-connect-x/hyper-connect-x.sln - Run:
dotnet run --project hyper-connect-x/ConsoleApp/ConsoleApp.csproj
On first run:
- Creates
hyper-connect-x/ConsoleApp/connectx.db - Ensures schema exists and seeds default game configurations
- Opens a simple menu-driven UI to start, save, load, and play games
What ConsoleApp/Program.cs does:
var options = new DbContextOptionsBuilder<ConnectXDbContext>()
.UseSqlite("Data Source=connectx.db")
.Options;
using var db = new ConnectXDbContext(options);
await db.Database.EnsureCreatedAsync();
DbSeed.DefaultGameConfigs(db);
var root = new MenuRoot(new MenuContext(new EfGameStateRepository(db)));
root.CreateMainMenu().Run();- Build:
dotnet build hyper-connect-x-web/hyper-connect-x-web.sln - Run:
cd hyper-connect-x-web/WebApp && dotnet run - Open the printed URL (e.g.,
http://localhost:5001) in your browser.
Features:
- New Game: Choose from preset configurations (Connect 4, 5-in-a-row, etc.) or create custom board sizes
- Player Setup: Configure Human vs Human, Human vs AI, or AI vs AI matches
- Live Gameplay: Interactive board with click-to-place mechanics and visual feedback for last move
- AI Opponent: Minimax algorithm with adaptive depth based on board size (smaller boards = deeper search)
- Save/Load: All games are automatically saved and can be resumed from the Load Game menu
- Identity Support: User authentication system (optional, can be extended)
Notes:
- Identity (user accounts) uses SQLite at
hyper-connect-x-web/WebApp/app.db. - Game state uses the SQLite DB file at
../../hyper-connect-x/ConsoleApp/connectx.db(relative toWebApp). This is configured inWebApp/Program.cs. - On startup the web app seeds default game configurations into the game DB.
- The web UI auto-refreshes when it's the AI's turn to maintain game flow.
Board.cs- Grid model backed by
int[,]where0means empty and>0is a player ID - Properties:
Width,Height,IsCylindrical - Methods:
CanPlacePices(int column)— checks if a piece can be dropped into a columnPlacePiece(int column, int player)— drops a piece from top to bottom, returns row index or-1if column is fullGetPiece(int row, int column)— safe read; wraps columns horizontally whenIsCylindricalis trueIsFull()— true if no more moves can be made
- Grid model backed by
GameBrain.cs- Orchestrates game rules and flow:
- Tracks
GameConfig,Player[], active player, game over state, and winner ID CanMakeMove(int column),MakeMove(int column)— validates and applies moves, switches turns, detects win/draw- Win detection via directional counting with proper handling for cylindrical boards
ExportGameState(string saveName)andImportGameState(GameStateDto)— serialization for persistenceGetBoard()— exposes the underlyingBoard
- Tracks
- Orchestrates game rules and flow:
GameConfig.cs- Rules for a game:
Rows,Columns,WinningSequence,IsCilinder(cylindrical),Name - Factory helper
CreateGameConfig(...)
- Rules for a game:
MinMaxAI.cs- Minimax-based AI to choose a column; search depth adapts to board size in the web UI
GameStateDto.cs- Serializable snapshot for saving/loading games
IGameStateRepository.cs,EfGameStateRepository.cs(and/orGameStateRepository.cs)- Abstractions and EF Core-backed implementation for persistence
ConnectXDbContext.cs- EF Core context with
DbSet<GameConfigEntity>,DbSet<GameStateEntity>,DbSet<PlayerEntity> - Unique indices:
GameConfigEntity.Name,GameStateEntity.SaveName - Stores
GameStateEntity.BoardJsonasTEXT
- EF Core context with
DbSeed.cs- Inserts default
GameConfigEntitypresets on startup
- Inserts default
GameConfigEntity.cs,GameStateEntity.cs,PlayerEntity.cs- Database entities
Migrations/- EF Core migrations for schema evolution
Player.cs- Simple model for a player (e.g.,
Id,Name,IsAi)
- Simple model for a player (e.g.,
MenuRoot.cs— builds the main menu and navigationMenuGamePlay.cs— runs the in-console game loop and interactionsMenuLoadAndDelete.cs— list/load/delete saved gamesMenuBuilder.cs,MenuContext.cs,MenuItem.cs,MenuHelpers.cs— menu utilities
Program.cs- Registers:
- Razor Pages
- Identity with SQLite at
app.db(ApplicationDbContext) - Game DB via
ConnectXDbContextusing../../hyper-connect-x/ConsoleApp/connectx.db - DI for
IGameStateRepository→EfGameStateRepository
- Seeds default game configs on startup
- Registers:
Pages/Play.cshtmlandPages/Play.cshtml.cs- Main gameplay UI: renders the board, handles clicks, animates last move, drives AI turns
- Key flow in
Play.cshtml.cs:// OnGet: load state and, if AI’s turn, make ONE AI move var state = _repo.Load(id); Brain = GameBrain.ImportGameState(state); if (!Brain.IsGameOver && Brain.CurrentPlayer.IsAi) { MakeOneAiMove(id); } // OnPostMove: human move var (row, gameOver, winnerId) = Brain.MakeMove(col); _repo.Save(Brain.ExportGameState(id)); return RedirectToPage("Play", new { id = id, lastRow = row, lastCol = col }); // AI move selection var ai = new MinimaxAI(depth); int column = ai.ChooseMove(Brain); var (row, gameOver, winnerId) = Brain.MakeMove(column); _repo.Save(Brain.ExportGameState(id));
Pages/NewGame/*— start a new game from presets or custom configPages/LoadGame/Index.cshtml— list and load saved gamesPages/Shared/_Layout.cshtml— common layout, scripts, styleswwwroot/— static files (CSS/JS)
- Board representation:
BoardLib.Boardmanages placements in a column and tracks occupancy. - Cylindrical boards: when
IsCilinder/IsCylindricalis true, horizontal and diagonal checks wrap across left/right edges. - Turn flow:
GameBrain.MakeMove(column)places a piece, checks for win/draw, then advances the current player. - AI:
MinMaxAIevaluates future states at a configurable depth and returns the chosen column.
- Storage: SQLite, modeled with EF Core via
ConnectXDbContext. - Entities: game configurations, game states (including the board as JSON), and players.
- Seeding:
DbSeed.DefaultGameConfigs(db)inserts default presets on startup for both console and web apps. - Save/Load:
GameStateDtoserializes the board, players, whose turn it is, and status flags.
-
Build solutions
dotnet build hyper-connect-x/hyper-connect-x.sln dotnet build hyper-connect-x-web/hyper-connect-x-web.sln
-
Run console app
dotnet run --project hyper-connect-x/ConsoleApp/ConsoleApp.csproj
-
Run web app
cd hyper-connect-x-web/WebApp dotnet runThen navigate to
http://localhost:5001 -
Clean build (if you have issues)
dotnet clean hyper-connect-x/hyper-connect-x.sln dotnet clean hyper-connect-x-web/hyper-connect-x-web.sln dotnet build hyper-connect-x/hyper-connect-x.sln dotnet build hyper-connect-x-web/hyper-connect-x-web.sln
-
Reset databases (dev only)
rm hyper-connect-x/ConsoleApp/connectx.db* rm hyper-connect-x-web/WebApp/app.db* # Rerun the apps to recreate and seed
- Build errors: "The type or namespace name 'Database' could not be found"
- The WebApp project references projects from
hyper-connect-x. Build those dependencies first:cd hyper-connect-x dotnet build Database/Database.csproj dotnet build GameLib/GameLib.csproj cd ../hyper-connect-x-web/WebApp dotnet build
- The WebApp project references projects from
- Web can't find the game DB
- Ensure
hyper-connect-x/ConsoleApp/connectx.dbexists. Either run the console app once or the web app will create it automatically on first run.
- Ensure
- EF Core migration/schema issues during development
- Delete the local
*.dbfiles and rerun the apps to recreate/seed:rm hyper-connect-x/ConsoleApp/connectx.db rm hyper-connect-x-web/WebApp/app.db
- Delete the local
- Clicks don't make moves in the web UI
- Human moves are ignored while it's the AI's turn. The page will auto-refresh when AI completes its move.
- Ensure the current player isn't marked as AI in the saved state.
- Performance on very large boards
- The web app adapts Minimax depth by board size (≤30 cells: depth 12, ≤56 cells: depth 8, else: depth 6).
- For custom large boards, reduce depth in
Play.cshtml.cs:75if needed.
- Add a new AI
- Create a class in
GameLibwith aChooseMove(GameBrain brain)method. - Instantiate it in the UI layer (console or web) or wire up via DI.
- Create a class in
- Add new presets
- Extend
DbSeed.DefaultGameConfigswith moreGameConfigEntityitems.
- Extend
- Change how games are stored
- Implement
IGameStateRepositoryfor a different data store (file system, cloud DB, etc.).
- Implement
- New front‑ends
- Reuse
GameLibandDatabasefromhyper-connect-xto build WPF, MAUI, or Blazor UIs.
- Reuse
- What does “Connect X” mean?
- It generalizes Connect Four so you can choose any winning length (
WinningSequence).
- It generalizes Connect Four so you can choose any winning length (
- What is a cylindrical board?
- Left and right edges are connected; horizontal/diagonal checks wrap around.
- Can I play Human vs Human?
- Yes. Configure both players as humans (non‑AI) in the UI/state.
Rows,Columns— board dimensionsWinningSequence— how many in a row to winIsCilinder/IsCylindrical— whether the board wraps horizontallyPlayer.Id— numeric ID used on the gridGameBrain— rule engine that applies moves and detects winsMinimaxAI— algorithm used by the AI to choose moves
This project is educational/student‑focused. If you plan to contribute, please:
- Keep core logic UI‑agnostic in
GameLib - Add features behind interfaces (e.g.,
IGameStateRepository) and implement adapters (EF, files, etc.) - Add or adjust presets via
DbSeed
Consider adding screenshots and badges to this README to improve discoverability and onboarding.